Get ACPI Px from dom0 and choose Px controller

Add platform op hypercall case to get ACPI Px info from dom0.
Chose Px controller from dom0 (cpufreq=dom0-kernel)
or hypervisor (cpufreq=xen).

Signed-off-by: Liu Jinsong <jinsong.liu@intel.com>
This commit is contained in:
Keir Fraser committed 2008-05-14 13:50:46 +01:00
1 parent a295f2a1c6
commit 2fa7bee0a0
11 files changed
+228 -9

No files matched your search

+2
View File
@@ -1,2 +1,4 @@
subdir-y += cpufreq
obj-y += boot.o
obj-y += power.o suspend.o wakeup_prot.o cpu_idle.o
+1 -1
View File
@@ -834,7 +834,7 @@ static int set_cx(struct acpi_processor_power *acpi_power,
return 0;
}
static int get_cpu_id(u8 acpi_id)
int get_cpu_id(u8 acpi_id)
{
int i;
u8 apic_id;
+1
View File
@@ -0,0 +1 @@
obj-y += cpufreq.o
+52
View File
@@ -0,0 +1,52 @@
/*
* cpufreq.c - ACPI Processor P-States Driver ($Revision: 1.4 $)
*
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
* Copyright (C) 2002 - 2004 Dominik Brodowski <linux@brodo.de>
* Copyright (C) 2006 Denis Sadykov <denis.m.sadykov@intel.com>
*
* Feb 2008 - Liu Jinsong <jinsong.liu@intel.com>
* porting acpi-cpufreq.c from Linux 2.6.23 to Xen hypervisor
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* 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 <xen/types.h>
#include <xen/errno.h>
#include <xen/delay.h>
#include <xen/cpumask.h>
#include <xen/timer.h>
#include <xen/xmalloc.h>
#include <asm/bug.h>
#include <asm/msr.h>
#include <asm/io.h>
#include <asm/config.h>
#include <asm/processor.h>
#include <asm/percpu.h>
#include <asm/cpufeature.h>
#include <acpi/acpi.h>
#include <acpi/cpufreq/processor_perf.h>
struct processor_pminfo processor_pminfo[NR_CPUS];
int acpi_cpufreq_init(void)
{
return 0;
}
+62 -2
View File
@@ -21,6 +21,7 @@
#include <xen/acpi.h>
#include <asm/current.h>
#include <public/platform.h>
#include <acpi/cpufreq/processor_perf.h>
#include <asm/edd.h>
#include <asm/mtrr.h>
#include "cpu/mtrr/mtrr.h"
@@ -346,9 +347,68 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
switch ( op->u.set_pminfo.type )
{
case XEN_PM_PX:
ret = -EINVAL;
{
static int cpu_count = 0;
struct xenpf_set_processor_pminfo *xenpmpt = &op->u.set_pminfo;
struct xen_processor_performance *xenpxpt = &op->u.set_pminfo.perf;
int cpuid = get_cpu_id(xenpmpt->id);
struct processor_pminfo *pmpt;
struct processor_performance *pxpt;
if ( cpuid < 0 )
{
ret = -EINVAL;
break;
}
pmpt = &processor_pminfo[cpuid];
pxpt = &processor_pminfo[cpuid].perf;
pmpt->acpi_id = xenpmpt->id;
pmpt->id = cpuid;
if ( xenpxpt->flags & XEN_PX_PCT )
{
memcpy ((void *)&pxpt->control_register,
(void *)&xenpxpt->control_register,
sizeof(struct xen_pct_register));
memcpy ((void *)&pxpt->status_register,
(void *)&xenpxpt->status_register,
sizeof(struct xen_pct_register));
}
if ( xenpxpt->flags & XEN_PX_PSS )
{
if ( !(pxpt->states = xmalloc_array(struct xen_processor_px,
xenpxpt->state_count)) )
{
ret = -ENOMEM;
break;
}
if ( copy_from_compat(pxpt->states, xenpxpt->states,
xenpxpt->state_count) )
{
xfree(pxpt->states);
ret = -EFAULT;
break;
}
pxpt->state_count = xenpxpt->state_count;
}
if ( xenpxpt->flags & XEN_PX_PSD )
{
pxpt->shared_type = xenpxpt->shared_type;
memcpy ((void *)&pxpt->domain_info,
(void *)&xenpxpt->domain_info,
sizeof(struct xen_psd_package));
}
if ( xenpxpt->flags & XEN_PX_PPC )
pxpt->ppc = xenpxpt->ppc;
if ( xenpxpt->flags == ( XEN_PX_PCT | XEN_PX_PSS |
XEN_PX_PSD | XEN_PX_PPC ) )
cpu_count++;
if ( cpu_count == num_online_cpus() )
ret = acpi_cpufreq_init();
break;
}
case XEN_PM_CX:
ret = set_cx_pminfo(op->u.set_pminfo.id, &op->u.set_pminfo.power);
break;
+12 -5
View File
@@ -95,9 +95,9 @@ extern int skip_ioapic_setup;
boolean_param("noapic", skip_ioapic_setup);
/* **** Linux config option: propagated to domain0. */
/* xen_processor_pm: xen control cstate. */
static int xen_processor_pm;
boolean_param("xen_processor_pm", xen_processor_pm);
/* xen_cpuidle: xen control cstate. */
static int xen_cpuidle;
boolean_param("cpuidle", xen_cpuidle);
int early_boot = 1;
@@ -988,6 +988,7 @@ void __init __start_xen(unsigned long mbi_p)
if ( (cmdline != NULL) || (kextra != NULL) )
{
static char dom0_cmdline[MAX_GUEST_CMDLINE];
char xen_pm_param[32];
cmdline = cmdline_cook(cmdline);
safe_strcpy(dom0_cmdline, cmdline);
@@ -1012,8 +1013,14 @@ void __init __start_xen(unsigned long mbi_p)
safe_strcat(dom0_cmdline, " acpi=");
safe_strcat(dom0_cmdline, acpi_param);
}
if ( xen_processor_pm && !strstr(dom0_cmdline, "xen_processor_pmbits=") )
safe_strcat(dom0_cmdline, " xen_processor_pmbits=1");
if ( xen_cpuidle )
xen_processor_pmbits |= XEN_PROCESSOR_PM_CX;
snprintf(xen_pm_param, sizeof(xen_pm_param),
" xen_processor_pmbits=%d", xen_processor_pmbits);
if ( !strstr(dom0_cmdline, "xen_processor_pmbits=") )
safe_strcat(dom0_cmdline, xen_pm_param);
cmdline = dom0_cmdline;
}
+6
View File
@@ -11,6 +11,12 @@ DEFINE_XEN_GUEST_HANDLE(compat_platform_op_t);
#define xen_platform_op_t compat_platform_op_t
#define do_platform_op(x) compat_platform_op(_##x)
#define xen_processor_px compat_processor_px
#define xen_processor_px_t compat_processor_px_t
#define xen_processor_performance compat_processor_performance
#define xen_processor_performance_t compat_processor_performance_t
#define xenpf_set_processor_pminfo compat_pf_set_processor_pminfo
#define xen_processor_power compat_processor_power
#define xen_processor_power_t compat_processor_power_t
#define set_cx_pminfo compat_set_cx_pminfo
+10
View File
@@ -30,6 +30,10 @@
#include <public/vcpu.h>
#include <xsm/xsm.h>
/* Linux config option: propageted to domain0 */
/* xen_processor_pmbits: xen control Cx, Px, ... */
unsigned int xen_processor_pmbits = 0;
/* opt_dom0_vcpus_pin: If true, dom0 VCPUs are pinned. */
static unsigned int opt_dom0_vcpus_pin;
boolean_param("dom0_vcpus_pin", opt_dom0_vcpus_pin);
@@ -39,9 +43,15 @@ static void __init setup_cpufreq_option(char *str)
{
if ( !strcmp(str, "dom0-kernel") )
{
xen_processor_pmbits &= ~XEN_PROCESSOR_PM_PX;
cpufreq_controller = FREQCTL_dom0_kernel;
opt_dom0_vcpus_pin = 1;
}
else if ( !strcmp(str, "xen") )
{
xen_processor_pmbits |= XEN_PROCESSOR_PM_PX;
cpufreq_controller = FREQCTL_none;
}
}
custom_param("cpufreq", setup_cpufreq_option);
+30
View File
@@ -0,0 +1,30 @@
#ifndef __XEN_PROCESSOR_PM_H__
#define __XEN_PROCESSOR_PM_H__
#include <public/platform.h>
int get_cpu_id(u8);
int acpi_cpufreq_init(void);
struct processor_performance {
uint32_t state;
uint32_t ppc;
struct xen_pct_register control_register;
struct xen_pct_register status_register;
uint32_t state_count;
struct xen_processor_px *states;
struct xen_psd_package domain_info;
cpumask_t shared_cpu_map;
uint32_t shared_type;
};
struct processor_pminfo {
uint32_t acpi_id;
uint32_t id;
uint32_t flag;
struct processor_performance perf;
};
extern struct processor_pminfo processor_pminfo[NR_CPUS];
#endif /* __XEN_PROCESSOR_PM_H__ */
+50 -1
View File
@@ -211,6 +211,12 @@ DEFINE_XEN_GUEST_HANDLE(xenpf_getidletime_t);
#define XEN_PM_PX 1
#define XEN_PM_TX 2
/* Px sub info type */
#define XEN_PX_PCT 1
#define XEN_PX_PSS 2
#define XEN_PX_PPC 4
#define XEN_PX_PSD 8
struct xen_power_register {
uint32_t space_id;
uint32_t bit_width;
@@ -252,12 +258,55 @@ struct xen_processor_power {
XEN_GUEST_HANDLE(xen_processor_cx_t) states; /* supported c states */
};
struct xen_pct_register {
uint8_t descriptor;
uint16_t length;
uint8_t space_id;
uint8_t bit_width;
uint8_t bit_offset;
uint8_t reserved;
uint64_t address;
};
struct xen_processor_px {
uint64_t core_frequency; /* megahertz */
uint64_t power; /* milliWatts */
uint64_t transition_latency; /* microseconds */
uint64_t bus_master_latency; /* microseconds */
uint64_t control; /* control value */
uint64_t status; /* success indicator */
};
typedef struct xen_processor_px xen_processor_px_t;
DEFINE_XEN_GUEST_HANDLE(xen_processor_px_t);
struct xen_psd_package {
uint64_t num_entries;
uint64_t revision;
uint64_t domain;
uint64_t coord_type;
uint64_t num_processors;
};
struct xen_processor_performance {
uint32_t flags; /* flag for Px sub info type */
uint32_t ppc; /* Platform limitation on freq usage */
struct xen_pct_register control_register;
struct xen_pct_register status_register;
uint32_t state_count; /* total available performance states */
XEN_GUEST_HANDLE(xen_processor_px_t) states;
struct xen_psd_package domain_info;
uint32_t shared_type; /* coordination type of this processor */
};
typedef struct xen_processor_performance xen_processor_performance_t;
DEFINE_XEN_GUEST_HANDLE(xen_processor_performance_t);
struct xenpf_set_processor_pminfo {
/* IN variables */
uint32_t id; /* ACPI CPU ID */
uint32_t type; /* {XEN_PM_CX, ...} */
uint32_t type; /* {XEN_PM_CX, XEN_PM_PX} */
union {
struct xen_processor_power power;/* Cx: _CST/_CSD */
struct xen_processor_performance perf; /* Px: _PPC/_PCT/_PSS/_PSD */
};
};
typedef struct xenpf_set_processor_pminfo xenpf_set_processor_pminfo_t;
+2
View File
@@ -57,4 +57,6 @@ void arch_dump_domain_info(struct domain *d);
int arch_vcpu_reset(struct vcpu *v);
extern unsigned int xen_processor_pmbits;
#endif /* __XEN_DOMAIN_H__ */
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.