diff options
-rw-r--r-- | arch/x86/xen/enlighten.c | 115 | ||||
-rw-r--r-- | include/linux/cpuhotplug.h | 1 |
2 files changed, 66 insertions, 50 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index c7f6b1f90efa..a9ba14ac3aea 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -140,7 +140,9 @@ RESERVE_BRK(shared_info_page_brk, PAGE_SIZE); | |||
140 | __read_mostly int xen_have_vector_callback; | 140 | __read_mostly int xen_have_vector_callback; |
141 | EXPORT_SYMBOL_GPL(xen_have_vector_callback); | 141 | EXPORT_SYMBOL_GPL(xen_have_vector_callback); |
142 | 142 | ||
143 | static struct notifier_block xen_cpu_notifier; | 143 | static int xen_cpu_up_prepare(unsigned int cpu); |
144 | static int xen_cpu_up_online(unsigned int cpu); | ||
145 | static int xen_cpu_dead(unsigned int cpu); | ||
144 | 146 | ||
145 | /* | 147 | /* |
146 | * Point at some empty memory to start with. We map the real shared_info | 148 | * Point at some empty memory to start with. We map the real shared_info |
@@ -1541,6 +1543,24 @@ static void __init xen_dom0_set_legacy_features(void) | |||
1541 | x86_platform.legacy.rtc = 1; | 1543 | x86_platform.legacy.rtc = 1; |
1542 | } | 1544 | } |
1543 | 1545 | ||
1546 | static int xen_cpuhp_setup(void) | ||
1547 | { | ||
1548 | int rc; | ||
1549 | |||
1550 | rc = cpuhp_setup_state_nocalls(CPUHP_XEN_PREPARE, | ||
1551 | "XEN_HVM_GUEST_PREPARE", | ||
1552 | xen_cpu_up_prepare, xen_cpu_dead); | ||
1553 | if (rc >= 0) { | ||
1554 | rc = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, | ||
1555 | "XEN_HVM_GUEST_ONLINE", | ||
1556 | xen_cpu_up_online, NULL); | ||
1557 | if (rc < 0) | ||
1558 | cpuhp_remove_state_nocalls(CPUHP_XEN_PREPARE); | ||
1559 | } | ||
1560 | |||
1561 | return rc >= 0 ? 0 : rc; | ||
1562 | } | ||
1563 | |||
1544 | /* First C function to be called on Xen boot */ | 1564 | /* First C function to be called on Xen boot */ |
1545 | asmlinkage __visible void __init xen_start_kernel(void) | 1565 | asmlinkage __visible void __init xen_start_kernel(void) |
1546 | { | 1566 | { |
@@ -1629,7 +1649,7 @@ asmlinkage __visible void __init xen_start_kernel(void) | |||
1629 | xen_initial_gdt = &per_cpu(gdt_page, 0); | 1649 | xen_initial_gdt = &per_cpu(gdt_page, 0); |
1630 | 1650 | ||
1631 | xen_smp_init(); | 1651 | xen_smp_init(); |
1632 | register_cpu_notifier(&xen_cpu_notifier); | 1652 | WARN_ON(xen_cpuhp_setup()); |
1633 | 1653 | ||
1634 | #ifdef CONFIG_ACPI_NUMA | 1654 | #ifdef CONFIG_ACPI_NUMA |
1635 | /* | 1655 | /* |
@@ -1823,63 +1843,58 @@ static void __init init_hvm_pv_info(void) | |||
1823 | xen_domain_type = XEN_HVM_DOMAIN; | 1843 | xen_domain_type = XEN_HVM_DOMAIN; |
1824 | } | 1844 | } |
1825 | 1845 | ||
1826 | static int xen_cpu_notify(struct notifier_block *self, unsigned long action, | 1846 | static int xen_cpu_up_prepare(unsigned int cpu) |
1827 | void *hcpu) | ||
1828 | { | 1847 | { |
1829 | int cpu = (long)hcpu; | ||
1830 | int rc; | 1848 | int rc; |
1831 | 1849 | ||
1832 | switch (action) { | 1850 | if (xen_hvm_domain()) { |
1833 | case CPU_UP_PREPARE: | 1851 | /* |
1834 | if (xen_hvm_domain()) { | 1852 | * This can happen if CPU was offlined earlier and |
1835 | /* | 1853 | * offlining timed out in common_cpu_die(). |
1836 | * This can happen if CPU was offlined earlier and | 1854 | */ |
1837 | * offlining timed out in common_cpu_die(). | 1855 | if (cpu_report_state(cpu) == CPU_DEAD_FROZEN) { |
1838 | */ | 1856 | xen_smp_intr_free(cpu); |
1839 | if (cpu_report_state(cpu) == CPU_DEAD_FROZEN) { | 1857 | xen_uninit_lock_cpu(cpu); |
1840 | xen_smp_intr_free(cpu); | ||
1841 | xen_uninit_lock_cpu(cpu); | ||
1842 | } | ||
1843 | |||
1844 | if (cpu_acpi_id(cpu) != U32_MAX) | ||
1845 | per_cpu(xen_vcpu_id, cpu) = cpu_acpi_id(cpu); | ||
1846 | else | ||
1847 | per_cpu(xen_vcpu_id, cpu) = cpu; | ||
1848 | xen_vcpu_setup(cpu); | ||
1849 | } | 1858 | } |
1850 | 1859 | ||
1851 | if (xen_pv_domain() || | 1860 | if (cpu_acpi_id(cpu) != U32_MAX) |
1852 | (xen_have_vector_callback && | 1861 | per_cpu(xen_vcpu_id, cpu) = cpu_acpi_id(cpu); |
1853 | xen_feature(XENFEAT_hvm_safe_pvclock))) | 1862 | else |
1854 | xen_setup_timer(cpu); | 1863 | per_cpu(xen_vcpu_id, cpu) = cpu; |
1864 | xen_vcpu_setup(cpu); | ||
1865 | } | ||
1855 | 1866 | ||
1856 | rc = xen_smp_intr_init(cpu); | 1867 | if (xen_pv_domain() || |
1857 | if (rc) { | 1868 | (xen_have_vector_callback && |
1858 | WARN(1, "xen_smp_intr_init() for CPU %d failed: %d\n", | 1869 | xen_feature(XENFEAT_hvm_safe_pvclock))) |
1859 | cpu, rc); | 1870 | xen_setup_timer(cpu); |
1860 | return NOTIFY_BAD; | ||
1861 | } | ||
1862 | 1871 | ||
1863 | break; | 1872 | rc = xen_smp_intr_init(cpu); |
1864 | case CPU_ONLINE: | 1873 | if (rc) { |
1865 | xen_init_lock_cpu(cpu); | 1874 | WARN(1, "xen_smp_intr_init() for CPU %d failed: %d\n", |
1866 | break; | 1875 | cpu, rc); |
1867 | case CPU_UP_CANCELED: | 1876 | return rc; |
1868 | xen_smp_intr_free(cpu); | ||
1869 | if (xen_pv_domain() || | ||
1870 | (xen_have_vector_callback && | ||
1871 | xen_feature(XENFEAT_hvm_safe_pvclock))) | ||
1872 | xen_teardown_timer(cpu); | ||
1873 | break; | ||
1874 | default: | ||
1875 | break; | ||
1876 | } | 1877 | } |
1877 | return NOTIFY_OK; | 1878 | return 0; |
1878 | } | 1879 | } |
1879 | 1880 | ||
1880 | static struct notifier_block xen_cpu_notifier = { | 1881 | static int xen_cpu_dead(unsigned int cpu) |
1881 | .notifier_call = xen_cpu_notify, | 1882 | { |
1882 | }; | 1883 | xen_smp_intr_free(cpu); |
1884 | |||
1885 | if (xen_pv_domain() || | ||
1886 | (xen_have_vector_callback && | ||
1887 | xen_feature(XENFEAT_hvm_safe_pvclock))) | ||
1888 | xen_teardown_timer(cpu); | ||
1889 | |||
1890 | return 0; | ||
1891 | } | ||
1892 | |||
1893 | static int xen_cpu_up_online(unsigned int cpu) | ||
1894 | { | ||
1895 | xen_init_lock_cpu(cpu); | ||
1896 | return 0; | ||
1897 | } | ||
1883 | 1898 | ||
1884 | #ifdef CONFIG_KEXEC_CORE | 1899 | #ifdef CONFIG_KEXEC_CORE |
1885 | static void xen_hvm_shutdown(void) | 1900 | static void xen_hvm_shutdown(void) |
@@ -1910,7 +1925,7 @@ static void __init xen_hvm_guest_init(void) | |||
1910 | if (xen_feature(XENFEAT_hvm_callback_vector)) | 1925 | if (xen_feature(XENFEAT_hvm_callback_vector)) |
1911 | xen_have_vector_callback = 1; | 1926 | xen_have_vector_callback = 1; |
1912 | xen_hvm_smp_init(); | 1927 | xen_hvm_smp_init(); |
1913 | register_cpu_notifier(&xen_cpu_notifier); | 1928 | WARN_ON(xen_cpuhp_setup()); |
1914 | xen_unplug_emulated_devices(); | 1929 | xen_unplug_emulated_devices(); |
1915 | x86_init.irqs.intr_init = xen_init_IRQ; | 1930 | x86_init.irqs.intr_init = xen_init_IRQ; |
1916 | xen_hvm_init_time_ops(); | 1931 | xen_hvm_init_time_ops(); |
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 242bf530edfc..33d352f3295d 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h | |||
@@ -21,6 +21,7 @@ enum cpuhp_state { | |||
21 | CPUHP_X2APIC_PREPARE, | 21 | CPUHP_X2APIC_PREPARE, |
22 | CPUHP_SMPCFD_PREPARE, | 22 | CPUHP_SMPCFD_PREPARE, |
23 | CPUHP_RCUTREE_PREP, | 23 | CPUHP_RCUTREE_PREP, |
24 | CPUHP_XEN_PREPARE, | ||
24 | CPUHP_NOTIFY_PREPARE, | 25 | CPUHP_NOTIFY_PREPARE, |
25 | CPUHP_TIMERS_DEAD, | 26 | CPUHP_TIMERS_DEAD, |
26 | CPUHP_BRINGUP_CPU, | 27 | CPUHP_BRINGUP_CPU, |