[PATCH 2/4] acpi/cppc: Add ACPI CPPC registers

2020-02-12 Thread Ying Fang
The Continuous Performance Control Package is used to
describe the ACPI CPPC registers.

Signed-off-by: Heyi Guo 
Signed-off-by: Ying Fang 
---
 hw/arm/virt-acpi-build.c| 74 -
 hw/arm/virt.c   |  1 +
 include/hw/acpi/acpi-defs.h | 32 
 include/hw/arm/virt.h   |  1 +
 4 files changed, 106 insertions(+), 2 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index bd5f771e9b..d133bad738 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -41,6 +41,7 @@
 #include "hw/acpi/pci.h"
 #include "hw/acpi/memory_hotplug.h"
 #include "hw/acpi/generic_event_device.h"
+#include "hw/acpi/acpi-defs.h"
 #include "hw/pci/pcie_host.h"
 #include "hw/pci/pci.h"
 #include "hw/arm/virt.h"
@@ -51,7 +52,70 @@
 
 #define ARM_SPI_BASE 32
 
-static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
+
+static void acpi_dsdt_add_psd(Aml *dev, int cpus)
+{
+Aml *pkg;
+Aml *sub;
+
+sub = aml_package(5);
+aml_append(sub, aml_int(5));
+aml_append(sub, aml_int(0));
+/* Assume all vCPUs belong to the same domain */
+aml_append(sub, aml_int(0));
+/* SW_ANY: OSPM coordinate, initiate on any processor */
+aml_append(sub, aml_int(0xFD));
+aml_append(sub, aml_int(cpus));
+
+pkg = aml_package(1);
+aml_append(pkg, sub);
+
+aml_append(dev, aml_name_decl("_PSD", pkg));
+}
+
+static void acpi_dsdt_add_cppc(Aml *dev, uint64_t cpu_base)
+{
+Aml *cpc;
+int i;
+
+/* ACPI 6.3 8.4.7.1, version 3 of the CPPC table is used */
+cpc = aml_package(23);
+aml_append(cpc, aml_int(23));
+aml_append(cpc, aml_int(3));
+
+for (i = 0; i < CPPC_REG_COUNT; i++) {
+Aml *res;
+uint8_t reg_width;
+uint8_t acc_type;
+uint64_t addr;
+/* Only some necessary registers are emulated */
+if ((i >= MIN_PERF && i < REFERENCE_CTR) ||
+(i >= ENABLE && i < LOWEST_FREQ)) {
+reg_width = 0;
+acc_type = AML_ANY_ACC;
+addr = 0;
+} else {
+addr = cpu_base + i * 4;
+if (i == REFERENCE_CTR || i == DELIVERED_CTR) {
+reg_width = 64;
+acc_type = AML_QWORD_ACC;
+} else {
+reg_width = 32;
+acc_type = AML_DWORD_ACC;
+}
+}
+
+res = aml_resource_template();
+aml_append(res, aml_generic_register(AML_SYSTEM_MEMORY, reg_width, 0,
+ acc_type, addr));
+aml_append(cpc, res);
+}
+
+aml_append(dev, aml_name_decl("_CPC", cpc));
+}
+
+static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus,
+   const MemMapEntry *cppc_memmap)
 {
 uint16_t i;
 
@@ -60,6 +124,12 @@ static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
 aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0007")));
 aml_append(dev, aml_name_decl("_UID", aml_int(i)));
 aml_append(scope, dev);
+/*
+ * Append _CPC and _PSD to show CPU frequency
+ */
+acpi_dsdt_add_cppc(dev,
+   cppc_memmap->base + i * CPPC_REG_PER_CPU_STRIDE);
+acpi_dsdt_add_psd(dev, smp_cpus);
 }
 }
 
@@ -736,7 +806,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, 
VirtMachineState *vms)
  * the RTC ACPI device at all when using UEFI.
  */
 scope = aml_scope("\\_SB");
-acpi_dsdt_add_cpus(scope, vms->smp_cpus);
+acpi_dsdt_add_cpus(scope, vms->smp_cpus, [VIRT_CPUFREQ]);
 acpi_dsdt_add_uart(scope, [VIRT_UART],
(irqmap[VIRT_UART] + ARM_SPI_BASE));
 acpi_dsdt_add_flash(scope, [VIRT_FLASH]);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index f788fe27d6..ed9dc38b60 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -144,6 +144,7 @@ static const MemMapEntry base_memmap[] = {
 [VIRT_PCDIMM_ACPI] ={ 0x0907, MEMORY_HOTPLUG_IO_LEN },
 [VIRT_ACPI_GED] =   { 0x0908, ACPI_GED_EVT_SEL_LEN },
 [VIRT_MMIO] =   { 0x0a00, 0x0200 },
+[VIRT_CPUFREQ] ={ 0x0b00, 0x0001 },
 /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
 [VIRT_PLATFORM_BUS] =   { 0x0c00, 0x0200 },
 [VIRT_SECURE_MEM] = { 0x0e00, 0x0100 },
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index 57a3f58b0c..3a33f7220d 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -634,4 +634,36 @@ struct AcpiIortRC {
 } QEMU_PACKED;
 typedef struct AcpiIortRC AcpiIortRC;
 
+/*
+ * CPPC register definition from kernel header
+ * include/acpi/cppc_acpi.h
+ * The last element is newly added for easy use
+ */
+enum cppc_regs {
+HIGHEST_PERF,
+NOMINAL_PERF,
+LOW_NON_LINEAR_PERF,
+LOWEST_PERF,
+GUARANTEED_PERF,
+DESIRED_PERF,
+MIN_PERF,
+MAX_PERF,
+

[PATCH 2/4] acpi/cppc: Add ACPI CPPC registers

2020-02-12 Thread fangying1
From: Ying Fang 

The Continuous Performance Control Package is used to
describe the ACPI CPPC registers.

Signed-off-by: Heyi Guo 
Signed-off-by: Ying Fang 
---
 hw/arm/virt-acpi-build.c| 74 -
 hw/arm/virt.c   |  1 +
 include/hw/acpi/acpi-defs.h | 32 
 include/hw/arm/virt.h   |  1 +
 4 files changed, 106 insertions(+), 2 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index bd5f771e9b..d133bad738 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -41,6 +41,7 @@
 #include "hw/acpi/pci.h"
 #include "hw/acpi/memory_hotplug.h"
 #include "hw/acpi/generic_event_device.h"
+#include "hw/acpi/acpi-defs.h"
 #include "hw/pci/pcie_host.h"
 #include "hw/pci/pci.h"
 #include "hw/arm/virt.h"
@@ -51,7 +52,70 @@
 
 #define ARM_SPI_BASE 32
 
-static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
+
+static void acpi_dsdt_add_psd(Aml *dev, int cpus)
+{
+Aml *pkg;
+Aml *sub;
+
+sub = aml_package(5);
+aml_append(sub, aml_int(5));
+aml_append(sub, aml_int(0));
+/* Assume all vCPUs belong to the same domain */
+aml_append(sub, aml_int(0));
+/* SW_ANY: OSPM coordinate, initiate on any processor */
+aml_append(sub, aml_int(0xFD));
+aml_append(sub, aml_int(cpus));
+
+pkg = aml_package(1);
+aml_append(pkg, sub);
+
+aml_append(dev, aml_name_decl("_PSD", pkg));
+}
+
+static void acpi_dsdt_add_cppc(Aml *dev, uint64_t cpu_base)
+{
+Aml *cpc;
+int i;
+
+/* ACPI 6.3 8.4.7.1, version 3 of the CPPC table is used */
+cpc = aml_package(23);
+aml_append(cpc, aml_int(23));
+aml_append(cpc, aml_int(3));
+
+for (i = 0; i < CPPC_REG_COUNT; i++) {
+Aml *res;
+uint8_t reg_width;
+uint8_t acc_type;
+uint64_t addr;
+/* Only some necessary registers are emulated */
+if ((i >= MIN_PERF && i < REFERENCE_CTR) ||
+(i >= ENABLE && i < LOWEST_FREQ)) {
+reg_width = 0;
+acc_type = AML_ANY_ACC;
+addr = 0;
+} else {
+addr = cpu_base + i * 4;
+if (i == REFERENCE_CTR || i == DELIVERED_CTR) {
+reg_width = 64;
+acc_type = AML_QWORD_ACC;
+} else {
+reg_width = 32;
+acc_type = AML_DWORD_ACC;
+}
+}
+
+res = aml_resource_template();
+aml_append(res, aml_generic_register(AML_SYSTEM_MEMORY, reg_width, 0,
+ acc_type, addr));
+aml_append(cpc, res);
+}
+
+aml_append(dev, aml_name_decl("_CPC", cpc));
+}
+
+static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus,
+   const MemMapEntry *cppc_memmap)
 {
 uint16_t i;
 
@@ -60,6 +124,12 @@ static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
 aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0007")));
 aml_append(dev, aml_name_decl("_UID", aml_int(i)));
 aml_append(scope, dev);
+/*
+ * Append _CPC and _PSD to show CPU frequency
+ */
+acpi_dsdt_add_cppc(dev,
+   cppc_memmap->base + i * CPPC_REG_PER_CPU_STRIDE);
+acpi_dsdt_add_psd(dev, smp_cpus);
 }
 }
 
@@ -736,7 +806,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, 
VirtMachineState *vms)
  * the RTC ACPI device at all when using UEFI.
  */
 scope = aml_scope("\\_SB");
-acpi_dsdt_add_cpus(scope, vms->smp_cpus);
+acpi_dsdt_add_cpus(scope, vms->smp_cpus, [VIRT_CPUFREQ]);
 acpi_dsdt_add_uart(scope, [VIRT_UART],
(irqmap[VIRT_UART] + ARM_SPI_BASE));
 acpi_dsdt_add_flash(scope, [VIRT_FLASH]);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index f788fe27d6..ed9dc38b60 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -144,6 +144,7 @@ static const MemMapEntry base_memmap[] = {
 [VIRT_PCDIMM_ACPI] ={ 0x0907, MEMORY_HOTPLUG_IO_LEN },
 [VIRT_ACPI_GED] =   { 0x0908, ACPI_GED_EVT_SEL_LEN },
 [VIRT_MMIO] =   { 0x0a00, 0x0200 },
+[VIRT_CPUFREQ] ={ 0x0b00, 0x0001 },
 /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
 [VIRT_PLATFORM_BUS] =   { 0x0c00, 0x0200 },
 [VIRT_SECURE_MEM] = { 0x0e00, 0x0100 },
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index 57a3f58b0c..3a33f7220d 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -634,4 +634,36 @@ struct AcpiIortRC {
 } QEMU_PACKED;
 typedef struct AcpiIortRC AcpiIortRC;
 
+/*
+ * CPPC register definition from kernel header
+ * include/acpi/cppc_acpi.h
+ * The last element is newly added for easy use
+ */
+enum cppc_regs {
+HIGHEST_PERF,
+NOMINAL_PERF,
+LOW_NON_LINEAR_PERF,
+LOWEST_PERF,
+GUARANTEED_PERF,
+DESIRED_PERF,
+MIN_PERF,
+MAX_PERF,
+