Index: xen-3.3.1-testing/xen/arch/x86/acpi/cpufreq/cpufreq.c =================================================================== --- xen-3.3.1-testing.orig/xen/arch/x86/acpi/cpufreq/cpufreq.c +++ xen-3.3.1-testing/xen/arch/x86/acpi/cpufreq/cpufreq.c @@ -44,7 +44,7 @@ #include #include -struct processor_pminfo processor_pminfo[NR_CPUS]; +struct processor_pminfo *__read_mostly processor_pminfo[NR_CPUS]; struct cpufreq_policy xen_px_policy[NR_CPUS]; static cpumask_t *cpufreq_dom_pt; @@ -436,7 +436,7 @@ acpi_cpufreq_cpu_init(struct cpufreq_pol drv_data[cpu] = data; - data->acpi_data = &processor_pminfo[cpu].perf; + data->acpi_data = &processor_pminfo[cpu]->perf; perf = data->acpi_data; policy->shared_type = perf->shared_type; @@ -575,8 +575,8 @@ int cpufreq_dom_init(void) cpufreq_dom_max = 0; for_each_online_cpu(i) { - if (cpufreq_dom_max < processor_pminfo[i].perf.domain_info.domain) - cpufreq_dom_max = processor_pminfo[i].perf.domain_info.domain; + if (cpufreq_dom_max < processor_pminfo[i]->perf.domain_info.domain) + cpufreq_dom_max = processor_pminfo[i]->perf.domain_info.domain; } cpufreq_dom_max++; @@ -592,13 +592,13 @@ int cpufreq_dom_init(void) memset(cpufreq_dom_pt, 0, cpufreq_dom_max * sizeof(cpumask_t)); for_each_online_cpu(i) { - __set_bit(processor_pminfo[i].perf.domain_info.domain, cpufreq_dom_mask); - cpu_set(i, cpufreq_dom_pt[processor_pminfo[i].perf.domain_info.domain]); + __set_bit(processor_pminfo[i]->perf.domain_info.domain, cpufreq_dom_mask); + cpu_set(i, cpufreq_dom_pt[processor_pminfo[i]->perf.domain_info.domain]); } for_each_online_cpu(i) - processor_pminfo[i].perf.shared_cpu_map = - cpufreq_dom_pt[processor_pminfo[i].perf.domain_info.domain]; + processor_pminfo[i]->perf.shared_cpu_map = + cpufreq_dom_pt[processor_pminfo[i]->perf.domain_info.domain]; return 0; } Index: xen-3.3.1-testing/xen/arch/x86/acpi/cpufreq/powernow.c =================================================================== --- xen-3.3.1-testing.orig/xen/arch/x86/acpi/cpufreq/powernow.c +++ xen-3.3.1-testing/xen/arch/x86/acpi/cpufreq/powernow.c @@ -49,9 +49,6 @@ #define MSR_PSTATE_CTRL 0xc0010062 /* Pstate control MSR */ #define MSR_PSTATE_CUR_LIMIT 0xc0010061 /* pstate current limit MSR */ -extern struct processor_pminfo processor_pminfo[NR_CPUS]; -extern struct cpufreq_policy xen_px_policy[NR_CPUS]; - struct powernow_cpufreq_data { struct processor_performance *acpi_data; struct cpufreq_frequency_table *freq_table; @@ -149,7 +146,7 @@ static int powernow_cpufreq_cpu_init(str drv_data[cpu] = data; - data->acpi_data = &processor_pminfo[cpu].perf; + data->acpi_data = &processor_pminfo[cpu]->perf; perf = data->acpi_data; policy->shared_type = perf->shared_type; @@ -271,8 +268,8 @@ int powernow_cpufreq_init(void) } if (ret) return ret; - if (max_dom < processor_pminfo[i].perf.domain_info.domain) - max_dom = processor_pminfo[i].perf.domain_info.domain; + if (max_dom < processor_pminfo[i]->perf.domain_info.domain) + max_dom = processor_pminfo[i]->perf.domain_info.domain; } max_dom++; @@ -288,13 +285,13 @@ int powernow_cpufreq_init(void) /* get cpumask of each psd domain */ for_each_online_cpu(i) { - __set_bit(processor_pminfo[i].perf.domain_info.domain, dom_mask); - cpu_set(i, pt[processor_pminfo[i].perf.domain_info.domain]); + __set_bit(processor_pminfo[i]->perf.domain_info.domain, dom_mask); + cpu_set(i, pt[processor_pminfo[i]->perf.domain_info.domain]); } for_each_online_cpu(i) - processor_pminfo[i].perf.shared_cpu_map = - pt[processor_pminfo[i].perf.domain_info.domain]; + processor_pminfo[i]->perf.shared_cpu_map = + pt[processor_pminfo[i]->perf.domain_info.domain]; cpufreq_driver = &powernow_cpufreq_driver; Index: xen-3.3.1-testing/xen/arch/x86/acpi/cpufreq/utility.c =================================================================== --- xen-3.3.1-testing.orig/xen/arch/x86/acpi/cpufreq/utility.c +++ xen-3.3.1-testing/xen/arch/x86/acpi/cpufreq/utility.c @@ -45,10 +45,12 @@ void px_statistic_suspend(void) now = NOW(); for_each_online_cpu(cpu) { - struct pm_px *pxpt = &px_statistic_data[cpu]; + struct pm_px *pxpt = px_statistic_data[cpu]; uint64_t total_idle_ns; uint64_t tmp_idle_ns; + if ( !pxpt || !pxpt->u.pt ) + continue; total_idle_ns = get_cpu_idle_time(cpu); tmp_idle_ns = total_idle_ns - pxpt->prev_idle_wall; @@ -66,7 +68,10 @@ void px_statistic_resume(void) now = NOW(); for_each_online_cpu(cpu) { - struct pm_px *pxpt = &px_statistic_data[cpu]; + struct pm_px *pxpt = px_statistic_data[cpu]; + + if ( !pxpt ) + continue; pxpt->prev_state_wall = now; pxpt->prev_idle_wall = get_cpu_idle_time(cpu); } @@ -80,11 +85,14 @@ void px_statistic_update(cpumask_t cpuma now = NOW(); for_each_cpu_mask(i, cpumask) { - struct pm_px *pxpt = &px_statistic_data[i]; - uint32_t statnum = processor_pminfo[i].perf.state_count; + struct pm_px *pxpt = px_statistic_data[i]; + struct processor_pminfo *pmpt = processor_pminfo[i]; uint64_t total_idle_ns; uint64_t tmp_idle_ns; + if ( !pxpt || !pxpt->u.pt || !pxpt->u.trans_pt || !pmpt ) + continue; + total_idle_ns = get_cpu_idle_time(i); tmp_idle_ns = total_idle_ns - pxpt->prev_idle_wall; @@ -94,7 +102,7 @@ void px_statistic_update(cpumask_t cpuma pxpt->u.pt[from].residency += now - pxpt->prev_state_wall; pxpt->u.pt[from].residency -= tmp_idle_ns; - (*(pxpt->u.trans_pt + from*statnum + to))++; + (*(pxpt->u.trans_pt + from * pmpt->perf.state_count + to))++; pxpt->prev_state_wall = now; pxpt->prev_idle_wall = total_idle_ns; @@ -104,11 +112,23 @@ void px_statistic_update(cpumask_t cpuma int px_statistic_init(int cpuid) { uint32_t i, count; - struct pm_px *pxpt = &px_statistic_data[cpuid]; - struct processor_pminfo *pmpt = &processor_pminfo[cpuid]; + struct pm_px *pxpt = px_statistic_data[cpuid]; + const struct processor_pminfo *pmpt = processor_pminfo[cpuid]; + + if ( !pmpt ) + return -EINVAL; count = pmpt->perf.state_count; + if ( !pxpt ) + { + pxpt = xmalloc(struct pm_px); + if ( !pxpt ) + return -ENOMEM; + memset(pxpt, 0, sizeof(*pxpt)); + px_statistic_data[cpuid] = pxpt; + } + pxpt->u.trans_pt = xmalloc_array(uint64_t, count * count); if (!pxpt->u.trans_pt) return -ENOMEM; @@ -137,9 +157,13 @@ int px_statistic_init(int cpuid) void px_statistic_reset(int cpuid) { uint32_t i, j, count; - struct pm_px *pxpt = &px_statistic_data[cpuid]; + struct pm_px *pxpt = px_statistic_data[cpuid]; + const struct processor_pminfo *pmpt = processor_pminfo[cpuid]; - count = processor_pminfo[cpuid].perf.state_count; + if ( !pxpt || !pxpt->u.pt || !pxpt->u.trans_pt || !pmpt ) + return; + + count = pmpt->perf.state_count; for (i=0; i < count; i++) { pxpt->u.pt[i].residency = 0; @@ -298,9 +322,9 @@ void cpufreq_suspend(void) /* to protect the case when Px was not controlled by xen */ for_each_online_cpu(cpu) { - struct processor_performance *perf = &processor_pminfo[cpu].perf; + const struct processor_pminfo *pmpt = processor_pminfo[cpu]; - if (!(perf->init & XEN_PX_INIT)) + if (!pmpt || !(pmpt->perf.init & XEN_PX_INIT)) return; } @@ -318,10 +342,11 @@ int cpufreq_resume(void) /* 1. to protect the case when Px was not controlled by xen */ /* 2. set state and resume flag to sync cpu to right state and freq */ for_each_online_cpu(cpu) { - struct processor_performance *perf = &processor_pminfo[cpu].perf; + struct processor_pminfo *pmpt = processor_pminfo[cpu]; + struct processor_performance *perf = &pmpt->perf; struct cpufreq_policy *policy = &xen_px_policy[cpu]; - if (!(perf->init & XEN_PX_INIT)) + if (!pmpt || !(perf->init & XEN_PX_INIT)) goto err; perf->state = 0; policy->resume = 1; Index: xen-3.3.1-testing/xen/arch/x86/acpi/cpu_idle.c =================================================================== --- xen-3.3.1-testing.orig/xen/arch/x86/acpi/cpu_idle.c +++ xen-3.3.1-testing/xen/arch/x86/acpi/cpu_idle.c @@ -128,7 +128,7 @@ struct acpi_processor_power struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER]; }; -static struct acpi_processor_power processor_powers[NR_CPUS]; +static struct acpi_processor_power *__read_mostly processor_powers[NR_CPUS]; static void print_acpi_power(uint32_t cpu, struct acpi_processor_power *power) { @@ -162,8 +162,11 @@ static void print_acpi_power(uint32_t cp static void dump_cx(unsigned char key) { - for( int i = 0; i < num_online_cpus(); i++ ) - print_acpi_power(i, &processor_powers[i]); + unsigned int cpu; + + for_each_online_cpu ( cpu ) + if (processor_powers[cpu]) + print_acpi_power(cpu, processor_powers[cpu]); } static int __init cpu_idle_key_init(void) @@ -272,14 +275,12 @@ static struct { static void acpi_processor_idle(void) { - struct acpi_processor_power *power = NULL; + struct acpi_processor_power *power = processor_powers[smp_processor_id()]; struct acpi_processor_cx *cx = NULL; struct acpi_processor_cx *next_state = NULL; int sleep_ticks = 0; u32 t1, t2 = 0; - power = &processor_powers[smp_processor_id()]; - /* * Interrupts must be disabled during bus mastering calculations and * for C2/C3 transitions. @@ -292,7 +293,7 @@ static void acpi_processor_idle(void) return; } - cx = power->state; + cx = power ? power->state : NULL; if ( !cx ) { if ( pm_idle_save ) @@ -949,7 +950,15 @@ long set_cx_pminfo(uint32_t cpu, struct return -EFAULT; } - acpi_power = &processor_powers[cpu_id]; + acpi_power = processor_powers[cpu_id]; + if ( !acpi_power ) + { + acpi_power = xmalloc(struct acpi_processor_power); + if ( !acpi_power ) + return -ENOMEM; + memset(acpi_power, 0, sizeof(*acpi_power)); + processor_powers[cpu_id] = acpi_power; + } init_cx_pminfo(acpi_power); @@ -985,18 +994,25 @@ long set_cx_pminfo(uint32_t cpu, struct uint32_t pmstat_get_cx_nr(uint32_t cpuid) { - return processor_powers[cpuid].count; + return processor_powers[cpuid] ? processor_powers[cpuid]->count : 0; } int pmstat_get_cx_stat(uint32_t cpuid, struct pm_cx_stat *stat) { - struct acpi_processor_power *power = &processor_powers[cpuid]; + const struct acpi_processor_power *power = processor_powers[cpuid]; struct vcpu *v = idle_vcpu[cpuid]; uint64_t usage; int i; + if ( unlikely(!power) ) + { + stat->last = 0; + stat->nr = 0; + stat->idle_time = 0; + return 0; + } stat->last = (power->state) ? power->state->type : 0; - stat->nr = processor_powers[cpuid].count; + stat->nr = power->count; stat->idle_time = v->runstate.time[RUNSTATE_running]; if ( v->is_running ) stat->idle_time += NOW() - v->runstate.state_entry_time; Index: xen-3.3.1-testing/xen/arch/x86/acpi/pmstat.c =================================================================== --- xen-3.3.1-testing.orig/xen/arch/x86/acpi/pmstat.c +++ xen-3.3.1-testing/xen/arch/x86/acpi/pmstat.c @@ -41,7 +41,7 @@ #include #include -struct pm_px px_statistic_data[NR_CPUS]; +struct pm_px *__read_mostly px_statistic_data[NR_CPUS]; extern uint32_t pmstat_get_cx_nr(uint32_t cpuid); extern int pmstat_get_cx_stat(uint32_t cpuid, struct pm_cx_stat *stat); @@ -55,7 +55,7 @@ int do_get_pm_info(struct xen_sysctl_get if ( !op || (op->cpuid >= NR_CPUS) || !cpu_online(op->cpuid) ) return -EINVAL; - pmpt = &processor_pminfo[op->cpuid]; + pmpt = processor_pminfo[op->cpuid]; switch ( op->type & PMSTAT_CATEGORY_MASK ) { @@ -86,7 +86,7 @@ int do_get_pm_info(struct xen_sysctl_get uint64_t now, ct; uint64_t total_idle_ns; uint64_t tmp_idle_ns; - struct pm_px *pxpt = &px_statistic_data[op->cpuid]; + struct pm_px *pxpt = px_statistic_data[op->cpuid]; if ( !pxpt || !pxpt->u.pt || !pxpt->u.trans_pt ) return -ENODATA; Index: xen-3.3.1-testing/xen/arch/x86/platform_hypercall.c =================================================================== --- xen-3.3.1-testing.orig/xen/arch/x86/platform_hypercall.c +++ xen-3.3.1-testing/xen/arch/x86/platform_hypercall.c @@ -364,8 +364,19 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe ret = -EINVAL; break; } - pmpt = &processor_pminfo[cpuid]; - pxpt = &processor_pminfo[cpuid].perf; + pmpt = processor_pminfo[cpuid]; + if ( !pmpt ) + { + pmpt = xmalloc(struct processor_pminfo); + if ( !pmpt ) + { + ret = -ENOMEM; + break; + } + memset(pmpt, 0, sizeof(*pmpt)); + processor_pminfo[cpuid] = pmpt; + } + pxpt = &pmpt->perf; pmpt->acpi_id = xenpmpt->id; pmpt->id = cpuid; Index: xen-3.3.1-testing/xen/include/acpi/cpufreq/processor_perf.h =================================================================== --- xen-3.3.1-testing.orig/xen/include/acpi/cpufreq/processor_perf.h +++ xen-3.3.1-testing/xen/include/acpi/cpufreq/processor_perf.h @@ -44,7 +44,7 @@ struct processor_pminfo { struct processor_performance perf; }; -extern struct processor_pminfo processor_pminfo[NR_CPUS]; +extern struct processor_pminfo *processor_pminfo[NR_CPUS]; struct px_stat { uint8_t total; /* total Px states */ @@ -61,6 +61,6 @@ struct pm_px { uint64_t prev_idle_wall; }; -extern struct pm_px px_statistic_data[NR_CPUS]; +extern struct pm_px *px_statistic_data[NR_CPUS]; #endif /* __XEN_PROCESSOR_PM_H__ */