]> git.proxmox.com Git - qemu-server.git/commitdiff
Rework get_cpu_options and allow custom CPU models
authorStefan Reiter <s.reiter@proxmox.com>
Tue, 7 Apr 2020 13:56:18 +0000 (15:56 +0200)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Tue, 7 Apr 2020 15:27:58 +0000 (17:27 +0200)
If a cputype is custom (check via prefix), try to load options from the
custom CPU model config, and set values accordingly.

While at it, extract currently hardcoded values into seperate sub and add
reasonings.

Since the new flag resolving outputs flags in sorted order for
consistency, adapt the test cases to not break. Only the order is
changed, not which flags are present.

Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
Reviewed-By: Fabian Ebner <f.ebner@proxmox.com>
Tested-By: Fabian Ebner <f.ebner@proxmox.com>
14 files changed:
PVE/QemuServer/CPUConfig.pm
test/cfg2cmd/efi-raw-old.conf.cmd
test/cfg2cmd/efi-raw.conf.cmd
test/cfg2cmd/i440fx-win10-hostpci.conf.cmd
test/cfg2cmd/minimal-defaults.conf.cmd
test/cfg2cmd/pinned-version.conf.cmd
test/cfg2cmd/q35-linux-hostpci-multifunction.conf.cmd
test/cfg2cmd/q35-linux-hostpci.conf.cmd
test/cfg2cmd/q35-win10-hostpci.conf.cmd
test/cfg2cmd/simple1.conf.cmd
test/cfg2cmd/spice-enhancments.conf.cmd
test/cfg2cmd/spice-linux-4.1.conf.cmd
test/cfg2cmd/spice-usb3.conf.cmd
test/cfg2cmd/spice-win.conf.cmd

index 9fa6af988d460b26db74b0212aa11a1f119013e9..af31b2b08abddf024249605cb9b952a92283349f 100644 (file)
@@ -384,99 +384,190 @@ sub print_cpuflag_hash {
     return $formatted;
 }
 
+sub parse_cpuflag_list {
+    my ($re, $reason, $flaglist) = @_;
+
+    my $res = {};
+    return $res if !$flaglist;
+
+    foreach my $flag (split(";", $flaglist)) {
+       if ($flag =~ $re) {
+           $res->{$2} = { op => $1, reason => $reason };
+       }
+    }
+
+    return $res;
+}
+
 # Calculate QEMU's '-cpu' argument from a given VM configuration
 sub get_cpu_options {
     my ($conf, $arch, $kvm, $kvm_off, $machine_version, $winversion, $gpu_passthrough) = @_;
 
-    my $cpuFlags = [];
-    my $ostype = $conf->{ostype};
-
-    my $cpu = $kvm ? "kvm64" : "qemu64";
+    my $cputype = $kvm ? "kvm64" : "qemu64";
     if ($arch eq 'aarch64') {
-       $cpu = 'cortex-a57';
-    }
-    my $hv_vendor_id;
-    if (my $cputype = $conf->{cpu}) {
-       my $cpuconf = PVE::JSONSchema::parse_property_string($cpu_fmt, $cputype)
-           or die "Cannot parse cpu description: $cputype\n";
-       $cpu = $cpuconf->{cputype};
-       $kvm_off = 1 if $cpuconf->{hidden};
-       $hv_vendor_id = $cpuconf->{'hv-vendor-id'};
-
-       if (defined(my $flags = $cpuconf->{flags})) {
-           push @$cpuFlags, split(";", $flags);
-       }
+       $cputype = 'cortex-a57';
     }
 
-    push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64' && $arch eq 'x86_64';
+    my $cpu = {};
+    my $custom_cpu;
+    my $hv_vendor_id;
+    if (my $cpu_prop_str = $conf->{cpu}) {
+       $cpu = parse_vm_cpu_conf($cpu_prop_str)
+           or die "Cannot parse cpu description: $cpu_prop_str\n";
 
-    push @$cpuFlags , '-x2apic' if $ostype && $ostype eq 'solaris';
+       $cputype = $cpu->{cputype};
 
-    push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
+       if (is_custom_model($cputype)) {
+           $custom_cpu = get_custom_model($cputype);
 
-    push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
+           $cputype = $custom_cpu->{'reported-model'} //
+               $cpu_fmt->{'reported-model'}->{default};
+           $kvm_off = $custom_cpu->{hidden}
+               if defined($custom_cpu->{hidden});
+           $hv_vendor_id = $custom_cpu->{'hv-vendor-id'};
+       }
 
-    if (min_version($machine_version, 2, 3) && $arch eq 'x86_64') {
+       # VM-specific settings override custom CPU config
+       $kvm_off = $cpu->{hidden}
+           if defined($cpu->{hidden});
+       $hv_vendor_id = $cpu->{'hv-vendor-id'}
+           if defined($cpu->{'hv-vendor-id'});
+    }
 
-       push @$cpuFlags , '+kvm_pv_unhalt' if $kvm;
-       push @$cpuFlags , '+kvm_pv_eoi' if $kvm;
+    my $pve_flags = get_pve_cpu_flags($conf, $kvm, $cputype, $arch,
+                                     $machine_version);
+
+    my $hv_flags = get_hyperv_enlightenments($winversion, $machine_version,
+       $conf->{bios}, $gpu_passthrough, $hv_vendor_id) if $kvm;
+
+    my $custom_cputype_flags = parse_cpuflag_list($cpu_flag_any_re,
+       "set by custom CPU model", $custom_cpu->{flags});
+
+    my $vm_flags = parse_cpuflag_list($cpu_flag_supported_re,
+       "manually set for VM", $cpu->{flags});
+
+    my $pve_forced_flags = {};
+    $pve_forced_flags->{'enforce'} = {
+       reason => "error if requested CPU settings not available",
+    } if $cputype ne 'host' && $kvm && $arch eq 'x86_64';
+    $pve_forced_flags->{'kvm'} = {
+       value => "off",
+       reason => "hide KVM virtualization from guest",
+    } if $kvm_off;
+
+    # $cputype is the "reported-model" for custom types, so we can just look up
+    # the vendor in the default list
+    my $cpu_vendor = $cpu_vendor_list->{$cputype};
+    if ($cpu_vendor) {
+       $pve_forced_flags->{'vendor'} = {
+           value => $cpu_vendor,
+       } if $cpu_vendor ne 'default';
+    } elsif ($arch ne 'aarch64') {
+       die "internal error"; # should not happen
     }
 
-    add_hyperv_enlightenments($cpuFlags, $winversion, $machine_version, $conf->{bios}, $gpu_passthrough, $hv_vendor_id) if $kvm;
+    my $cpu_str = $cputype;
 
-    push @$cpuFlags, 'enforce' if $cpu ne 'host' && $kvm && $arch eq 'x86_64';
+    # will be resolved in parameter order
+    $cpu_str .= resolve_cpu_flags($pve_flags, $hv_flags, $custom_cputype_flags,
+                             $vm_flags, $pve_forced_flags);
 
-    push @$cpuFlags, 'kvm=off' if $kvm_off;
+    return ('-cpu', $cpu_str);
+}
 
-    if (my $cpu_vendor = $cpu_vendor_list->{$cpu}) {
-       push @$cpuFlags, "vendor=${cpu_vendor}"
-           if $cpu_vendor ne 'default';
-    } elsif ($arch ne 'aarch64') {
-       die "internal error"; # should not happen
+# Some hardcoded flags required by certain configurations
+sub get_pve_cpu_flags {
+    my ($conf, $kvm, $cputype, $arch, $machine_version) = @_;
+
+    my $pve_flags = {};
+    my $pve_msg = "set by PVE;";
+
+    $pve_flags->{'lahf_lm'} = {
+       op => '+',
+       reason => "$pve_msg to support Windows 8.1+",
+    } if $cputype eq 'kvm64' && $arch eq 'x86_64';
+
+    $pve_flags->{'x2apic'} = {
+       op => '-',
+       reason => "$pve_msg incompatible with Solaris",
+    } if $conf->{ostype} && $conf->{ostype} eq 'solaris';
+
+    $pve_flags->{'sep'} = {
+       op => '+',
+       reason => "$pve_msg to support Windows 8+ and improve Windows XP+",
+    } if $cputype eq 'kvm64' || $cputype eq 'kvm32';
+
+    $pve_flags->{'rdtscp'} = {
+       op => '-',
+       reason => "$pve_msg broken on AMD Opteron",
+    } if $cputype =~ m/^Opteron/;
+
+    if (min_version($machine_version, 2, 3) && $kvm && $arch eq 'x86_64') {
+       $pve_flags->{'kvm_pv_unhalt'} = {
+           op => '+',
+           reason => "$pve_msg to improve Linux guest spinlock performance",
+       };
+       $pve_flags->{'kvm_pv_eoi'} = {
+           op => '+',
+           reason => "$pve_msg to improve Linux guest interrupt performance",
+       };
     }
 
-    $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
-
-    return ('-cpu', $cpu);
+    return $pve_flags;
 }
 
-sub add_hyperv_enlightenments {
-    my ($cpuFlags, $winversion, $machine_version, $bios, $gpu_passthrough, $hv_vendor_id) = @_;
+sub get_hyperv_enlightenments {
+    my ($winversion, $machine_version, $bios, $gpu_passthrough, $hv_vendor_id) = @_;
 
     return if $winversion < 6;
     return if $bios && $bios eq 'ovmf' && $winversion < 8;
 
-    if ($gpu_passthrough || defined($hv_vendor_id)) {
+    my $flags = {};
+    my $default_reason = "automatic Hyper-V enlightenment for Windows";
+    my $flagfn = sub {
+       my ($flag, $value, $reason) = @_;
+       $flags->{$flag} = {
+           reason => $reason // $default_reason,
+           value => $value,
+       }
+    };
+
+    my $hv_vendor_set = defined($hv_vendor_id);
+    if ($gpu_passthrough || $hv_vendor_set) {
        $hv_vendor_id //= 'proxmox';
-       push @$cpuFlags , "hv_vendor_id=$hv_vendor_id";
+       $flagfn->('hv_vendor_id', $hv_vendor_id, $hv_vendor_set ?
+           "custom hv_vendor_id set" : "NVIDIA workaround for GPU passthrough");
     }
 
     if (min_version($machine_version, 2, 3)) {
-       push @$cpuFlags , 'hv_spinlocks=0x1fff';
-       push @$cpuFlags , 'hv_vapic';
-       push @$cpuFlags , 'hv_time';
+       $flagfn->('hv_spinlocks', '0x1fff');
+       $flagfn->('hv_vapic');
+       $flagfn->('hv_time');
     } else {
-       push @$cpuFlags , 'hv_spinlocks=0xffff';
+       $flagfn->('hv_spinlocks', '0xffff');
     }
 
     if (min_version($machine_version, 2, 6)) {
-       push @$cpuFlags , 'hv_reset';
-       push @$cpuFlags , 'hv_vpindex';
-       push @$cpuFlags , 'hv_runtime';
+       $flagfn->('hv_reset');
+       $flagfn->('hv_vpindex');
+       $flagfn->('hv_runtime');
     }
 
     if ($winversion >= 7) {
-       push @$cpuFlags , 'hv_relaxed';
+       my $win7_reason = $default_reason . " 7 and higher";
+       $flagfn->('hv_relaxed', undef, $win7_reason);
 
        if (min_version($machine_version, 2, 12)) {
-           push @$cpuFlags , 'hv_synic';
-           push @$cpuFlags , 'hv_stimer';
+           $flagfn->('hv_synic', undef, $win7_reason);
+           $flagfn->('hv_stimer', undef, $win7_reason);
        }
 
        if (min_version($machine_version, 3, 1)) {
-           push @$cpuFlags , 'hv_ipi';
+           $flagfn->('hv_ipi', undef, $win7_reason);
        }
     }
+
+    return $flags;
 }
 
 sub get_cpu_from_running_vm {
index 5526a48980433c5acae3696a6a9d21acdcdfa21b..666cdb173287f242c344d9d1e041f1adb97fbb68 100644 (file)
@@ -14,7 +14,7 @@
   -nodefaults \
   -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
   -vnc unix:/var/run/qemu-server/8006.vnc,password \
-  -cpu kvm64,+lahf_lm,+sep,+kvm_pv_unhalt,+kvm_pv_eoi,enforce \
+  -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
   -m 512 \
   -device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
   -device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
index a3369327efb9745110d79762bad4d8970920c392..cb0e984b5b0881b2eef1ad9db8214192ddaacf72 100644 (file)
@@ -14,7 +14,7 @@
   -nodefaults \
   -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
   -vnc unix:/var/run/qemu-server/8006.vnc,password \
-  -cpu kvm64,+lahf_lm,+sep,+kvm_pv_unhalt,+kvm_pv_eoi,enforce \
+  -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
   -m 512 \
   -device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
   -device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
index 43741ae9323f15971a775a3c5dae1aeaa8a11268..2fe34a1d4bb7896f61ed7b88213d139d042bf81d 100644 (file)
@@ -15,7 +15,7 @@
   -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
   -vnc unix:/var/run/qemu-server/8006.vnc,password \
   -no-hpet \
-  -cpu 'kvm64,+lahf_lm,+sep,+kvm_pv_unhalt,+kvm_pv_eoi,hv_spinlocks=0x1fff,hv_vapic,hv_time,hv_reset,hv_vpindex,hv_runtime,hv_relaxed,hv_synic,hv_stimer,hv_ipi,enforce' \
+  -cpu 'kvm64,enforce,hv_ipi,hv_relaxed,hv_reset,hv_runtime,hv_spinlocks=0x1fff,hv_stimer,hv_synic,hv_time,hv_vapic,hv_vpindex,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep' \
   -m 512 \
   -object 'memory-backend-ram,id=ram-node0,size=256M' \
   -numa 'node,nodeid=0,cpus=0,memdev=ram-node0' \
index c499a8590fb1dc5a92e3ea377398acdb02acdc5b..0735f43e76dcfe4eb48cc8e4ca5f29732f677a65 100644 (file)
@@ -12,7 +12,7 @@
   -nodefaults \
   -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
   -vnc unix:/var/run/qemu-server/8006.vnc,password \
-  -cpu kvm64,+lahf_lm,+sep,+kvm_pv_unhalt,+kvm_pv_eoi,enforce \
+  -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
   -m 512 \
   -device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
   -device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
index 2fc31fc70b8177b3b147b889698e5c34274edf4c..a7d0ae210092b098e497f8f03730e5091492d427 100644 (file)
@@ -12,7 +12,7 @@
   -nodefaults \
   -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
   -vnc unix:/var/run/qemu-server/8006.vnc,password \
-  -cpu kvm64,+lahf_lm,+sep,+kvm_pv_unhalt,+kvm_pv_eoi,enforce \
+  -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
   -m 1024 \
   -readconfig /usr/share/qemu-server/pve-q35.cfg \
   -device 'vmgenid,guid=bdd46b98-fefc-11e9-97b4-d72c378e0f96' \
index c766d3386d784bd392320125a7494e835ff8ed8e..a008939e2a2e7bb2cf1ddd55dd2452cc77cf6ad4 100644 (file)
@@ -14,7 +14,7 @@
   -nodefaults \
   -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
   -vnc unix:/var/run/qemu-server/8006.vnc,password \
-  -cpu kvm64,+lahf_lm,+sep,+kvm_pv_unhalt,+kvm_pv_eoi,enforce \
+  -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
   -m 512 \
   -object 'memory-backend-ram,id=ram-node0,size=256M' \
   -numa 'node,nodeid=0,cpus=0,memdev=ram-node0' \
index 7059b298b3b6af05ecb8eccb12ba5eb8a9e7e5df..7e829ae24831963b39ef04dd25550d344a5591f8 100644 (file)
@@ -14,7 +14,7 @@
   -nodefaults \
   -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
   -vnc unix:/var/run/qemu-server/8006.vnc,password \
-  -cpu kvm64,+lahf_lm,+sep,+kvm_pv_unhalt,+kvm_pv_eoi,enforce \
+  -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
   -m 512 \
   -object 'memory-backend-ram,id=ram-node0,size=256M' \
   -numa 'node,nodeid=0,cpus=0,memdev=ram-node0' \
index 3397324b4d701b0a0c9ef1a6bb107cd5b590b605..133c08636ebf154fabdd0349456b48a1c0be8c1a 100644 (file)
@@ -15,7 +15,7 @@
   -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
   -vnc unix:/var/run/qemu-server/8006.vnc,password \
   -no-hpet \
-  -cpu 'kvm64,+lahf_lm,+sep,+kvm_pv_unhalt,+kvm_pv_eoi,hv_spinlocks=0x1fff,hv_vapic,hv_time,hv_reset,hv_vpindex,hv_runtime,hv_relaxed,hv_synic,hv_stimer,hv_ipi,enforce' \
+  -cpu 'kvm64,enforce,hv_ipi,hv_relaxed,hv_reset,hv_runtime,hv_spinlocks=0x1fff,hv_stimer,hv_synic,hv_time,hv_vapic,hv_vpindex,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep' \
   -m 512 \
   -object 'memory-backend-ram,id=ram-node0,size=256M' \
   -numa 'node,nodeid=0,cpus=0,memdev=ram-node0' \
index b5c06cf4b293f4b69676128a3987be71751a66cb..34850644d4a33fff3e16acf0c673ac27e36eb740 100644 (file)
@@ -12,7 +12,7 @@
   -nodefaults \
   -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
   -vnc unix:/var/run/qemu-server/8006.vnc,password \
-  -cpu kvm64,+lahf_lm,+sep,+kvm_pv_unhalt,+kvm_pv_eoi,enforce \
+  -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
   -m 768 \
   -device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
   -device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
index 2d49b3a25b53ebae0bbcc421417f217e8cca4aa6..3951c0657beca8509ed3611be2e96b634c13cf8f 100644 (file)
@@ -12,7 +12,7 @@
   -nodefaults \
   -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
   -vnc unix:/var/run/qemu-server/8006.vnc,password \
-  -cpu kvm64,+lahf_lm,+sep,+kvm_pv_unhalt,+kvm_pv_eoi,enforce \
+  -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
   -m 512 \
   -device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
   -device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
index 6aa781b96a97c333dd45841368462e1a06921785..2748cc996118b98f05dcf792fb476cb7e2cff7de 100644 (file)
@@ -12,7 +12,7 @@
   -nodefaults \
   -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
   -vnc unix:/var/run/qemu-server/8006.vnc,password \
-  -cpu kvm64,+lahf_lm,+sep,+kvm_pv_unhalt,+kvm_pv_eoi,enforce \
+  -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
   -m 768 \
   -device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
   -device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
index 627c0777ef7d6b6ca610b4ac3487230e14c87e21..c51564447b3af565f31444c6b39a70e67ebb3a18 100644 (file)
@@ -12,7 +12,7 @@
   -nodefaults \
   -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
   -vnc unix:/var/run/qemu-server/8006.vnc,password \
-  -cpu kvm64,+lahf_lm,+sep,+kvm_pv_unhalt,+kvm_pv_eoi,enforce \
+  -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
   -m 768 \
   -device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
   -device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
index 6f9435849b94f37b657a5a780a8deb6bb78b2ecb..22dfa9d704611a5884868c7a46af3f463d6c89b5 100644 (file)
@@ -13,7 +13,7 @@
   -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
   -vnc unix:/var/run/qemu-server/8006.vnc,password \
   -no-hpet \
-  -cpu 'kvm64,+lahf_lm,+sep,+kvm_pv_unhalt,+kvm_pv_eoi,hv_spinlocks=0x1fff,hv_vapic,hv_time,hv_reset,hv_vpindex,hv_runtime,hv_relaxed,hv_synic,hv_stimer,hv_ipi,enforce' \
+  -cpu 'kvm64,enforce,hv_ipi,hv_relaxed,hv_reset,hv_runtime,hv_spinlocks=0x1fff,hv_stimer,hv_synic,hv_time,hv_vapic,hv_vpindex,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep' \
   -m 768 \
   -device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
   -device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \