|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 08/15] x86/PVH: split pvh_setup_acpi()
All E820 manipulations want to happen before the initrd is placed, or else
pvh_steal_ram() may steal from the tail part of it. As a second step,
split placing ACPI data from actually populating it. To reuse size
calculations and limit churn, convert pvh_setup_acpi_{madt,xsdt}() to
two-pass functions: The 1st pass merely reserves space, while the 2nd pass
actually populates information.
While altering the copying of the RSDP pointer into Dom0's start-info, add
a BUILD_BUG_ON() making sure field sizes actually match up.
Fixes: 1d74282c455f ("x86: setup PVHv2 Dom0 ACPI tables")
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
--- a/xen/arch/x86/hvm/dom0_build.c
+++ b/xen/arch/x86/hvm/dom0_build.c
@@ -920,8 +920,9 @@ static int __init pvh_setup_acpi_madt(st
int rc;
/* Count number of interrupt overrides in the MADT. */
- acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE,
- acpi_count_intr_ovr, UINT_MAX);
+ if ( !*addr )
+ acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE,
+ acpi_count_intr_ovr, UINT_MAX);
/* Calculate the size of the crafted MADT. */
size = sizeof(*madt);
@@ -929,6 +930,22 @@ static int __init pvh_setup_acpi_madt(st
size += sizeof(*intsrcovr) * acpi_intr_overrides;
size += sizeof(*x2apic) * d->max_vcpus;
+ if ( !*addr )
+ {
+ /* Reserve space to place the new MADT in guest memory space. */
+ if ( pvh_steal_ram(d, size, 0, GB(4), addr) )
+ {
+ printk("Unable to steal guest RAM for MADT\n");
+ return -ENOMEM;
+ }
+
+ /* Mark this region as E820_ACPI. */
+ if ( pvh_add_mem_range(d, *addr, *addr + size, E820_ACPI) )
+ printk("Unable to add MADT region to memory map\n");
+
+ return 0;
+ }
+
madt = xzalloc_bytes(size);
if ( !madt )
{
@@ -991,17 +1008,6 @@ static int __init pvh_setup_acpi_madt(st
madt->header.checksum -= acpi_tb_checksum(ACPI_CAST_PTR(u8, madt), size);
/* Place the new MADT in guest memory space. */
- if ( pvh_steal_ram(d, size, 0, GB(4), addr) )
- {
- printk("Unable to steal guest RAM for MADT\n");
- rc = -ENOMEM;
- goto out;
- }
-
- /* Mark this region as E820_ACPI. */
- if ( pvh_add_mem_range(d, *addr, *addr + size, E820_ACPI) )
- printk("Unable to add MADT region to memory map\n");
-
rc = hvm_copy_to_guest_phys(*addr, madt, size, d->vcpu[0]);
if ( rc )
{
@@ -1116,6 +1122,22 @@ static int __init pvh_setup_acpi_xsdt(st
*/
size += num_tables * sizeof(xsdt->table_offset_entry[0]);
+ if ( !*addr )
+ {
+ /* Reserve space to place the new XSDT in guest memory space. */
+ if ( pvh_steal_ram(d, size, 0, GB(4), addr) )
+ {
+ printk("Unable to find guest RAM for XSDT\n");
+ return -ENOMEM;
+ }
+
+ /* Mark this region as E820_ACPI. */
+ if ( pvh_add_mem_range(d, *addr, *addr + size, E820_ACPI) )
+ printk("Unable to add XSDT region to memory map\n");
+
+ return 0;
+ }
+
xsdt = xzalloc_bytes(size);
if ( !xsdt )
{
@@ -1179,17 +1201,6 @@ static int __init pvh_setup_acpi_xsdt(st
xsdt->header.checksum -= acpi_tb_checksum(ACPI_CAST_PTR(u8, xsdt), size);
/* Place the new XSDT in guest memory space. */
- if ( pvh_steal_ram(d, size, 0, GB(4), addr) )
- {
- printk("Unable to find guest RAM for XSDT\n");
- rc = -ENOMEM;
- goto out;
- }
-
- /* Mark this region as E820_ACPI. */
- if ( pvh_add_mem_range(d, *addr, *addr + size, E820_ACPI) )
- printk("Unable to add XSDT region to memory map\n");
-
rc = hvm_copy_to_guest_phys(*addr, xsdt, size, d->vcpu[0]);
if ( rc )
{
@@ -1205,18 +1216,18 @@ static int __init pvh_setup_acpi_xsdt(st
return rc;
}
-static int __init pvh_setup_acpi(struct domain *d, paddr_t start_info)
+struct acpi_info {
+ paddr_t madt;
+ paddr_t xsdt;
+ paddr_t rsdp;
+};
+
+static int __init pvh_place_acpi(
+ struct domain *d,
+ struct acpi_info *info)
{
- unsigned long pfn, nr_pages;
- paddr_t madt_paddr, xsdt_paddr, rsdp_paddr;
unsigned int i;
int rc;
- struct acpi_table_rsdp *native_rsdp, rsdp = {
- .signature = ACPI_SIG_RSDP,
- .revision = 2,
- .length = sizeof(rsdp),
- };
-
/* Scan top-level tables and add their regions to the guest memory map. */
for( i = 0; i < acpi_gbl_root_table_list.count; i++ )
@@ -1239,6 +1250,8 @@ static int __init pvh_setup_acpi(struct
/* Identity map ACPI e820 regions. */
for ( i = 0; i < d->arch.nr_e820; i++ )
{
+ unsigned long pfn, nr_pages;
+
if ( d->arch.e820[i].type != E820_ACPI &&
d->arch.e820[i].type != E820_NVS )
continue;
@@ -1267,32 +1280,49 @@ static int __init pvh_setup_acpi(struct
}
}
- rc = pvh_setup_acpi_madt(d, &madt_paddr);
+ rc = pvh_setup_acpi_madt(d, &info->madt);
if ( rc )
return rc;
- rc = pvh_setup_acpi_xsdt(d, madt_paddr, &xsdt_paddr);
+ rc = pvh_setup_acpi_xsdt(d, info->madt, &info->xsdt);
if ( rc )
return rc;
- /* Craft a custom RSDP. */
- native_rsdp = acpi_os_map_memory(acpi_os_get_root_pointer(), sizeof(rsdp));
- if ( !native_rsdp )
+ if ( pvh_steal_ram(d, sizeof(struct acpi_table_rsdp), 0, GB(4),
+ &info->rsdp) )
{
- printk("Failed to map native RSDP\n");
+ printk("Unable to allocate guest RAM for RSDP\n");
return -ENOMEM;
}
- memcpy(rsdp.oem_id, native_rsdp->oem_id, sizeof(rsdp.oem_id));
- acpi_os_unmap_memory(native_rsdp, sizeof(rsdp));
- rsdp.xsdt_physical_address = xsdt_paddr;
- /*
- * Calling acpi_tb_checksum here is a layering violation, but
- * introducing a wrapper for such simple usage seems overkill.
- */
- rsdp.checksum -= acpi_tb_checksum(ACPI_CAST_PTR(u8, &rsdp),
- ACPI_RSDP_REV0_SIZE);
- rsdp.extended_checksum -= acpi_tb_checksum(ACPI_CAST_PTR(u8, &rsdp),
- sizeof(rsdp));
+
+ /* Mark this region as E820_ACPI. */
+ if ( pvh_add_mem_range(d, info->rsdp,
+ info->rsdp + sizeof(struct acpi_table_rsdp),
+ E820_ACPI) )
+ printk("Unable to add RSDP region to memory map\n");
+
+ return 0;
+}
+
+static int __init pvh_setup_acpi(
+ struct domain *d,
+ struct acpi_info *info,
+ paddr_t start_info)
+{
+ int rc;
+ struct acpi_table_rsdp *native_rsdp, rsdp = {
+ .signature = ACPI_SIG_RSDP,
+ .revision = 2,
+ .length = sizeof(rsdp),
+ };
+
+ rc = pvh_setup_acpi_madt(d, &info->madt);
+ if ( rc )
+ return rc;
+
+ rc = pvh_setup_acpi_xsdt(d, info->madt, &info->xsdt);
+ if ( rc )
+ return rc;
/*
* Place the new RSDP in guest memory space.
@@ -1302,19 +1332,27 @@ static int __init pvh_setup_acpi(struct
* the native RSDT, and should not be used for the Dom0 kernel's boot
* purposes (we keep it visible for post boot access).
*/
- if ( pvh_steal_ram(d, sizeof(rsdp), 0, GB(4), &rsdp_paddr) )
+ native_rsdp = acpi_os_map_memory(acpi_os_get_root_pointer(), sizeof(rsdp));
+ if ( !native_rsdp )
{
- printk("Unable to allocate guest RAM for RSDP\n");
+ printk("Failed to map native RSDP\n");
return -ENOMEM;
}
+ memcpy(rsdp.oem_id, native_rsdp->oem_id, sizeof(rsdp.oem_id));
+ acpi_os_unmap_memory(native_rsdp, sizeof(rsdp));
+ rsdp.xsdt_physical_address = info->xsdt;
- /* Mark this region as E820_ACPI. */
- if ( pvh_add_mem_range(d, rsdp_paddr, rsdp_paddr + sizeof(rsdp),
- E820_ACPI) )
- printk("Unable to add RSDP region to memory map\n");
+ /*
+ * Calling acpi_tb_checksum here is a layering violation, but
+ * introducing a wrapper for such simple usage seems overkill.
+ */
+ rsdp.checksum -= acpi_tb_checksum(ACPI_CAST_PTR(u8, &rsdp),
+ ACPI_RSDP_REV0_SIZE);
+ rsdp.extended_checksum -= acpi_tb_checksum(ACPI_CAST_PTR(u8, &rsdp),
+ sizeof(rsdp));
/* Copy RSDP into guest memory. */
- rc = hvm_copy_to_guest_phys(rsdp_paddr, &rsdp, sizeof(rsdp), d->vcpu[0]);
+ rc = hvm_copy_to_guest_phys(info->rsdp, &rsdp, sizeof(rsdp), d->vcpu[0]);
if ( rc )
{
printk("Unable to copy RSDP into guest memory\n");
@@ -1322,9 +1360,11 @@ static int __init pvh_setup_acpi(struct
}
/* Copy RSDP address to start_info. */
+ BUILD_BUG_ON(sizeof(info->rsdp) !=
+ sizeof_field(struct hvm_start_info, rsdp_paddr));
rc = hvm_copy_to_guest_phys(start_info +
offsetof(struct hvm_start_info, rsdp_paddr),
- &rsdp_paddr,
+ &info->rsdp,
sizeof_field(struct hvm_start_info,
rsdp_paddr),
d->vcpu[0]);
if ( rc )
@@ -1361,6 +1401,7 @@ int __init dom0_construct_pvh(const stru
struct elf_binary elf;
struct e820entry *orig_e820;
unsigned int nr_orig_e820;
+ struct acpi_info acpi = {};
int rc;
printk(XENLOG_INFO "*** Building a PVH Dom%d ***\n", d->domain_id);
@@ -1414,6 +1455,13 @@ int __init dom0_construct_pvh(const stru
return rc;
}
+ rc = pvh_place_acpi(d, &acpi);
+ if ( rc )
+ {
+ printk("Failed to place Dom0 ACPI tables: %d\n", rc);
+ return rc;
+ }
+
rc = pvh_populate_p2m(d, orig_e820, nr_orig_e820);
if ( rc )
{
@@ -1437,7 +1485,7 @@ int __init dom0_construct_pvh(const stru
return rc;
}
- rc = pvh_setup_acpi(d, start_info);
+ rc = pvh_setup_acpi(d, &acpi, start_info);
if ( rc )
{
printk("Failed to setup Dom0 ACPI tables: %d\n", rc);
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |