feat: support duplicate device IDs in dracut

This commit is contained in:
jedrw 2025-01-02 14:38:13 +00:00
parent c1f11ce1c3
commit adedfb01b9
5 changed files with 170 additions and 57 deletions

View file

@ -3,11 +3,13 @@ package pages
import (
"fmt"
"os"
"regexp"
"github.com/gookit/color"
"github.com/HikariKnight/quickpassthrough/internal/common"
"github.com/HikariKnight/quickpassthrough/internal/configs"
"github.com/HikariKnight/quickpassthrough/internal/logger"
"github.com/HikariKnight/quickpassthrough/internal/lsiommu"
"github.com/HikariKnight/quickpassthrough/pkg/command"
"github.com/HikariKnight/quickpassthrough/pkg/fileio"
@ -94,37 +96,67 @@ func viewGPU(config *configs.Config, ext ...int) {
// Get the device ids for the selected gpu using ls-iommu
config.Gpu_IDs = lsiommu.GetIOMMU("-g", mode, "-i", config.Gpu_Group, "--id")
// If the kernel_args file already exists
if exists, _ := fileio.FileExist(config.Path.CMDLINE); exists {
// Delete it as we will have to make a new one anyway
err := os.Remove(config.Path.CMDLINE)
common.ErrorCheck(err, fmt.Sprintf("Could not remove %s", config.Path.CMDLINE))
}
// Write initial kernel_arg file
configs.Set_Cmdline(config.Gpu_IDs)
// Go to the vbios dumper page
genVBIOS_dumper(config)
case "manual":
config.Gpu_IDs = menu.ManualInput(
"Please manually enter the vendorID:deviceID for every device to use except PCI Express Switches\n"+
"NOTE: All devices sharing the same IOMMU group will still get pulled into the VM!",
"xxxx:yyyy,xxxx:yyyy,xxxx:yyyy",
)
}
// If the kernel_args file already exists
if exists, _ := fileio.FileExist(config.Path.CMDLINE); exists {
// Delete it as we will have to make a new one anyway
err := os.Remove(config.Path.CMDLINE)
common.ErrorCheck(err, fmt.Sprintf("Could not remove %s", config.Path.CMDLINE))
logger.Printf("Checking for duplicate device Ids")
hasDuplicateDeviceIds := detectDuplicateDeviceIds(config.Gpu_Group, config.Gpu_IDs)
if hasDuplicateDeviceIds {
config.HasDuplicateDeviceIds = true
config.Gpu_Addresses = lsiommu.GetIOMMU("-g", mode, "-i", config.Gpu_Group, "--pciaddr")
}
// If the kernel_args file already exists
if exists, _ := fileio.FileExist(config.Path.CMDLINE); exists {
// Delete it as we will have to make a new one anyway
err := os.Remove(config.Path.CMDLINE)
common.ErrorCheck(err, fmt.Sprintf("Could not remove %s", config.Path.CMDLINE))
}
// Write initial kernel_arg file
configs.Set_Cmdline(config.Gpu_IDs, !config.HasDuplicateDeviceIds)
// Go to the vbios dumper page
genVBIOS_dumper(config)
}
func detectDuplicateDeviceIds(selectedGpuGroup string, selectedDeviceIds []string) bool {
// TODO: this would be made much simpler if ls-iommu allowed using the --id flag without
// the "-i" flag.
gpus := lsiommu.GetIOMMU("-g", "-F", "vendor:,prod_name,optional_revision:,device_id")
iommu_group_regex := regexp.MustCompile(`(\d{1,3})`)
iommuGroups := []string{}
for _, gpu := range gpus {
iommuGroup := iommu_group_regex.FindString(gpu)
iommuGroups = append(iommuGroups, iommuGroup)
}
allDeviceIds := []string{}
for _, group := range iommuGroups {
if group == selectedGpuGroup {
continue
}
// Write initial kernel_arg file
configs.Set_Cmdline(config.Gpu_IDs)
// Go to the vbios dumper page
genVBIOS_dumper(config)
deviceIds := lsiommu.GetIOMMU("-g", "-r", "-i", group, "--id")
for _, deviceId := range deviceIds {
allDeviceIds = append(allDeviceIds, deviceId)
}
}
for _, deviceId := range allDeviceIds {
for _, selectedDeviceId := range selectedDeviceIds {
if deviceId == selectedDeviceId {
logger.Printf("Found duplicate device id: %s", deviceId)
return true
}
}
}
return false
}

View file

@ -6,6 +6,7 @@ import (
"log"
"os"
"os/user"
"strings"
"syscall"
"github.com/gookit/color"
@ -29,7 +30,7 @@ func prepModules(config *configs.Config) {
// If we have a folder for dracut
if exists, _ := fileio.FileExist(config.Path.DRACUT); exists {
// Configure dracut
configs.Set_Dracut()
configs.Set_Dracut(config)
}
// If we have a mkinitcpio.conf file
@ -209,6 +210,17 @@ func installPassthrough(config *configs.Config) {
// Copy dracut config to /etc/dracut.conf.d/vfio
configs.CopyToSystem(config.IsRoot, dracutFile, "/etc/dracut.conf.d/vfio")
if config.HasDuplicateDeviceIds {
moduleSysPath := strings.Replace(config.Path.DRACUTMODULE, "config", "", 1)
if err := command.ExecAndLogSudo(config.IsRoot, false, "mkdir", "-p", moduleSysPath); err != nil {
log.Fatalf("Failed to create dracut module directory: %s", err)
}
for configPath, sysPath := range config.EarlyBindFilePaths {
configs.CopyToSystem(config.IsRoot, configPath, sysPath)
}
}
// Get systeminfo
sysinfo := uname.New()