RE: [Xen-devel] [PATCH 1/2] Xen acpi pad implement

From: Liu, Jinsong
Date: Tue Nov 06 2012 - 00:49:05 EST


Stefano Stabellini wrote:
>>> diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
>>> index 0e86370..a2af622 100644
>>> --- a/drivers/xen/Makefile
>>> +++ b/drivers/xen/Makefile
>>> @@ -29,6 +29,7 @@ obj-$(CONFIG_XEN_MCE_LOG) += mcelog.o
>>> obj-$(CONFIG_XEN_PCIDEV_BACKEND) += xen-pciback/
>>> obj-$(CONFIG_XEN_PRIVCMD) += xen-privcmd.o
>>> obj-$(CONFIG_XEN_ACPI_PROCESSOR) += xen-acpi-processor.o
>>> +obj-$(CONFIG_XEN_DOM0) += xen_acpi_pad.o
>>> xen-evtchn-y := evtchn.o
>>> xen-gntdev-y := gntdev.o
>>> xen-gntalloc-y := gntalloc.o
>
> it should really depend on ACPI and maybe also X86, otherwise it is
> going to break the ARM build
>
>

Hmm, XEN_DOM0 has already depended on ACPI and X86_LOCAL_APIC (which depends on X86_64).

Thanks,
Jinsong

>>> diff --git a/drivers/xen/xen_acpi_pad.c b/drivers/xen/xen_acpi_pad.c
>>> new file mode 100644
>>> index 0000000..e8c26a4
>>> --- /dev/null
>>> +++ b/drivers/xen/xen_acpi_pad.c
>>> @@ -0,0 +1,206 @@
>>> +/*
>>> + * xen_acpi_pad.c - Xen pad interface
>>> + *
>>> + * Copyright (c) 2012, Intel Corporation.
>>> + * Author: Liu, Jinsong <jinsong.liu@xxxxxxxxx> + *
>>> + * This program is free software; you can redistribute it and/or
>>> modify it + * under the terms and conditions of the GNU General
>>> Public License, + * version 2, as published by the Free Software
>>> Foundation. + * + * This program is distributed in the hope 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.
>>> + */ +
>>> +#include <linux/kernel.h>
>>> +#include <linux/types.h>
>>> +#include <acpi/acpi_bus.h>
>>> +#include <acpi/acpi_drivers.h>
>>> +#include <asm/xen/hypercall.h>
>>> +#include <xen/interface/version.h>
>>> +
>>> +#define ACPI_PROCESSOR_AGGREGATOR_CLASS "acpi_pad"
>>> +#define ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME "Processor
>>> Aggregator" +#define ACPI_PROCESSOR_AGGREGATOR_NOTIFY 0x80
>>> +
>>> +static DEFINE_MUTEX(xen_pad_lock);
>>> +
>>> +static int xen_pad_set_idle_cpus(int num_cpus)
>>> +{
>>> + struct xen_platform_op op;
>>> +
>>> + if (num_cpus < 0)
>>> + return -EINVAL;
>>> +
>>> + /* set cpu nums expected to be idled */
>>> + op.cmd = XENPF_core_parking;
>>> + op.u.core_parking.type = XEN_CORE_PARKING_SET;
>>> + op.u.core_parking.idle_nums = num_cpus;
>>> +
>>> + return HYPERVISOR_dom0_op(&op);
>>> +}
>>> +
>>> +/*
>>> + * Cannot get idle cpus by using hypercall once (shared with _SET)
>>> + * because of the characteristic of Xen continue_hypercall_on_cpu
>>> + */ +static int xen_pad_get_idle_cpus(void)
>>> +{
>>> + int ret;
>>> + struct xen_platform_op op;
>>> +
>>> + /* get cpu nums actually be idled */
>>> + op.cmd = XENPF_core_parking;
>>> + op.u.core_parking.type = XEN_CORE_PARKING_GET;
>>> + ret = HYPERVISOR_dom0_op(&op);
>>> + if (ret < 0)
>>> + return ret;
>>> +
>>> + return op.u.core_parking.idle_nums;
>>> +}
>>> +
>>> +/*
>>> + * Query firmware how many CPUs should be idle
>>> + * return -1 on failure
>>> + */
>>> +static int xen_acpi_pad_pur(acpi_handle handle)
>>> +{
>>> + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
>>> + union acpi_object *package;
>>> + int num = -1;
>>> +
>>> + if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PUR", NULL,
>>> &buffer))) + return num; +
>>> + if (!buffer.length || !buffer.pointer)
>>> + return num;
>>> +
>>> + package = buffer.pointer;
>>> +
>>> + if (package->type == ACPI_TYPE_PACKAGE &&
>>> + package->package.count == 2 &&
>>> + package->package.elements[0].integer.value == 1) /*
>>> rev 1 */ + + num =
>>> package->package.elements[1].integer.value; + +
>>> kfree(buffer.pointer); + return num;
>>> +}
>>> +
>>> +/* Notify firmware how many CPUs are idle */
>>> +static void xen_acpi_pad_ost(acpi_handle handle, int stat, +
>>> uint32_t idle_cpus) +{
>>> + union acpi_object params[3] = {
>>> + {.type = ACPI_TYPE_INTEGER,},
>>> + {.type = ACPI_TYPE_INTEGER,},
>>> + {.type = ACPI_TYPE_BUFFER,},
>>> + };
>>> + struct acpi_object_list arg_list = {3, params}; +
>>> + params[0].integer.value = ACPI_PROCESSOR_AGGREGATOR_NOTIFY;
>>> + params[1].integer.value = stat;
>>> + params[2].buffer.length = 4;
>>> + params[2].buffer.pointer = (void *)&idle_cpus;
>>> + acpi_evaluate_object(handle, "_OST", &arg_list, NULL); +}
>>> +
>>> +static void xen_acpi_pad_handle_notify(acpi_handle handle) +{
>>> + int num_cpus;
>>> +
>>> + num_cpus = xen_acpi_pad_pur(handle);
>>> + if (num_cpus < 0)
>>> + return;
>>> +
>>> + mutex_lock(&xen_pad_lock);
>>> + if (xen_pad_set_idle_cpus(num_cpus)) {
>>> + mutex_unlock(&xen_pad_lock);
>>> + return;
>>> + }
>>> +
>>> + num_cpus = xen_pad_get_idle_cpus();
>>> + if (num_cpus < 0) {
>>> + mutex_unlock(&xen_pad_lock);
>>> + return;
>>> + }
>>> + mutex_unlock(&xen_pad_lock);
>>> +
>>> + xen_acpi_pad_ost(handle, 0, num_cpus);
>>> +}
>>> +
>>> +static void xen_acpi_pad_notify(acpi_handle handle, u32 event, +
>>> void *data) +{
>>> + switch (event) {
>>> + case ACPI_PROCESSOR_AGGREGATOR_NOTIFY:
>>> + xen_acpi_pad_handle_notify(handle);
>>> + break;
>>> + default:
>>> + pr_warn("Unsupported event [0x%x]\n", event); +
>>> break; + }
>>> +}
>>> +
>>> +static int xen_acpi_pad_add(struct acpi_device *device) +{
>>> + acpi_status status;
>>> +
>>> + strcpy(acpi_device_name(device),
>>> ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME); +
>>> strcpy(acpi_device_class(device), ACPI_PROCESSOR_AGGREGATOR_CLASS);
>>> + + status = acpi_install_notify_handler(device->handle, +
>>> ACPI_DEVICE_NOTIFY, xen_acpi_pad_notify, device); + if
>>> (ACPI_FAILURE(status)) + return -ENODEV;
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static int xen_acpi_pad_remove(struct acpi_device *device, +
>>> int type) +{
>>> + mutex_lock(&xen_pad_lock);
>>> + xen_pad_set_idle_cpus(0);
>>> + mutex_unlock(&xen_pad_lock);
>>> +
>>> + acpi_remove_notify_handler(device->handle,
>>> + ACPI_DEVICE_NOTIFY, xen_acpi_pad_notify); +
>>> return 0; +}
>>> +
>>> +static const struct acpi_device_id pad_device_ids[] = { +
>>> {"ACPI000C", 0}, + {"", 0},
>>> +};
>>> +
>>> +static struct acpi_driver xen_acpi_pad_driver = {
>>> + .name = "processor_aggregator",
>>> + .class = ACPI_PROCESSOR_AGGREGATOR_CLASS,
>>> + .ids = pad_device_ids,
>>> + .ops = {
>>> + .add = xen_acpi_pad_add,
>>> + .remove = xen_acpi_pad_remove,
>>> + },
>>> +};
>>> +
>>> +static int __init xen_acpi_pad_init(void)
>>> +{
>>> + int ret = -ENOSYS;
>>> + unsigned int version = HYPERVISOR_xen_version(XENVER_version,
>>> NULL);
>>
>> Heh. so if you run this on baremetal I wonder what will happen.
>>
>>> + unsigned int major = version >> 16;
>>> + unsigned int minor = version & 0xffff;
>>> +
>>> + /* Only DOM0 is responsible for Xen acpi pad */
>>> + if (!xen_initial_domain())
>>> + return -ENODEV;
>>> +
>>
>> I think the check for version should happen here.
>>
>>> + /* Only Xen4.2 or later support Xen acpi pad */
>>> + if (((major == 4) && (minor >= 2)) || (major > 4))
>>> + ret = acpi_bus_register_driver(&xen_acpi_pad_driver);
>>> + + return ret;
>>> +}
>>> +subsys_initcall(xen_acpi_pad_init);
>>> diff --git a/include/xen/interface/platform.h
>>> b/include/xen/interface/platform.h index 4755b5f..a3be54c 100644
>>> --- a/include/xen/interface/platform.h +++
>>> b/include/xen/interface/platform.h @@ -324,6 +324,22 @@ struct
>>> xenpf_cpu_ol { };
>>> DEFINE_GUEST_HANDLE_STRUCT(xenpf_cpu_ol);
>>>
>>> +/*
>>> + * CMD 58 and 59 are reserved for cpu hotadd and memory hotadd,
>>> + * which are already occupied at Xen hypervisor side. + */
>>> +#define XENPF_core_parking 60
>>> +struct xenpf_core_parking {
>>> + /* IN variables */
>>> +#define XEN_CORE_PARKING_SET 1
>>> +#define XEN_CORE_PARKING_GET 2
>>> + uint32_t type;
>>> + /* IN variables: set cpu nums expected to be idled */
>>> + /* OUT variables: get cpu nums actually be idled */ +
>>> uint32_t idle_nums; +};
>>> +DEFINE_GUEST_HANDLE_STRUCT(xenpf_core_parking);
>>> +
>>> struct xen_platform_op {
>>> uint32_t cmd;
>>> uint32_t interface_version; /* XENPF_INTERFACE_VERSION */
>>> @@ -341,6 +357,7 @@ struct xen_platform_op {
>>> struct xenpf_set_processor_pminfo set_pminfo;
>>> struct xenpf_pcpuinfo pcpu_info;
>>> struct xenpf_cpu_ol cpu_ol;
>>> + struct xenpf_core_parking core_parking;
>>> uint8_t pad[128]; } u;
>>> };
>>> --
>>> 1.7.1
>>
>>
>>> _______________________________________________
>>> Xen-devel mailing list
>>> Xen-devel@xxxxxxxxxxxxx
>>> http://lists.xen.org/xen-devel
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe
>> linux-kernel" in the body of a message to majordomo@xxxxxxxxxxxxxxx
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>> Please read the FAQ at http://www.tux.org/lkml/

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/