summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/bpf/verifier.c5
-rw-r--r--kernel/cgroup/cgroup.c7
-rw-r--r--kernel/cgroup/cpuset.c5
-rw-r--r--kernel/cgroup/legacy_freezer.c9
-rw-r--r--kernel/dma/pool.c27
-rw-r--r--kernel/liveupdate/kexec_handover.c37
-rw-r--r--kernel/module/kmod.c1
-rw-r--r--kernel/panic.c4
-rw-r--r--kernel/power/em_netlink.c213
-rw-r--r--kernel/power/em_netlink_autogen.c58
-rw-r--r--kernel/power/em_netlink_autogen.h22
-rw-r--r--kernel/power/energy_model.c6
-rw-r--r--kernel/printk/nbcon.c38
-rw-r--r--kernel/sched/core.c18
-rw-r--r--kernel/sched/deadline.c36
-rw-r--r--kernel/sched/ext.c1
-rw-r--r--kernel/sched/sched.h27
-rw-r--r--kernel/sched/syscalls.c32
-rw-r--r--kernel/time/hrtimer.c2
-rw-r--r--kernel/trace/ftrace.c29
-rw-r--r--kernel/watchdog.c2
21 files changed, 335 insertions, 244 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index f0ca69f888fa..3135643d5695 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -9609,6 +9609,11 @@ static int check_reg_const_str(struct bpf_verifier_env *env,
if (reg->type != PTR_TO_MAP_VALUE)
return -EINVAL;
+ if (map->map_type == BPF_MAP_TYPE_INSN_ARRAY) {
+ verbose(env, "R%d points to insn_array map which cannot be used as const string\n", regno);
+ return -EACCES;
+ }
+
if (!bpf_map_is_rdonly(map)) {
verbose(env, "R%d does not point to a readonly map'\n", regno);
return -EACCES;
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index e717208cfb18..5f0d33b04910 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Generic process-grouping system.
*
@@ -20,10 +21,6 @@
* 2003-10-22 Updates by Stephen Hemminger.
* 2004 May-July Rework by Paul Jackson.
* ---------------------------------------------------
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of the Linux
- * distribution for more details.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -5847,7 +5844,7 @@ static struct cgroup *cgroup_create(struct cgroup *parent, const char *name,
int ret;
/* allocate the cgroup and its ID, 0 is reserved for the root */
- cgrp = kzalloc(struct_size(cgrp, ancestors, (level + 1)), GFP_KERNEL);
+ cgrp = kzalloc(struct_size(cgrp, _low_ancestors, level), GFP_KERNEL);
if (!cgrp)
return ERR_PTR(-ENOMEM);
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 3e8cc34d8d50..c06e2e96f79d 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* kernel/cpuset.c
*
@@ -16,10 +17,6 @@
* 2006 Rework by Paul Menage to use generic cgroups
* 2008 Rework of the scheduler domains and CPU hotplug handling
* by Max Krasnyansky
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of the Linux
- * distribution for more details.
*/
#include "cpuset-internal.h"
diff --git a/kernel/cgroup/legacy_freezer.c b/kernel/cgroup/legacy_freezer.c
index 915b02f65980..817c33450fee 100644
--- a/kernel/cgroup/legacy_freezer.c
+++ b/kernel/cgroup/legacy_freezer.c
@@ -1,17 +1,10 @@
+// SPDX-License-Identifier: LGPL-2.1
/*
* cgroup_freezer.c - control group freezer subsystem
*
* Copyright IBM Corporation, 2007
*
* Author : Cedric Le Goater <clg@fr.ibm.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2.1 of the GNU Lesser General Public License
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <linux/export.h>
diff --git a/kernel/dma/pool.c b/kernel/dma/pool.c
index 26392badc36b..c5da29ad010c 100644
--- a/kernel/dma/pool.c
+++ b/kernel/dma/pool.c
@@ -184,6 +184,12 @@ static __init struct gen_pool *__dma_atomic_pool_init(size_t pool_size,
return pool;
}
+#ifdef CONFIG_ZONE_DMA32
+#define has_managed_dma32 has_managed_zone(ZONE_DMA32)
+#else
+#define has_managed_dma32 false
+#endif
+
static int __init dma_atomic_pool_init(void)
{
int ret = 0;
@@ -199,17 +205,20 @@ static int __init dma_atomic_pool_init(void)
}
INIT_WORK(&atomic_pool_work, atomic_pool_work_fn);
- atomic_pool_kernel = __dma_atomic_pool_init(atomic_pool_size,
+ /* All memory might be in the DMA zone(s) to begin with */
+ if (has_managed_zone(ZONE_NORMAL)) {
+ atomic_pool_kernel = __dma_atomic_pool_init(atomic_pool_size,
GFP_KERNEL);
- if (!atomic_pool_kernel)
- ret = -ENOMEM;
+ if (!atomic_pool_kernel)
+ ret = -ENOMEM;
+ }
if (has_managed_dma()) {
atomic_pool_dma = __dma_atomic_pool_init(atomic_pool_size,
GFP_KERNEL | GFP_DMA);
if (!atomic_pool_dma)
ret = -ENOMEM;
}
- if (IS_ENABLED(CONFIG_ZONE_DMA32)) {
+ if (has_managed_dma32) {
atomic_pool_dma32 = __dma_atomic_pool_init(atomic_pool_size,
GFP_KERNEL | GFP_DMA32);
if (!atomic_pool_dma32)
@@ -224,11 +233,11 @@ postcore_initcall(dma_atomic_pool_init);
static inline struct gen_pool *dma_guess_pool(struct gen_pool *prev, gfp_t gfp)
{
if (prev == NULL) {
- if (IS_ENABLED(CONFIG_ZONE_DMA32) && (gfp & GFP_DMA32))
- return atomic_pool_dma32;
- if (atomic_pool_dma && (gfp & GFP_DMA))
- return atomic_pool_dma;
- return atomic_pool_kernel;
+ if (gfp & GFP_DMA)
+ return atomic_pool_dma ?: atomic_pool_dma32 ?: atomic_pool_kernel;
+ if (gfp & GFP_DMA32)
+ return atomic_pool_dma32 ?: atomic_pool_dma ?: atomic_pool_kernel;
+ return atomic_pool_kernel ?: atomic_pool_dma32 ?: atomic_pool_dma;
}
if (prev == atomic_pool_kernel)
return atomic_pool_dma32 ? atomic_pool_dma32 : atomic_pool_dma;
diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
index 9dc51fab604f..d4482b6e3cae 100644
--- a/kernel/liveupdate/kexec_handover.c
+++ b/kernel/liveupdate/kexec_handover.c
@@ -460,27 +460,23 @@ static void __init deserialize_bitmap(unsigned int order,
}
}
-/* Return true if memory was deserizlied */
-static bool __init kho_mem_deserialize(const void *fdt)
+/* Returns physical address of the preserved memory map from FDT */
+static phys_addr_t __init kho_get_mem_map_phys(const void *fdt)
{
- struct khoser_mem_chunk *chunk;
const void *mem_ptr;
- u64 mem;
int len;
mem_ptr = fdt_getprop(fdt, 0, PROP_PRESERVED_MEMORY_MAP, &len);
if (!mem_ptr || len != sizeof(u64)) {
pr_err("failed to get preserved memory bitmaps\n");
- return false;
+ return 0;
}
- mem = get_unaligned((const u64 *)mem_ptr);
- chunk = mem ? phys_to_virt(mem) : NULL;
-
- /* No preserved physical pages were passed, no deserialization */
- if (!chunk)
- return false;
+ return get_unaligned((const u64 *)mem_ptr);
+}
+static void __init kho_mem_deserialize(struct khoser_mem_chunk *chunk)
+{
while (chunk) {
unsigned int i;
@@ -489,8 +485,6 @@ static bool __init kho_mem_deserialize(const void *fdt)
&chunk->bitmaps[i]);
chunk = KHOSER_LOAD_PTR(chunk->hdr.next);
}
-
- return true;
}
/*
@@ -1253,6 +1247,7 @@ bool kho_finalized(void)
struct kho_in {
phys_addr_t fdt_phys;
phys_addr_t scratch_phys;
+ phys_addr_t mem_map_phys;
struct kho_debugfs dbg;
};
@@ -1434,12 +1429,10 @@ static void __init kho_release_scratch(void)
void __init kho_memory_init(void)
{
- if (kho_in.scratch_phys) {
+ if (kho_in.mem_map_phys) {
kho_scratch = phys_to_virt(kho_in.scratch_phys);
kho_release_scratch();
-
- if (!kho_mem_deserialize(kho_get_fdt()))
- kho_in.fdt_phys = 0;
+ kho_mem_deserialize(phys_to_virt(kho_in.mem_map_phys));
} else {
kho_reserve_scratch();
}
@@ -1448,8 +1441,9 @@ void __init kho_memory_init(void)
void __init kho_populate(phys_addr_t fdt_phys, u64 fdt_len,
phys_addr_t scratch_phys, u64 scratch_len)
{
- void *fdt = NULL;
struct kho_scratch *scratch = NULL;
+ phys_addr_t mem_map_phys;
+ void *fdt = NULL;
int err = 0;
unsigned int scratch_cnt = scratch_len / sizeof(*kho_scratch);
@@ -1475,6 +1469,12 @@ void __init kho_populate(phys_addr_t fdt_phys, u64 fdt_len,
goto out;
}
+ mem_map_phys = kho_get_mem_map_phys(fdt);
+ if (!mem_map_phys) {
+ err = -ENOENT;
+ goto out;
+ }
+
scratch = early_memremap(scratch_phys, scratch_len);
if (!scratch) {
pr_warn("setup: failed to memremap scratch (phys=0x%llx, len=%lld)\n",
@@ -1515,6 +1515,7 @@ void __init kho_populate(phys_addr_t fdt_phys, u64 fdt_len,
kho_in.fdt_phys = fdt_phys;
kho_in.scratch_phys = scratch_phys;
+ kho_in.mem_map_phys = mem_map_phys;
kho_scratch_cnt = scratch_cnt;
pr_info("found kexec handover data.\n");
diff --git a/kernel/module/kmod.c b/kernel/module/kmod.c
index 25f253812512..a25dccdf7aa7 100644
--- a/kernel/module/kmod.c
+++ b/kernel/module/kmod.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* kmod - the kernel module loader
*
diff --git a/kernel/panic.c b/kernel/panic.c
index 0d52210a9e2b..0c20fcaae98a 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -131,7 +131,8 @@ static int proc_taint(const struct ctl_table *table, int write,
static int sysctl_panic_print_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
- panic_print_deprecated();
+ if (write)
+ panic_print_deprecated();
return proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
}
@@ -1014,7 +1015,6 @@ static int panic_print_set(const char *val, const struct kernel_param *kp)
static int panic_print_get(char *val, const struct kernel_param *kp)
{
- panic_print_deprecated();
return param_get_ulong(val, kp);
}
diff --git a/kernel/power/em_netlink.c b/kernel/power/em_netlink.c
index 4b85da138a06..5a611d3950fd 100644
--- a/kernel/power/em_netlink.c
+++ b/kernel/power/em_netlink.c
@@ -12,27 +12,35 @@
#include <linux/energy_model.h>
#include <net/sock.h>
#include <net/genetlink.h>
-#include <uapi/linux/energy_model.h>
+#include <uapi/linux/dev_energymodel.h>
#include "em_netlink.h"
#include "em_netlink_autogen.h"
-#define EM_A_PD_CPUS_LEN 256
-
/*************************** Command encoding ********************************/
+struct dump_ctx {
+ int idx;
+ int start;
+ struct sk_buff *skb;
+ struct netlink_callback *cb;
+};
+
static int __em_nl_get_pd_size(struct em_perf_domain *pd, void *data)
{
- char cpus_buf[EM_A_PD_CPUS_LEN];
+ int nr_cpus, msg_sz, cpus_sz;
int *tot_msg_sz = data;
- int msg_sz, cpus_sz;
- cpus_sz = snprintf(cpus_buf, sizeof(cpus_buf), "%*pb",
- cpumask_pr_args(to_cpumask(pd->cpus)));
+ nr_cpus = cpumask_weight(to_cpumask(pd->cpus));
+ cpus_sz = nla_total_size_64bit(sizeof(u64)) * nr_cpus;
- msg_sz = nla_total_size(0) + /* EM_A_PDS_PD */
- nla_total_size(sizeof(u32)) + /* EM_A_PD_PD_ID */
- nla_total_size_64bit(sizeof(u64)) + /* EM_A_PD_FLAGS */
- nla_total_size(cpus_sz); /* EM_A_PD_CPUS */
+ msg_sz = nla_total_size(0) +
+ /* DEV_ENERGYMODEL_A_PERF_DOMAINS_PERF_DOMAIN */
+ nla_total_size(sizeof(u32)) +
+ /* DEV_ENERGYMODEL_A_PERF_DOMAIN_PERF_DOMAIN_ID */
+ nla_total_size_64bit(sizeof(u64)) +
+ /* DEV_ENERGYMODEL_A_PERF_DOMAIN_FLAGS */
+ nla_total_size(cpus_sz);
+ /* DEV_ENERGYMODEL_A_PERF_DOMAIN_CPUS */
*tot_msg_sz += nlmsg_total_size(genlmsg_msg_size(msg_sz));
return 0;
@@ -40,56 +48,80 @@ static int __em_nl_get_pd_size(struct em_perf_domain *pd, void *data)
static int __em_nl_get_pd(struct em_perf_domain *pd, void *data)
{
- char cpus_buf[EM_A_PD_CPUS_LEN];
struct sk_buff *msg = data;
- struct nlattr *entry;
-
- entry = nla_nest_start(msg, EM_A_PDS_PD);
- if (!entry)
- goto out_cancel_nest;
+ struct cpumask *cpumask;
+ int cpu;
- if (nla_put_u32(msg, EM_A_PD_PD_ID, pd->id))
+ if (nla_put_u32(msg, DEV_ENERGYMODEL_A_PERF_DOMAIN_PERF_DOMAIN_ID,
+ pd->id))
goto out_cancel_nest;
- if (nla_put_u64_64bit(msg, EM_A_PD_FLAGS, pd->flags, EM_A_PD_PAD))
+ if (nla_put_u64_64bit(msg, DEV_ENERGYMODEL_A_PERF_DOMAIN_FLAGS,
+ pd->flags, DEV_ENERGYMODEL_A_PERF_DOMAIN_PAD))
goto out_cancel_nest;
- snprintf(cpus_buf, sizeof(cpus_buf), "%*pb",
- cpumask_pr_args(to_cpumask(pd->cpus)));
- if (nla_put_string(msg, EM_A_PD_CPUS, cpus_buf))
- goto out_cancel_nest;
-
- nla_nest_end(msg, entry);
+ cpumask = to_cpumask(pd->cpus);
+ for_each_cpu(cpu, cpumask) {
+ if (nla_put_u64_64bit(msg, DEV_ENERGYMODEL_A_PERF_DOMAIN_CPUS,
+ cpu, DEV_ENERGYMODEL_A_PERF_DOMAIN_PAD))
+ goto out_cancel_nest;
+ }
return 0;
out_cancel_nest:
- nla_nest_cancel(msg, entry);
-
return -EMSGSIZE;
}
-int em_nl_get_pds_doit(struct sk_buff *skb, struct genl_info *info)
+static int __em_nl_get_pd_for_dump(struct em_perf_domain *pd, void *data)
{
- struct sk_buff *msg;
+ const struct genl_info *info;
+ struct dump_ctx *ctx = data;
void *hdr;
+ int ret;
+
+ if (ctx->idx++ < ctx->start)
+ return 0;
+
+ info = genl_info_dump(ctx->cb);
+ hdr = genlmsg_iput(ctx->skb, info);
+ if (!hdr) {
+ genlmsg_cancel(ctx->skb, hdr);
+ return -EMSGSIZE;
+ }
+
+ ret = __em_nl_get_pd(pd, ctx->skb);
+ genlmsg_end(ctx->skb, hdr);
+ return ret;
+}
+
+int dev_energymodel_nl_get_perf_domains_doit(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ int id, ret = -EMSGSIZE, msg_sz = 0;
int cmd = info->genlhdr->cmd;
- int ret = -EMSGSIZE, msg_sz = 0;
+ struct em_perf_domain *pd;
+ struct sk_buff *msg;
+ void *hdr;
+
+ if (!info->attrs[DEV_ENERGYMODEL_A_PERF_DOMAIN_PERF_DOMAIN_ID])
+ return -EINVAL;
- for_each_em_perf_domain(__em_nl_get_pd_size, &msg_sz);
+ id = nla_get_u32(info->attrs[DEV_ENERGYMODEL_A_PERF_DOMAIN_PERF_DOMAIN_ID]);
+ pd = em_perf_domain_get_by_id(id);
+ __em_nl_get_pd_size(pd, &msg_sz);
msg = genlmsg_new(msg_sz, GFP_KERNEL);
if (!msg)
return -ENOMEM;
- hdr = genlmsg_put_reply(msg, info, &em_nl_family, 0, cmd);
+ hdr = genlmsg_put_reply(msg, info, &dev_energymodel_nl_family, 0, cmd);
if (!hdr)
goto out_free_msg;
- ret = for_each_em_perf_domain(__em_nl_get_pd, msg);
+ ret = __em_nl_get_pd(pd, msg);
if (ret)
goto out_cancel_msg;
-
genlmsg_end(msg, hdr);
return genlmsg_reply(msg, info);
@@ -98,19 +130,31 @@ out_cancel_msg:
genlmsg_cancel(msg, hdr);
out_free_msg:
nlmsg_free(msg);
-
return ret;
}
+int dev_energymodel_nl_get_perf_domains_dumpit(struct sk_buff *skb,
+ struct netlink_callback *cb)
+{
+ struct dump_ctx ctx = {
+ .idx = 0,
+ .start = cb->args[0],
+ .skb = skb,
+ .cb = cb,
+ };
+
+ return for_each_em_perf_domain(__em_nl_get_pd_for_dump, &ctx);
+}
+
static struct em_perf_domain *__em_nl_get_pd_table_id(struct nlattr **attrs)
{
struct em_perf_domain *pd;
int id;
- if (!attrs[EM_A_PD_TABLE_PD_ID])
+ if (!attrs[DEV_ENERGYMODEL_A_PERF_TABLE_PERF_DOMAIN_ID])
return NULL;
- id = nla_get_u32(attrs[EM_A_PD_TABLE_PD_ID]);
+ id = nla_get_u32(attrs[DEV_ENERGYMODEL_A_PERF_TABLE_PERF_DOMAIN_ID]);
pd = em_perf_domain_get_by_id(id);
return pd;
}
@@ -119,25 +163,34 @@ static int __em_nl_get_pd_table_size(const struct em_perf_domain *pd)
{
int id_sz, ps_sz;
- id_sz = nla_total_size(sizeof(u32)); /* EM_A_PD_TABLE_PD_ID */
- ps_sz = nla_total_size(0) + /* EM_A_PD_TABLE_PS */
- nla_total_size_64bit(sizeof(u64)) + /* EM_A_PS_PERFORMANCE */
- nla_total_size_64bit(sizeof(u64)) + /* EM_A_PS_FREQUENCY */
- nla_total_size_64bit(sizeof(u64)) + /* EM_A_PS_POWER */
- nla_total_size_64bit(sizeof(u64)) + /* EM_A_PS_COST */
- nla_total_size_64bit(sizeof(u64)); /* EM_A_PS_FLAGS */
+ id_sz = nla_total_size(sizeof(u32));
+ /* DEV_ENERGYMODEL_A_PERF_TABLE_PERF_DOMAIN_ID */
+ ps_sz = nla_total_size(0) +
+ /* DEV_ENERGYMODEL_A_PERF_TABLE_PERF_STATE */
+ nla_total_size_64bit(sizeof(u64)) +
+ /* DEV_ENERGYMODEL_A_PERF_STATE_PERFORMANCE */
+ nla_total_size_64bit(sizeof(u64)) +
+ /* DEV_ENERGYMODEL_A_PERF_STATE_FREQUENCY */
+ nla_total_size_64bit(sizeof(u64)) +
+ /* DEV_ENERGYMODEL_A_PERF_STATE_POWER */
+ nla_total_size_64bit(sizeof(u64)) +
+ /* DEV_ENERGYMODEL_A_PERF_STATE_COST */
+ nla_total_size_64bit(sizeof(u64));
+ /* DEV_ENERGYMODEL_A_PERF_STATE_FLAGS */
ps_sz *= pd->nr_perf_states;
return nlmsg_total_size(genlmsg_msg_size(id_sz + ps_sz));
}
-static int __em_nl_get_pd_table(struct sk_buff *msg, const struct em_perf_domain *pd)
+static
+int __em_nl_get_pd_table(struct sk_buff *msg, const struct em_perf_domain *pd)
{
struct em_perf_state *table, *ps;
struct nlattr *entry;
int i;
- if (nla_put_u32(msg, EM_A_PD_TABLE_PD_ID, pd->id))
+ if (nla_put_u32(msg, DEV_ENERGYMODEL_A_PERF_TABLE_PERF_DOMAIN_ID,
+ pd->id))
goto out_err;
rcu_read_lock();
@@ -146,24 +199,35 @@ static int __em_nl_get_pd_table(struct sk_buff *msg, const struct em_perf_domain
for (i = 0; i < pd->nr_perf_states; i++) {
ps = &table[i];
- entry = nla_nest_start(msg, EM_A_PD_TABLE_PS);
+ entry = nla_nest_start(msg,
+ DEV_ENERGYMODEL_A_PERF_TABLE_PERF_STATE);
if (!entry)
goto out_unlock_ps;
- if (nla_put_u64_64bit(msg, EM_A_PS_PERFORMANCE,
- ps->performance, EM_A_PS_PAD))
+ if (nla_put_u64_64bit(msg,
+ DEV_ENERGYMODEL_A_PERF_STATE_PERFORMANCE,
+ ps->performance,
+ DEV_ENERGYMODEL_A_PERF_STATE_PAD))
goto out_cancel_ps_nest;
- if (nla_put_u64_64bit(msg, EM_A_PS_FREQUENCY,
- ps->frequency, EM_A_PS_PAD))
+ if (nla_put_u64_64bit(msg,
+ DEV_ENERGYMODEL_A_PERF_STATE_FREQUENCY,
+ ps->frequency,
+ DEV_ENERGYMODEL_A_PERF_STATE_PAD))
goto out_cancel_ps_nest;
- if (nla_put_u64_64bit(msg, EM_A_PS_POWER,
- ps->power, EM_A_PS_PAD))
+ if (nla_put_u64_64bit(msg,
+ DEV_ENERGYMODEL_A_PERF_STATE_POWER,
+ ps->power,
+ DEV_ENERGYMODEL_A_PERF_STATE_PAD))
goto out_cancel_ps_nest;
- if (nla_put_u64_64bit(msg, EM_A_PS_COST,
- ps->cost, EM_A_PS_PAD))
+ if (nla_put_u64_64bit(msg,
+ DEV_ENERGYMODEL_A_PERF_STATE_COST,
+ ps->cost,
+ DEV_ENERGYMODEL_A_PERF_STATE_PAD))
goto out_cancel_ps_nest;
- if (nla_put_u64_64bit(msg, EM_A_PS_FLAGS,
- ps->flags, EM_A_PS_PAD))
+ if (nla_put_u64_64bit(msg,
+ DEV_ENERGYMODEL_A_PERF_STATE_FLAGS,
+ ps->flags,
+ DEV_ENERGYMODEL_A_PERF_STATE_PAD))
goto out_cancel_ps_nest;
nla_nest_end(msg, entry);
@@ -179,7 +243,8 @@ out_err:
return -EMSGSIZE;
}
-int em_nl_get_pd_table_doit(struct sk_buff *skb, struct genl_info *info)
+int dev_energymodel_nl_get_perf_table_doit(struct sk_buff *skb,
+ struct genl_info *info)
{
int cmd = info->genlhdr->cmd;
int msg_sz, ret = -EMSGSIZE;
@@ -197,7 +262,7 @@ int em_nl_get_pd_table_doit(struct sk_buff *skb, struct genl_info *info)
if (!msg)
return -ENOMEM;
- hdr = genlmsg_put_reply(msg, info, &em_nl_family, 0, cmd);
+ hdr = genlmsg_put_reply(msg, info, &dev_energymodel_nl_family, 0, cmd);
if (!hdr)
goto out_free_msg;
@@ -221,7 +286,7 @@ static void __em_notify_pd_table(const struct em_perf_domain *pd, int ntf_type)
int msg_sz, ret = -EMSGSIZE;
void *hdr;
- if (!genl_has_listeners(&em_nl_family, &init_net, EM_NLGRP_EVENT))
+ if (!genl_has_listeners(&dev_energymodel_nl_family, &init_net, DEV_ENERGYMODEL_NLGRP_EVENT))
return;
msg_sz = __em_nl_get_pd_table_size(pd);
@@ -230,7 +295,7 @@ static void __em_notify_pd_table(const struct em_perf_domain *pd, int ntf_type)
if (!msg)
return;
- hdr = genlmsg_put(msg, 0, 0, &em_nl_family, 0, ntf_type);
+ hdr = genlmsg_put(msg, 0, 0, &dev_energymodel_nl_family, 0, ntf_type);
if (!hdr)
goto out_free_msg;
@@ -240,28 +305,28 @@ static void __em_notify_pd_table(const struct em_perf_domain *pd, int ntf_type)
genlmsg_end(msg, hdr);
- genlmsg_multicast(&em_nl_family, msg, 0, EM_NLGRP_EVENT, GFP_KERNEL);
+ genlmsg_multicast(&dev_energymodel_nl_family, msg, 0,
+ DEV_ENERGYMODEL_NLGRP_EVENT, GFP_KERNEL);
return;
out_free_msg:
nlmsg_free(msg);
- return;
}
void em_notify_pd_created(const struct em_perf_domain *pd)
{
- __em_notify_pd_table(pd, EM_CMD_PD_CREATED);
+ __em_notify_pd_table(pd, DEV_ENERGYMODEL_CMD_PERF_DOMAIN_CREATED);
}
void em_notify_pd_updated(const struct em_perf_domain *pd)
{
- __em_notify_pd_table(pd, EM_CMD_PD_UPDATED);
+ __em_notify_pd_table(pd, DEV_ENERGYMODEL_CMD_PERF_DOMAIN_UPDATED);
}
static int __em_notify_pd_deleted_size(const struct em_perf_domain *pd)
{
- int id_sz = nla_total_size(sizeof(u32)); /* EM_A_PD_TABLE_PD_ID */
+ int id_sz = nla_total_size(sizeof(u32)); /* DEV_ENERGYMODEL_A_PERF_TABLE_PERF_DOMAIN_ID */
return nlmsg_total_size(genlmsg_msg_size(id_sz));
}
@@ -272,7 +337,8 @@ void em_notify_pd_deleted(const struct em_perf_domain *pd)
void *hdr;
int msg_sz;
- if (!genl_has_listeners(&em_nl_family, &init_net, EM_NLGRP_EVENT))
+ if (!genl_has_listeners(&dev_energymodel_nl_family, &init_net,
+ DEV_ENERGYMODEL_NLGRP_EVENT))
return;
msg_sz = __em_notify_pd_deleted_size(pd);
@@ -281,28 +347,29 @@ void em_notify_pd_deleted(const struct em_perf_domain *pd)
if (!msg)
return;
- hdr = genlmsg_put(msg, 0, 0, &em_nl_family, 0, EM_CMD_PD_DELETED);
+ hdr = genlmsg_put(msg, 0, 0, &dev_energymodel_nl_family, 0,
+ DEV_ENERGYMODEL_CMD_PERF_DOMAIN_DELETED);
if (!hdr)
goto out_free_msg;
- if (nla_put_u32(msg, EM_A_PD_TABLE_PD_ID, pd->id)) {
+ if (nla_put_u32(msg, DEV_ENERGYMODEL_A_PERF_TABLE_PERF_DOMAIN_ID,
+ pd->id))
goto out_free_msg;
- }
genlmsg_end(msg, hdr);
- genlmsg_multicast(&em_nl_family, msg, 0, EM_NLGRP_EVENT, GFP_KERNEL);
+ genlmsg_multicast(&dev_energymodel_nl_family, msg, 0,
+ DEV_ENERGYMODEL_NLGRP_EVENT, GFP_KERNEL);
return;
out_free_msg:
nlmsg_free(msg);
- return;
}
/**************************** Initialization *********************************/
static int __init em_netlink_init(void)
{
- return genl_register_family(&em_nl_family);
+ return genl_register_family(&dev_energymodel_nl_family);
}
postcore_initcall(em_netlink_init);
diff --git a/kernel/power/em_netlink_autogen.c b/kernel/power/em_netlink_autogen.c
index ceb3b2bb6ebe..fedd473e4244 100644
--- a/kernel/power/em_netlink_autogen.c
+++ b/kernel/power/em_netlink_autogen.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
/* Do not edit directly, auto-generated from: */
-/* Documentation/netlink/specs/em.yaml */
+/* Documentation/netlink/specs/dev-energymodel.yaml */
/* YNL-GEN kernel source */
/* To regenerate run: tools/net/ynl/ynl-regen.sh */
@@ -9,41 +9,53 @@
#include "em_netlink_autogen.h"
-#include <uapi/linux/energy_model.h>
+#include <uapi/linux/dev_energymodel.h>
-/* EM_CMD_GET_PD_TABLE - do */
-static const struct nla_policy em_get_pd_table_nl_policy[EM_A_PD_TABLE_PD_ID + 1] = {
- [EM_A_PD_TABLE_PD_ID] = { .type = NLA_U32, },
+/* DEV_ENERGYMODEL_CMD_GET_PERF_DOMAINS - do */
+static const struct nla_policy dev_energymodel_get_perf_domains_nl_policy[DEV_ENERGYMODEL_A_PERF_DOMAIN_PERF_DOMAIN_ID + 1] = {
+ [DEV_ENERGYMODEL_A_PERF_DOMAIN_PERF_DOMAIN_ID] = { .type = NLA_U32, },
};
-/* Ops table for em */
-static const struct genl_split_ops em_nl_ops[] = {
+/* DEV_ENERGYMODEL_CMD_GET_PERF_TABLE - do */
+static const struct nla_policy dev_energymodel_get_perf_table_nl_policy[DEV_ENERGYMODEL_A_PERF_TABLE_PERF_DOMAIN_ID + 1] = {
+ [DEV_ENERGYMODEL_A_PERF_TABLE_PERF_DOMAIN_ID] = { .type = NLA_U32, },
+};
+
+/* Ops table for dev_energymodel */
+static const struct genl_split_ops dev_energymodel_nl_ops[] = {
+ {
+ .cmd = DEV_ENERGYMODEL_CMD_GET_PERF_DOMAINS,
+ .doit = dev_energymodel_nl_get_perf_domains_doit,
+ .policy = dev_energymodel_get_perf_domains_nl_policy,
+ .maxattr = DEV_ENERGYMODEL_A_PERF_DOMAIN_PERF_DOMAIN_ID,
+ .flags = GENL_CMD_CAP_DO,
+ },
{
- .cmd = EM_CMD_GET_PDS,
- .doit = em_nl_get_pds_doit,
- .flags = GENL_CMD_CAP_DO,
+ .cmd = DEV_ENERGYMODEL_CMD_GET_PERF_DOMAINS,
+ .dumpit = dev_energymodel_nl_get_perf_domains_dumpit,
+ .flags = GENL_CMD_CAP_DUMP,
},
{
- .cmd = EM_CMD_GET_PD_TABLE,
- .doit = em_nl_get_pd_table_doit,
- .policy = em_get_pd_table_nl_policy,
- .maxattr = EM_A_PD_TABLE_PD_ID,
+ .cmd = DEV_ENERGYMODEL_CMD_GET_PERF_TABLE,
+ .doit = dev_energymodel_nl_get_perf_table_doit,
+ .policy = dev_energymodel_get_perf_table_nl_policy,
+ .maxattr = DEV_ENERGYMODEL_A_PERF_TABLE_PERF_DOMAIN_ID,
.flags = GENL_CMD_CAP_DO,
},
};
-static const struct genl_multicast_group em_nl_mcgrps[] = {
- [EM_NLGRP_EVENT] = { "event", },
+static const struct genl_multicast_group dev_energymodel_nl_mcgrps[] = {
+ [DEV_ENERGYMODEL_NLGRP_EVENT] = { "event", },
};
-struct genl_family em_nl_family __ro_after_init = {
- .name = EM_FAMILY_NAME,
- .version = EM_FAMILY_VERSION,
+struct genl_family dev_energymodel_nl_family __ro_after_init = {
+ .name = DEV_ENERGYMODEL_FAMILY_NAME,
+ .version = DEV_ENERGYMODEL_FAMILY_VERSION,
.netnsok = true,
.parallel_ops = true,
.module = THIS_MODULE,
- .split_ops = em_nl_ops,
- .n_split_ops = ARRAY_SIZE(em_nl_ops),
- .mcgrps = em_nl_mcgrps,
- .n_mcgrps = ARRAY_SIZE(em_nl_mcgrps),
+ .split_ops = dev_energymodel_nl_ops,
+ .n_split_ops = ARRAY_SIZE(dev_energymodel_nl_ops),
+ .mcgrps = dev_energymodel_nl_mcgrps,
+ .n_mcgrps = ARRAY_SIZE(dev_energymodel_nl_mcgrps),
};
diff --git a/kernel/power/em_netlink_autogen.h b/kernel/power/em_netlink_autogen.h
index 140ab548103c..5caf2f7e18a5 100644
--- a/kernel/power/em_netlink_autogen.h
+++ b/kernel/power/em_netlink_autogen.h
@@ -1,24 +1,28 @@
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/* Do not edit directly, auto-generated from: */
-/* Documentation/netlink/specs/em.yaml */
+/* Documentation/netlink/specs/dev-energymodel.yaml */
/* YNL-GEN kernel header */
/* To regenerate run: tools/net/ynl/ynl-regen.sh */
-#ifndef _LINUX_EM_GEN_H
-#define _LINUX_EM_GEN_H
+#ifndef _LINUX_DEV_ENERGYMODEL_GEN_H
+#define _LINUX_DEV_ENERGYMODEL_GEN_H
#include <net/netlink.h>
#include <net/genetlink.h>
-#include <uapi/linux/energy_model.h>
+#include <uapi/linux/dev_energymodel.h>
-int em_nl_get_pds_doit(struct sk_buff *skb, struct genl_info *info);
-int em_nl_get_pd_table_doit(struct sk_buff *skb, struct genl_info *info);
+int dev_energymodel_nl_get_perf_domains_doit(struct sk_buff *skb,
+ struct genl_info *info);
+int dev_energymodel_nl_get_perf_domains_dumpit(struct sk_buff *skb,
+ struct netlink_callback *cb);
+int dev_energymodel_nl_get_perf_table_doit(struct sk_buff *skb,
+ struct genl_info *info);
enum {
- EM_NLGRP_EVENT,
+ DEV_ENERGYMODEL_NLGRP_EVENT,
};
-extern struct genl_family em_nl_family;
+extern struct genl_family dev_energymodel_nl_family;
-#endif /* _LINUX_EM_GEN_H */
+#endif /* _LINUX_DEV_ENERGYMODEL_GEN_H */
diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c
index 11af9f64aa82..5b055cbe5341 100644
--- a/kernel/power/energy_model.c
+++ b/kernel/power/energy_model.c
@@ -449,8 +449,10 @@ static int em_create_pd(struct device *dev, int nr_states,
INIT_LIST_HEAD(&pd->node);
id = ida_alloc(&em_pd_ida, GFP_KERNEL);
- if (id < 0)
- return -ENOMEM;
+ if (id < 0) {
+ kfree(pd);
+ return id;
+ }
pd->id = id;
em_table = em_table_alloc(pd);
diff --git a/kernel/printk/nbcon.c b/kernel/printk/nbcon.c
index 3fa403f9831f..32fc12e53675 100644
--- a/kernel/printk/nbcon.c
+++ b/kernel/printk/nbcon.c
@@ -1557,18 +1557,27 @@ static int __nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq)
ctxt->allow_unsafe_takeover = nbcon_allow_unsafe_takeover();
while (nbcon_seq_read(con) < stop_seq) {
- if (!nbcon_context_try_acquire(ctxt, false))
- return -EPERM;
-
/*
- * nbcon_emit_next_record() returns false when the console was
- * handed over or taken over. In both cases the context is no
- * longer valid.
+ * Atomic flushing does not use console driver synchronization
+ * (i.e. it does not hold the port lock for uart consoles).
+ * Therefore IRQs must be disabled to avoid being interrupted
+ * and then calling into a driver that will deadlock trying
+ * to acquire console ownership.
*/
- if (!nbcon_emit_next_record(&wctxt, true))
- return -EAGAIN;
+ scoped_guard(irqsave) {
+ if (!nbcon_context_try_acquire(ctxt, false))
+ return -EPERM;
- nbcon_context_release(ctxt);
+ /*
+ * nbcon_emit_next_record() returns false when
+ * the console was handed over or taken over.
+ * In both cases the context is no longer valid.
+ */
+ if (!nbcon_emit_next_record(&wctxt, true))
+ return -EAGAIN;
+
+ nbcon_context_release(ctxt);
+ }
if (!ctxt->backlog) {
/* Are there reserved but not yet finalized records? */
@@ -1595,22 +1604,11 @@ static int __nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq)
static void nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq)
{
struct console_flush_type ft;
- unsigned long flags;
int err;
again:
- /*
- * Atomic flushing does not use console driver synchronization (i.e.
- * it does not hold the port lock for uart consoles). Therefore IRQs
- * must be disabled to avoid being interrupted and then calling into
- * a driver that will deadlock trying to acquire console ownership.
- */
- local_irq_save(flags);
-
err = __nbcon_atomic_flush_pending_con(con, stop_seq);
- local_irq_restore(flags);
-
/*
* If there was a new owner (-EPERM, -EAGAIN), that context is
* responsible for completing.
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 60afadb6eede..045f83ad261e 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -4950,9 +4950,13 @@ struct balance_callback *splice_balance_callbacks(struct rq *rq)
return __splice_balance_callbacks(rq, true);
}
-static void __balance_callbacks(struct rq *rq)
+void __balance_callbacks(struct rq *rq, struct rq_flags *rf)
{
+ if (rf)
+ rq_unpin_lock(rq, rf);
do_balance_callbacks(rq, __splice_balance_callbacks(rq, false));
+ if (rf)
+ rq_repin_lock(rq, rf);
}
void balance_callbacks(struct rq *rq, struct balance_callback *head)
@@ -4991,7 +4995,7 @@ static inline void finish_lock_switch(struct rq *rq)
* prev into current:
*/
spin_acquire(&__rq_lockp(rq)->dep_map, 0, 0, _THIS_IP_);
- __balance_callbacks(rq);
+ __balance_callbacks(rq, NULL);
raw_spin_rq_unlock_irq(rq);
}
@@ -6867,7 +6871,7 @@ keep_resched:
proxy_tag_curr(rq, next);
rq_unpin_lock(rq, &rf);
- __balance_callbacks(rq);
+ __balance_callbacks(rq, NULL);
raw_spin_rq_unlock_irq(rq);
}
trace_sched_exit_tp(is_switch);
@@ -7316,7 +7320,7 @@ void rt_mutex_setprio(struct task_struct *p, struct task_struct *pi_task)
trace_sched_pi_setprio(p, pi_task);
oldprio = p->prio;
- if (oldprio == prio)
+ if (oldprio == prio && !dl_prio(prio))
queue_flag &= ~DEQUEUE_MOVE;
prev_class = p->sched_class;
@@ -7362,9 +7366,7 @@ void rt_mutex_setprio(struct task_struct *p, struct task_struct *pi_task)
out_unlock:
/* Caller holds task_struct::pi_lock, IRQs are still disabled */
- rq_unpin_lock(rq, &rf);
- __balance_callbacks(rq);
- rq_repin_lock(rq, &rf);
+ __balance_callbacks(rq, &rf);
__task_rq_unlock(rq, p, &rf);
}
#endif /* CONFIG_RT_MUTEXES */
@@ -9124,6 +9126,8 @@ void sched_move_task(struct task_struct *tsk, bool for_autogroup)
if (resched)
resched_curr(rq);
+
+ __balance_callbacks(rq, &rq_guard.rf);
}
static struct cgroup_subsys_state *
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index 319439fe1870..c509f2e7d69d 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -752,8 +752,6 @@ static inline void setup_new_dl_entity(struct sched_dl_entity *dl_se)
struct dl_rq *dl_rq = dl_rq_of_se(dl_se);
struct rq *rq = rq_of_dl_rq(dl_rq);
- update_rq_clock(rq);
-
WARN_ON(is_dl_boosted(dl_se));
WARN_ON(dl_time_before(rq_clock(rq), dl_se->deadline));
@@ -1420,7 +1418,7 @@ update_stats_dequeue_dl(struct dl_rq *dl_rq, struct sched_dl_entity *dl_se, int
static void update_curr_dl_se(struct rq *rq, struct sched_dl_entity *dl_se, s64 delta_exec)
{
- bool idle = rq->curr == rq->idle;
+ bool idle = idle_rq(rq);
s64 scaled_delta_exec;
if (unlikely(delta_exec <= 0)) {
@@ -1603,8 +1601,8 @@ void dl_server_update(struct sched_dl_entity *dl_se, s64 delta_exec)
* | 8 | B:zero_laxity-wait | | |
* | | | <---+ |
* | +--------------------------------+ |
- * | | ^ ^ 2 |
- * | | 7 | 2 +--------------------+
+ * | | ^ ^ 2 |
+ * | | 7 | 2, 1 +----------------+
* | v |
* | +-------------+ |
* +-- | C:idle-wait | -+
@@ -1649,8 +1647,11 @@ void dl_server_update(struct sched_dl_entity *dl_se, s64 delta_exec)
* dl_defer_idle = 0
*
*
- * [1] A->B, A->D
+ * [1] A->B, A->D, C->B
* dl_server_start()
+ * dl_defer_idle = 0;
+ * if (dl_server_active)
+ * return; // [B]
* dl_server_active = 1;
* enqueue_dl_entity()
* update_dl_entity(WAKEUP)
@@ -1759,6 +1760,7 @@ void dl_server_update(struct sched_dl_entity *dl_se, s64 delta_exec)
* "B:zero_laxity-wait" -> "C:idle-wait" [label="7:dl_server_update_idle"]
* "B:zero_laxity-wait" -> "D:running" [label="3:dl_server_timer"]
* "C:idle-wait" -> "A:init" [label="8:dl_server_timer"]
+ * "C:idle-wait" -> "B:zero_laxity-wait" [label="1:dl_server_start"]
* "C:idle-wait" -> "B:zero_laxity-wait" [label="2:dl_server_update"]
* "C:idle-wait" -> "C:idle-wait" [label="7:dl_server_update_idle"]
* "D:running" -> "A:init" [label="4:pick_task_dl"]
@@ -1784,6 +1786,7 @@ void dl_server_start(struct sched_dl_entity *dl_se)
{
struct rq *rq = dl_se->rq;
+ dl_se->dl_defer_idle = 0;
if (!dl_server(dl_se) || dl_se->dl_server_active)
return;
@@ -1834,6 +1837,7 @@ void sched_init_dl_servers(void)
rq = cpu_rq(cpu);
guard(rq_lock_irq)(rq);
+ update_rq_clock(rq);
dl_se = &rq->fair_server;
@@ -2210,7 +2214,7 @@ enqueue_dl_entity(struct sched_dl_entity *dl_se, int flags)
update_dl_entity(dl_se);
} else if (flags & ENQUEUE_REPLENISH) {
replenish_dl_entity(dl_se);
- } else if ((flags & ENQUEUE_RESTORE) &&
+ } else if ((flags & ENQUEUE_MOVE) &&
!is_dl_boosted(dl_se) &&
dl_time_before(dl_se->deadline, rq_clock(rq_of_dl_se(dl_se)))) {
setup_new_dl_entity(dl_se);
@@ -3154,7 +3158,7 @@ void dl_add_task_root_domain(struct task_struct *p)
struct rq *rq;
struct dl_bw *dl_b;
unsigned int cpu;
- struct cpumask *msk = this_cpu_cpumask_var_ptr(local_cpu_mask_dl);
+ struct cpumask *msk;
raw_spin_lock_irqsave(&p->pi_lock, rf.flags);
if (!dl_task(p) || dl_entity_is_special(&p->dl)) {
@@ -3162,20 +3166,12 @@ void dl_add_task_root_domain(struct task_struct *p)
return;
}
- /*
- * Get an active rq, whose rq->rd traces the correct root
- * domain.
- * Ideally this would be under cpuset reader lock until rq->rd is
- * fetched. However, sleepable locks cannot nest inside pi_lock, so we
- * rely on the caller of dl_add_task_root_domain() holds 'cpuset_mutex'
- * to guarantee the CPU stays in the cpuset.
- */
+ msk = this_cpu_cpumask_var_ptr(local_cpu_mask_dl);
dl_get_task_effective_cpus(p, msk);
cpu = cpumask_first_and(cpu_active_mask, msk);
BUG_ON(cpu >= nr_cpu_ids);
rq = cpu_rq(cpu);
dl_b = &rq->rd->dl_bw;
- /* End of fetching rd */
raw_spin_lock(&dl_b->lock);
__dl_add(dl_b, p->dl.dl_bw, cpumask_weight(rq->rd->span));
@@ -3299,6 +3295,12 @@ static void switched_to_dl(struct rq *rq, struct task_struct *p)
static u64 get_prio_dl(struct rq *rq, struct task_struct *p)
{
+ /*
+ * Make sure to update current so we don't return a stale value.
+ */
+ if (task_current_donor(rq, p))
+ update_curr_dl(rq);
+
return p->dl.deadline;
}
diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c
index 8f6d8d7f895c..afe28c04d5aa 100644
--- a/kernel/sched/ext.c
+++ b/kernel/sched/ext.c
@@ -545,6 +545,7 @@ static void scx_task_iter_start(struct scx_task_iter *iter)
static void __scx_task_iter_rq_unlock(struct scx_task_iter *iter)
{
if (iter->locked_task) {
+ __balance_callbacks(iter->rq, &iter->rf);
task_rq_unlock(iter->rq, iter->locked_task, &iter->rf);
iter->locked_task = NULL;
}
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index d30cca6870f5..93fce4bbff5e 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -1364,6 +1364,28 @@ static inline u32 sched_rng(void)
#define cpu_curr(cpu) (cpu_rq(cpu)->curr)
#define raw_rq() raw_cpu_ptr(&runqueues)
+static inline bool idle_rq(struct rq *rq)
+{
+ return rq->curr == rq->idle && !rq->nr_running && !rq->ttwu_pending;
+}
+
+/**
+ * available_idle_cpu - is a given CPU idle for enqueuing work.
+ * @cpu: the CPU in question.
+ *
+ * Return: 1 if the CPU is currently idle. 0 otherwise.
+ */
+static inline bool available_idle_cpu(int cpu)
+{
+ if (!idle_rq(cpu_rq(cpu)))
+ return 0;
+
+ if (vcpu_is_preempted(cpu))
+ return 0;
+
+ return 1;
+}
+
#ifdef CONFIG_SCHED_PROXY_EXEC
static inline void rq_set_donor(struct rq *rq, struct task_struct *t)
{
@@ -2366,7 +2388,8 @@ extern const u32 sched_prio_to_wmult[40];
* should preserve as much state as possible.
*
* MOVE - paired with SAVE/RESTORE, explicitly does not preserve the location
- * in the runqueue.
+ * in the runqueue. IOW the priority is allowed to change. Callers
+ * must expect to deal with balance callbacks.
*
* NOCLOCK - skip the update_rq_clock() (avoids double updates)
*
@@ -3947,6 +3970,8 @@ extern void enqueue_task(struct rq *rq, struct task_struct *p, int flags);
extern bool dequeue_task(struct rq *rq, struct task_struct *p, int flags);
extern struct balance_callback *splice_balance_callbacks(struct rq *rq);
+
+extern void __balance_callbacks(struct rq *rq, struct rq_flags *rf);
extern void balance_callbacks(struct rq *rq, struct balance_callback *head);
/*
diff --git a/kernel/sched/syscalls.c b/kernel/sched/syscalls.c
index 0496dc29ed0f..6f10db3646e7 100644
--- a/kernel/sched/syscalls.c
+++ b/kernel/sched/syscalls.c
@@ -180,35 +180,7 @@ int task_prio(const struct task_struct *p)
*/
int idle_cpu(int cpu)
{
- struct rq *rq = cpu_rq(cpu);
-
- if (rq->curr != rq->idle)
- return 0;
-
- if (rq->nr_running)
- return 0;
-
- if (rq->ttwu_pending)
- return 0;
-
- return 1;
-}
-
-/**
- * available_idle_cpu - is a given CPU idle for enqueuing work.
- * @cpu: the CPU in question.
- *
- * Return: 1 if the CPU is currently idle. 0 otherwise.
- */
-int available_idle_cpu(int cpu)
-{
- if (!idle_cpu(cpu))
- return 0;
-
- if (vcpu_is_preempted(cpu))
- return 0;
-
- return 1;
+ return idle_rq(cpu_rq(cpu));
}
/**
@@ -667,7 +639,7 @@ change:
* itself.
*/
newprio = rt_effective_prio(p, newprio);
- if (newprio == oldprio)
+ if (newprio == oldprio && !dl_prio(newprio))
queue_flags &= ~DEQUEUE_MOVE;
}
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index bdb30cc5e873..0e4bc1ca15ff 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -913,7 +913,7 @@ static bool update_needs_ipi(struct hrtimer_cpu_base *cpu_base,
return true;
/* Extra check for softirq clock bases */
- if (base->clockid < HRTIMER_BASE_MONOTONIC_SOFT)
+ if (base->index < HRTIMER_BASE_MONOTONIC_SOFT)
continue;
if (cpu_base->softirq_activated)
continue;
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index ef2d5dca6f70..aa758efc3731 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -1148,7 +1148,6 @@ struct ftrace_page {
};
#define ENTRY_SIZE sizeof(struct dyn_ftrace)
-#define ENTRIES_PER_PAGE (PAGE_SIZE / ENTRY_SIZE)
static struct ftrace_page *ftrace_pages_start;
static struct ftrace_page *ftrace_pages;
@@ -3834,7 +3833,8 @@ static int ftrace_update_code(struct module *mod, struct ftrace_page *new_pgs)
return 0;
}
-static int ftrace_allocate_records(struct ftrace_page *pg, int count)
+static int ftrace_allocate_records(struct ftrace_page *pg, int count,
+ unsigned long *num_pages)
{
int order;
int pages;
@@ -3844,7 +3844,7 @@ static int ftrace_allocate_records(struct ftrace_page *pg, int count)
return -EINVAL;
/* We want to fill as much as possible, with no empty pages */
- pages = DIV_ROUND_UP(count, ENTRIES_PER_PAGE);
+ pages = DIV_ROUND_UP(count * ENTRY_SIZE, PAGE_SIZE);
order = fls(pages) - 1;
again:
@@ -3859,6 +3859,7 @@ static int ftrace_allocate_records(struct ftrace_page *pg, int count)
}
ftrace_number_of_pages += 1 << order;
+ *num_pages += 1 << order;
ftrace_number_of_groups++;
cnt = (PAGE_SIZE << order) / ENTRY_SIZE;
@@ -3887,12 +3888,14 @@ static void ftrace_free_pages(struct ftrace_page *pages)
}
static struct ftrace_page *
-ftrace_allocate_pages(unsigned long num_to_init)
+ftrace_allocate_pages(unsigned long num_to_init, unsigned long *num_pages)
{
struct ftrace_page *start_pg;
struct ftrace_page *pg;
int cnt;
+ *num_pages = 0;
+
if (!num_to_init)
return NULL;
@@ -3906,7 +3909,7 @@ ftrace_allocate_pages(unsigned long num_to_init)
* waste as little space as possible.
*/
for (;;) {
- cnt = ftrace_allocate_records(pg, num_to_init);
+ cnt = ftrace_allocate_records(pg, num_to_init, num_pages);
if (cnt < 0)
goto free_pages;
@@ -7192,8 +7195,6 @@ static int ftrace_process_locs(struct module *mod,
if (!count)
return 0;
- pages = DIV_ROUND_UP(count, ENTRIES_PER_PAGE);
-
/*
* Sorting mcount in vmlinux at build time depend on
* CONFIG_BUILDTIME_MCOUNT_SORT, while mcount loc in
@@ -7206,7 +7207,7 @@ static int ftrace_process_locs(struct module *mod,
test_is_sorted(start, count);
}
- start_pg = ftrace_allocate_pages(count);
+ start_pg = ftrace_allocate_pages(count, &pages);
if (!start_pg)
return -ENOMEM;
@@ -7305,27 +7306,27 @@ static int ftrace_process_locs(struct module *mod,
/* We should have used all pages unless we skipped some */
if (pg_unuse) {
unsigned long pg_remaining, remaining = 0;
- unsigned long skip;
+ long skip;
/* Count the number of entries unused and compare it to skipped. */
- pg_remaining = (ENTRIES_PER_PAGE << pg->order) - pg->index;
+ pg_remaining = (PAGE_SIZE << pg->order) / ENTRY_SIZE - pg->index;
if (!WARN(skipped < pg_remaining, "Extra allocated pages for ftrace")) {
skip = skipped - pg_remaining;
- for (pg = pg_unuse; pg; pg = pg->next)
+ for (pg = pg_unuse; pg && skip > 0; pg = pg->next) {
remaining += 1 << pg->order;
+ skip -= (PAGE_SIZE << pg->order) / ENTRY_SIZE;
+ }
pages -= remaining;
- skip = DIV_ROUND_UP(skip, ENTRIES_PER_PAGE);
-
/*
* Check to see if the number of pages remaining would
* just fit the number of entries skipped.
*/
- WARN(skip != remaining, "Extra allocated pages for ftrace: %lu with %lu skipped",
+ WARN(pg || skip > 0, "Extra allocated pages for ftrace: %lu with %lu skipped",
remaining, skipped);
}
/* Need to synchronize with ftrace_location_range() */
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 0685e3a8aa0a..366122f4a0f8 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -71,7 +71,7 @@ unsigned int __read_mostly hardlockup_panic =
* hard lockup is detected, it could be task, memory, lock etc.
* Refer include/linux/sys_info.h for detailed bit definition.
*/
-static unsigned long hardlockup_si_mask;
+unsigned long hardlockup_si_mask;
#ifdef CONFIG_SYSFS