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.
Cc: Tristan Gingold <tgingold@xxxxxxx>
Signed-off-by: Simon Horman <horms@xxxxxxxxxxxx>
---
Date: Thu, 20 Sep 2007 12:24:33 +0900
From: Horms <horms@xxxxxxxxxxxx>
To: Alex Williamson <alex.williamson@xxxxxx>
Cc: xen-ia64-devel@xxxxxxxxxxxxxxxxxxx, Tristan Gingold <tgingold@xxxxxxx>
I looked through this issue again and basically the problem is
that due to the virtualisation of lid (lsapic->id and lsapic->eid)
that occurs in acpi_update_lsapic(), the seccond kernel is
unable to bring up the AP on the HP 2620.
wakeup_secondary_cpu() sends the wakeup using ia64_send_ipi(), which
uses cpu_physical_id() to detiemine the destination. This call is backed
by ia64_get_lid() which uses lsapic->id and lsapic->eid.
So in a nutshell, on the box in question, the second kernel ends up
trying to wake up CPU 0x100, where it should be trying CPU 0x200.
On my Tiger2 this doesn't manifest, because 0x200 happens to
be the correct physical ID.
The approach that I implemented aleviates this problem by restoring the
ACPI table before going into purgatory and in turn booting the second
kernel. Its a little heavy handed and could be trimmed - though that
would make little difference to the ammount of code, and the ammount of
memory used should be trivial in any case.
Although the patch is in common code, because the mangling is in
common code. Its actually only relevant to IA64 because only
IA64's mangling callbacks cause the problem described above.
I guess I could move the code into IA64 specific files, though
the common code would probably still need to be taught to call the
save and restore rotuines.
My question is, what is the purpose of the virtualisation of lid. I
tried removing the mangling of id and eid and was successfully able to
boot dom0, though clearly this isn't a comprehensive test. If the
mangling is neccessary, could it be achived in a different way, perhaps
by modifying ia64_get_lid() - though perhaps that wouldn't work on all
platforms ?
Index: xen-ia64-unstable.hg/xen/arch/ia64/xen/dom_fw_dom0.c
===================================================================
--- xen-ia64-unstable.hg.orig/xen/arch/ia64/xen/dom_fw_dom0.c 2007-06-28
15:07:12.000000000 +0900
+++ xen-ia64-unstable.hg/xen/arch/ia64/xen/dom_fw_dom0.c 2007-06-28
15:10:13.000000000 +0900
@@ -121,6 +121,7 @@ void __init efi_systable_init_dom0(struc
int i = 1;
/* Write messages to the console. */
+ acpi_table_save();
touch_acpi_table();
printk("Domain0 EFI passthrough:");
Index: xen-ia64-unstable.hg/xen/drivers/acpi/tables.c
===================================================================
--- xen-ia64-unstable.hg.orig/xen/drivers/acpi/tables.c 2007-06-28
15:07:12.000000000 +0900
+++ xen-ia64-unstable.hg/xen/drivers/acpi/tables.c 2007-06-28
15:10:13.000000000 +0900
@@ -74,7 +74,8 @@ struct acpi_table_sdt {
static unsigned long sdt_pa; /* Physical Address */
static unsigned long sdt_count; /* Table count */
-static struct acpi_table_sdt sdt_entry[ACPI_MAX_TABLES] __initdata;
+static struct acpi_table_sdt sdt_entry[ACPI_MAX_TABLES];
+static struct acpi_table_sdt sdt_entry_backup[ACPI_MAX_TABLES];
void acpi_table_print(struct acpi_table_header *header, unsigned long
phys_addr)
{
@@ -377,6 +378,50 @@ acpi_table_parse_madt(enum acpi_madt_ent
handler, max_entries);
}
+/* Xen modifies the ACPI table,
+ * so save it so it can be restored before kexecing */
+void __init
+acpi_table_save(void)
+{
+ unsigned int i;
+ void *in, *out;
+
+ BUG_ON(sdt_entry_backup[0].pa);
+
+ for (i = 0; i < sdt_count; i++) {
+ in = __acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size);
+ BUG_ON(!in);
+
+ /* XXX: Is this the right way to grab some memory? */
+ out = xmalloc_bytes(sdt_entry[i].size);
+ BUG_ON(!out);
+
+ sdt_entry_backup[i].size = sdt_entry[i].size;
+ sdt_entry_backup[i].id = sdt_entry[i].id;
+ sdt_entry_backup[i].pa = __pa(out);
+ memcpy(out, in, sdt_entry[i].size);
+ }
+}
+
+void
+acpi_table_restore(void)
+{
+ unsigned int i;
+ void *in, *out;
+
+ BUG_ON(!sdt_entry_backup[0].pa);
+
+ for (i = 0; i < sdt_count; i++) {
+ out = __acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size);
+ BUG_ON(!out);
+
+ sdt_entry[i].size = sdt_entry_backup[i].size;
+ sdt_entry[i].id = sdt_entry_backup[i].id;
+ in = __va(sdt_entry_backup[i].pa);
+ memcpy(out, in, sdt_entry_backup[i].size);
+ }
+}
+
int __init acpi_table_parse(enum acpi_table_id id, acpi_table_handler handler)
{
int count = 0;
Index: xen-ia64-unstable.hg/xen/include/xen/acpi.h
===================================================================
--- xen-ia64-unstable.hg.orig/xen/include/xen/acpi.h 2007-06-28
15:07:12.000000000 +0900
+++ xen-ia64-unstable.hg/xen/include/xen/acpi.h 2007-06-28 15:10:13.000000000
+0900
@@ -386,6 +386,8 @@ int acpi_table_init (void);
int acpi_table_parse (enum acpi_table_id id, acpi_table_handler handler);
int acpi_get_table_header_early (enum acpi_table_id id, struct
acpi_table_header **header);
int acpi_table_parse_madt (enum acpi_madt_entry_id id, acpi_madt_entry_handler
handler, unsigned int max_entries);
+void acpi_table_save(void);
+void acpi_table_restore(void);
int acpi_table_parse_srat (enum acpi_srat_entry_id id, acpi_madt_entry_handler
handler, unsigned int max_entries);
void acpi_table_print (struct acpi_table_header *header, unsigned long
phys_addr);
void acpi_table_print_madt_entry (acpi_table_entry_header *madt);
Index: xen-ia64-unstable.hg/xen/arch/ia64/xen/machine_kexec.c
===================================================================
--- xen-ia64-unstable.hg.orig/xen/arch/ia64/xen/machine_kexec.c 2007-06-28
15:10:27.000000000 +0900
+++ xen-ia64-unstable.hg/xen/arch/ia64/xen/machine_kexec.c 2007-06-28
15:10:42.000000000 +0900
@@ -185,6 +185,7 @@ static void machine_shutdown(void)
}
#endif
kexec_disable_iosapic();
+ acpi_table_restore();
}
void machine_kexec(xen_kexec_image_t *image)
--
--
Horms
H: http://www.vergenet.net/~horms/
W: http://www.valinux.co.jp/en/
_______________________________________________
Xen-ia64-devel mailing list
Xen-ia64-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ia64-devel
|