The px/cx data is critical to support the power transition. DM will get
these data to build DSDT for UOS. With this DSDT, UOS would have the
capability on power control if acpi-cpufreq/idle driver is enabled in
kernel.
Add the PM ioctl that is used to obtain the info of power state
so that the DM can construct the DSDT with Power frequence/C-state idle
for guest system.

Co-developed-by: Jason Chen CJ <jason.cj.c...@intel.com>
Signed-off-by: Jason Chen CJ <jason.cj.c...@intel.com>
Co-developed-by: Victor Sun <victor....@intel.com>
Signed-off-by: Victor Sun <victor....@intel.com>
Signed-off-by: Zhao Yakui <yakui.z...@intel.com>
---
 drivers/staging/acrn/acrn_dev.c           | 75 +++++++++++++++++++++++++++++++
 include/uapi/linux/acrn/acrn_ioctl_defs.h | 36 +++++++++++++++
 2 files changed, 111 insertions(+)

diff --git a/drivers/staging/acrn/acrn_dev.c b/drivers/staging/acrn/acrn_dev.c
index 93f45e3..ef0ec50 100644
--- a/drivers/staging/acrn/acrn_dev.c
+++ b/drivers/staging/acrn/acrn_dev.c
@@ -432,6 +432,81 @@ long acrn_dev_ioctl(struct file *filep,
                break;
        }
 
+       case IC_PM_GET_CPU_STATE: {
+               u64 cmd;
+
+               if (copy_from_user(&cmd, (void *)ioctl_param, sizeof(cmd)))
+                       return -EFAULT;
+
+               switch (cmd & PMCMD_TYPE_MASK) {
+               case PMCMD_GET_PX_CNT:
+               case PMCMD_GET_CX_CNT: {
+                       u64 *pm_info;
+
+                       pm_info = kmalloc(sizeof(u64), GFP_KERNEL);
+                       if (!pm_info)
+                               return -ENOMEM;
+
+                       ret = hcall_get_cpu_state(cmd, virt_to_phys(pm_info));
+                       if (ret < 0) {
+                               kfree(pm_info);
+                               return -EFAULT;
+                       }
+
+                       if (copy_to_user((void *)ioctl_param,
+                                        pm_info, sizeof(u64)))
+                               ret = -EFAULT;
+
+                       kfree(pm_info);
+                       break;
+               }
+               case PMCMD_GET_PX_DATA: {
+                       struct cpu_px_data *px_data;
+
+                       px_data = kmalloc(sizeof(*px_data), GFP_KERNEL);
+                       if (!px_data)
+                               return -ENOMEM;
+
+                       ret = hcall_get_cpu_state(cmd, virt_to_phys(px_data));
+                       if (ret < 0) {
+                               kfree(px_data);
+                               return -EFAULT;
+                       }
+
+                       if (copy_to_user((void *)ioctl_param,
+                                        px_data, sizeof(*px_data)))
+                               ret = -EFAULT;
+
+                       kfree(px_data);
+                       break;
+               }
+               case PMCMD_GET_CX_DATA: {
+                       struct cpu_cx_data *cx_data;
+
+                       cx_data = kmalloc(sizeof(*cx_data), GFP_KERNEL);
+                       if (!cx_data)
+                               return -ENOMEM;
+
+                       ret = hcall_get_cpu_state(cmd, virt_to_phys(cx_data));
+                       if (ret < 0) {
+                               kfree(cx_data);
+                               return -EFAULT;
+                       }
+
+                       if (copy_to_user((void *)ioctl_param,
+                                        cx_data, sizeof(*cx_data)))
+                               ret = -EFAULT;
+                       kfree(cx_data);
+                       break;
+               }
+               default:
+                       ret = -EFAULT;
+                       break;
+               }
+
+               break;
+       }
+
        default:
                pr_warn("Unknown IOCTL 0x%x\n", ioctl_num);
                ret = -EFAULT;
diff --git a/include/uapi/linux/acrn/acrn_ioctl_defs.h 
b/include/uapi/linux/acrn/acrn_ioctl_defs.h
index c3c4f98..c762bd2 100644
--- a/include/uapi/linux/acrn/acrn_ioctl_defs.h
+++ b/include/uapi/linux/acrn/acrn_ioctl_defs.h
@@ -234,6 +234,39 @@ struct ioreq_notify {
        uint32_t vcpu;
 };
 
+struct acrn_generic_address {
+       uint8_t         space_id;
+       uint8_t         bit_width;
+       uint8_t         bit_offset;
+       uint8_t         access_size;
+       uint64_t        address;
+};
+
+struct cpu_cx_data {
+       struct acrn_generic_address cx_reg;
+       uint8_t         type;
+       uint32_t        latency;
+       uint64_t        power;
+};
+
+struct cpu_px_data {
+       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 */
+};
+
+#define PMCMD_TYPE_MASK                0x000000ff
+
+enum pm_cmd_type {
+       PMCMD_GET_PX_CNT,
+       PMCMD_GET_PX_DATA,
+       PMCMD_GET_CX_CNT,
+       PMCMD_GET_CX_DATA,
+};
+
 /*
  * Common IOCTL ID definition for DM
  */
@@ -281,4 +314,7 @@ struct ioreq_notify {
 #define IC_SET_PTDEV_INTR_INFO         _IC_ID(IC_ID, IC_ID_PCI_BASE + 0x03)
 #define IC_RESET_PTDEV_INTR_INFO       _IC_ID(IC_ID, IC_ID_PCI_BASE + 0x04)
 
+/* Power management */
+#define IC_ID_PM_BASE                   0x60UL
+#define IC_PM_GET_CPU_STATE            _IC_ID(IC_ID, IC_ID_PM_BASE + 0x00)
 #endif /* __ACRN_IOCTL_DEFS_H__ */
-- 
2.7.4

_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to