diff options
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/reboot.c | 3 | ||||
-rw-r--r-- | arch/x86/kernel/setup.c | 3 | ||||
-rw-r--r-- | arch/x86/kernel/smpboot.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/tboot.c | 58 |
4 files changed, 50 insertions, 16 deletions
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 9de01c5d9794..18ce5c04242a 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -3,6 +3,7 @@ #include <linux/init.h> #include <linux/pm.h> #include <linux/efi.h> +#include <linux/tboot.h> #include <acpi/reboot.h> #include <asm/io.h> #include <asm/apic.h> @@ -24,8 +25,6 @@ # include <asm/iommu.h> #endif -#include <asm/tboot.h> - /* * Power off function, if any */ diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 80d6e9e32483..6ce0d6f38f7f 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -66,6 +66,7 @@ #include <linux/percpu.h> #include <linux/crash_dump.h> +#include <linux/tboot.h> #include <video/edid.h> @@ -145,8 +146,6 @@ struct boot_params __initdata boot_params; struct boot_params boot_params; #endif -#include <asm/tboot.h> - /* * Machine setup.. */ diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 61cc40887c48..7d9d8eea20a0 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -47,6 +47,7 @@ #include <linux/bootmem.h> #include <linux/err.h> #include <linux/nmi.h> +#include <linux/tboot.h> #include <asm/acpi.h> #include <asm/desc.h> @@ -62,7 +63,6 @@ #include <asm/vmi.h> #include <asm/apic.h> #include <asm/setup.h> -#include <asm/tboot.h> #include <asm/uv/uv.h> #include <linux/mc146818rtc.h> diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c index c2e760ca7b01..86c9f91b48ae 100644 --- a/arch/x86/kernel/tboot.c +++ b/arch/x86/kernel/tboot.c @@ -22,11 +22,14 @@ #include <linux/dma_remapping.h> #include <linux/init_task.h> #include <linux/spinlock.h> +#include <linux/delay.h> #include <linux/sched.h> #include <linux/init.h> #include <linux/dmar.h> +#include <linux/cpu.h> #include <linux/pfn.h> #include <linux/mm.h> +#include <linux/tboot.h> #include <asm/trampoline.h> #include <asm/processor.h> @@ -36,7 +39,6 @@ #include <asm/fixmap.h> #include <asm/proto.h> #include <asm/setup.h> -#include <asm/tboot.h> #include <asm/e820.h> #include <asm/io.h> @@ -154,13 +156,10 @@ static int map_tboot_pages(unsigned long vaddr, unsigned long start_pfn, return 0; } -void tboot_create_trampoline(void) +static void tboot_create_trampoline(void) { u32 map_base, map_size; - if (!tboot_enabled()) - return; - /* Create identity map for tboot shutdown code. */ map_base = PFN_DOWN(tboot->tboot_base); map_size = PFN_UP(tboot->tboot_size); @@ -295,21 +294,58 @@ void tboot_sleep(u8 sleep_state, u32 pm1a_control, u32 pm1b_control) tboot_shutdown(acpi_shutdown_map[sleep_state]); } -int tboot_wait_for_aps(int num_aps) +static atomic_t ap_wfs_count; + +static int tboot_wait_for_aps(int num_aps) { unsigned long timeout; + timeout = AP_WAIT_TIMEOUT*HZ; + while (atomic_read((atomic_t *)&tboot->num_in_wfs) != num_aps && + timeout) { + mdelay(1); + timeout--; + } + + if (timeout) + pr_warning("tboot wait for APs timeout\n"); + + return !(atomic_read((atomic_t *)&tboot->num_in_wfs) == num_aps); +} + +static int __cpuinit tboot_cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + switch (action) { + case CPU_DYING: + atomic_inc(&ap_wfs_count); + if (num_online_cpus() == 1) + if (tboot_wait_for_aps(atomic_read(&ap_wfs_count))) + return NOTIFY_BAD; + break; + } + return NOTIFY_OK; +} + +static struct notifier_block tboot_cpu_notifier __cpuinitdata = +{ + .notifier_call = tboot_cpu_callback, +}; + +static __init int tboot_late_init(void) +{ if (!tboot_enabled()) return 0; - timeout = jiffies + AP_WAIT_TIMEOUT*HZ; - while (atomic_read((atomic_t *)&tboot->num_in_wfs) != num_aps && - time_before(jiffies, timeout)) - cpu_relax(); + tboot_create_trampoline(); - return time_before(jiffies, timeout) ? 0 : 1; + atomic_set(&ap_wfs_count, 0); + register_hotcpu_notifier(&tboot_cpu_notifier); + return 0; } +late_initcall(tboot_late_init); + /* * TXT configuration registers (offsets from TXT_{PUB, PRIV}_CONFIG_REGS_BASE) */ |