IA64: add ia64 cpufreq notify hypercall This patch adds ia64 notify hypercall to pass cpufreq ACPI information to hypervisor, and get cpufreq statistic data from hypervisor. Signed-off-by: Yu Ke Signed-off-by: Liu Jinsong diff -r fc1b82ca1e6a arch/ia64/kernel/Makefile --- a/arch/ia64/kernel/Makefile Mon Sep 29 10:07:48 2008 +0100 +++ b/arch/ia64/kernel/Makefile Thu Oct 02 16:43:42 2008 +0900 @@ -16,6 +16,9 @@ ifneq ($(CONFIG_ACPI_PROCESSOR),) obj-y += acpi-processor.o +ifneq ($(CONFIG_PROCESSOR_EXTERNAL_CONTROL),) +obj-$(CONFIG_XEN) += processor_extcntl_xen.o +endif endif obj-$(CONFIG_IA64_PALINFO) += palinfo.o diff -r fc1b82ca1e6a arch/ia64/kernel/processor_extcntl_xen.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arch/ia64/kernel/processor_extcntl_xen.c Thu Oct 02 16:43:42 2008 +0900 @@ -0,0 +1,164 @@ +/* + * processor_extcntl_xen.c - interface to notify Xen + * + * Copyright (C) 2008, Intel corporation + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int xen_cx_notifier(struct acpi_processor *pr, int action) +{ + printk(KERN_WARNING "Cx is not supported yet\n"); + + return -EINVAL; +} + +static int xen_px_notifier(struct acpi_processor *pr, int action) +{ + int ret = -EINVAL; + xen_platform_op_t op = { + .cmd = XENPF_set_processor_pminfo, + .interface_version = XENPF_INTERFACE_VERSION, + .u.set_pminfo.id = pr->acpi_id, + .u.set_pminfo.type = XEN_PM_PX, + }; + struct xen_processor_performance *perf; + struct xen_processor_px *states = NULL; + struct acpi_processor_performance *px; + struct acpi_psd_package *pdomain; + struct xencomm_handle *states_desc; + + if (!pr || !pr->performance) + return -EINVAL; + + perf = &op.u.set_pminfo.perf; + px = pr->performance; + + switch(action) { + case PROCESSOR_PM_CHANGE: + /* ppc dynamic handle */ + perf->flags = XEN_PX_PPC; + perf->platform_limit = pr->performance_platform_limit; + + ret = HYPERVISOR_platform_op(&op); + break; + + case PROCESSOR_PM_INIT: + /* px normal init */ + perf->flags = XEN_PX_PPC | + XEN_PX_PCT | + XEN_PX_PSS | + XEN_PX_PSD; + + /* ppc */ + perf->platform_limit = pr->performance_platform_limit; + + /* pct */ + xen_convert_pct_reg(&perf->control_register, + &px->control_register); + xen_convert_pct_reg(&perf->status_register, + &px->status_register); + + /* pss */ + perf->state_count = px->state_count; + states = kzalloc( + px->state_count * sizeof(xen_processor_px_t), + GFP_KERNEL); + if (!states){ + ret = -ENOMEM; + break; + } + xen_convert_pss_states(states, px->states, + px->state_count); + set_xen_guest_handle(perf->states, states); + states_desc = xencomm_map_no_alloc( + xen_guest_handle(perf->states), + sizeof(*xen_guest_handle(perf->states))); + set_xen_guest_handle(perf->states, + (xen_processor_px_t*)states_desc); + + /* psd */ + pdomain = &px->domain_info; + xen_convert_psd_pack(&perf->domain_info, pdomain); + if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ALL) + perf->shared_type = CPUFREQ_SHARED_TYPE_ALL; + else if (pdomain->coord_type == + DOMAIN_COORD_TYPE_SW_ANY) + perf->shared_type = CPUFREQ_SHARED_TYPE_ANY; + else if (pdomain->coord_type == + DOMAIN_COORD_TYPE_HW_ALL) + perf->shared_type = CPUFREQ_SHARED_TYPE_HW; + else { + ret = -ENODEV; + kfree(states); + break; + } + + ret = HYPERVISOR_platform_op(&op); + kfree(states); + break; + + default: + ret = -EINVAL; + } + + return ret; +} + +static int xen_tx_notifier(struct acpi_processor *pr, int action) +{ + return -EINVAL; +} +static int xen_hotplug_notifier(struct acpi_processor *pr, int event) +{ + return -EINVAL; +} + +static struct processor_extcntl_ops xen_extcntl_ops = { + .hotplug = xen_hotplug_notifier, +}; + +void arch_acpi_processor_init_extcntl(const struct processor_extcntl_ops **ops) +{ + unsigned int pmbits = (xen_start_info->flags & SIF_PM_MASK) >> 8; + + if (!pmbits) + return; + + if (pmbits & XEN_PROCESSOR_PM_CX) + xen_extcntl_ops.pm_ops[PM_TYPE_IDLE] = xen_cx_notifier; + if (pmbits & XEN_PROCESSOR_PM_PX) + xen_extcntl_ops.pm_ops[PM_TYPE_PERF] = xen_px_notifier; + if (pmbits & XEN_PROCESSOR_PM_TX) + xen_extcntl_ops.pm_ops[PM_TYPE_THR] = xen_tx_notifier; + + *ops = &xen_extcntl_ops; +} +EXPORT_SYMBOL(arch_acpi_processor_init_extcntl); diff -r fc1b82ca1e6a arch/ia64/xen/xcom_hcall.c --- a/arch/ia64/xen/xcom_hcall.c Mon Sep 29 10:07:48 2008 +0100 +++ b/arch/ia64/xen/xcom_hcall.c Thu Oct 02 16:43:42 2008 +0900 @@ -284,6 +284,15 @@ return xencomm_arch_hypercall_sched_op(cmd, desc); } EXPORT_SYMBOL_GPL(xencomm_hypercall_sched_op); + +int xencomm_hypercall_platform_op(struct xen_platform_op *arg) +{ + return xencomm_arch_hypercall_platform_op( + xencomm_map_no_alloc(arg, + sizeof(struct xen_platform_op)) + ); +} +EXPORT_SYMBOL_GPL(xencomm_hypercall_platform_op); int xencomm_hypercall_multicall(void *call_list, int nr_calls) diff -r fc1b82ca1e6a arch/ia64/xen/xcom_privcmd.c --- a/arch/ia64/xen/xcom_privcmd.c Mon Sep 29 10:07:48 2008 +0100 +++ b/arch/ia64/xen/xcom_privcmd.c Thu Oct 02 16:43:42 2008 +0900 @@ -193,6 +193,31 @@ set_xen_guest_handle(kern_op.u.physinfo.cpu_to_node, (void *)desc); break; + + case XEN_SYSCTL_get_pmstat: + if (kern_op.u.get_pmstat.type == PMSTAT_get_pxstat) { + struct pm_px_stat *getpx = + &kern_op.u.get_pmstat.u.getpx; + desc = xencomm_map( + xen_guest_handle(getpx->trans_pt), + getpx->total * getpx->total * + sizeof(uint64_t)); + if (xen_guest_handle(getpx->trans_pt) != NULL && + getpx->total > 0 && desc == NULL) + return -ENOMEM; + + set_xen_guest_handle(getpx->trans_pt, (void *)desc); + + desc1 = xencomm_map(xen_guest_handle(getpx->pt), + getpx->total * sizeof(pm_px_val_t)); + if (xen_guest_handle(getpx->pt) != NULL && + getpx->total > 0 && desc1 == NULL) + return -ENOMEM; + + set_xen_guest_handle(getpx->pt, (void *)desc1); + } + break; + default: printk("%s: unknown sysctl cmd %d\n", __func__, kern_op.cmd); return -ENOSYS; diff -r fc1b82ca1e6a drivers/acpi/Kconfig --- a/drivers/acpi/Kconfig Mon Sep 29 10:07:48 2008 +0100 +++ b/drivers/acpi/Kconfig Thu Oct 02 16:43:42 2008 +0900 @@ -370,7 +370,7 @@ config PROCESSOR_EXTERNAL_CONTROL bool - depends on X86 && XEN + depends on (X86 || IA64) && XEN default y endif # ACPI diff -r fc1b82ca1e6a include/asm-ia64/hypercall.h --- a/include/asm-ia64/hypercall.h Mon Sep 29 10:07:48 2008 +0100 +++ b/include/asm-ia64/hypercall.h Thu Oct 02 16:43:42 2008 +0900 @@ -437,6 +437,7 @@ /* Use xencomm to do hypercalls. */ #define HYPERVISOR_sched_op xencomm_hypercall_sched_op +#define HYPERVISOR_platform_op xencomm_hypercall_platform_op #define HYPERVISOR_event_channel_op xencomm_hypercall_event_channel_op #define HYPERVISOR_callback_op xencomm_hypercall_callback_op #define HYPERVISOR_multicall xencomm_hypercall_multicall diff -r fc1b82ca1e6a include/asm-ia64/xen/xcom_hcall.h --- a/include/asm-ia64/xen/xcom_hcall.h Mon Sep 29 10:07:48 2008 +0100 +++ b/include/asm-ia64/xen/xcom_hcall.h Thu Oct 02 16:43:42 2008 +0900 @@ -36,6 +36,8 @@ extern int xencomm_hypercall_sched_op(int cmd, void *arg); +extern int xencomm_hypercall_platform_op(struct xen_platform_op *arg); + extern int xencomm_hypercall_multicall(void *call_list, int nr_calls); extern int xencomm_hypercall_callback_op(int cmd, void *arg);