dm: add _CPC to guest ACPI pm tables

The optional object _CPC declares an interface that allows OSPM to
transition the processor into a performance state based on a continuous
range of allowable values.

It is associated with HWP on intel CPUs. Although Linux intel_pstate driver
can have its performance managing abilities without _CPC, it may still
need this _CPC table to implement some features such as providing the kernel
multi-core scheduler with core priority info.

As currently we are giving guests a vHWP interface for the multi-core
scheduler, this patch adds _CPC to the guest ACPI. _CPC is written only
when the hypervisor decides the guest should have vHWP, using the
existing pm hypercall ACRN_PMCMD_GET_PX_CNT. The idea is:
- If the VM supports vHWP, then the guest is having continuous p-state.
  Thus it doesn't have a specific px_cnt. The hypercall returns success
  and px_cnt = 0.
- If the VM's p-state is hidden or hv doesn't have its p-state info,
  the hypercall returns fail.

Tracked-On: #8414
Signed-off-by: Wu Zhou <wu.zhou@intel.com>
Reviewed-by: Jian Jun Chen <jian.jun.chen@intel.com>
This commit is contained in:
Wu Zhou 2023-02-15 02:58:36 -08:00 committed by acrnsi-robot
parent c5d019b836
commit 8c38cd5734
1 changed files with 71 additions and 8 deletions

View File

@ -22,15 +22,15 @@ static inline int get_vcpu_pm_info(struct vmctx *ctx, int vcpu_id,
return vm_get_cpu_state(ctx, pm_info);
}
static inline uint8_t get_vcpu_px_cnt(struct vmctx *ctx, int vcpu_id)
static inline int get_vcpu_px_cnt(struct vmctx *ctx, int vcpu_id, uint8_t *px_cnt)
{
uint64_t px_cnt;
uint64_t px_cnt_u64;
int ret;
if (get_vcpu_pm_info(ctx, vcpu_id, ACRN_PMCMD_GET_PX_CNT, &px_cnt)) {
return 0;
}
ret = get_vcpu_pm_info(ctx, vcpu_id, ACRN_PMCMD_GET_PX_CNT, &px_cnt_u64);
*px_cnt = (uint8_t)px_cnt_u64;
return (uint8_t)px_cnt;
return ret;
}
uint8_t get_vcpu_cx_cnt(struct vmctx *ctx, int vcpu_id)
@ -259,9 +259,13 @@ static int dsdt_write_pss(struct vmctx *ctx, int vcpu_id)
uint8_t vcpu_px_cnt;
int i;
struct acrn_pstate_data *vcpu_px_data;
int ret;
vcpu_px_cnt = get_vcpu_px_cnt(ctx, vcpu_id);
if (!vcpu_px_cnt) {
ret = get_vcpu_px_cnt(ctx, vcpu_id, &vcpu_px_cnt);
/* vcpu_px_cnt = 0 Indicates vcpu supports continuous pstate.
* Then we should write _CPC instate of _PSS
*/
if (ret || !vcpu_px_cnt) {
return -1;
}
@ -316,10 +320,49 @@ static int dsdt_write_pss(struct vmctx *ctx, int vcpu_id)
return 0;
}
/* _CPC: Continuous Performance Control
* Hard code a V3 CPC table, describing HWP register interface.
*/
static void dsdt_write_cpc(void)
{
dsdt_line("");
dsdt_line(" Method (_CPC, 0, NotSerialized)");
dsdt_line(" {");
dsdt_line(" Return (Package (0x17)");
dsdt_line(" {");
dsdt_line(" 0x17,");
dsdt_line(" 0x03,");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x00, 0x0000000000000771, 0x04, )},");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x08, 0x00000000000000CE, 0x04, )},");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x10, 0x0000000000000771, 0x04, )},");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x18, 0x0000000000000771, 0x04, )},");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x08, 0x0000000000000771, 0x04, )},");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x10, 0x0000000000000774, 0x04, )},");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x00, 0x0000000000000774, 0x04, )},");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x08, 0x0000000000000774, 0x04, )},");
dsdt_line(" ResourceTemplate() {Register(SystemMemory, 0x00, 0x00, 0x0000000000000000, , )},");
dsdt_line(" ResourceTemplate() {Register(SystemMemory, 0x00, 0x00, 0x0000000000000000, , )},");
dsdt_line(" ResourceTemplate() {Register(SystemMemory, 0x00, 0x00, 0x0000000000000000, , )},");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x40, 0x00, 0x00000000000000E7, 0x04, )},");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x40, 0x00, 0x00000000000000E8, 0x04, )},");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x02, 0x01, 0x0000000000000777, 0x04, )},");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x01, 0x00, 0x0000000000000770, 0x04, )},");
dsdt_line(" One,");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x0A, 0x20, 0x0000000000000774, 0x04, )},");
dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x18, 0x0000000000000774, 0x04, )},");
dsdt_line(" Zero,");
dsdt_line(" Zero,");
dsdt_line(" Zero");
dsdt_line(" })");
dsdt_line(" }");
}
void pm_write_dsdt(struct vmctx *ctx, int ncpu)
{
int i;
int ret;
bool is_cpc = false;
uint8_t px_cnt;
/* Scope (_PR) */
dsdt_line("");
@ -364,6 +407,26 @@ void pm_write_dsdt(struct vmctx *ctx, int ncpu)
}
}
ret = get_vcpu_px_cnt(ctx, i, &px_cnt);
if (ret == 0 && px_cnt == 0) {
/* px_cnt = 0 Indicates vcpu supports continuous pstate.
* Then we can write _CPC
*/
is_cpc = true;
}
if (is_cpc) {
if (i == 0) {
dsdt_write_cpc();
} else {
dsdt_line(" Method (_CPC, 0, NotSerialized)");
dsdt_line(" {");
dsdt_line(" Return (^^PR00._CPC)");
dsdt_line(" }");
dsdt_line("");
}
}
dsdt_line(" }");
}
}