Skip to content

Commit

Permalink
pillar/hypervisor: extract PCI template filling
Browse files Browse the repository at this point in the history
into separate function to make it easier to test it

Signed-off-by: Christoph Ostarek <[email protected]>
  • Loading branch information
christoph-zededa authored and OhmSpectator committed Nov 14, 2024
1 parent c680a2d commit 2315460
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 36 deletions.
83 changes: 47 additions & 36 deletions pkg/pillar/hypervisor/kvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,50 @@ func getFmlCustomResolution(status *types.DomainStatus, globalConfig *types.Conf
return "", fmt.Errorf("invalid fml resolution %s", fmlResolutions)
}

func pciAssignmentsTemplateFill(file io.Writer, pciAssignments []pciDevice, pciID int) error {
if len(pciAssignments) == 0 {
return nil
}

pciPTContext := struct {
PCIId int
PciShortAddr string
Xvga bool
Xopregion bool
}{PCIId: pciID, PciShortAddr: "", Xvga: false, Xopregion: false}

tRootPortPCI, _ := template.New("qemuPciPT").Parse(qemuRootPortPciPassthruTemplate)
tPCI, _ := template.New("qemuPciPT").Parse(qemuPciPassthruTemplate)
for _, pa := range pciAssignments {
short := types.PCILongToShort(pa.pciLong)
pciPTContext.Xvga = pa.isVGA()

if vendor, err := pa.vid(); err == nil {
// check for Intel vendor
if vendor == "0x8086" {
if pciPTContext.Xvga {
// we set opregion for Intel vga
// https://github.com/qemu/qemu/blob/stable-5.0/docs/igd-assign.txt#L91-L96
pciPTContext.Xopregion = true
}
}
}

pciPTContext.PciShortAddr = short
if err := tRootPortPCI.Execute(file, pciPTContext); err != nil {
return logError("can't write Root Port PCI Passthrough to config file (%v)", err)
}
if err := tPCI.Execute(file, pciPTContext); err != nil {
return logError("can't write PCI Passthrough to config file (%v)", err)
}
pciPTContext.Xvga = false
pciPTContext.Xopregion = false
pciPTContext.PCIId = pciPTContext.PCIId + 1
}

return nil
}

// CreateDomConfig creates a domain config (a qemu config file,
// typically named something like xen-%d.cfg)
func (ctx KvmContext) CreateDomConfig(domainName string,
Expand Down Expand Up @@ -1082,42 +1126,9 @@ func (ctx KvmContext) CreateDomConfig(domainName string,
}
}
}
if len(pciAssignments) != 0 {
pciPTContext := struct {
PCIId int
PciShortAddr string
Xvga bool
Xopregion bool
}{PCIId: netContext.PCIId, PciShortAddr: "", Xvga: false, Xopregion: false}

tRootPortPCI, _ := template.New("qemuPciPT").Parse(qemuRootPortPciPassthruTemplate)
tPCI, _ := template.New("qemuPciPT").Parse(qemuPciPassthruTemplate)
for _, pa := range pciAssignments {
short := types.PCILongToShort(pa.pciLong)
pciPTContext.Xvga = pa.isVGA()

if vendor, err := pa.vid(); err == nil {
// check for Intel vendor
if vendor == "0x8086" {
if pciPTContext.Xvga {
// we set opregion for Intel vga
// https://github.com/qemu/qemu/blob/stable-5.0/docs/igd-assign.txt#L91-L96
pciPTContext.Xopregion = true
}
}
}

pciPTContext.PciShortAddr = short
if err := tRootPortPCI.Execute(file, pciPTContext); err != nil {
return logError("can't write Root Port PCI Passthrough to config file %s (%v)", file.Name(), err)
}
if err := tPCI.Execute(file, pciPTContext); err != nil {
return logError("can't write PCI Passthrough to config file %s (%v)", file.Name(), err)
}
pciPTContext.Xvga = false
pciPTContext.Xopregion = false
pciPTContext.PCIId = pciPTContext.PCIId + 1
}
err = pciAssignmentsTemplateFill(file, pciAssignments, netContext.PCIId)
if err != nil {
return fmt.Errorf("writing to template file %s failed: %w", file.Name(), err)
}
if len(serialAssignments) != 0 {
serialPortContext := struct {
Expand Down
52 changes: 52 additions & 0 deletions pkg/pillar/hypervisor/kvm_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package hypervisor

import (
"bytes"
"fmt"
"net"
"os"
"os/exec"
"regexp"
"testing"

"github.com/google/go-cmp/cmp"
zconfig "github.com/lf-edge/eve-api/go/config"
"github.com/lf-edge/eve/pkg/pillar/types"
uuid "github.com/satori/go.uuid"
Expand Down Expand Up @@ -2756,3 +2758,53 @@ func TestCreateDomConfigContainerVNC(t *testing.T) {
t.Errorf("got an unexpected resulting config %s", string(result))
}
}

func expectedMultifunctionDevice() string {
return `
[device "pci.0"]
driver = "pcie-root-port"
port = "10"
chassis = "0"
bus = "pcie.0"
multifunction = "on"
addr = "0x0"
[device]
driver = "vfio-pci"
host = "0d.0"
bus = "pci.0"
addr = "0x0"
[device "pci.1"]
driver = "pcie-root-port"
port = "11"
chassis = "1"
bus = "pcie.0"
multifunction = "on"
addr = "0x1"
[device]
driver = "vfio-pci"
host = "0d.2"
bus = "pci.1"
addr = "0x0"`
}

func TestPCIAssignmentsTemplateFillMultifunctionDevice(t *testing.T) {
pciAssignments := []pciDevice{
{
pciLong: "00:0d.0",
ioType: 0,
},
{
pciLong: "00:0d.2",
ioType: 0,
},
}

wr := bytes.Buffer{}
pciAssignmentsTemplateFill(&wr, pciAssignments, 0)

if wr.String() != expectedMultifunctionDevice() {
t.Fatalf("not equal, diff: \n%s\n", cmp.Diff(wr.String(), expectedMultifunctionDevice()))
}
}

0 comments on commit 2315460

Please sign in to comment.