On Fri, May 04, 2012 at 10:46:00AM -0400, Kevin O'Connor wrote:
On Fri, May 04, 2012 at 04:01:56PM +0200, Gerd Hoffmann wrote:
On 05/04/12 15:18, Kevin O'Connor wrote:
On Fri, May 04, 2012 at 10:21:22AM +0200, Gerd Hoffmann wrote:
Hi,
This patch series makes the PCI I/O windows runtime-configurable via qemu firmware config interface. Main advantage is that we can size and shuffle around the PCI i/O windows according to the amount of memory the virtual machine has. We don't need a hole for 64bit PCI bars, we can just map them above the main memory. The hole for 32bit PCI bars can be enlarged for guests with less than 3.5 GB of memory.
Why pass in a PCI IO range through fw_cfg if SeaBIOS can figure out an acceptable range from the amount of memory in the machine?
Suggestions on how to update the pci host bridge windows in the dsdt then?
Perhaps malloc_high() a struct with the info you need and then create an OperationRegion() in the dynamically generated SSDT with the address of the struct.
I played with this a little and came up with the below as an example.
-Kevin
diff --git a/src/acpi-dsdt.dsl b/src/acpi-dsdt.dsl index 4a18617..960f9fb 100644 --- a/src/acpi-dsdt.dsl +++ b/src/acpi-dsdt.dsl @@ -132,7 +132,7 @@ DefinitionBlock ( B0EJ, 32, }
- Name (_CRS, ResourceTemplate () + Name (CRES, ResourceTemplate () { WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode, 0x0000, // Address Space Granularity @@ -183,6 +183,18 @@ DefinitionBlock ( 0x8000000000, // Address Length ,, , AddressRangeMemory, TypeStatic) }) + Method (_CRS, 0) + { + External (_SB.BDAT) + Field(_SB.BDAT, DWordAcc, NoLock, Preserve) { + VAL1, 32, + VAL2, 32, + } + DBUG("Got") + DBUG(VAL1) + DBUG(VAL2) + Return (CRES) + } } }
diff --git a/src/acpi.c b/src/acpi.c index 30888b9..3e0d4da 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -415,7 +415,8 @@ build_ssdt(void) int length = ((1+3+4) + (acpi_cpus * SD_SIZEOF) + (1+2+5+(12*acpi_cpus)) - + (6+2+1+(1*acpi_cpus))); + + (6+2+1+(1*acpi_cpus)) + + 17); u8 *ssdt = malloc_high(sizeof(struct acpi_table_header) + length); if (! ssdt) { warn_noalloc(); @@ -477,6 +478,26 @@ build_ssdt(void) for (i=0; i<acpi_cpus; i++) *(ssdt_ptr++) = (i < CountCPUs) ? 0x01 : 0x00;
+ // XXX + u32 *myval = malloc_high(sizeof(*myval) * 2); + myval[0] = 0x1234abcd; + myval[1] = 0xdcba8976; + + // build "OperationRegion(BDAT, SystemMemory, 0x12345678, 0x87654321)" + *(ssdt_ptr++) = 0x5B; // ExtOpPrefix + *(ssdt_ptr++) = 0x80; // OpRegionOp + *(ssdt_ptr++) = 'B'; + *(ssdt_ptr++) = 'D'; + *(ssdt_ptr++) = 'A'; + *(ssdt_ptr++) = 'T'; + *(ssdt_ptr++) = 0x00; // SystemMemory + *(ssdt_ptr++) = 0x0C; // DWordPrefix + *(u32*)ssdt_ptr = (u32)myval; + ssdt_ptr += 4; + *(ssdt_ptr++) = 0x0C; // DWordPrefix + *(u32*)ssdt_ptr = sizeof(*myval)*2; + ssdt_ptr += 4; + build_header((void*)ssdt, SSDT_SIGNATURE, ssdt_ptr - ssdt, 1);
//hexdump(ssdt, ssdt_ptr - ssdt);