From 71d9d375b82be4c5c336831042bc7401b9ed0e07 Mon Sep 17 00:00:00 2001 From: Yongcong Du Date: Sat, 4 Aug 2012 22:12:40 +0800 Subject: [PATCH] cpuidle: move generic cpuidle to generic After this change, low level cpuidle drivers load the generic cpuidle module if they can support the underlying platform. change the intel cpuidle driver accordingly, now it's loaded by acpi bus manager during boot, although it doesn't depend on acpi Signed-off-by: Fredrik Holmqvist --- headers/os/drivers/cpuidle.h | 15 +- src/add-ons/kernel/Jamfile | 1 - src/add-ons/kernel/drivers/power/Jamfile | 1 + .../kernel/drivers/power/x86_cpuidle/Jamfile | 10 + .../power/x86_cpuidle/acpi_cpuidle.cpp | 181 ++++++++++++++++++ .../power/x86_cpuidle/intel_cpuidle.cpp | 125 ++++++++++++ .../drivers/power/x86_cpuidle/x86_cpuidle.h | 27 +++ src/add-ons/kernel/generic/Jamfile | 1 + src/add-ons/kernel/generic/cpuidle/Jamfile | 7 + .../kernel/generic/cpuidle/cpuidle.cpp | 105 ++++++++++ src/add-ons/kernel/idle/Jamfile | 4 - src/add-ons/kernel/idle/cpuidles/Jamfile | 3 - .../idle/cpuidles/intel_cpuidle/Jamfile | 7 - .../cpuidles/intel_cpuidle/intel_cpuidle.cpp | 157 --------------- src/add-ons/kernel/idle/generic/Jamfile | 7 - src/add-ons/kernel/idle/generic/cpuidle.cpp | 146 -------------- 16 files changed, 463 insertions(+), 334 deletions(-) create mode 100644 src/add-ons/kernel/drivers/power/x86_cpuidle/Jamfile create mode 100644 src/add-ons/kernel/drivers/power/x86_cpuidle/acpi_cpuidle.cpp create mode 100644 src/add-ons/kernel/drivers/power/x86_cpuidle/intel_cpuidle.cpp create mode 100644 src/add-ons/kernel/drivers/power/x86_cpuidle/x86_cpuidle.h create mode 100644 src/add-ons/kernel/generic/cpuidle/Jamfile create mode 100644 src/add-ons/kernel/generic/cpuidle/cpuidle.cpp delete mode 100644 src/add-ons/kernel/idle/Jamfile delete mode 100644 src/add-ons/kernel/idle/cpuidles/Jamfile delete mode 100644 src/add-ons/kernel/idle/cpuidles/intel_cpuidle/Jamfile delete mode 100644 src/add-ons/kernel/idle/cpuidles/intel_cpuidle/intel_cpuidle.cpp delete mode 100644 src/add-ons/kernel/idle/generic/Jamfile delete mode 100644 src/add-ons/kernel/idle/generic/cpuidle.cpp diff --git a/headers/os/drivers/cpuidle.h b/headers/os/drivers/cpuidle.h index ed79be9622..7649cdadab 100644 --- a/headers/os/drivers/cpuidle.h +++ b/headers/os/drivers/cpuidle.h @@ -14,7 +14,7 @@ extern "C" { #define CPUIDLE_CSTATE_MAX 8 #define CSTATE_NAME_LENGTH 32 -#define B_CPUIDLE_MODULE_NAME "idle/generic/cpuidle/v1" +#define B_CPUIDLE_MODULE_NAME "generic/cpuidle/v1" struct CpuidleStat { @@ -28,28 +28,25 @@ struct CpuidleInfo { CpuidleStat stats[CPUIDLE_CSTATE_MAX]; }; +struct CpuidleDevice; struct CpuidleCstate { char name[CSTATE_NAME_LENGTH]; int32 latency; - int32 (*EnterIdle)(int32 state, CpuidleCstate *cstate); + int32 (*EnterIdle)(int32 state, CpuidleDevice *device); void *pData; }; -struct CpuidleModuleInfo { - module_info info; +struct CpuidleDevice { CpuidleCstate cStates[CPUIDLE_CSTATE_MAX]; int32 cStateCount; }; -struct GenCpuidle { +struct CpuidleModuleInfo { module_info info; - int32 (*GetIdleStateCount)(void); - char * (*GetIdleStateName)(int32 state); - void (*GetIdleStateInfo)(int32 cpu, int32 state, - CpuidleStat *stat); + status_t (*AddDevice)(CpuidleDevice *device); }; diff --git a/src/add-ons/kernel/Jamfile b/src/add-ons/kernel/Jamfile index 03f57867b9..5a5b275cb3 100644 --- a/src/add-ons/kernel/Jamfile +++ b/src/add-ons/kernel/Jamfile @@ -8,7 +8,6 @@ SubInclude HAIKU_TOP src add-ons kernel debugger ; SubInclude HAIKU_TOP src add-ons kernel drivers ; SubInclude HAIKU_TOP src add-ons kernel file_cache ; SubInclude HAIKU_TOP src add-ons kernel file_systems ; -SubInclude HAIKU_TOP src add-ons kernel idle ; SubInclude HAIKU_TOP src add-ons kernel interrupt_controllers ; SubInclude HAIKU_TOP src add-ons kernel network ; SubInclude HAIKU_TOP src add-ons kernel media ; diff --git a/src/add-ons/kernel/drivers/power/Jamfile b/src/add-ons/kernel/drivers/power/Jamfile index 56d91431ba..45feced8e9 100644 --- a/src/add-ons/kernel/drivers/power/Jamfile +++ b/src/add-ons/kernel/drivers/power/Jamfile @@ -5,3 +5,4 @@ SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_button ; SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_lid ; SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_thermal ; SubInclude HAIKU_TOP src add-ons kernel drivers power enhanced_speedstep ; +SubInclude HAIKU_TOP src add-ons kernel drivers power x86_cpuidle ; diff --git a/src/add-ons/kernel/drivers/power/x86_cpuidle/Jamfile b/src/add-ons/kernel/drivers/power/x86_cpuidle/Jamfile new file mode 100644 index 0000000000..51612506a6 --- /dev/null +++ b/src/add-ons/kernel/drivers/power/x86_cpuidle/Jamfile @@ -0,0 +1,10 @@ +SubDir HAIKU_TOP src add-ons kernel drivers power x86_cpuidle ; + +UsePrivateKernelHeaders ; + +KernelAddon x86_cpuidle : + acpi_cpuidle.cpp + intel_cpuidle.cpp + ; + +Depends x86_cpuidle : acpi ; diff --git a/src/add-ons/kernel/drivers/power/x86_cpuidle/acpi_cpuidle.cpp b/src/add-ons/kernel/drivers/power/x86_cpuidle/acpi_cpuidle.cpp new file mode 100644 index 0000000000..8064d506e0 --- /dev/null +++ b/src/add-ons/kernel/drivers/power/x86_cpuidle/acpi_cpuidle.cpp @@ -0,0 +1,181 @@ +/* + * Copyright 2012, Haiku, Inc. All Rights Reserved. + * + * Distributed under the terms of the MIT License. + * + * Authors: + * Yongcong Du + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "x86_cpuidle.h" + +#define ACPI_CPUIDLE_MODULE_NAME "drivers/power/x86_cpuidle/acpi/driver_v1" + +struct acpi_cpuidle_driver_info { + device_node *node; + acpi_device_module_info *acpi; + acpi_device acpi_cookie; +}; + +static device_manager_info *sDeviceManager; +static acpi_cpuidle_driver_info *acpi_processor[B_MAX_CPU_COUNT]; + + +static status_t +acpi_cpuidle_init(void) +{ + dprintf("acpi_cpuidle_init\n"); + + return B_ERROR; +} + + +static status_t +acpi_processor_init(acpi_cpuidle_driver_info *device) +{ + status_t status = B_ERROR; + + acpi_data buffer; + buffer.pointer = NULL; + buffer.length = ACPI_ALLOCATE_BUFFER; + dprintf("get acpi processor @%p\n", device->acpi_cookie); + status = device->acpi->evaluate_method(device->acpi_cookie, NULL, NULL, + &buffer); + if (status != B_OK) { + dprintf("failed to get processor obj\n"); + return B_IO_ERROR; + } + acpi_object_type *object = (acpi_object_type *)buffer.pointer; + dprintf("acpi cpu%"B_PRId32": P_BLK at %#x/%lu\n", + object->data.processor.cpu_id, + object->data.processor.pblk_address, + object->data.processor.pblk_length); + int32 cpuid = object->data.processor.cpu_id; + free(buffer.pointer); + if (cpuid > smp_get_num_cpus()) + return B_ERROR; + + if (smp_get_num_cpus() == 1) + cpuid = 1; + + acpi_processor[cpuid-1] = device; + + if (cpuid == 1) { + if (intel_cpuidle_init() != B_OK) + return acpi_cpuidle_init(); + } + + return B_OK; +} + + +static float +acpi_cpuidle_support(device_node *parent) +{ + const char *bus; + uint32 device_type; + + dprintf("acpi_cpuidle_support\n"); + // make sure parent is really the ACPI bus manager + if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)) + return -1; + + if (strcmp(bus, "acpi")) + return 0.0; + + // check whether it's really a cpu Device + if (sDeviceManager->get_attr_uint32(parent, ACPI_DEVICE_TYPE_ITEM, &device_type, false) != B_OK + || device_type != ACPI_TYPE_PROCESSOR) { + return 0.0; + } + + return 0.6; +} + + +static status_t +acpi_cpuidle_register_device(device_node *node) +{ + device_attr attrs[] = { + { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { string: "ACPI CPU IDLE" }}, + { NULL } + }; + + dprintf("acpi_cpuidle_register_device\n"); + return sDeviceManager->register_node(node, ACPI_CPUIDLE_MODULE_NAME, attrs, + NULL, NULL); +} + + +static status_t +acpi_cpuidle_init_driver(device_node *node, void **driverCookie) +{ + dprintf("acpi_cpuidle_init_driver\n"); + acpi_cpuidle_driver_info *device; + device = (acpi_cpuidle_driver_info *)calloc(1, sizeof(*device)); + if (device == NULL) + return B_NO_MEMORY; + + *driverCookie = device; + + device->node = node; + + device_node *parent; + parent = sDeviceManager->get_parent_node(node); + sDeviceManager->get_driver(parent, (driver_module_info **)&device->acpi, + (void **)&device->acpi_cookie); + sDeviceManager->put_node(parent); + + return acpi_processor_init(device); +} + + +static void +acpi_cpuidle_uninit_driver(void *driverCookie) +{ + dprintf("acpi_cpuidle_uninit_driver"); + acpi_cpuidle_driver_info *device = (acpi_cpuidle_driver_info *)driverCookie; + free(device); +} + + +module_dependency module_dependencies[] = { + { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&sDeviceManager }, + {} +}; + + +static driver_module_info sAcpiidleModule = { + { + ACPI_CPUIDLE_MODULE_NAME, + 0, + NULL + }, + + acpi_cpuidle_support, + acpi_cpuidle_register_device, + acpi_cpuidle_init_driver, + acpi_cpuidle_uninit_driver, + NULL, + NULL, // rescan + NULL, // removed +}; + + +module_info *modules[] = { + (module_info *)&sAcpiidleModule, + NULL +}; diff --git a/src/add-ons/kernel/drivers/power/x86_cpuidle/intel_cpuidle.cpp b/src/add-ons/kernel/drivers/power/x86_cpuidle/intel_cpuidle.cpp new file mode 100644 index 0000000000..1032a5d5e2 --- /dev/null +++ b/src/add-ons/kernel/drivers/power/x86_cpuidle/intel_cpuidle.cpp @@ -0,0 +1,125 @@ +/* + * Copyright 2012, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Yongcong Du + */ + +#include +#include +#include + +#include + +#include + +#include "x86_cpuidle.h" + +static CpuidleModuleInfo *sIdle; +static CpuidleDevice sIntelDevice; + +static void *kMwaitEax[] = { + // C0, we never use it + (void *)0x00, + // MWAIT C1 + (void *)0x00, + // MWAIT C2 + (void *)0x10, + // MWAIT C3 + (void *)0x20, + // MWAIT C4 + (void *)0x30, + // MWAIT C5 + (void *)0x40, + // MWAIT C6, 0x2 is used to fully shrink L2 cache + (void *)0x52 +}; + + +static int32 +IntelCstateIdleEnter(int32 state, CpuidleDevice *device) +{ + cpu_ent *cpu = get_cpu_struct(); + if (cpu->invoke_scheduler) + return 0; + + CpuidleCstate *cState = &device->cStates[state]; + x86_monitor((void *)&cpu->invoke_scheduler, 0, 0); + if (!cpu->invoke_scheduler) + x86_mwait((unsigned long)cState->pData, 1); + + return state; +} + + +static CpuidleCstate sSnbcStates[CPUIDLE_CSTATE_MAX] = { + {}, + { + "C1-SNB", + 1, + IntelCstateIdleEnter, + }, + { + "C3-SNB", + 80, + IntelCstateIdleEnter, + }, + { + "C6-SNB", + 104, + IntelCstateIdleEnter, + }, + { + "C7-SNB", + 109, + IntelCstateIdleEnter, + }, +}; + + +status_t +intel_cpuidle_init(void) +{ + dprintf("intel idle init\n"); + if (get_module(B_CPUIDLE_MODULE_NAME, (module_info**)&sIdle) != B_OK) + return B_ERROR; + cpu_ent *cpu = get_cpu_struct(); + if (cpu->arch.vendor != VENDOR_INTEL || cpu->arch.family != 6) + return B_ERROR; + + // Calculated Model Value: M = (Extended Model << 4) + Model + uint32 model = (cpu->arch.extended_model << 4) + cpu->arch.model; + if (model != 0x2a && model != 0x2d) + return B_ERROR; + + cpuid_info cpuid; + get_current_cpuid(&cpuid, 5); + /* ecx[0] monitor/mwait extension supported + * ecx[1] support for treating interrupts as break-events for mwait + * edx number of sub-states + */ + if (!((cpuid.regs.ecx & 0x1) && (cpuid.regs.ecx & 0x2) && + cpuid.regs.edx)) { + return B_ERROR; + } + + sIntelDevice.cStateCount = 1; + for (int32 i = 1; i < CPUIDLE_CSTATE_MAX; i++) { + int32 subStates = (cpuid.regs.edx >> ((i) * 4)) & 0xf; + // no sub-states means the state is not available + if (!subStates) + continue; + sIntelDevice.cStates[sIntelDevice.cStateCount] = + sSnbcStates[i]; + sIntelDevice.cStates[sIntelDevice.cStateCount].pData = + kMwaitEax[i]; + sIntelDevice.cStateCount++; + } + status_t status = sIdle->AddDevice(&sIntelDevice); + if (status == B_OK) + dprintf("using intel idle\n"); + else + put_module(B_CPUIDLE_MODULE_NAME); + return status; +} diff --git a/src/add-ons/kernel/drivers/power/x86_cpuidle/x86_cpuidle.h b/src/add-ons/kernel/drivers/power/x86_cpuidle/x86_cpuidle.h new file mode 100644 index 0000000000..b524ef19cc --- /dev/null +++ b/src/add-ons/kernel/drivers/power/x86_cpuidle/x86_cpuidle.h @@ -0,0 +1,27 @@ +/* + * Copyright 2012, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ + +#ifdef __cplusplus +extern "C" { +#endif +static inline void +x86_monitor(const void *addr, unsigned long ecx, unsigned long edx) +{ + asm volatile("monitor" + :: "a" (addr), "c" (ecx), "d"(edx)); +} + +static inline void +x86_mwait(unsigned long eax, unsigned long ecx) +{ + asm volatile("mwait" + :: "a" (eax), "c" (ecx)); +} + +status_t intel_cpuidle_init(void); + +#ifdef __cplusplus +} +#endif diff --git a/src/add-ons/kernel/generic/Jamfile b/src/add-ons/kernel/generic/Jamfile index a2a6bfc1fa..719061b0dc 100644 --- a/src/add-ons/kernel/generic/Jamfile +++ b/src/add-ons/kernel/generic/Jamfile @@ -2,6 +2,7 @@ SubDir HAIKU_TOP src add-ons kernel generic ; SubInclude HAIKU_TOP src add-ons kernel generic ata_adapter ; SubInclude HAIKU_TOP src add-ons kernel generic atomizer ; +SubInclude HAIKU_TOP src add-ons kernel generic cpuidle ; SubInclude HAIKU_TOP src add-ons kernel generic dpc ; SubInclude HAIKU_TOP src add-ons kernel generic ide_adapter ; SubInclude HAIKU_TOP src add-ons kernel generic locked_pool ; diff --git a/src/add-ons/kernel/generic/cpuidle/Jamfile b/src/add-ons/kernel/generic/cpuidle/Jamfile new file mode 100644 index 0000000000..bb7cdd2746 --- /dev/null +++ b/src/add-ons/kernel/generic/cpuidle/Jamfile @@ -0,0 +1,7 @@ +SubDir HAIKU_TOP src add-ons kernel generic cpuidle ; + +UsePrivateKernelHeaders ; + +KernelAddon cpuidle : + cpuidle.cpp + ; diff --git a/src/add-ons/kernel/generic/cpuidle/cpuidle.cpp b/src/add-ons/kernel/generic/cpuidle/cpuidle.cpp new file mode 100644 index 0000000000..cc17be8fac --- /dev/null +++ b/src/add-ons/kernel/generic/cpuidle/cpuidle.cpp @@ -0,0 +1,105 @@ +/* + * Copyright 2012, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Yongcong Du + */ + +#include +#include +#include + +#include +#include + + +static CpuidleInfo sPerCPU[B_MAX_CPU_COUNT]; +static CpuidleDevice *sDevice; +extern void (*gCpuIdleFunc)(void); + + +/* + * next cstate selection algorithm is based on NetBSD's + * it's simple, stupid + */ +static int32 +SelectCstate(CpuidleInfo *info) +{ + static const int32 csFactor = 3; + + for (int32 i = sDevice->cStateCount - 1; i > 0; i--) { + CpuidleCstate *cState = &sDevice->cStates[i]; + if (info->cstateSleep > cState->latency * csFactor) + return i; + } + + /* Choose C1 if there's no state found */ + return 1; +} + + +static inline void +EnterCstate(int32 state, CpuidleInfo *info) +{ + CpuidleCstate *cstate = &sDevice->cStates[state]; + bigtime_t now = system_time(); + int32 finalState = cstate->EnterIdle(state, sDevice); + if (finalState > 0) { + bigtime_t diff = system_time() - now; + info->cstateSleep = diff; + info->stats[finalState].usageCount++; + info->stats[finalState].usageTime += diff; + } else { + info->cstateSleep = 0; + } +} + + +static void +CpuCstateIdle(void) +{ + CpuidleInfo *info = &sPerCPU[smp_get_current_cpu()]; + int32 state = SelectCstate(info); + EnterCstate(state, info); +} + + +static status_t +std_ops(int32 op, ...) +{ + switch (op) { + case B_MODULE_INIT: + return B_OK; + case B_MODULE_UNINIT: + return B_OK; + } + + return B_ERROR; +} + + +status_t AddDevice(CpuidleDevice *device) +{ + sDevice = device; + memory_write_barrier(); + gCpuIdleFunc = CpuCstateIdle; + return B_OK; +} + + +static CpuidleModuleInfo sCpuidleModule = { + { + B_CPUIDLE_MODULE_NAME, + 0, + std_ops + }, + + AddDevice, +}; + + +module_info *modules[] = { + (module_info *)&sCpuidleModule, + NULL +}; diff --git a/src/add-ons/kernel/idle/Jamfile b/src/add-ons/kernel/idle/Jamfile deleted file mode 100644 index 878fd5cc5e..0000000000 --- a/src/add-ons/kernel/idle/Jamfile +++ /dev/null @@ -1,4 +0,0 @@ -SubDir HAIKU_TOP src add-ons kernel idle ; - -SubInclude HAIKU_TOP src add-ons kernel idle cpuidles ; -SubInclude HAIKU_TOP src add-ons kernel idle generic ; diff --git a/src/add-ons/kernel/idle/cpuidles/Jamfile b/src/add-ons/kernel/idle/cpuidles/Jamfile deleted file mode 100644 index 03a6a3c860..0000000000 --- a/src/add-ons/kernel/idle/cpuidles/Jamfile +++ /dev/null @@ -1,3 +0,0 @@ -SubDir HAIKU_TOP src add-ons kernel idle cpuidles ; - -SubInclude HAIKU_TOP src add-ons kernel idle cpuidles intel_cpuidle ; diff --git a/src/add-ons/kernel/idle/cpuidles/intel_cpuidle/Jamfile b/src/add-ons/kernel/idle/cpuidles/intel_cpuidle/Jamfile deleted file mode 100644 index 4b74f09e92..0000000000 --- a/src/add-ons/kernel/idle/cpuidles/intel_cpuidle/Jamfile +++ /dev/null @@ -1,7 +0,0 @@ -SubDir HAIKU_TOP src add-ons kernel idle cpuidles intel_cpuidle ; - -UsePrivateKernelHeaders ; - -KernelAddon intel_cpuidle : - intel_cpuidle.cpp - ; diff --git a/src/add-ons/kernel/idle/cpuidles/intel_cpuidle/intel_cpuidle.cpp b/src/add-ons/kernel/idle/cpuidles/intel_cpuidle/intel_cpuidle.cpp deleted file mode 100644 index 6265c7326a..0000000000 --- a/src/add-ons/kernel/idle/cpuidles/intel_cpuidle/intel_cpuidle.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2012, Haiku, Inc. All Rights Reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Yongcong Du - */ - -#include -#include - -#include -#include -#include - - -static status_t std_ops(int32 op, ...); - - -static inline void -x86_monitor(const void *addr, unsigned long ecx, unsigned long edx) -{ - asm volatile("monitor" - :: "a" (addr), "c" (ecx), "d"(edx)); -} - - -static inline void -x86_mwait(unsigned long eax, unsigned long ecx) -{ - asm volatile("mwait" - :: "a" (eax), "c" (ecx)); -} - - -static void *kMwaitEax[] = { - // C0, we never use it - (void *)0x00, - // MWAIT C1 - (void *)0x00, - // MWAIT C2 - (void *)0x10, - // MWAIT C3 - (void *)0x20, - // MWAIT C4 - (void *)0x30, - // MWAIT C5 - (void *)0x40, - // MWAIT C6, 0x2 is used to fully shrink L2 cache - (void *)0x52 -}; - - -static int32 -IntelCstateIdleEnter(int32 state, CpuidleCstate *cstate) -{ - cpu_ent *cpu = get_cpu_struct(); - if (cpu->invoke_scheduler) - return 0; - - x86_monitor((void *)&cpu->invoke_scheduler, 0, 0); - if (!cpu->invoke_scheduler) - x86_mwait((unsigned long)cstate->pData, 1); - - return state; -} - - -static CpuidleCstate sSnbcStates[CPUIDLE_CSTATE_MAX] = { - {}, - { - "C1-SNB", - 1, - IntelCstateIdleEnter, - }, - { - "C3-SNB", - 80, - IntelCstateIdleEnter, - }, - { - "C6-SNB", - 104, - IntelCstateIdleEnter, - }, - { - "C7-SNB", - 109, - IntelCstateIdleEnter, - }, -}; - - -static CpuidleModuleInfo sIntelidleModule = { - { - "idle/cpuidles/intel_cpuidle/v1", - 0, - std_ops - }, - -}; - - -static status_t -std_ops(int32 op, ...) -{ - switch (op) { - case B_MODULE_INIT: - { - cpu_ent *cpu = get_cpu_struct(); - if (cpu->arch.vendor != VENDOR_INTEL || cpu->arch.family != 6) - return B_ERROR; - - // Calculated Model Value: M = (Extended Model << 4) + Model - uint32 model = (cpu->arch.extended_model << 4) + cpu->arch.model; - if (model != 0x2a && model != 0x2d) - return B_ERROR; - - cpuid_info cpuid; - get_current_cpuid(&cpuid, 5); - /* ecx[0] monitor/mwait extension supported - * ecx[1] support for treating interrupts as break-events for mwait - * edx number of sub-states - */ - if (!((cpuid.regs.ecx & 0x1) && (cpuid.regs.ecx & 0x2) && - cpuid.regs.edx)) { - return B_ERROR; - } - - sIntelidleModule.cStateCount = 1; - for (int32 i = 1; i < CPUIDLE_CSTATE_MAX; i++) { - int32 subStates = (cpuid.regs.edx >> ((i) * 4)) & 0xf; - // no sub-states means the state is not available - if (!subStates) - continue; - sIntelidleModule.cStates[sIntelidleModule.cStateCount] = - sSnbcStates[i]; - sIntelidleModule.cStates[sIntelidleModule.cStateCount].pData = - kMwaitEax[i]; - sIntelidleModule.cStateCount++; - } - dprintf("intel idle init\n"); - return B_OK; - } - case B_MODULE_UNINIT: - dprintf("intel idle uninit\n"); - return B_OK; - } - - return B_ERROR; -} - - -module_info *modules[] = { - (module_info *)&sIntelidleModule, - NULL -}; diff --git a/src/add-ons/kernel/idle/generic/Jamfile b/src/add-ons/kernel/idle/generic/Jamfile deleted file mode 100644 index f7ff039052..0000000000 --- a/src/add-ons/kernel/idle/generic/Jamfile +++ /dev/null @@ -1,7 +0,0 @@ -SubDir HAIKU_TOP src add-ons kernel idle generic ; - -UsePrivateKernelHeaders ; - -KernelAddon cpuidle : - cpuidle.cpp - ; diff --git a/src/add-ons/kernel/idle/generic/cpuidle.cpp b/src/add-ons/kernel/idle/generic/cpuidle.cpp deleted file mode 100644 index 0ce9851132..0000000000 --- a/src/add-ons/kernel/idle/generic/cpuidle.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2012, Haiku, Inc. All Rights Reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Yongcong Du - */ - -#include -#include -#include - -#include -#include - - -static CpuidleInfo sPerCPU[B_MAX_CPU_COUNT]; -static CpuidleModuleInfo *sCpuidleModule; - -extern void (*gCpuIdleFunc)(void); - - -/* - * next cstate selection algorithm is based on NetBSD's - * it's simple, stupid - */ -static int32 -SelectCstate(CpuidleInfo *info) -{ - static const int32 csFactor = 3; - - for (int32 i = sCpuidleModule->cStateCount - 1; i > 0; i--) { - CpuidleCstate *cState = &sCpuidleModule->cStates[i]; - if (info->cstateSleep > cState->latency * csFactor) - return i; - } - - /* Choose C1 if there's no state found */ - return 1; -} - - -static inline void -EnterCstate(int32 state, CpuidleInfo *info) -{ - CpuidleCstate *cstate = &sCpuidleModule->cStates[state]; - bigtime_t now = system_time(); - if (cstate->EnterIdle(state, cstate) > 0) { - bigtime_t diff = system_time() - now; - info->cstateSleep = diff; - info->stats[state].usageCount++; - info->stats[state].usageTime += diff; - } else { - info->cstateSleep = 0; - } -} - - -static void -CpuCstateIdle(void) -{ - CpuidleInfo *info = &sPerCPU[smp_get_current_cpu()]; - int32 state = SelectCstate(info); - EnterCstate(state, info); -} - - -static status_t -std_ops(int32 op, ...) -{ - switch (op) { - case B_MODULE_INIT: - { - dprintf("generic cpuidle init\n"); - void *cookie = open_module_list("idle/cpuidles"); - if (cookie == NULL) - return B_ERROR; - - char name[B_FILE_NAME_LENGTH]; - size_t nameLength = sizeof(name); - - while (read_next_module_name(cookie, name, &nameLength) == B_OK) { - if (get_module(name, (module_info **)&sCpuidleModule) == B_OK) { - break; - } - } - - close_module_list(cookie); - if (sCpuidleModule->cStateCount < 3) { - dprintf("no enough available cstates, exiting...\n"); - put_module(sCpuidleModule->info.name); - return B_ERROR; - } else { - dprintf("using %s\n", sCpuidleModule->info.name); - gCpuIdleFunc = CpuCstateIdle; - return B_OK; - } - } - case B_MODULE_UNINIT: - dprintf("generic cpuidle uninit\n"); - put_module(sCpuidleModule->info.name); - return B_OK; - } - - return B_ERROR; -} - - -static char * -GetIdleStateName(int32 state) -{ - return sCpuidleModule->cStates[state].name; -} - - -static int32 -GetIdleStateCount(void) -{ - return sCpuidleModule->cStateCount; -} - - -static void -GetIdleStateInfo(int32 cpu, int32 state, CpuidleStat *stat) -{ - memcpy(stat, &sPerCPU[cpu].stats[state], sizeof(CpuidleStat)); -} - - -static GenCpuidle sModule = { - { - B_CPUIDLE_MODULE_NAME, - 0, - std_ops - }, - - GetIdleStateCount, - GetIdleStateName, - GetIdleStateInfo -}; - - -module_info *modules[] = { - (module_info *)&sModule, - NULL -};