diff mbox

[SeaBIOS,seabios,0/5] dynamic pci i/o windows

Message ID 20120504153725.GA6782@morn.localdomain
State New
Headers show

Commit Message

Kevin O'Connor May 4, 2012, 3:37 p.m. UTC
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

Comments

Gleb Natapov May 6, 2012, 8:50 a.m. UTC | #1
On Fri, May 04, 2012 at 11:37:25AM -0400, Kevin O'Connor wrote:
> 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.
> 
IMO that is much better than reading fw_cfg from AML. fw_cfg wasn't
meant to be touched while OS is running. Another option is to patch the
DSDT directly. We have the infrastructure for that in place.

> -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);

--
			Gleb.
diff mbox

Patch

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);