提交 5c14d4a7 编写于 作者: C chenjiajun 提交者: Yang Yingliang

cpuidle: fix kabi broken in cpuidle_device and cpuidle_driver

euleros inclusion
category: feature
bugzilla: https://bugzilla.openeuler.org/show_bug.cgi?id=34
CVE: NA

Since we add poll_limit_ns in struct cpuidle_device,
governor in struct cpuidle_driver which broken the kabi.
So we wrapper to fix kabi broken.
Signed-off-by: NJiajun Chen <chenjiajun8@huawei.com>
Reviewed-by: NXie XiuQi <xiexiuqi@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 a74a2ab8
...@@ -22,7 +22,7 @@ static bool force __read_mostly; ...@@ -22,7 +22,7 @@ static bool force __read_mostly;
module_param(force, bool, 0444); module_param(force, bool, 0444);
MODULE_PARM_DESC(force, "Load unconditionally"); MODULE_PARM_DESC(force, "Load unconditionally");
static struct cpuidle_device __percpu *haltpoll_cpuidle_devices; static struct cpuidle_device_wrapper __percpu *haltpoll_cpuidle_dev_wrap;
static enum cpuhp_state haltpoll_hp_state; static enum cpuhp_state haltpoll_hp_state;
static int default_enter_idle(struct cpuidle_device *dev, static int default_enter_idle(struct cpuidle_device *dev,
...@@ -36,29 +36,34 @@ static int default_enter_idle(struct cpuidle_device *dev, ...@@ -36,29 +36,34 @@ static int default_enter_idle(struct cpuidle_device *dev,
return index; return index;
} }
static struct cpuidle_driver haltpoll_driver = { static struct cpuidle_driver_wrapper haltpoll_driver_wrapper = {
.name = "haltpoll", .drv = {
.governor = "haltpoll", .name = "haltpoll",
.states = { .states = {
{ /* entry 0 is for polling */ }, { /* entry 0 is for polling */ },
{ {
.enter = default_enter_idle, .enter = default_enter_idle,
.exit_latency = 1, .exit_latency = 1,
.target_residency = 1, .target_residency = 1,
.power_usage = -1, .power_usage = -1,
.name = "haltpoll idle", .name = "haltpoll idle",
.desc = "default architecture idle", .desc =
"default architecture idle",
},
}, },
.safe_state_index = 0,
.state_count = 2,
}, },
.safe_state_index = 0, .governor = "haltpoll",
.state_count = 2,
}; };
static int haltpoll_cpu_online(unsigned int cpu) static int haltpoll_cpu_online(unsigned int cpu)
{ {
struct cpuidle_device *dev; struct cpuidle_device *dev;
struct cpuidle_device_wrapper *devw;
dev = per_cpu_ptr(haltpoll_cpuidle_devices, cpu); devw = per_cpu_ptr(haltpoll_cpuidle_dev_wrap, cpu);
dev = &(devw->dev);
if (!dev->registered) { if (!dev->registered) {
dev->cpu = cpu; dev->cpu = cpu;
if (cpuidle_register_device(dev)) { if (cpuidle_register_device(dev)) {
...@@ -74,8 +79,10 @@ static int haltpoll_cpu_online(unsigned int cpu) ...@@ -74,8 +79,10 @@ static int haltpoll_cpu_online(unsigned int cpu)
static int haltpoll_cpu_offline(unsigned int cpu) static int haltpoll_cpu_offline(unsigned int cpu)
{ {
struct cpuidle_device *dev; struct cpuidle_device *dev;
struct cpuidle_device_wrapper *devw;
dev = per_cpu_ptr(haltpoll_cpuidle_devices, cpu); devw = per_cpu_ptr(haltpoll_cpuidle_dev_wrap, cpu);
dev = &(devw->dev);
if (dev->registered) { if (dev->registered) {
arch_haltpoll_disable(cpu); arch_haltpoll_disable(cpu);
cpuidle_unregister_device(dev); cpuidle_unregister_device(dev);
...@@ -88,10 +95,10 @@ static void haltpoll_uninit(void) ...@@ -88,10 +95,10 @@ static void haltpoll_uninit(void)
{ {
if (haltpoll_hp_state) if (haltpoll_hp_state)
cpuhp_remove_state(haltpoll_hp_state); cpuhp_remove_state(haltpoll_hp_state);
cpuidle_unregister_driver(&haltpoll_driver); cpuidle_unregister_driver(&(haltpoll_driver_wrapper.drv));
free_percpu(haltpoll_cpuidle_devices); free_percpu(haltpoll_cpuidle_dev_wrap);
haltpoll_cpuidle_devices = NULL; haltpoll_cpuidle_dev_wrap = NULL;
} }
static bool haltpoll_want(void) static bool haltpoll_want(void)
...@@ -102,7 +109,7 @@ static bool haltpoll_want(void) ...@@ -102,7 +109,7 @@ static bool haltpoll_want(void)
static int __init haltpoll_init(void) static int __init haltpoll_init(void)
{ {
int ret; int ret;
struct cpuidle_driver *drv = &haltpoll_driver; struct cpuidle_driver *drv = &(haltpoll_driver_wrapper.drv);
cpuidle_poll_state_init(drv); cpuidle_poll_state_init(drv);
...@@ -113,8 +120,8 @@ static int __init haltpoll_init(void) ...@@ -113,8 +120,8 @@ static int __init haltpoll_init(void)
if (ret < 0) if (ret < 0)
return ret; return ret;
haltpoll_cpuidle_devices = alloc_percpu(struct cpuidle_device); haltpoll_cpuidle_dev_wrap = alloc_percpu(struct cpuidle_device_wrapper);
if (haltpoll_cpuidle_devices == NULL) { if (haltpoll_cpuidle_dev_wrap == NULL) {
cpuidle_unregister_driver(drv); cpuidle_unregister_driver(drv);
return -ENOMEM; return -ENOMEM;
} }
......
...@@ -330,11 +330,13 @@ void cpuidle_reflect(struct cpuidle_device *dev, int index) ...@@ -330,11 +330,13 @@ void cpuidle_reflect(struct cpuidle_device *dev, int index)
u64 cpuidle_poll_time(struct cpuidle_driver *drv, u64 cpuidle_poll_time(struct cpuidle_driver *drv,
struct cpuidle_device *dev) struct cpuidle_device *dev)
{ {
struct cpuidle_device_wrapper *devw =
container_of(dev, struct cpuidle_device_wrapper, dev);
int i; int i;
u64 limit_ns; u64 limit_ns;
if (dev->poll_limit_ns) if (devw->poll_limit_ns)
return dev->poll_limit_ns; return devw->poll_limit_ns;
limit_ns = TICK_NSEC; limit_ns = TICK_NSEC;
for (i = 1; i < drv->state_count; i++) { for (i = 1; i < drv->state_count; i++) {
...@@ -346,9 +348,9 @@ u64 cpuidle_poll_time(struct cpuidle_driver *drv, ...@@ -346,9 +348,9 @@ u64 cpuidle_poll_time(struct cpuidle_driver *drv,
break; break;
} }
dev->poll_limit_ns = limit_ns; devw->poll_limit_ns = limit_ns;
return dev->poll_limit_ns; return devw->poll_limit_ns;
} }
/** /**
......
...@@ -254,16 +254,18 @@ static void __cpuidle_unregister_driver(struct cpuidle_driver *drv) ...@@ -254,16 +254,18 @@ static void __cpuidle_unregister_driver(struct cpuidle_driver *drv)
int cpuidle_register_driver(struct cpuidle_driver *drv) int cpuidle_register_driver(struct cpuidle_driver *drv)
{ {
struct cpuidle_governor *gov; struct cpuidle_governor *gov;
struct cpuidle_driver_wrapper *drvw;
int ret; int ret;
spin_lock(&cpuidle_driver_lock); spin_lock(&cpuidle_driver_lock);
ret = __cpuidle_register_driver(drv); ret = __cpuidle_register_driver(drv);
spin_unlock(&cpuidle_driver_lock); spin_unlock(&cpuidle_driver_lock);
drvw = container_of(drv, struct cpuidle_driver_wrapper, drv);
if (!ret && !strlen(param_governor) && drv->governor && if (!ret && !strlen(param_governor) && drvw->governor &&
(cpuidle_get_driver() == drv)) { (cpuidle_get_driver() == drv)) {
mutex_lock(&cpuidle_lock); mutex_lock(&cpuidle_lock);
gov = cpuidle_find_governor(drv->governor); gov = cpuidle_find_governor(drvw->governor);
if (gov) { if (gov) {
cpuidle_prev_governor = cpuidle_curr_governor; cpuidle_prev_governor = cpuidle_curr_governor;
if (cpuidle_switch_governor(gov) < 0) if (cpuidle_switch_governor(gov) < 0)
......
...@@ -53,6 +53,8 @@ static int haltpoll_select(struct cpuidle_driver *drv, ...@@ -53,6 +53,8 @@ static int haltpoll_select(struct cpuidle_driver *drv,
struct cpuidle_device *dev, struct cpuidle_device *dev,
bool *stop_tick) bool *stop_tick)
{ {
struct cpuidle_device_wrapper *devw =
container_of(dev, struct cpuidle_device_wrapper, dev);
int latency_req = cpuidle_governor_latency_req(dev->cpu); int latency_req = cpuidle_governor_latency_req(dev->cpu);
if (!drv->state_count || latency_req == 0) { if (!drv->state_count || latency_req == 0) {
...@@ -60,11 +62,11 @@ static int haltpoll_select(struct cpuidle_driver *drv, ...@@ -60,11 +62,11 @@ static int haltpoll_select(struct cpuidle_driver *drv,
return 0; return 0;
} }
if (dev->poll_limit_ns == 0) if (devw->poll_limit_ns == 0)
return 1; return 1;
/* Last state was poll? */ /* Last state was poll? */
if (dev->last_state_idx == 0) { if (devw->last_state_idx == 0) {
/* Halt if no event occurred on poll window */ /* Halt if no event occurred on poll window */
if (dev->poll_time_limit == true) if (dev->poll_time_limit == true)
return 1; return 1;
...@@ -81,31 +83,33 @@ static int haltpoll_select(struct cpuidle_driver *drv, ...@@ -81,31 +83,33 @@ static int haltpoll_select(struct cpuidle_driver *drv,
static void adjust_poll_limit(struct cpuidle_device *dev, unsigned int block_us) static void adjust_poll_limit(struct cpuidle_device *dev, unsigned int block_us)
{ {
struct cpuidle_device_wrapper *devw =
container_of(dev, struct cpuidle_device_wrapper, dev);
unsigned int val; unsigned int val;
u64 block_ns = block_us*NSEC_PER_USEC; u64 block_ns = block_us*NSEC_PER_USEC;
/* Grow cpu_halt_poll_us if /* Grow cpu_halt_poll_us if
* cpu_halt_poll_us < block_ns < guest_halt_poll_us * cpu_halt_poll_us < block_ns < guest_halt_poll_us
*/ */
if (block_ns > dev->poll_limit_ns && block_ns <= guest_halt_poll_ns) { if (block_ns > devw->poll_limit_ns && block_ns <= guest_halt_poll_ns) {
val = dev->poll_limit_ns * guest_halt_poll_grow; val = devw->poll_limit_ns * guest_halt_poll_grow;
if (val < guest_halt_poll_grow_start) if (val < guest_halt_poll_grow_start)
val = guest_halt_poll_grow_start; val = guest_halt_poll_grow_start;
if (val > guest_halt_poll_ns) if (val > guest_halt_poll_ns)
val = guest_halt_poll_ns; val = guest_halt_poll_ns;
dev->poll_limit_ns = val; devw->poll_limit_ns = val;
} else if (block_ns > guest_halt_poll_ns && } else if (block_ns > guest_halt_poll_ns &&
guest_halt_poll_allow_shrink) { guest_halt_poll_allow_shrink) {
unsigned int shrink = guest_halt_poll_shrink; unsigned int shrink = guest_halt_poll_shrink;
val = dev->poll_limit_ns; val = devw->poll_limit_ns;
if (shrink == 0) if (shrink == 0)
val = 0; val = 0;
else else
val /= shrink; val /= shrink;
dev->poll_limit_ns = val; devw->poll_limit_ns = val;
} }
} }
...@@ -116,7 +120,9 @@ static void adjust_poll_limit(struct cpuidle_device *dev, unsigned int block_us) ...@@ -116,7 +120,9 @@ static void adjust_poll_limit(struct cpuidle_device *dev, unsigned int block_us)
*/ */
static void haltpoll_reflect(struct cpuidle_device *dev, int index) static void haltpoll_reflect(struct cpuidle_device *dev, int index)
{ {
dev->last_state_idx = index; struct cpuidle_device_wrapper *devw =
container_of(dev, struct cpuidle_device_wrapper, dev);
devw->last_state_idx = index;
if (index != 0) if (index != 0)
adjust_poll_limit(dev, dev->last_residency); adjust_poll_limit(dev, dev->last_residency);
...@@ -130,7 +136,10 @@ static void haltpoll_reflect(struct cpuidle_device *dev, int index) ...@@ -130,7 +136,10 @@ static void haltpoll_reflect(struct cpuidle_device *dev, int index)
static int haltpoll_enable_device(struct cpuidle_driver *drv, static int haltpoll_enable_device(struct cpuidle_driver *drv,
struct cpuidle_device *dev) struct cpuidle_device *dev)
{ {
dev->poll_limit_ns = 0; struct cpuidle_device_wrapper *devw =
container_of(dev, struct cpuidle_device_wrapper, dev);
devw->poll_limit_ns = 0;
return 0; return 0;
} }
......
...@@ -38,6 +38,7 @@ struct ladder_device_state { ...@@ -38,6 +38,7 @@ struct ladder_device_state {
struct ladder_device { struct ladder_device {
struct ladder_device_state states[CPUIDLE_STATE_MAX]; struct ladder_device_state states[CPUIDLE_STATE_MAX];
int last_state_idx;
}; };
static DEFINE_PER_CPU(struct ladder_device, ladder_devices); static DEFINE_PER_CPU(struct ladder_device, ladder_devices);
...@@ -48,13 +49,12 @@ static DEFINE_PER_CPU(struct ladder_device, ladder_devices); ...@@ -48,13 +49,12 @@ static DEFINE_PER_CPU(struct ladder_device, ladder_devices);
* @old_idx: the current state index * @old_idx: the current state index
* @new_idx: the new target state index * @new_idx: the new target state index
*/ */
static inline void ladder_do_selection(struct cpuidle_device *dev, static inline void ladder_do_selection(struct ladder_device *ldev,
struct ladder_device *ldev,
int old_idx, int new_idx) int old_idx, int new_idx)
{ {
ldev->states[old_idx].stats.promotion_count = 0; ldev->states[old_idx].stats.promotion_count = 0;
ldev->states[old_idx].stats.demotion_count = 0; ldev->states[old_idx].stats.demotion_count = 0;
dev->last_state_idx = new_idx; ldev->last_state_idx = new_idx;
} }
/** /**
...@@ -68,13 +68,13 @@ static int ladder_select_state(struct cpuidle_driver *drv, ...@@ -68,13 +68,13 @@ static int ladder_select_state(struct cpuidle_driver *drv,
{ {
struct ladder_device *ldev = this_cpu_ptr(&ladder_devices); struct ladder_device *ldev = this_cpu_ptr(&ladder_devices);
struct ladder_device_state *last_state; struct ladder_device_state *last_state;
int last_residency, last_idx = dev->last_state_idx; int last_residency, last_idx = ldev->last_state_idx;
int first_idx = drv->states[0].flags & CPUIDLE_FLAG_POLLING ? 1 : 0; int first_idx = drv->states[0].flags & CPUIDLE_FLAG_POLLING ? 1 : 0;
int latency_req = cpuidle_governor_latency_req(dev->cpu); int latency_req = cpuidle_governor_latency_req(dev->cpu);
/* Special case when user has set very strict latency requirement */ /* Special case when user has set very strict latency requirement */
if (unlikely(latency_req == 0)) { if (unlikely(latency_req == 0)) {
ladder_do_selection(dev, ldev, last_idx, 0); ladder_do_selection(ldev, last_idx, 0);
return 0; return 0;
} }
...@@ -91,7 +91,7 @@ static int ladder_select_state(struct cpuidle_driver *drv, ...@@ -91,7 +91,7 @@ static int ladder_select_state(struct cpuidle_driver *drv,
last_state->stats.promotion_count++; last_state->stats.promotion_count++;
last_state->stats.demotion_count = 0; last_state->stats.demotion_count = 0;
if (last_state->stats.promotion_count >= last_state->threshold.promotion_count) { if (last_state->stats.promotion_count >= last_state->threshold.promotion_count) {
ladder_do_selection(dev, ldev, last_idx, last_idx + 1); ladder_do_selection(ldev, last_idx, last_idx + 1);
return last_idx + 1; return last_idx + 1;
} }
} }
...@@ -107,7 +107,7 @@ static int ladder_select_state(struct cpuidle_driver *drv, ...@@ -107,7 +107,7 @@ static int ladder_select_state(struct cpuidle_driver *drv,
if (drv->states[i].exit_latency <= latency_req) if (drv->states[i].exit_latency <= latency_req)
break; break;
} }
ladder_do_selection(dev, ldev, last_idx, i); ladder_do_selection(ldev, last_idx, i);
return i; return i;
} }
...@@ -116,7 +116,7 @@ static int ladder_select_state(struct cpuidle_driver *drv, ...@@ -116,7 +116,7 @@ static int ladder_select_state(struct cpuidle_driver *drv,
last_state->stats.demotion_count++; last_state->stats.demotion_count++;
last_state->stats.promotion_count = 0; last_state->stats.promotion_count = 0;
if (last_state->stats.demotion_count >= last_state->threshold.demotion_count) { if (last_state->stats.demotion_count >= last_state->threshold.demotion_count) {
ladder_do_selection(dev, ldev, last_idx, last_idx - 1); ladder_do_selection(ldev, last_idx, last_idx - 1);
return last_idx - 1; return last_idx - 1;
} }
} }
...@@ -139,7 +139,7 @@ static int ladder_enable_device(struct cpuidle_driver *drv, ...@@ -139,7 +139,7 @@ static int ladder_enable_device(struct cpuidle_driver *drv,
struct ladder_device_state *lstate; struct ladder_device_state *lstate;
struct cpuidle_state *state; struct cpuidle_state *state;
dev->last_state_idx = first_idx; ldev->last_state_idx = first_idx;
for (i = first_idx; i < drv->state_count; i++) { for (i = first_idx; i < drv->state_count; i++) {
state = &drv->states[i]; state = &drv->states[i];
...@@ -167,8 +167,9 @@ static int ladder_enable_device(struct cpuidle_driver *drv, ...@@ -167,8 +167,9 @@ static int ladder_enable_device(struct cpuidle_driver *drv,
*/ */
static void ladder_reflect(struct cpuidle_device *dev, int index) static void ladder_reflect(struct cpuidle_device *dev, int index)
{ {
struct ladder_device *ldev = this_cpu_ptr(&ladder_devices);
if (index > 0) if (index > 0)
dev->last_state_idx = index; ldev->last_state_idx = index;
} }
static struct cpuidle_governor ladder_governor = { static struct cpuidle_governor ladder_governor = {
......
...@@ -119,6 +119,7 @@ ...@@ -119,6 +119,7 @@
*/ */
struct menu_device { struct menu_device {
int last_state_idx;
int needs_update; int needs_update;
int tick_wakeup; int tick_wakeup;
...@@ -464,7 +465,7 @@ static void menu_reflect(struct cpuidle_device *dev, int index) ...@@ -464,7 +465,7 @@ static void menu_reflect(struct cpuidle_device *dev, int index)
{ {
struct menu_device *data = this_cpu_ptr(&menu_devices); struct menu_device *data = this_cpu_ptr(&menu_devices);
dev->last_state_idx = index; data->last_state_idx = index;
data->needs_update = 1; data->needs_update = 1;
data->tick_wakeup = tick_nohz_idle_got_tick(); data->tick_wakeup = tick_nohz_idle_got_tick();
} }
...@@ -477,7 +478,7 @@ static void menu_reflect(struct cpuidle_device *dev, int index) ...@@ -477,7 +478,7 @@ static void menu_reflect(struct cpuidle_device *dev, int index)
static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev)
{ {
struct menu_device *data = this_cpu_ptr(&menu_devices); struct menu_device *data = this_cpu_ptr(&menu_devices);
int last_idx = dev->last_state_idx; int last_idx = data->last_state_idx;
struct cpuidle_state *target = &drv->states[last_idx]; struct cpuidle_state *target = &drv->states[last_idx];
unsigned int measured_us; unsigned int measured_us;
unsigned int new_factor; unsigned int new_factor;
......
...@@ -411,12 +411,14 @@ static ssize_t cpuidle_state_store(struct kobject *kobj, struct attribute *attr, ...@@ -411,12 +411,14 @@ static ssize_t cpuidle_state_store(struct kobject *kobj, struct attribute *attr,
struct cpuidle_state_usage *state_usage = kobj_to_state_usage(kobj); struct cpuidle_state_usage *state_usage = kobj_to_state_usage(kobj);
struct cpuidle_state_attr *cattr = attr_to_stateattr(attr); struct cpuidle_state_attr *cattr = attr_to_stateattr(attr);
struct cpuidle_device *dev = kobj_to_device(kobj); struct cpuidle_device *dev = kobj_to_device(kobj);
struct cpuidle_device_wrapper *devw =
container_of(dev, struct cpuidle_device_wrapper, dev);
if (cattr->store) if (cattr->store)
ret = cattr->store(state, state_usage, buf, size); ret = cattr->store(state, state_usage, buf, size);
/* reset poll time cache */ /* reset poll time cache */
dev->poll_limit_ns = 0; devw->poll_limit_ns = 0;
return ret; return ret;
} }
......
...@@ -84,9 +84,7 @@ struct cpuidle_device { ...@@ -84,9 +84,7 @@ struct cpuidle_device {
unsigned int poll_time_limit:1; unsigned int poll_time_limit:1;
unsigned int cpu; unsigned int cpu;
int last_state_idx;
int last_residency; int last_residency;
u64 poll_limit_ns;
struct cpuidle_state_usage states_usage[CPUIDLE_STATE_MAX]; struct cpuidle_state_usage states_usage[CPUIDLE_STATE_MAX];
struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX]; struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
struct cpuidle_driver_kobj *kobj_driver; struct cpuidle_driver_kobj *kobj_driver;
...@@ -99,6 +97,12 @@ struct cpuidle_device { ...@@ -99,6 +97,12 @@ struct cpuidle_device {
#endif #endif
}; };
struct cpuidle_device_wrapper {
struct cpuidle_device dev;
int last_state_idx;
u64 poll_limit_ns;
};
DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices); DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
DECLARE_PER_CPU(struct cpuidle_device, cpuidle_dev); DECLARE_PER_CPU(struct cpuidle_device, cpuidle_dev);
...@@ -130,9 +134,12 @@ struct cpuidle_driver { ...@@ -130,9 +134,12 @@ struct cpuidle_driver {
/* the driver handles the cpus in cpumask */ /* the driver handles the cpus in cpumask */
struct cpumask *cpumask; struct cpumask *cpumask;
};
struct cpuidle_driver_wrapper {
struct cpuidle_driver drv;
/* preferred governor to switch at register time */ /* preferred governor to switch at register time */
const char *governor; const char *governor;
}; };
#ifdef CONFIG_CPU_IDLE #ifdef CONFIG_CPU_IDLE
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册