mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
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:
1 parent
a295f2a1c6
commit
2fa7bee0a0
11 files changed
+228
-9
No files matched your search
@@ -1,2 +1,4 @@
|
||||
subdir-y += cpufreq
|
||||
|
||||
obj-y += boot.o
|
||||
obj-y += power.o suspend.o wakeup_prot.o cpu_idle.o
|
||||
@@ -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;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
obj-y += cpufreq.o
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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__ */
|
||||
@@ -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;
|
||||
|
||||
@@ -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__ */
|
||||