Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions hypervisor/x86.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package hypervisor

import (
"context"

"j5.nz/cc/hypervisor/x86state"
)

Expand Down Expand Up @@ -33,6 +34,10 @@ const (
// The PC interrupt controllers and interval timer are provided by the backend.
// Firmware, disk and display device semantics belong to the caller.
type X86 interface {
// SupportedCPUID returns an owned table of accelerator-supported leaves.
SupportedCPUID() ([]x86state.CPUIDEntry, error)
// SetCPUID installs the machine's feature policy before the first Run.
SetCPUID([]x86state.CPUIDEntry) error
MapRAM(base, size uint64) ([]byte, error)
MapRAMRegions(size uint64, regions []RAMRegion) ([]byte, error)
Registers() (x86state.Registers, error)
Expand Down
7 changes: 7 additions & 0 deletions hypervisor/x86state/cpuid.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package x86state

// CPUIDEntry describes one architectural CPUID leaf and subleaf.
type CPUIDEntry struct {
Function, Index, Flags uint32
Eax, Ebx, Ecx, Edx uint32
}
39 changes: 39 additions & 0 deletions internal/hv/kvm/cpuid_linux_amd64.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//go:build linux && amd64

package kvm

import (
"fmt"

"j5.nz/cc/hypervisor/x86state"
)

// SupportedCPUID returns an owned copy of the features the accelerator can run.
func (v *VM) SupportedCPUID() ([]x86state.CPUIDEntry, error) {
entries, err := getSupportedCPUID(v.kvm.fd)
if err != nil {
return nil, err
}
result := make([]x86state.CPUIDEntry, 0, entries.Nr)
for _, e := range cpuidEntries(entries) {
result = append(result, x86state.CPUIDEntry{Function: e.Function, Index: e.Index, Flags: e.Flags, Eax: e.Eax, Ebx: e.Ebx, Ecx: e.Ecx, Edx: e.Edx})
}
return result, nil
}

// SetCPUID configures the single CPU before its first execution. Feature and
// topology policy belongs to the machine model, not this accelerator boundary.
func (v *VM) SetCPUID(entries []x86state.CPUIDEntry) error {
if len(v.vcpus) != 1 || len(entries) == 0 || len(entries) > cpuidMaxEntries {
return fmt.Errorf("invalid single-CPU CPUID table")
}
table, err := getSupportedCPUID(v.kvm.fd)
if err != nil {
return err
}
table.Nr = uint32(len(entries))
for i, e := range entries {
cpuidStorage(table)[i] = kvmCPUIDEntry2{Function: e.Function, Index: e.Index, Flags: e.Flags, Eax: e.Eax, Ebx: e.Ebx, Ecx: e.Ecx, Edx: e.Edx}
}
return setVCPUID(v.vcpufd, table)
}
Loading