mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
x86: Implement cpu hotplug notifiers. Use them.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
This commit is contained in:
1 parent
2a814aeaaf
commit
2e4146ddc2
27 files changed
+371
-169
No files matched your search
@@ -139,6 +139,8 @@ SECTIONS
|
||||
.initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET)
|
||||
{
|
||||
__initcall_start = .;
|
||||
*(.initcallpresmp.init)
|
||||
__presmp_initcall_end = .;
|
||||
*(.initcall1.init)
|
||||
*(.initcall2.init)
|
||||
*(.initcall3.init)
|
||||
|
||||
@@ -89,13 +89,6 @@ xen_count_pages(u64 start, u64 end, void *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __init do_initcalls(void)
|
||||
{
|
||||
initcall_t *call;
|
||||
for ( call = &__initcall_start; call < &__initcall_end; call++ )
|
||||
(*call)();
|
||||
}
|
||||
|
||||
/*
|
||||
* IPF loader only supports one command line currently, for
|
||||
* both xen and guest kernel. This function provides pre-parse
|
||||
@@ -612,15 +605,15 @@ skip_move:
|
||||
/* Enable IRQ to receive IPI (needed for ITC sync). */
|
||||
local_irq_enable();
|
||||
|
||||
do_presmp_initcalls();
|
||||
|
||||
printk("num_online_cpus=%d, max_cpus=%d\n",num_online_cpus(),max_cpus);
|
||||
for_each_present_cpu ( i )
|
||||
{
|
||||
if ( num_online_cpus() >= max_cpus )
|
||||
break;
|
||||
if ( !cpu_online(i) ) {
|
||||
rcu_online_cpu(i);
|
||||
__cpu_up(i);
|
||||
}
|
||||
if ( !cpu_online(i) )
|
||||
cpu_up(i);
|
||||
}
|
||||
|
||||
local_irq_disable();
|
||||
@@ -629,8 +622,6 @@ printk("num_online_cpus=%d, max_cpus=%d\n",num_online_cpus(),max_cpus);
|
||||
smp_cpus_done(max_cpus);
|
||||
#endif
|
||||
|
||||
initialise_gdb(); /* could be moved earlier */
|
||||
|
||||
iommu_setup(); /* setup iommu if available */
|
||||
|
||||
do_initcalls();
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <xen/delay.h>
|
||||
#include <xen/smp.h>
|
||||
#include <xen/mm.h>
|
||||
#include <xen/cpu.h>
|
||||
#include <asm/processor.h>
|
||||
#include <public/sysctl.h>
|
||||
#include <asm/system.h>
|
||||
@@ -788,7 +789,7 @@ static void __cpu_mcheck_distribute_cmci(void *unused)
|
||||
cmci_discover();
|
||||
}
|
||||
|
||||
void cpu_mcheck_distribute_cmci(void)
|
||||
static void cpu_mcheck_distribute_cmci(void)
|
||||
{
|
||||
if (cmci_support && !mce_disabled)
|
||||
on_each_cpu(__cpu_mcheck_distribute_cmci, NULL, 0);
|
||||
@@ -816,7 +817,7 @@ static void clear_cmci(void)
|
||||
}
|
||||
}
|
||||
|
||||
void cpu_mcheck_disable(void)
|
||||
static void cpu_mcheck_disable(void)
|
||||
{
|
||||
clear_in_cr4(X86_CR4_MCE);
|
||||
|
||||
@@ -1007,4 +1008,31 @@ int intel_mce_rdmsr(uint32_t msr, uint64_t *val)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cpu_callback(
|
||||
struct notifier_block *nfb, unsigned long action, void *hcpu)
|
||||
{
|
||||
switch ( action )
|
||||
{
|
||||
case CPU_DYING:
|
||||
cpu_mcheck_disable();
|
||||
break;
|
||||
case CPU_DEAD:
|
||||
cpu_mcheck_distribute_cmci();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block cpu_nfb = {
|
||||
.notifier_call = cpu_callback
|
||||
};
|
||||
|
||||
static int __init intel_mce_initcall(void)
|
||||
{
|
||||
register_cpu_notifier(&cpu_nfb);
|
||||
return 0;
|
||||
}
|
||||
presmp_initcall(intel_mce_initcall);
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <xen/acpi.h>
|
||||
#include <xen/pci.h>
|
||||
#include <xen/paging.h>
|
||||
#include <xen/cpu.h>
|
||||
#include <public/sysctl.h>
|
||||
#include <asm/regs.h>
|
||||
#include <asm/mc146818rtc.h>
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <xen/guest_access.h>
|
||||
#include <xen/event.h>
|
||||
#include <xen/paging.h>
|
||||
#include <xen/cpu.h>
|
||||
#include <asm/shadow.h>
|
||||
#include <asm/hap.h>
|
||||
#include <asm/current.h>
|
||||
@@ -70,6 +71,28 @@ struct hvm_function_table hvm_funcs __read_mostly;
|
||||
unsigned long __attribute__ ((__section__ (".bss.page_aligned")))
|
||||
hvm_io_bitmap[3*PAGE_SIZE/BYTES_PER_LONG];
|
||||
|
||||
static int cpu_callback(
|
||||
struct notifier_block *nfb, unsigned long action, void *hcpu)
|
||||
{
|
||||
unsigned int cpu = (unsigned long)hcpu;
|
||||
int rc = 0;
|
||||
|
||||
switch ( action )
|
||||
{
|
||||
case CPU_UP_PREPARE:
|
||||
rc = hvm_funcs.cpu_prepare(cpu);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return !rc ? NOTIFY_DONE : notifier_from_errno(rc);
|
||||
}
|
||||
|
||||
static struct notifier_block cpu_nfb = {
|
||||
.notifier_call = cpu_callback
|
||||
};
|
||||
|
||||
void hvm_enable(struct hvm_function_table *fns)
|
||||
{
|
||||
extern int hvm_port80_allowed;
|
||||
@@ -91,6 +114,8 @@ void hvm_enable(struct hvm_function_table *fns)
|
||||
|
||||
if ( hvm_funcs.hap_supported )
|
||||
printk("HVM: Hardware Assisted Paging detected.\n");
|
||||
|
||||
register_cpu_notifier(&cpu_nfb);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <xen/iocap.h>
|
||||
#include <xen/guest_access.h>
|
||||
#include <xen/acpi.h>
|
||||
#include <xen/cpu.h>
|
||||
#include <asm/current.h>
|
||||
#include <public/platform.h>
|
||||
#include <acpi/cpufreq/processor_perf.h>
|
||||
|
||||
+3
-18
@@ -156,13 +156,6 @@ static void __init parse_acpi_param(char *s)
|
||||
}
|
||||
}
|
||||
|
||||
static void __init do_initcalls(void)
|
||||
{
|
||||
initcall_t *call;
|
||||
for ( call = &__initcall_start; call < &__initcall_end; call++ )
|
||||
(*call)();
|
||||
}
|
||||
|
||||
#define EARLY_FAIL(f, a...) do { \
|
||||
printk( f , ## a ); \
|
||||
for ( ; ; ) halt(); \
|
||||
@@ -1070,15 +1063,14 @@ void __init __start_xen(unsigned long mbi_p)
|
||||
|
||||
console_init_postirq();
|
||||
|
||||
do_presmp_initcalls();
|
||||
|
||||
for_each_present_cpu ( i )
|
||||
{
|
||||
if ( num_online_cpus() >= max_cpus )
|
||||
break;
|
||||
if ( !cpu_online(i) )
|
||||
{
|
||||
rcu_online_cpu(i);
|
||||
__cpu_up(i);
|
||||
}
|
||||
cpu_up(i);
|
||||
|
||||
/* Set up cpu_to_node[]. */
|
||||
srat_detect_node(i);
|
||||
@@ -1089,8 +1081,6 @@ void __init __start_xen(unsigned long mbi_p)
|
||||
printk("Brought up %ld CPUs\n", (long)num_online_cpus());
|
||||
smp_cpus_done(max_cpus);
|
||||
|
||||
initialise_gdb(); /* could be moved earlier */
|
||||
|
||||
do_initcalls();
|
||||
|
||||
if ( opt_watchdog )
|
||||
@@ -1099,11 +1089,6 @@ void __init __start_xen(unsigned long mbi_p)
|
||||
if ( !tboot_protect_mem_regions() )
|
||||
panic("Could not protect TXT memory regions\n");
|
||||
|
||||
/* Create initial cpupool 0. */
|
||||
cpupool0 = cpupool_create(0, NULL);
|
||||
if ( (cpupool0 == NULL) || cpupool0_cpu_assign(cpupool0) )
|
||||
panic("Error creating cpupool 0\n");
|
||||
|
||||
/* Create initial domain 0. */
|
||||
dom0 = domain_create(0, DOMCRF_s3_integrity, DOM0_SSIDREF);
|
||||
if ( (dom0 == NULL) || (alloc_dom0_vcpu0() == NULL) )
|
||||
|
||||
+59
-42
@@ -47,6 +47,7 @@
|
||||
#include <xen/serial.h>
|
||||
#include <xen/numa.h>
|
||||
#include <xen/event.h>
|
||||
#include <xen/cpu.h>
|
||||
#include <asm/current.h>
|
||||
#include <asm/mc146818rtc.h>
|
||||
#include <asm/desc.h>
|
||||
@@ -106,7 +107,6 @@ static void map_cpu_to_logical_apicid(void);
|
||||
DEFINE_PER_CPU(int, cpu_state) = { 0 };
|
||||
|
||||
void *stack_base[NR_CPUS];
|
||||
DEFINE_SPINLOCK(cpu_add_remove_lock);
|
||||
|
||||
/*
|
||||
* The bootstrap kernel entry code has set these up. Save them for
|
||||
@@ -1272,17 +1272,6 @@ int __cpu_disable(void)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
/*
|
||||
* Perhaps use cpufreq to drop frequency, but that could go
|
||||
* into generic code.
|
||||
*
|
||||
* We won't take down the boot processor on i386 due to some
|
||||
* interrupts only being able to be serviced by the BSP.
|
||||
* Especially so if we're not using an IOAPIC -zwane
|
||||
*/
|
||||
if (cpu == 0)
|
||||
return -EBUSY;
|
||||
|
||||
local_irq_disable();
|
||||
clear_local_APIC();
|
||||
/* Allow any queued timer interrupts to get serviced */
|
||||
@@ -1292,8 +1281,6 @@ int __cpu_disable(void)
|
||||
|
||||
time_suspend();
|
||||
|
||||
cpu_mcheck_disable();
|
||||
|
||||
remove_siblinginfo(cpu);
|
||||
|
||||
/* It's now safe to remove this processor from the online map */
|
||||
@@ -1313,10 +1300,8 @@ void __cpu_die(unsigned int cpu)
|
||||
|
||||
for (;;) {
|
||||
/* They ack this in play_dead by setting CPU_DEAD */
|
||||
if (per_cpu(cpu_state, cpu) == CPU_DEAD) {
|
||||
printk ("CPU %u is now offline\n", cpu);
|
||||
if (per_cpu(cpu_state, cpu) == CPU_DEAD)
|
||||
return;
|
||||
}
|
||||
mdelay(100);
|
||||
mb();
|
||||
process_pending_softirqs();
|
||||
@@ -1327,7 +1312,19 @@ void __cpu_die(unsigned int cpu)
|
||||
|
||||
static int take_cpu_down(void *unused)
|
||||
{
|
||||
return __cpu_disable();
|
||||
void *hcpu = (void *)(long)smp_processor_id();
|
||||
int rc;
|
||||
|
||||
spin_lock(&cpu_add_remove_lock);
|
||||
|
||||
if (cpu_notifier_call_chain(CPU_DYING, hcpu) != NOTIFY_DONE)
|
||||
BUG();
|
||||
|
||||
rc = __cpu_disable();
|
||||
|
||||
spin_unlock(&cpu_add_remove_lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1339,7 +1336,8 @@ static cpumask_t cpu_offlining;
|
||||
|
||||
int cpu_down(unsigned int cpu)
|
||||
{
|
||||
int err = 0;
|
||||
int err, notifier_rc, nr_calls;
|
||||
void *hcpu = (void *)(long)cpu;
|
||||
|
||||
spin_lock(&cpu_add_remove_lock);
|
||||
|
||||
@@ -1350,32 +1348,42 @@ int cpu_down(unsigned int cpu)
|
||||
|
||||
cpu_set(cpu, cpu_offlining);
|
||||
|
||||
err = cpupool_cpu_remove(cpu);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
printk("Prepare to bring CPU%d down...\n", cpu);
|
||||
|
||||
cpufreq_del_cpu(cpu);
|
||||
notifier_rc = __cpu_notifier_call_chain(
|
||||
CPU_DOWN_PREPARE, hcpu, -1, &nr_calls);
|
||||
if (notifier_rc != NOTIFY_DONE) {
|
||||
err = notifier_to_errno(notifier_rc);
|
||||
nr_calls--;
|
||||
notifier_rc = __cpu_notifier_call_chain(
|
||||
CPU_DOWN_FAILED, hcpu, nr_calls, NULL);
|
||||
BUG_ON(notifier_rc != NOTIFY_DONE);
|
||||
goto out;
|
||||
}
|
||||
|
||||
spin_unlock(&cpu_add_remove_lock);
|
||||
err = stop_machine_run(take_cpu_down, NULL, cpu);
|
||||
spin_lock(&cpu_add_remove_lock);
|
||||
|
||||
if (err < 0) {
|
||||
cpupool_cpu_add(cpu);
|
||||
notifier_rc = cpu_notifier_call_chain(CPU_DOWN_FAILED, hcpu);
|
||||
BUG_ON(notifier_rc != NOTIFY_DONE);
|
||||
goto out;
|
||||
}
|
||||
|
||||
__cpu_die(cpu);
|
||||
BUG_ON(cpu_online(cpu));
|
||||
|
||||
migrate_tasklets_from_cpu(cpu);
|
||||
cpu_mcheck_distribute_cmci();
|
||||
notifier_rc = cpu_notifier_call_chain(CPU_DEAD, hcpu);
|
||||
BUG_ON(notifier_rc != NOTIFY_DONE);
|
||||
|
||||
out:
|
||||
if (!err)
|
||||
if (!err) {
|
||||
printk("CPU %u is now offline\n", cpu);
|
||||
send_guest_global_virq(dom0, VIRQ_PCPU_STATE);
|
||||
} else {
|
||||
printk("Failed to take down CPU %u (error %d)\n", cpu, err);
|
||||
}
|
||||
cpu_clear(cpu, cpu_offlining);
|
||||
spin_unlock(&cpu_add_remove_lock);
|
||||
return err;
|
||||
@@ -1392,8 +1400,6 @@ int cpu_up(unsigned int cpu)
|
||||
goto out;
|
||||
}
|
||||
|
||||
rcu_online_cpu(cpu);
|
||||
|
||||
err = __cpu_up(cpu);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
@@ -1525,11 +1531,16 @@ int cpu_add(uint32_t apic_id, uint32_t acpi_id, uint32_t pxm)
|
||||
|
||||
int __devinit __cpu_up(unsigned int cpu)
|
||||
{
|
||||
int ret;
|
||||
int notifier_rc, ret = 0, nr_calls;
|
||||
void *hcpu = (void *)(long)cpu;
|
||||
|
||||
ret = hvm_cpu_prepare(cpu);
|
||||
if (ret)
|
||||
return ret;
|
||||
notifier_rc = __cpu_notifier_call_chain(
|
||||
CPU_UP_PREPARE, hcpu, -1, &nr_calls);
|
||||
if (notifier_rc != NOTIFY_DONE) {
|
||||
ret = notifier_to_errno(notifier_rc);
|
||||
nr_calls--;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* We do warm boot only on cpus that had booted earlier
|
||||
@@ -1542,18 +1553,18 @@ int __devinit __cpu_up(unsigned int cpu)
|
||||
smpboot_restore_warm_reset_vector();
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return -EIO;
|
||||
if (ret) {
|
||||
ret = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* In case one didn't come up */
|
||||
if (!cpu_isset(cpu, cpu_callin_map)) {
|
||||
printk(KERN_DEBUG "skipping cpu%d, didn't come online\n", cpu);
|
||||
local_irq_enable();
|
||||
return -EIO;
|
||||
ret = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
local_irq_enable();
|
||||
/*per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;*/
|
||||
/* Unleash the CPU! */
|
||||
cpu_set(cpu, smp_commenced_mask);
|
||||
while (!cpu_isset(cpu, cpu_online_map)) {
|
||||
@@ -1561,9 +1572,15 @@ int __devinit __cpu_up(unsigned int cpu)
|
||||
process_pending_softirqs();
|
||||
}
|
||||
|
||||
cpupool_cpu_add(cpu);
|
||||
cpufreq_add_cpu(cpu);
|
||||
notifier_rc = cpu_notifier_call_chain(CPU_ONLINE, hcpu);
|
||||
BUG_ON(notifier_rc != NOTIFY_DONE);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
notifier_rc = __cpu_notifier_call_chain(
|
||||
CPU_UP_CANCELED, hcpu, nr_calls, NULL);
|
||||
BUG_ON(notifier_rc != NOTIFY_DONE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -89,6 +89,8 @@ SECTIONS
|
||||
} :text
|
||||
.initcall.init : {
|
||||
__initcall_start = .;
|
||||
*(.initcallpresmp.init)
|
||||
__presmp_initcall_end = .;
|
||||
*(.initcall1.init)
|
||||
__initcall_end = .;
|
||||
} :text
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <xen/config.h>
|
||||
#include <xen/cpumask.h>
|
||||
#include <xen/cpu.h>
|
||||
|
||||
/*
|
||||
* cpu_bit_bitmap[] is a special, "compressed" data structure that
|
||||
@@ -24,3 +25,36 @@ const unsigned long cpu_bit_bitmap[BITS_PER_LONG+1][BITS_TO_LONGS(NR_CPUS)] = {
|
||||
MASK_DECLARE_8(48), MASK_DECLARE_8(56),
|
||||
#endif
|
||||
};
|
||||
|
||||
DEFINE_SPINLOCK(cpu_add_remove_lock);
|
||||
|
||||
static RAW_NOTIFIER_HEAD(cpu_chain);
|
||||
|
||||
int register_cpu_notifier(struct notifier_block *nb)
|
||||
{
|
||||
int ret;
|
||||
spin_lock(&cpu_add_remove_lock);
|
||||
ret = raw_notifier_chain_register(&cpu_chain, nb);
|
||||
spin_unlock(&cpu_add_remove_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void unregister_cpu_notifier(struct notifier_block *nb)
|
||||
{
|
||||
spin_lock(&cpu_add_remove_lock);
|
||||
raw_notifier_chain_unregister(&cpu_chain, nb);
|
||||
spin_unlock(&cpu_add_remove_lock);
|
||||
}
|
||||
|
||||
int cpu_notifier_call_chain(unsigned long val, void *v)
|
||||
{
|
||||
BUG_ON(!spin_is_locked(&cpu_add_remove_lock));
|
||||
return raw_notifier_call_chain(&cpu_chain, val, v);
|
||||
}
|
||||
|
||||
int __cpu_notifier_call_chain(
|
||||
unsigned long val, void *v, int nr_to_call, int *nr_calls)
|
||||
{
|
||||
BUG_ON(!spin_is_locked(&cpu_add_remove_lock));
|
||||
return __raw_notifier_call_chain(&cpu_chain, val, v, nr_to_call, nr_calls);
|
||||
}
|
||||
+50
-26
@@ -17,6 +17,7 @@
|
||||
#include <xen/percpu.h>
|
||||
#include <xen/sched.h>
|
||||
#include <xen/sched-if.h>
|
||||
#include <xen/cpu.h>
|
||||
|
||||
#define for_each_cpupool(ptr) \
|
||||
for ((ptr) = &cpupool_list; *(ptr) != NULL; (ptr) = &((*(ptr))->next))
|
||||
@@ -178,10 +179,8 @@ static int cpupool_assign_cpu_locked(struct cpupool *c, unsigned int cpu)
|
||||
*/
|
||||
int cpupool_assign_ncpu(struct cpupool *c, int ncpu)
|
||||
{
|
||||
int i;
|
||||
int n;
|
||||
int i, n = 0;
|
||||
|
||||
n = 0;
|
||||
spin_lock(&cpupool_lock);
|
||||
for_each_cpu_mask(i, cpupool_free_cpus)
|
||||
{
|
||||
@@ -293,21 +292,6 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* assign cpus to the default cpupool
|
||||
* default are all cpus, less cpus may be specified as boot parameter
|
||||
* possible failures:
|
||||
* - no cpu assigned
|
||||
*/
|
||||
int __init cpupool0_cpu_assign(struct cpupool *c)
|
||||
{
|
||||
if ( (cpupool0_max_cpus == 0) || (cpupool0_max_cpus > num_online_cpus()) )
|
||||
cpupool0_max_cpus = num_online_cpus();
|
||||
if ( !cpupool_assign_ncpu(cpupool0, cpupool0_max_cpus) )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* add a new domain to a cpupool
|
||||
* possible failures:
|
||||
@@ -363,16 +347,14 @@ void cpupool_rm_domain(struct domain *d)
|
||||
* called to add a new cpu to pool admin
|
||||
* we add a hotplugged cpu to the cpupool0 to be able to add it to dom0
|
||||
*/
|
||||
void cpupool_cpu_add(unsigned int cpu)
|
||||
static void cpupool_cpu_add(unsigned int cpu)
|
||||
{
|
||||
if ( cpupool0 == NULL )
|
||||
return;
|
||||
spin_lock(&cpupool_lock);
|
||||
cpu_clear(cpu, cpupool_locked_cpus);
|
||||
cpu_set(cpu, cpupool_free_cpus);
|
||||
cpupool_assign_cpu_locked(cpupool0, cpu);
|
||||
if ( cpupool0 != NULL )
|
||||
cpupool_assign_cpu_locked(cpupool0, cpu);
|
||||
spin_unlock(&cpupool_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -380,7 +362,7 @@ void cpupool_cpu_add(unsigned int cpu)
|
||||
* the cpu to be removed is locked to avoid removing it from dom0
|
||||
* returns failure if not in pool0
|
||||
*/
|
||||
int cpupool_cpu_remove(unsigned int cpu)
|
||||
static int cpupool_cpu_remove(unsigned int cpu)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
@@ -588,10 +570,52 @@ void dump_runq(unsigned char key)
|
||||
spin_unlock(&cpupool_lock);
|
||||
}
|
||||
|
||||
static int cpu_callback(
|
||||
struct notifier_block *nfb, unsigned long action, void *hcpu)
|
||||
{
|
||||
unsigned int cpu = (unsigned long)hcpu;
|
||||
int rc = 0;
|
||||
|
||||
switch ( action )
|
||||
{
|
||||
case CPU_DOWN_FAILED:
|
||||
case CPU_ONLINE:
|
||||
cpupool_cpu_add(cpu);
|
||||
break;
|
||||
case CPU_DOWN_PREPARE:
|
||||
rc = cpupool_cpu_remove(cpu);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return !rc ? NOTIFY_DONE : notifier_from_errno(rc);
|
||||
}
|
||||
|
||||
static struct notifier_block cpu_nfb = {
|
||||
.notifier_call = cpu_callback
|
||||
};
|
||||
|
||||
static int __init cpupool_presmp_init(void)
|
||||
{
|
||||
void *cpu = (void *)(long)smp_processor_id();
|
||||
cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
|
||||
register_cpu_notifier(&cpu_nfb);
|
||||
return 0;
|
||||
}
|
||||
presmp_initcall(cpupool_presmp_init);
|
||||
|
||||
static int __init cpupool_init(void)
|
||||
{
|
||||
cpupool_free_cpus = cpu_online_map;
|
||||
cpupool_list = NULL;
|
||||
cpupool0 = cpupool_create(0, NULL);
|
||||
BUG_ON(cpupool0 == NULL);
|
||||
|
||||
if ( (cpupool0_max_cpus == 0) || (cpupool0_max_cpus > num_online_cpus()) )
|
||||
cpupool0_max_cpus = num_online_cpus();
|
||||
|
||||
if ( !cpupool_assign_ncpu(cpupool0, cpupool0_max_cpus) )
|
||||
BUG();
|
||||
|
||||
return 0;
|
||||
}
|
||||
__initcall(cpupool_init);
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <xen/console.h>
|
||||
#include <xen/errno.h>
|
||||
#include <xen/delay.h>
|
||||
#include <xen/init.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
/* Printk isn't particularly safe just after we've trapped to the
|
||||
@@ -639,23 +640,25 @@ __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie)
|
||||
return rc;
|
||||
}
|
||||
|
||||
void __init
|
||||
initialise_gdb(void)
|
||||
static int __init initialise_gdb(void)
|
||||
{
|
||||
if ( *opt_gdb == '\0' )
|
||||
return;
|
||||
return 0;
|
||||
|
||||
gdb_ctx->serhnd = serial_parse_handle(opt_gdb);
|
||||
if ( gdb_ctx->serhnd == -1 )
|
||||
{
|
||||
printk("Bad gdb= option '%s'\n", opt_gdb);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
serial_start_sync(gdb_ctx->serhnd);
|
||||
|
||||
printk("GDB stub initialised.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
presmp_initcall(initialise_gdb);
|
||||
|
||||
static void gdb_pause_this_cpu(void *unused)
|
||||
{
|
||||
|
||||
@@ -147,6 +147,22 @@ void add_taint(unsigned flag)
|
||||
tainted |= flag;
|
||||
}
|
||||
|
||||
extern initcall_t __initcall_start, __presmp_initcall_end, __initcall_end;
|
||||
|
||||
void __init do_presmp_initcalls(void)
|
||||
{
|
||||
initcall_t *call;
|
||||
for ( call = &__initcall_start; call < &__presmp_initcall_end; call++ )
|
||||
(*call)();
|
||||
}
|
||||
|
||||
void __init do_initcalls(void)
|
||||
{
|
||||
initcall_t *call;
|
||||
for ( call = &__presmp_initcall_end; call < &__initcall_end; call++ )
|
||||
(*call)();
|
||||
}
|
||||
|
||||
# define DO(fn) long do_##fn
|
||||
|
||||
#endif
|
||||
|
||||
@@ -65,6 +65,9 @@ static int notifier_call_chain(
|
||||
int ret = NOTIFY_DONE;
|
||||
struct notifier_block *nb, *next_nb;
|
||||
|
||||
if ( nr_calls )
|
||||
*nr_calls = 0;
|
||||
|
||||
nb = rcu_dereference(*nl);
|
||||
|
||||
while ( nb && nr_to_call )
|
||||
|
||||
+23
-4
@@ -43,6 +43,7 @@
|
||||
#include <xen/bitops.h>
|
||||
#include <xen/percpu.h>
|
||||
#include <xen/softirq.h>
|
||||
#include <xen/cpu.h>
|
||||
|
||||
/* Definition for rcupdate control block. */
|
||||
struct rcu_ctrlblk rcu_ctrlblk = {
|
||||
@@ -334,15 +335,33 @@ static void rcu_init_percpu_data(int cpu, struct rcu_ctrlblk *rcp,
|
||||
rdp->blimit = blimit;
|
||||
}
|
||||
|
||||
void __devinit rcu_online_cpu(int cpu)
|
||||
static int cpu_callback(
|
||||
struct notifier_block *nfb, unsigned long action, void *hcpu)
|
||||
{
|
||||
struct rcu_data *rdp = &per_cpu(rcu_data, cpu);
|
||||
unsigned int cpu = (unsigned long)hcpu;
|
||||
|
||||
rcu_init_percpu_data(cpu, &rcu_ctrlblk, rdp);
|
||||
switch ( action )
|
||||
{
|
||||
case CPU_UP_PREPARE: {
|
||||
struct rcu_data *rdp = &per_cpu(rcu_data, cpu);
|
||||
rcu_init_percpu_data(cpu, &rcu_ctrlblk, rdp);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block cpu_nfb = {
|
||||
.notifier_call = cpu_callback
|
||||
};
|
||||
|
||||
void __init rcu_init(void)
|
||||
{
|
||||
rcu_online_cpu(smp_processor_id());
|
||||
void *cpu = (void *)(long)smp_processor_id();
|
||||
cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
|
||||
register_cpu_notifier(&cpu_nfb);
|
||||
open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
|
||||
}
|
||||
+32
-9
@@ -16,9 +16,10 @@
|
||||
#include <xen/sched.h>
|
||||
#include <xen/softirq.h>
|
||||
#include <xen/tasklet.h>
|
||||
#include <xen/cpu.h>
|
||||
|
||||
/* Some subsystems call into us before we are initialised. We ignore them. */
|
||||
static bool_t tasklets_initialised;
|
||||
static cpumask_t tasklets_initialised;
|
||||
|
||||
DEFINE_PER_CPU(unsigned long, tasklet_work_to_do);
|
||||
|
||||
@@ -43,7 +44,7 @@ void tasklet_schedule_on_cpu(struct tasklet *t, unsigned int cpu)
|
||||
|
||||
spin_lock_irqsave(&tasklet_lock, flags);
|
||||
|
||||
if ( tasklets_initialised && !t->is_dead )
|
||||
if ( cpu_isset(cpu, tasklets_initialised) && !t->is_dead )
|
||||
{
|
||||
t->scheduled_on = cpu;
|
||||
if ( !t->is_running )
|
||||
@@ -135,7 +136,7 @@ void tasklet_kill(struct tasklet *t)
|
||||
spin_unlock_irqrestore(&tasklet_lock, flags);
|
||||
}
|
||||
|
||||
void migrate_tasklets_from_cpu(unsigned int cpu)
|
||||
static void migrate_tasklets_from_cpu(unsigned int cpu)
|
||||
{
|
||||
struct list_head *list = &per_cpu(tasklet_list, cpu);
|
||||
unsigned long flags;
|
||||
@@ -165,14 +166,36 @@ void tasklet_init(
|
||||
t->data = data;
|
||||
}
|
||||
|
||||
static int cpu_callback(
|
||||
struct notifier_block *nfb, unsigned long action, void *hcpu)
|
||||
{
|
||||
unsigned int cpu = (unsigned long)hcpu;
|
||||
|
||||
switch ( action )
|
||||
{
|
||||
case CPU_UP_PREPARE:
|
||||
if ( !cpu_test_and_set(cpu, tasklets_initialised) )
|
||||
INIT_LIST_HEAD(&per_cpu(tasklet_list, cpu));
|
||||
break;
|
||||
case CPU_DEAD:
|
||||
migrate_tasklets_from_cpu(cpu);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block cpu_nfb = {
|
||||
.notifier_call = cpu_callback
|
||||
};
|
||||
|
||||
void __init tasklet_subsys_init(void)
|
||||
{
|
||||
unsigned int cpu;
|
||||
|
||||
for_each_possible_cpu ( cpu )
|
||||
INIT_LIST_HEAD(&per_cpu(tasklet_list, cpu));
|
||||
|
||||
tasklets_initialised = 1;
|
||||
void *hcpu = (void *)(long)smp_processor_id();
|
||||
cpu_callback(&cpu_nfb, CPU_UP_PREPARE, hcpu);
|
||||
register_cpu_notifier(&cpu_nfb);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <xen/xmalloc.h>
|
||||
#include <xen/guest_access.h>
|
||||
#include <xen/domain.h>
|
||||
#include <xen/cpu.h>
|
||||
#include <asm/bug.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/config.h>
|
||||
@@ -582,3 +583,38 @@ void __init cpufreq_cmdline_parse(char *str)
|
||||
str = end;
|
||||
} while (str);
|
||||
}
|
||||
|
||||
static int cpu_callback(
|
||||
struct notifier_block *nfb, unsigned long action, void *hcpu)
|
||||
{
|
||||
unsigned int cpu = (unsigned long)hcpu;
|
||||
|
||||
switch ( action )
|
||||
{
|
||||
case CPU_DOWN_FAILED:
|
||||
case CPU_ONLINE:
|
||||
(void)cpufreq_add_cpu(cpu);
|
||||
break;
|
||||
case CPU_DOWN_PREPARE:
|
||||
(void)cpufreq_del_cpu(cpu);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block cpu_nfb = {
|
||||
.notifier_call = cpu_callback
|
||||
};
|
||||
|
||||
static int __init cpufreq_presmp_init(void)
|
||||
{
|
||||
void *cpu = (void *)(long)smp_processor_id();
|
||||
cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
|
||||
register_cpu_notifier(&cpu_nfb);
|
||||
return 0;
|
||||
}
|
||||
presmp_initcall(cpufreq_presmp_init);
|
||||
|
||||
@@ -295,12 +295,6 @@ uint8_t hvm_combine_hw_exceptions(uint8_t vec1, uint8_t vec2);
|
||||
|
||||
void hvm_set_rdtsc_exiting(struct domain *d, bool_t enable);
|
||||
|
||||
static inline int
|
||||
hvm_cpu_prepare(unsigned int cpu)
|
||||
{
|
||||
return (hvm_funcs.cpu_prepare ? hvm_funcs.cpu_prepare(cpu) : 0);
|
||||
}
|
||||
|
||||
static inline int hvm_cpu_up(void)
|
||||
{
|
||||
return (hvm_funcs.cpu_up ? hvm_funcs.cpu_up() : 1);
|
||||
|
||||
@@ -551,8 +551,6 @@ extern void mtrr_bp_init(void);
|
||||
|
||||
void mcheck_init(struct cpuinfo_x86 *c);
|
||||
asmlinkage void do_machine_check(struct cpu_user_regs *regs);
|
||||
void cpu_mcheck_distribute_cmci(void);
|
||||
void cpu_mcheck_disable(void);
|
||||
|
||||
int cpuid_hypervisor_leaves( uint32_t idx, uint32_t sub_idx,
|
||||
uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
|
||||
|
||||
@@ -53,10 +53,7 @@ extern u32 cpu_2_logical_apicid[];
|
||||
#define cpu_physical_id(cpu) x86_cpu_to_apicid[cpu]
|
||||
|
||||
/* State of each CPU. */
|
||||
#define CPU_ONLINE 0x0002 /* CPU is up */
|
||||
#define CPU_DEAD 0x0004 /* CPU is dead */
|
||||
DECLARE_PER_CPU(int, cpu_state);
|
||||
extern spinlock_t(cpu_add_remove_lock);
|
||||
|
||||
#define cpu_is_offline(cpu) unlikely(!cpu_online(cpu))
|
||||
extern int cpu_down(unsigned int cpu);
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef __XEN_CPU_H__
|
||||
#define __XEN_CPU_H__
|
||||
|
||||
#include <xen/types.h>
|
||||
#include <xen/spinlock.h>
|
||||
#include <xen/notifier.h>
|
||||
|
||||
extern spinlock_t cpu_add_remove_lock;
|
||||
|
||||
int register_cpu_notifier(struct notifier_block *nb);
|
||||
void unregister_cpu_notifier(struct notifier_block *nb);
|
||||
int cpu_notifier_call_chain(unsigned long val, void *v);
|
||||
int __cpu_notifier_call_chain(
|
||||
unsigned long val, void *v, int nr_to_call, int *nr_calls);
|
||||
|
||||
/*
|
||||
* Notification actions: note that only CPU_{UP,DOWN}_PREPARE may fail ---
|
||||
* all other handlers *must* return NOTIFY_DONE.
|
||||
*/
|
||||
#define CPU_UP_PREPARE 0x0002 /* CPU is coming up */
|
||||
#define CPU_UP_CANCELED 0x0003 /* CPU is no longer coming up */
|
||||
#define CPU_ONLINE 0x0004 /* CPU is up */
|
||||
#define CPU_DOWN_PREPARE 0x0005 /* CPU is going down */
|
||||
#define CPU_DOWN_FAILED 0x0006 /* CPU is no longer going down */
|
||||
#define CPU_DYING 0x0007 /* CPU is nearly dead (in stop_machine ctxt) */
|
||||
#define CPU_DEAD 0x0008 /* CPU is dead */
|
||||
|
||||
#endif /* __XEN_CPU_H__ */
|
||||
@@ -88,12 +88,6 @@ void gdb_arch_exit(struct cpu_user_regs *regs);
|
||||
#define SIGALRM 14
|
||||
#define SIGTERM 15
|
||||
|
||||
void initialise_gdb(void);
|
||||
|
||||
#else
|
||||
|
||||
#define initialise_gdb() ((void)0)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __XEN_GDBSTUB_H__ */
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
__attribute_used__ __attribute__ ((__section__ (".exit.data")))
|
||||
#define __initsetup \
|
||||
__attribute_used__ __attribute__ ((__section__ (".init.setup")))
|
||||
#define __init_call \
|
||||
__attribute_used__ __attribute__ ((__section__ (".initcall1.init")))
|
||||
#define __init_call(lvl) \
|
||||
__attribute_used__ __attribute__ ((__section__ (".initcall" lvl ".init")))
|
||||
#define __exit_call \
|
||||
__attribute_used__ __attribute__ ((__section__ (".exitcall.exit")))
|
||||
|
||||
@@ -66,13 +66,16 @@
|
||||
typedef int (*initcall_t)(void);
|
||||
typedef void (*exitcall_t)(void);
|
||||
|
||||
extern initcall_t __initcall_start, __initcall_end;
|
||||
|
||||
#define presmp_initcall(fn) \
|
||||
static initcall_t __initcall_##fn __init_call("presmp") = fn
|
||||
#define __initcall(fn) \
|
||||
static initcall_t __initcall_##fn __init_call = fn
|
||||
static initcall_t __initcall_##fn __init_call("1") = fn
|
||||
#define __exitcall(fn) \
|
||||
static exitcall_t __exitcall_##fn __exit_call = fn
|
||||
|
||||
void do_presmp_initcalls(void);
|
||||
void do_initcalls(void);
|
||||
|
||||
/*
|
||||
* Used for kernel command line parameter setup
|
||||
*/
|
||||
|
||||
@@ -52,38 +52,21 @@ int __raw_notifier_call_chain(
|
||||
struct raw_notifier_head *nh, unsigned long val, void *v,
|
||||
int nr_to_call, int *nr_calls);
|
||||
|
||||
#define NOTIFY_DONE 0x0000 /* Don't care */
|
||||
#define NOTIFY_OK 0x0001 /* Suits me */
|
||||
#define NOTIFY_STOP_MASK 0x8000 /* Don't call further */
|
||||
#define NOTIFY_BAD (NOTIFY_STOP_MASK|0x0002)
|
||||
/* Bad/Veto action */
|
||||
/*
|
||||
* Clean way to return from the notifier and stop further calls.
|
||||
*/
|
||||
#define NOTIFY_STOP (NOTIFY_OK|NOTIFY_STOP_MASK)
|
||||
#define NOTIFY_DONE 0x0000
|
||||
#define NOTIFY_STOP_MASK 0x8000
|
||||
#define NOTIFY_STOP (NOTIFY_STOP_MASK|NOTIFY_DONE)
|
||||
#define NOTIFY_BAD (NOTIFY_STOP_MASK|EINVAL)
|
||||
|
||||
/* Encapsulate (negative) errno value (in particular, NOTIFY_BAD <=> EPERM). */
|
||||
/* Encapsulate (negative) errno value. */
|
||||
static inline int notifier_from_errno(int err)
|
||||
{
|
||||
return NOTIFY_STOP_MASK | (NOTIFY_OK - err);
|
||||
return NOTIFY_STOP_MASK | -err;
|
||||
}
|
||||
|
||||
/* Restore (negative) errno value from notify return value. */
|
||||
static inline int notifier_to_errno(int ret)
|
||||
{
|
||||
ret &= ~NOTIFY_STOP_MASK;
|
||||
return ret > NOTIFY_OK ? NOTIFY_OK - ret : 0;
|
||||
return -(ret & ~NOTIFY_STOP_MASK);
|
||||
}
|
||||
|
||||
#define CPU_ONLINE 0x0002 /* CPU (unsigned)v is up */
|
||||
#define CPU_UP_PREPARE 0x0003 /* CPU (unsigned)v coming up */
|
||||
#define CPU_UP_CANCELED 0x0004 /* CPU (unsigned)v NOT coming up */
|
||||
#define CPU_DOWN_PREPARE 0x0005 /* CPU (unsigned)v going down */
|
||||
#define CPU_DOWN_FAILED 0x0006 /* CPU (unsigned)v NOT going down */
|
||||
#define CPU_DEAD 0x0007 /* CPU (unsigned)v dead */
|
||||
#define CPU_DYING 0x0008 /* CPU (unsigned)v not running any task,
|
||||
* not handling interrupts, soon dead */
|
||||
#define CPU_POST_DEAD 0x0009 /* CPU (unsigned)v dead, cpu_hotplug
|
||||
* lock is dropped */
|
||||
|
||||
#endif /* __XEN_NOTIFIER_H__ */
|
||||
@@ -190,7 +190,6 @@ typedef struct _rcu_read_lock rcu_read_lock_t;
|
||||
#define rcu_assign_pointer(p, v) ({ smp_wmb(); (p) = (v); })
|
||||
|
||||
void rcu_init(void);
|
||||
void __devinit rcu_online_cpu(int cpu);
|
||||
void rcu_check_callbacks(int cpu);
|
||||
|
||||
/* Exported interfaces */
|
||||
|
||||
@@ -622,10 +622,7 @@ extern enum cpufreq_controller {
|
||||
|
||||
struct cpupool *cpupool_create(int poolid, char *sched);
|
||||
int cpupool_destroy(struct cpupool *c);
|
||||
int cpupool0_cpu_assign(struct cpupool *c);
|
||||
int cpupool_assign_ncpu(struct cpupool *c, int ncpu);
|
||||
void cpupool_cpu_add(unsigned int cpu);
|
||||
int cpupool_cpu_remove(unsigned int cpu);
|
||||
int cpupool_add_domain(struct domain *d, int poolid);
|
||||
void cpupool_rm_domain(struct domain *d);
|
||||
int cpupool_do_sysctl(struct xen_sysctl_cpupool_op *op);
|
||||
|
||||
@@ -35,7 +35,6 @@ void tasklet_schedule_on_cpu(struct tasklet *t, unsigned int cpu);
|
||||
void tasklet_schedule(struct tasklet *t);
|
||||
void do_tasklet(void);
|
||||
void tasklet_kill(struct tasklet *t);
|
||||
void migrate_tasklets_from_cpu(unsigned int cpu);
|
||||
void tasklet_init(
|
||||
struct tasklet *t, void (*func)(unsigned long), unsigned long data);
|
||||
void tasklet_subsys_init(void);
|
||||
|
||||