On Thu, 2007-09-27 at 17:17 +0900, Simon Horman wrote:
> plain text document attachment (ia64-xen-kexec-save-acpi.patch)
> Xen mangles the MADT tables on boot up. But the pristine tables are needed
> on kexec. So save the tables and restore them on kexec.
>
> Note that this saves all the tables. A trimmed down save could
> be done if prefered.
Hi Simon,
I made an attempt to re-write this one. The most obvious reason for
virtualizing the id/eid is for indexing into the domain vcpu array.
Even if we made use of the real id/eid for that lookup, there are a
couple other places where we're disabling bits of ACPI for dom0. So, it
seems like we're stuck with backing up tables before dom0 is built and
restoring them on kexec. I took a little bit more surgical approach in
the implementation below (only backing up tables we mangle) and kept the
changes in architecture specific code. This is a little more space
efficient, but does require that we explicitly backup tables before we
mangle them. Let me know what you think (or if it works - I can't seem
to get a kexec to happen, no console output after machine_shutdown).
Thanks,
Alex
Signed-off-by: Alex Williamson <alex.williamson@xxxxxx>
--
diff -r 3165e43ce734 xen/arch/ia64/xen/dom_fw_dom0.c
--- a/xen/arch/ia64/xen/dom_fw_dom0.c Tue Oct 02 11:31:55 2007 -0600
+++ b/xen/arch/ia64/xen/dom_fw_dom0.c Wed Oct 03 10:54:50 2007 -0600
@@ -28,6 +28,7 @@
#include <xen/acpi.h>
#include <xen/errno.h>
#include <xen/sched.h>
+#include <xen/list.h>
#include <asm/dom_fw.h>
#include <asm/dom_fw_common.h>
@@ -35,6 +36,15 @@
#include <asm/dom_fw_utils.h>
#include <linux/sort.h>
+
+struct acpi_backup_table_entry {
+ struct list_head list;
+ unsigned long pa;
+ unsigned long size;
+ unsigned char data[0];
+};
+
+static LIST_HEAD(acpi_backup_table_list);
static u32 lsapic_nbr;
@@ -100,11 +110,67 @@ acpi_update_madt_checksum(unsigned long
return 0;
}
+static int __init
+acpi_backup_table(unsigned long phys_addr, unsigned long size)
+{
+ struct acpi_backup_table_entry *entry;
+ void *vaddr = __va(phys_addr);
+
+ if (!phys_addr || !size)
+ return -EINVAL;
+
+ entry = xmalloc_bytes(sizeof(*entry) + size);
+ if (!entry) {
+ dprintk(XENLOG_WARNING, "Failed to allocate memory for "
+ "%.4s table backup\n",
+ ((struct acpi_table_header *)vaddr)->signature);
+ return -ENOMEM;
+ }
+
+ entry->pa = phys_addr;
+ entry->size = size;
+
+ memcpy(entry->data, vaddr, size);
+
+ list_add(&entry->list, &acpi_backup_table_list);
+
+ printk(XENLOG_INFO "Backup %.4s table stored @0x%p\n",
+ ((struct acpi_table_header *)entry->data)->signature,
+ entry->data);
+
+ return 0;
+}
+
+void
+acpi_restore_tables()
+{
+ struct acpi_backup_table_entry *entry;
+
+ list_for_each_entry(entry, &acpi_backup_table_list, list) {
+ printk(XENLOG_INFO "Restoring backup %.4s table @0x%p\n",
+ ((struct acpi_table_header *)entry->data)->signature,
+ entry->data);
+
+ memcpy(__va(entry->pa), entry->data, entry->size);
+ /* Only called from kexec path, no need to free entries */
+ }
+}
+
/* base is physical address of acpi table */
static void __init touch_acpi_table(void)
{
int result;
lsapic_nbr = 0;
+
+ /*
+ * Modify dom0 MADT:
+ * - Disable CPUs that would exceed max vCPUs for the domain
+ * - Virtualize id/eid for indexing into domain vCPU array
+ * - Hide CPEI interrupt source
+ *
+ * ACPI tables must be backed-up before modification!
+ */
+ acpi_table_parse(ACPI_APIC, acpi_backup_table);
if (acpi_table_parse_madt(ACPI_MADT_LSAPIC, acpi_update_lsapic, 0) < 0)
printk("Error parsing MADT - no LAPIC entries\n");
@@ -112,6 +178,17 @@ static void __init touch_acpi_table(void
acpi_patch_plat_int_src, 0) < 0)
printk("Error parsing MADT - no PLAT_INT_SRC entries\n");
+ acpi_table_parse(ACPI_APIC, acpi_update_madt_checksum);
+
+ /*
+ * SRAT & SLIT tables aren't useful for Dom0 until
+ * we support more NUMA configuration information in Xen.
+ *
+ * NB - backup ACPI tables first.
+ */
+ acpi_table_parse(ACPI_SRAT, acpi_backup_table);
+ acpi_table_parse(ACPI_SLIT, acpi_backup_table);
+
result = acpi_table_disable(ACPI_SRAT);
if ( result == 0 )
printk("Success Disabling SRAT\n");
@@ -124,8 +201,6 @@ static void __init touch_acpi_table(void
else if ( result != -ENOENT )
printk("ERROR: Failed Disabling SLIT\n");
- acpi_table_parse(ACPI_APIC, acpi_update_madt_checksum);
-
return;
}
@@ -133,9 +208,9 @@ void __init efi_systable_init_dom0(struc
{
int i = 1;
+ touch_acpi_table();
+
/* Write messages to the console. */
- touch_acpi_table();
-
printk("Domain0 EFI passthrough:");
if (efi.mps) {
tables->efi_tables[i].guid = MPS_TABLE_GUID;
diff -r 3165e43ce734 xen/arch/ia64/xen/machine_kexec.c
--- a/xen/arch/ia64/xen/machine_kexec.c Tue Oct 02 11:31:55 2007 -0600
+++ b/xen/arch/ia64/xen/machine_kexec.c Tue Oct 02 15:41:59 2007 -0600
@@ -23,6 +23,7 @@
#include <linux/cpu.h>
#include <linux/cpu.h>
#include <linux/notifier.h>
+#include <asm/dom_fw_dom0.h>
typedef asmlinkage NORET_TYPE void (*relocate_new_kernel_t)(
unsigned long indirection_page,
@@ -149,6 +150,7 @@ static void machine_shutdown(void)
}
#endif
kexec_disable_iosapic();
+ acpi_restore_tables();
}
void machine_kexec(xen_kexec_image_t *image)
diff -r 3165e43ce734 xen/include/asm-ia64/dom_fw_dom0.h
--- a/xen/include/asm-ia64/dom_fw_dom0.h Tue Oct 02 11:31:55 2007 -0600
+++ b/xen/include/asm-ia64/dom_fw_dom0.h Tue Oct 02 15:41:32 2007 -0600
@@ -26,6 +26,7 @@ struct domain;
void efi_systable_init_dom0(struct fw_tables *tables);
int complete_dom0_memmap(struct domain *d, struct fw_tables *tables);
+void acpi_restore_tables(void);
#endif /* __ASM_IA64_DOM_FW_DOM0_H__ */
/*
_______________________________________________
Xen-ia64-devel mailing list
Xen-ia64-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ia64-devel
|