pci: acpi: add _DSM method to PCI devices
Implement _DSM according to:
    PCI Firmware Specification 3.1
    4.6.7.  DSM for Naming a PCI or PCI Express Device Under
            Operating Systems
and wire it up to cold and hot-plugged PCI devices.
Feature depends on ACPI hotplug being enabled (as that provides
PCI devices descriptions in ACPI and MMIO registers that are
reused to fetch acpi-index).
acpi-index should work for
  - cold plugged NICs:
      $QEMU -device e1000,acpi-index=100
         => 'eno100'
  - hot-plugged
      (monitor) device_add e1000,acpi-index=200,id=remove_me
         => 'eno200'
  - re-plugged
      (monitor) device_del remove_me
      (monitor) device_add e1000,acpi-index=1
         => 'eno1'
Windows also sees index under "PCI Label Id" field in properties
dialog but otherwise it doesn't seem to have any effect.
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Message-Id: <20210315180102.3008391-6-imammedo@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
			
			
This commit is contained in:
		
							parent
							
								
									910e406971
								
							
						
					
					
						commit
						b7f23f62e4
					
				| @ -397,6 +397,13 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, | ||||
|                     aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN")) | ||||
|                 ); | ||||
|                 aml_append(dev, method); | ||||
|                 method = aml_method("_DSM", 4, AML_SERIALIZED); | ||||
|                 aml_append(method, | ||||
|                     aml_return(aml_call6("PDSM", aml_arg(0), aml_arg(1), | ||||
|                                          aml_arg(2), aml_arg(3), | ||||
|                                          aml_name("BSEL"), aml_name("_SUN"))) | ||||
|                 ); | ||||
|                 aml_append(dev, method); | ||||
|                 aml_append(parent_scope, dev); | ||||
| 
 | ||||
|                 build_append_pcihp_notify_entry(notify_method, slot); | ||||
| @ -424,6 +431,16 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, | ||||
|         dev = aml_device("S%.02X", PCI_DEVFN(slot, 0)); | ||||
|         aml_append(dev, aml_name_decl("_ADR", aml_int(slot << 16))); | ||||
| 
 | ||||
|         if (bsel) { | ||||
|             aml_append(dev, aml_name_decl("_SUN", aml_int(slot))); | ||||
|             method = aml_method("_DSM", 4, AML_SERIALIZED); | ||||
|             aml_append(method, aml_return( | ||||
|                 aml_call6("PDSM", aml_arg(0), aml_arg(1), aml_arg(2), | ||||
|                           aml_arg(3), aml_name("BSEL"), aml_name("_SUN")) | ||||
|             )); | ||||
|             aml_append(dev, method); | ||||
|         } | ||||
| 
 | ||||
|         if (pc->class_id == PCI_CLASS_DISPLAY_VGA) { | ||||
|             /* add VGA specific AML methods */ | ||||
|             int s3d; | ||||
| @ -446,9 +463,7 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, | ||||
|             aml_append(method, aml_return(aml_int(s3d))); | ||||
|             aml_append(dev, method); | ||||
|         } else if (hotplug_enabled_dev) { | ||||
|             /* add _SUN/_EJ0 to make slot hotpluggable  */ | ||||
|             aml_append(dev, aml_name_decl("_SUN", aml_int(slot))); | ||||
| 
 | ||||
|             /* add _EJ0 to make slot hotpluggable  */ | ||||
|             method = aml_method("_EJ0", 1, AML_NOTSERIALIZED); | ||||
|             aml_append(method, | ||||
|                 aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN")) | ||||
| @ -511,6 +526,88 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, | ||||
|     qobject_unref(bsel); | ||||
| } | ||||
| 
 | ||||
| Aml *aml_pci_device_dsm(void) | ||||
| { | ||||
|     Aml *method, *UUID, *ifctx, *ifctx1, *ifctx2, *ifctx3, *elsectx; | ||||
|     Aml *acpi_index = aml_local(0); | ||||
|     Aml *zero = aml_int(0); | ||||
|     Aml *bnum = aml_arg(4); | ||||
|     Aml *func = aml_arg(2); | ||||
|     Aml *rev = aml_arg(1); | ||||
|     Aml *sun = aml_arg(5); | ||||
| 
 | ||||
|     method = aml_method("PDSM", 6, AML_SERIALIZED); | ||||
| 
 | ||||
|     /*
 | ||||
|      * PCI Firmware Specification 3.1 | ||||
|      * 4.6.  _DSM Definitions for PCI | ||||
|      */ | ||||
|     UUID = aml_touuid("E5C937D0-3553-4D7A-9117-EA4D19C3434D"); | ||||
|     ifctx = aml_if(aml_equal(aml_arg(0), UUID)); | ||||
|     { | ||||
|         aml_append(ifctx, aml_store(aml_call2("AIDX", bnum, sun), acpi_index)); | ||||
|         ifctx1 = aml_if(aml_equal(func, zero)); | ||||
|         { | ||||
|             uint8_t byte_list[1]; | ||||
| 
 | ||||
|             ifctx2 = aml_if(aml_equal(rev, aml_int(2))); | ||||
|             { | ||||
|                 /*
 | ||||
|                  * advertise function 7 if device has acpi-index | ||||
|                  * acpi_index values: | ||||
|                  *            0: not present (default value) | ||||
|                  *     FFFFFFFF: not supported (old QEMU without PIDX reg) | ||||
|                  *        other: device's acpi-index | ||||
|                  */ | ||||
|                 ifctx3 = aml_if(aml_lnot( | ||||
|                     aml_or(aml_equal(acpi_index, zero), | ||||
|                            aml_equal(acpi_index, aml_int(0xFFFFFFFF)), NULL) | ||||
|                 )); | ||||
|                 { | ||||
|                     byte_list[0] = | ||||
|                         1 /* have supported functions */ | | ||||
|                         1 << 7 /* support for function 7 */ | ||||
|                     ; | ||||
|                     aml_append(ifctx3, aml_return(aml_buffer(1, byte_list))); | ||||
|                 } | ||||
|                 aml_append(ifctx2, ifctx3); | ||||
|              } | ||||
|              aml_append(ifctx1, ifctx2); | ||||
| 
 | ||||
|              byte_list[0] = 0; /* nothing supported */ | ||||
|              aml_append(ifctx1, aml_return(aml_buffer(1, byte_list))); | ||||
|          } | ||||
|          aml_append(ifctx, ifctx1); | ||||
|          elsectx = aml_else(); | ||||
|          /*
 | ||||
|           * PCI Firmware Specification 3.1 | ||||
|           * 4.6.7. _DSM for Naming a PCI or PCI Express Device Under | ||||
|           *        Operating Systems | ||||
|           */ | ||||
|          ifctx1 = aml_if(aml_equal(func, aml_int(7))); | ||||
|          { | ||||
|              Aml *pkg = aml_package(2); | ||||
|              Aml *ret = aml_local(1); | ||||
| 
 | ||||
|              aml_append(pkg, zero); | ||||
|              /*
 | ||||
|               * optional, if not impl. should return null string | ||||
|               */ | ||||
|              aml_append(pkg, aml_string("%s", "")); | ||||
|              aml_append(ifctx1, aml_store(pkg, ret)); | ||||
|              /*
 | ||||
|               * update acpi-index to actual value | ||||
|               */ | ||||
|              aml_append(ifctx1, aml_store(acpi_index, aml_index(ret, zero))); | ||||
|              aml_append(ifctx1, aml_return(ret)); | ||||
|          } | ||||
|          aml_append(elsectx, ifctx1); | ||||
|          aml_append(ifctx, elsectx); | ||||
|     } | ||||
|     aml_append(method, ifctx); | ||||
|     return method; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * build_prt_entry: | ||||
|  * @link_name: link name for PCI route entry | ||||
| @ -1195,6 +1292,8 @@ static void build_piix4_pci_hotplug(Aml *table) | ||||
|     aml_append(method, aml_return(aml_local(0))); | ||||
|     aml_append(scope, method); | ||||
| 
 | ||||
|     aml_append(scope, aml_pci_device_dsm()); | ||||
| 
 | ||||
|     aml_append(table, scope); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -35,4 +35,5 @@ typedef struct AcpiMcfgInfo { | ||||
| 
 | ||||
| void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info, | ||||
|                 const char *oem_id, const char *oem_table_id); | ||||
| Aml *aml_pci_device_dsm(void); | ||||
| #endif | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Igor Mammedov
						Igor Mammedov