Skip to content

Commit

Permalink
Generic acpi and reset of PCI audio device
Browse files Browse the repository at this point in the history
Lenovo X1 PCI audio device needs to be reset when audioVM shuts down
Generic version that allows configuration for other platforms

Signed-off-by: Jon Sahlberg <[email protected]>
  • Loading branch information
josa41 authored and brianmcgillion committed Dec 9, 2024
1 parent 745a6df commit 8938072
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 11 deletions.
15 changes: 15 additions & 0 deletions modules/hardware/definition.nix
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,21 @@ in
};

audio = {
removePciDevice = mkOption {
description = "PCI Device path to remove at VM reboot";
type = types.nullOr types.str;
default = null;
};
rescanPciDevice = mkOption {
description = "PCI Device path to rescan at VM reboot";
type = types.nullOr types.str;
default = null;
};
acpiPath = mkOption {
description = "Path to ACPI file to add to a VM";
type = types.nullOr types.str;
default = null;
};
# With the current implementation, the whole PCI IOMMU group 14:
# 00:1f.x in the example from Lenovo X1 Carbon
# must be defined for passthrough to AudioVM
Expand Down
16 changes: 10 additions & 6 deletions modules/microvm/virtualization/microvm/audiovm.nix
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ let
vmName = "audio-vm";
macAddress = "02:00:00:03:03:03";
isGuiVmEnabled = config.ghaf.virtualization.microvm.guivm.enable;
has_acpi_path = config.ghaf.hardware.definition.audio.acpiPath != null;

sshKeysHelper = pkgs.callPackage ../../../../packages/ssh-keys-helper {
inherit pkgs;
Expand Down Expand Up @@ -119,12 +120,15 @@ let
aarch64-linux = "virt";
}
.${configHost.nixpkgs.hostPlatform.system};
extraArgs = [
"-device"
"qemu-xhci"
"-acpitable"
"file=/sys/firmware/acpi/tables/NHLT"
];
extraArgs =
[
"-device"
"qemu-xhci"
]
++ lib.optionals has_acpi_path [
"-acpitable"
"file=${config.ghaf.hardware.definition.audio.acpiPath}"
];
};
};

Expand Down
18 changes: 13 additions & 5 deletions modules/microvm/virtualization/microvm/microvm-host.nix
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@
}:
let
cfg = config.ghaf.virtualization.microvm-host;
has_remove_pci_device = config.ghaf.hardware.definition.audio.removePciDevice != null;
has_rescan_pci_device = config.ghaf.hardware.definition.audio.rescanPciDevice != null;
has_acpi_path = config.ghaf.hardware.definition.audio.acpiPath != null;
rescan_pci_device =
if has_rescan_pci_device then
config.ghaf.hardware.definition.audio.rescanPciDevice
else
config.ghaf.hardware.definition.audio.removePciDevice;
in
{
imports = [
Expand Down Expand Up @@ -62,21 +70,21 @@ in
lib.optionalAttrs config.ghaf.virtualization.microvm.audiovm.enable
{
# The + here is a systemd feature to make the script run as root.
ExecStartPre = [
ExecStartPre = lib.mkIf has_acpi_path [
"+${pkgs.writeShellScript "ACPI-table-permission" ''
# The script gives permissionf sot a microvm user
# to read ACPI tables of soundcaed mic array.
${pkgs.coreutils}/bin/chmod 444 /sys/firmware/acpi/tables/NHLT
${pkgs.coreutils}/bin/chmod 444 ${config.ghaf.hardware.definition.audio.acpiPath}
''}"
];
ExecStopPost = [
ExecStopPost = lib.mkIf has_remove_pci_device [
"+${pkgs.writeShellScript "reload-audio" ''
# The script makes audio device internal state to reset
# This fixes issue of audio device getting into some unexpected
# state when the VM is being shutdown during audio mic recording
echo "1" > /sys/bus/pci/devices/0000:00:1f.3/remove
echo "1" > ${config.ghaf.hardware.definition.audio.removePciDevice}
sleep 0.1
echo "1" > /sys/bus/pci/devices/0000:00:1f.0/rescan
echo "1" > ${rescan_pci_device}
''}"
];
};
Expand Down
7 changes: 7 additions & 0 deletions modules/reference/hardware/lenovo-x1/definitions/x1-gen10.nix
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@
# 00:1f.x in the Lenovo X1 Carbon 10 gen
# must be defined for passthrough to AudioVM
audio = {
# Force a PCI device reset to the device to get pci device to the default state at shutdown
removePciDevice = "0000:00:1f.3";
# Force a PCI device rescan after resetting a device to refind the device on host
rescanPciDevice = "0000:00:1f.0";
# Add acpi table to audioVM to enable microphone array profile
acpiPath = "/sys/firmware/acpi/tables/NHLT";

pciDevices = [
{
# ISA bridge: Intel Corporation Alder Lake PCH eSPI Controller(rev 01)
Expand Down
9 changes: 9 additions & 0 deletions modules/reference/hardware/lenovo-x1/definitions/x1-gen11.nix
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@
# 00:1f.x in the example from Lenovo X1 Carbon
# must be defined for passthrough to AudioVM
audio = {
# Force a PCI device reset to the audio device
# This is to get the pci hardware device to the default state at shutdown
removePciDevice = "0000:00:1f.3";
# Force a PCI device rescan after resetting a device
# to refind the device on host after reset
rescanPciDevice = "0000:00:1f.0";
# Add acpi table file to audioVM to enable Lenovo X1 microphone array profile
acpiPath = "/sys/firmware/acpi/tables/NHLT";

pciDevices = [
{
# ISA bridge: Intel Corporation Raptor Lake LPC/eSPI Controller (rev 01)
Expand Down

0 comments on commit 8938072

Please sign in to comment.