Merge tag 'v4.20-rc5' into irq/core, to pick up fixes
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
@@ -553,7 +553,6 @@ bool is_bpf_text_address(unsigned long addr)
|
||||
int bpf_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
|
||||
char *sym)
|
||||
{
|
||||
unsigned long symbol_start, symbol_end;
|
||||
struct bpf_prog_aux *aux;
|
||||
unsigned int it = 0;
|
||||
int ret = -ERANGE;
|
||||
@@ -566,10 +565,9 @@ int bpf_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
|
||||
if (it++ != symnum)
|
||||
continue;
|
||||
|
||||
bpf_get_prog_addr_region(aux->prog, &symbol_start, &symbol_end);
|
||||
bpf_get_prog_name(aux->prog, sym);
|
||||
|
||||
*value = symbol_start;
|
||||
*value = (unsigned long)aux->prog->bpf_func;
|
||||
*type = BPF_SYM_ELF_TYPE;
|
||||
|
||||
ret = 0;
|
||||
@@ -674,6 +672,40 @@ void __weak bpf_jit_free(struct bpf_prog *fp)
|
||||
bpf_prog_unlock_free(fp);
|
||||
}
|
||||
|
||||
int bpf_jit_get_func_addr(const struct bpf_prog *prog,
|
||||
const struct bpf_insn *insn, bool extra_pass,
|
||||
u64 *func_addr, bool *func_addr_fixed)
|
||||
{
|
||||
s16 off = insn->off;
|
||||
s32 imm = insn->imm;
|
||||
u8 *addr;
|
||||
|
||||
*func_addr_fixed = insn->src_reg != BPF_PSEUDO_CALL;
|
||||
if (!*func_addr_fixed) {
|
||||
/* Place-holder address till the last pass has collected
|
||||
* all addresses for JITed subprograms in which case we
|
||||
* can pick them up from prog->aux.
|
||||
*/
|
||||
if (!extra_pass)
|
||||
addr = NULL;
|
||||
else if (prog->aux->func &&
|
||||
off >= 0 && off < prog->aux->func_cnt)
|
||||
addr = (u8 *)prog->aux->func[off]->bpf_func;
|
||||
else
|
||||
return -EINVAL;
|
||||
} else {
|
||||
/* Address of a BPF helper call. Since part of the core
|
||||
* kernel, it's always at a fixed location. __bpf_call_base
|
||||
* and the helper with imm relative to it are both in core
|
||||
* kernel.
|
||||
*/
|
||||
addr = (u8 *)__bpf_call_base + imm;
|
||||
}
|
||||
|
||||
*func_addr = (unsigned long)addr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bpf_jit_blind_insn(const struct bpf_insn *from,
|
||||
const struct bpf_insn *aux,
|
||||
struct bpf_insn *to_buff)
|
||||
|
@@ -139,7 +139,8 @@ static int cgroup_storage_update_elem(struct bpf_map *map, void *_key,
|
||||
return -ENOENT;
|
||||
|
||||
new = kmalloc_node(sizeof(struct bpf_storage_buffer) +
|
||||
map->value_size, __GFP_ZERO | GFP_USER,
|
||||
map->value_size,
|
||||
__GFP_ZERO | GFP_ATOMIC | __GFP_NOWARN,
|
||||
map->numa_node);
|
||||
if (!new)
|
||||
return -ENOMEM;
|
||||
|
@@ -7,6 +7,7 @@
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/capability.h>
|
||||
#include "percpu_freelist.h"
|
||||
|
||||
#define QUEUE_STACK_CREATE_FLAG_MASK \
|
||||
@@ -45,8 +46,12 @@ static bool queue_stack_map_is_full(struct bpf_queue_stack *qs)
|
||||
/* Called from syscall */
|
||||
static int queue_stack_map_alloc_check(union bpf_attr *attr)
|
||||
{
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
/* check sanity of attributes */
|
||||
if (attr->max_entries == 0 || attr->key_size != 0 ||
|
||||
attr->value_size == 0 ||
|
||||
attr->map_flags & ~QUEUE_STACK_CREATE_FLAG_MASK)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -63,15 +68,10 @@ static struct bpf_map *queue_stack_map_alloc(union bpf_attr *attr)
|
||||
{
|
||||
int ret, numa_node = bpf_map_attr_numa_node(attr);
|
||||
struct bpf_queue_stack *qs;
|
||||
u32 size, value_size;
|
||||
u64 queue_size, cost;
|
||||
u64 size, queue_size, cost;
|
||||
|
||||
size = attr->max_entries + 1;
|
||||
value_size = attr->value_size;
|
||||
|
||||
queue_size = sizeof(*qs) + (u64) value_size * size;
|
||||
|
||||
cost = queue_size;
|
||||
size = (u64) attr->max_entries + 1;
|
||||
cost = queue_size = sizeof(*qs) + size * attr->value_size;
|
||||
if (cost >= U32_MAX - PAGE_SIZE)
|
||||
return ERR_PTR(-E2BIG);
|
||||
|
||||
|
@@ -2078,6 +2078,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
|
||||
info.jited_prog_len = 0;
|
||||
info.xlated_prog_len = 0;
|
||||
info.nr_jited_ksyms = 0;
|
||||
info.nr_jited_func_lens = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -2158,11 +2159,11 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
|
||||
}
|
||||
|
||||
ulen = info.nr_jited_ksyms;
|
||||
info.nr_jited_ksyms = prog->aux->func_cnt;
|
||||
info.nr_jited_ksyms = prog->aux->func_cnt ? : 1;
|
||||
if (info.nr_jited_ksyms && ulen) {
|
||||
if (bpf_dump_raw_ok()) {
|
||||
unsigned long ksym_addr;
|
||||
u64 __user *user_ksyms;
|
||||
ulong ksym_addr;
|
||||
u32 i;
|
||||
|
||||
/* copy the address of the kernel symbol
|
||||
@@ -2170,10 +2171,17 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
|
||||
*/
|
||||
ulen = min_t(u32, info.nr_jited_ksyms, ulen);
|
||||
user_ksyms = u64_to_user_ptr(info.jited_ksyms);
|
||||
for (i = 0; i < ulen; i++) {
|
||||
ksym_addr = (ulong) prog->aux->func[i]->bpf_func;
|
||||
ksym_addr &= PAGE_MASK;
|
||||
if (put_user((u64) ksym_addr, &user_ksyms[i]))
|
||||
if (prog->aux->func_cnt) {
|
||||
for (i = 0; i < ulen; i++) {
|
||||
ksym_addr = (unsigned long)
|
||||
prog->aux->func[i]->bpf_func;
|
||||
if (put_user((u64) ksym_addr,
|
||||
&user_ksyms[i]))
|
||||
return -EFAULT;
|
||||
}
|
||||
} else {
|
||||
ksym_addr = (unsigned long) prog->bpf_func;
|
||||
if (put_user((u64) ksym_addr, &user_ksyms[0]))
|
||||
return -EFAULT;
|
||||
}
|
||||
} else {
|
||||
@@ -2182,7 +2190,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
|
||||
}
|
||||
|
||||
ulen = info.nr_jited_func_lens;
|
||||
info.nr_jited_func_lens = prog->aux->func_cnt;
|
||||
info.nr_jited_func_lens = prog->aux->func_cnt ? : 1;
|
||||
if (info.nr_jited_func_lens && ulen) {
|
||||
if (bpf_dump_raw_ok()) {
|
||||
u32 __user *user_lens;
|
||||
@@ -2191,9 +2199,16 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
|
||||
/* copy the JITed image lengths for each function */
|
||||
ulen = min_t(u32, info.nr_jited_func_lens, ulen);
|
||||
user_lens = u64_to_user_ptr(info.jited_func_lens);
|
||||
for (i = 0; i < ulen; i++) {
|
||||
func_len = prog->aux->func[i]->jited_len;
|
||||
if (put_user(func_len, &user_lens[i]))
|
||||
if (prog->aux->func_cnt) {
|
||||
for (i = 0; i < ulen; i++) {
|
||||
func_len =
|
||||
prog->aux->func[i]->jited_len;
|
||||
if (put_user(func_len, &user_lens[i]))
|
||||
return -EFAULT;
|
||||
}
|
||||
} else {
|
||||
func_len = prog->jited_len;
|
||||
if (put_user(func_len, &user_lens[0]))
|
||||
return -EFAULT;
|
||||
}
|
||||
} else {
|
||||
|
@@ -5650,7 +5650,7 @@ static void adjust_subprog_starts(struct bpf_verifier_env *env, u32 off, u32 len
|
||||
return;
|
||||
/* NOTE: fake 'exit' subprog should be updated as well. */
|
||||
for (i = 0; i <= env->subprog_cnt; i++) {
|
||||
if (env->subprog_info[i].start < off)
|
||||
if (env->subprog_info[i].start <= off)
|
||||
continue;
|
||||
env->subprog_info[i].start += len - 1;
|
||||
}
|
||||
|
15
kernel/cpu.c
15
kernel/cpu.c
@@ -10,6 +10,7 @@
|
||||
#include <linux/sched/signal.h>
|
||||
#include <linux/sched/hotplug.h>
|
||||
#include <linux/sched/task.h>
|
||||
#include <linux/sched/smt.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/oom.h>
|
||||
@@ -367,6 +368,12 @@ static void lockdep_release_cpus_lock(void)
|
||||
|
||||
#endif /* CONFIG_HOTPLUG_CPU */
|
||||
|
||||
/*
|
||||
* Architectures that need SMT-specific errata handling during SMT hotplug
|
||||
* should override this.
|
||||
*/
|
||||
void __weak arch_smt_update(void) { }
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_SMT
|
||||
enum cpuhp_smt_control cpu_smt_control __read_mostly = CPU_SMT_ENABLED;
|
||||
EXPORT_SYMBOL_GPL(cpu_smt_control);
|
||||
@@ -1011,6 +1018,7 @@ out:
|
||||
* concurrent CPU hotplug via cpu_add_remove_lock.
|
||||
*/
|
||||
lockup_detector_cleanup();
|
||||
arch_smt_update();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1139,6 +1147,7 @@ static int _cpu_up(unsigned int cpu, int tasks_frozen, enum cpuhp_state target)
|
||||
ret = cpuhp_up_callbacks(cpu, st, target);
|
||||
out:
|
||||
cpus_write_unlock();
|
||||
arch_smt_update();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2055,12 +2064,6 @@ static void cpuhp_online_cpu_device(unsigned int cpu)
|
||||
kobject_uevent(&dev->kobj, KOBJ_ONLINE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Architectures that need SMT-specific errata handling during SMT hotplug
|
||||
* should override this.
|
||||
*/
|
||||
void __weak arch_smt_update(void) { };
|
||||
|
||||
static int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval)
|
||||
{
|
||||
int cpu, ret = 0;
|
||||
|
@@ -179,14 +179,14 @@ kdb_bt(int argc, const char **argv)
|
||||
kdb_printf("no process for cpu %ld\n", cpu);
|
||||
return 0;
|
||||
}
|
||||
sprintf(buf, "btt 0x%p\n", KDB_TSK(cpu));
|
||||
sprintf(buf, "btt 0x%px\n", KDB_TSK(cpu));
|
||||
kdb_parse(buf);
|
||||
return 0;
|
||||
}
|
||||
kdb_printf("btc: cpu status: ");
|
||||
kdb_parse("cpu\n");
|
||||
for_each_online_cpu(cpu) {
|
||||
sprintf(buf, "btt 0x%p\n", KDB_TSK(cpu));
|
||||
sprintf(buf, "btt 0x%px\n", KDB_TSK(cpu));
|
||||
kdb_parse(buf);
|
||||
touch_nmi_watchdog();
|
||||
}
|
||||
|
@@ -216,7 +216,7 @@ static char *kdb_read(char *buffer, size_t bufsize)
|
||||
int count;
|
||||
int i;
|
||||
int diag, dtab_count;
|
||||
int key;
|
||||
int key, buf_size, ret;
|
||||
|
||||
|
||||
diag = kdbgetintenv("DTABCOUNT", &dtab_count);
|
||||
@@ -336,9 +336,8 @@ poll_again:
|
||||
else
|
||||
p_tmp = tmpbuffer;
|
||||
len = strlen(p_tmp);
|
||||
count = kallsyms_symbol_complete(p_tmp,
|
||||
sizeof(tmpbuffer) -
|
||||
(p_tmp - tmpbuffer));
|
||||
buf_size = sizeof(tmpbuffer) - (p_tmp - tmpbuffer);
|
||||
count = kallsyms_symbol_complete(p_tmp, buf_size);
|
||||
if (tab == 2 && count > 0) {
|
||||
kdb_printf("\n%d symbols are found.", count);
|
||||
if (count > dtab_count) {
|
||||
@@ -350,9 +349,13 @@ poll_again:
|
||||
}
|
||||
kdb_printf("\n");
|
||||
for (i = 0; i < count; i++) {
|
||||
if (WARN_ON(!kallsyms_symbol_next(p_tmp, i)))
|
||||
ret = kallsyms_symbol_next(p_tmp, i, buf_size);
|
||||
if (WARN_ON(!ret))
|
||||
break;
|
||||
kdb_printf("%s ", p_tmp);
|
||||
if (ret != -E2BIG)
|
||||
kdb_printf("%s ", p_tmp);
|
||||
else
|
||||
kdb_printf("%s... ", p_tmp);
|
||||
*(p_tmp + len) = '\0';
|
||||
}
|
||||
if (i >= dtab_count)
|
||||
|
@@ -173,11 +173,11 @@ int kdb_get_kbd_char(void)
|
||||
case KT_LATIN:
|
||||
if (isprint(keychar))
|
||||
break; /* printable characters */
|
||||
/* drop through */
|
||||
/* fall through */
|
||||
case KT_SPEC:
|
||||
if (keychar == K_ENTER)
|
||||
break;
|
||||
/* drop through */
|
||||
/* fall through */
|
||||
default:
|
||||
return -1; /* ignore unprintables */
|
||||
}
|
||||
|
@@ -1192,7 +1192,7 @@ static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs,
|
||||
if (reason == KDB_REASON_DEBUG) {
|
||||
/* special case below */
|
||||
} else {
|
||||
kdb_printf("\nEntering kdb (current=0x%p, pid %d) ",
|
||||
kdb_printf("\nEntering kdb (current=0x%px, pid %d) ",
|
||||
kdb_current, kdb_current ? kdb_current->pid : 0);
|
||||
#if defined(CONFIG_SMP)
|
||||
kdb_printf("on processor %d ", raw_smp_processor_id());
|
||||
@@ -1208,7 +1208,7 @@ static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs,
|
||||
*/
|
||||
switch (db_result) {
|
||||
case KDB_DB_BPT:
|
||||
kdb_printf("\nEntering kdb (0x%p, pid %d) ",
|
||||
kdb_printf("\nEntering kdb (0x%px, pid %d) ",
|
||||
kdb_current, kdb_current->pid);
|
||||
#if defined(CONFIG_SMP)
|
||||
kdb_printf("on processor %d ", raw_smp_processor_id());
|
||||
@@ -1493,6 +1493,7 @@ static void kdb_md_line(const char *fmtstr, unsigned long addr,
|
||||
char cbuf[32];
|
||||
char *c = cbuf;
|
||||
int i;
|
||||
int j;
|
||||
unsigned long word;
|
||||
|
||||
memset(cbuf, '\0', sizeof(cbuf));
|
||||
@@ -1538,25 +1539,9 @@ static void kdb_md_line(const char *fmtstr, unsigned long addr,
|
||||
wc.word = word;
|
||||
#define printable_char(c) \
|
||||
({unsigned char __c = c; isascii(__c) && isprint(__c) ? __c : '.'; })
|
||||
switch (bytesperword) {
|
||||
case 8:
|
||||
for (j = 0; j < bytesperword; j++)
|
||||
*c++ = printable_char(*cp++);
|
||||
*c++ = printable_char(*cp++);
|
||||
*c++ = printable_char(*cp++);
|
||||
*c++ = printable_char(*cp++);
|
||||
addr += 4;
|
||||
case 4:
|
||||
*c++ = printable_char(*cp++);
|
||||
*c++ = printable_char(*cp++);
|
||||
addr += 2;
|
||||
case 2:
|
||||
*c++ = printable_char(*cp++);
|
||||
addr++;
|
||||
case 1:
|
||||
*c++ = printable_char(*cp++);
|
||||
addr++;
|
||||
break;
|
||||
}
|
||||
addr += bytesperword;
|
||||
#undef printable_char
|
||||
}
|
||||
}
|
||||
@@ -2048,7 +2033,7 @@ static int kdb_lsmod(int argc, const char **argv)
|
||||
if (mod->state == MODULE_STATE_UNFORMED)
|
||||
continue;
|
||||
|
||||
kdb_printf("%-20s%8u 0x%p ", mod->name,
|
||||
kdb_printf("%-20s%8u 0x%px ", mod->name,
|
||||
mod->core_layout.size, (void *)mod);
|
||||
#ifdef CONFIG_MODULE_UNLOAD
|
||||
kdb_printf("%4d ", module_refcount(mod));
|
||||
@@ -2059,7 +2044,7 @@ static int kdb_lsmod(int argc, const char **argv)
|
||||
kdb_printf(" (Loading)");
|
||||
else
|
||||
kdb_printf(" (Live)");
|
||||
kdb_printf(" 0x%p", mod->core_layout.base);
|
||||
kdb_printf(" 0x%px", mod->core_layout.base);
|
||||
|
||||
#ifdef CONFIG_MODULE_UNLOAD
|
||||
{
|
||||
@@ -2341,7 +2326,7 @@ void kdb_ps1(const struct task_struct *p)
|
||||
return;
|
||||
|
||||
cpu = kdb_process_cpu(p);
|
||||
kdb_printf("0x%p %8d %8d %d %4d %c 0x%p %c%s\n",
|
||||
kdb_printf("0x%px %8d %8d %d %4d %c 0x%px %c%s\n",
|
||||
(void *)p, p->pid, p->parent->pid,
|
||||
kdb_task_has_cpu(p), kdb_process_cpu(p),
|
||||
kdb_task_state_char(p),
|
||||
@@ -2354,7 +2339,7 @@ void kdb_ps1(const struct task_struct *p)
|
||||
} else {
|
||||
if (KDB_TSK(cpu) != p)
|
||||
kdb_printf(" Error: does not match running "
|
||||
"process table (0x%p)\n", KDB_TSK(cpu));
|
||||
"process table (0x%px)\n", KDB_TSK(cpu));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2687,7 +2672,7 @@ int kdb_register_flags(char *cmd,
|
||||
for_each_kdbcmd(kp, i) {
|
||||
if (kp->cmd_name && (strcmp(kp->cmd_name, cmd) == 0)) {
|
||||
kdb_printf("Duplicate kdb command registered: "
|
||||
"%s, func %p help %s\n", cmd, func, help);
|
||||
"%s, func %px help %s\n", cmd, func, help);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@@ -83,7 +83,7 @@ typedef struct __ksymtab {
|
||||
unsigned long sym_start;
|
||||
unsigned long sym_end;
|
||||
} kdb_symtab_t;
|
||||
extern int kallsyms_symbol_next(char *prefix_name, int flag);
|
||||
extern int kallsyms_symbol_next(char *prefix_name, int flag, int buf_size);
|
||||
extern int kallsyms_symbol_complete(char *prefix_name, int max_len);
|
||||
|
||||
/* Exported Symbols for kernel loadable modules to use. */
|
||||
|
@@ -40,7 +40,7 @@
|
||||
int kdbgetsymval(const char *symname, kdb_symtab_t *symtab)
|
||||
{
|
||||
if (KDB_DEBUG(AR))
|
||||
kdb_printf("kdbgetsymval: symname=%s, symtab=%p\n", symname,
|
||||
kdb_printf("kdbgetsymval: symname=%s, symtab=%px\n", symname,
|
||||
symtab);
|
||||
memset(symtab, 0, sizeof(*symtab));
|
||||
symtab->sym_start = kallsyms_lookup_name(symname);
|
||||
@@ -88,7 +88,7 @@ int kdbnearsym(unsigned long addr, kdb_symtab_t *symtab)
|
||||
char *knt1 = NULL;
|
||||
|
||||
if (KDB_DEBUG(AR))
|
||||
kdb_printf("kdbnearsym: addr=0x%lx, symtab=%p\n", addr, symtab);
|
||||
kdb_printf("kdbnearsym: addr=0x%lx, symtab=%px\n", addr, symtab);
|
||||
memset(symtab, 0, sizeof(*symtab));
|
||||
|
||||
if (addr < 4096)
|
||||
@@ -149,7 +149,7 @@ int kdbnearsym(unsigned long addr, kdb_symtab_t *symtab)
|
||||
symtab->mod_name = "kernel";
|
||||
if (KDB_DEBUG(AR))
|
||||
kdb_printf("kdbnearsym: returns %d symtab->sym_start=0x%lx, "
|
||||
"symtab->mod_name=%p, symtab->sym_name=%p (%s)\n", ret,
|
||||
"symtab->mod_name=%px, symtab->sym_name=%px (%s)\n", ret,
|
||||
symtab->sym_start, symtab->mod_name, symtab->sym_name,
|
||||
symtab->sym_name);
|
||||
|
||||
@@ -221,11 +221,13 @@ int kallsyms_symbol_complete(char *prefix_name, int max_len)
|
||||
* Parameters:
|
||||
* prefix_name prefix of a symbol name to lookup
|
||||
* flag 0 means search from the head, 1 means continue search.
|
||||
* buf_size maximum length that can be written to prefix_name
|
||||
* buffer
|
||||
* Returns:
|
||||
* 1 if a symbol matches the given prefix.
|
||||
* 0 if no string found
|
||||
*/
|
||||
int kallsyms_symbol_next(char *prefix_name, int flag)
|
||||
int kallsyms_symbol_next(char *prefix_name, int flag, int buf_size)
|
||||
{
|
||||
int prefix_len = strlen(prefix_name);
|
||||
static loff_t pos;
|
||||
@@ -235,10 +237,8 @@ int kallsyms_symbol_next(char *prefix_name, int flag)
|
||||
pos = 0;
|
||||
|
||||
while ((name = kdb_walk_kallsyms(&pos))) {
|
||||
if (strncmp(name, prefix_name, prefix_len) == 0) {
|
||||
strncpy(prefix_name, name, strlen(name)+1);
|
||||
return 1;
|
||||
}
|
||||
if (!strncmp(name, prefix_name, prefix_len))
|
||||
return strscpy(prefix_name, name, buf_size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -432,7 +432,7 @@ int kdb_getphysword(unsigned long *word, unsigned long addr, size_t size)
|
||||
*word = w8;
|
||||
break;
|
||||
}
|
||||
/* drop through */
|
||||
/* fall through */
|
||||
default:
|
||||
diag = KDB_BADWIDTH;
|
||||
kdb_printf("kdb_getphysword: bad width %ld\n", (long) size);
|
||||
@@ -481,7 +481,7 @@ int kdb_getword(unsigned long *word, unsigned long addr, size_t size)
|
||||
*word = w8;
|
||||
break;
|
||||
}
|
||||
/* drop through */
|
||||
/* fall through */
|
||||
default:
|
||||
diag = KDB_BADWIDTH;
|
||||
kdb_printf("kdb_getword: bad width %ld\n", (long) size);
|
||||
@@ -525,7 +525,7 @@ int kdb_putword(unsigned long addr, unsigned long word, size_t size)
|
||||
diag = kdb_putarea(addr, w8);
|
||||
break;
|
||||
}
|
||||
/* drop through */
|
||||
/* fall through */
|
||||
default:
|
||||
diag = KDB_BADWIDTH;
|
||||
kdb_printf("kdb_putword: bad width %ld\n", (long) size);
|
||||
@@ -887,13 +887,13 @@ void debug_kusage(void)
|
||||
__func__, dah_first);
|
||||
if (dah_first) {
|
||||
h_used = (struct debug_alloc_header *)debug_alloc_pool;
|
||||
kdb_printf("%s: h_used %p size %d\n", __func__, h_used,
|
||||
kdb_printf("%s: h_used %px size %d\n", __func__, h_used,
|
||||
h_used->size);
|
||||
}
|
||||
do {
|
||||
h_used = (struct debug_alloc_header *)
|
||||
((char *)h_free + dah_overhead + h_free->size);
|
||||
kdb_printf("%s: h_used %p size %d caller %p\n",
|
||||
kdb_printf("%s: h_used %px size %d caller %px\n",
|
||||
__func__, h_used, h_used->size, h_used->caller);
|
||||
h_free = (struct debug_alloc_header *)
|
||||
(debug_alloc_pool + h_free->next);
|
||||
@@ -902,7 +902,7 @@ void debug_kusage(void)
|
||||
((char *)h_free + dah_overhead + h_free->size);
|
||||
if ((char *)h_used - debug_alloc_pool !=
|
||||
sizeof(debug_alloc_pool_aligned))
|
||||
kdb_printf("%s: h_used %p size %d caller %p\n",
|
||||
kdb_printf("%s: h_used %px size %d caller %px\n",
|
||||
__func__, h_used, h_used->size, h_used->caller);
|
||||
out:
|
||||
spin_unlock(&dap_lock);
|
||||
|
@@ -679,7 +679,8 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
|
||||
}
|
||||
|
||||
if (!dev_is_dma_coherent(dev) &&
|
||||
(attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
|
||||
(attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0 &&
|
||||
dev_addr != DIRECT_MAPPING_ERROR)
|
||||
arch_sync_dma_for_device(dev, phys, size, dir);
|
||||
|
||||
return dev_addr;
|
||||
|
@@ -829,7 +829,7 @@ static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
|
||||
BUG_ON((uprobe->offset & ~PAGE_MASK) +
|
||||
UPROBE_SWBP_INSN_SIZE > PAGE_SIZE);
|
||||
|
||||
smp_wmb(); /* pairs with rmb() in find_active_uprobe() */
|
||||
smp_wmb(); /* pairs with the smp_rmb() in handle_swbp() */
|
||||
set_bit(UPROBE_COPY_INSN, &uprobe->flags);
|
||||
|
||||
out:
|
||||
@@ -2178,10 +2178,18 @@ static void handle_swbp(struct pt_regs *regs)
|
||||
* After we hit the bp, _unregister + _register can install the
|
||||
* new and not-yet-analyzed uprobe at the same address, restart.
|
||||
*/
|
||||
smp_rmb(); /* pairs with wmb() in install_breakpoint() */
|
||||
if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags)))
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Pairs with the smp_wmb() in prepare_uprobe().
|
||||
*
|
||||
* Guarantees that if we see the UPROBE_COPY_INSN bit set, then
|
||||
* we must also see the stores to &uprobe->arch performed by the
|
||||
* prepare_uprobe() call.
|
||||
*/
|
||||
smp_rmb();
|
||||
|
||||
/* Tracing handlers use ->utask to communicate with fetch methods */
|
||||
if (!get_utask())
|
||||
goto out;
|
||||
|
@@ -56,7 +56,7 @@ struct kcov {
|
||||
struct task_struct *t;
|
||||
};
|
||||
|
||||
static bool check_kcov_mode(enum kcov_mode needed_mode, struct task_struct *t)
|
||||
static notrace bool check_kcov_mode(enum kcov_mode needed_mode, struct task_struct *t)
|
||||
{
|
||||
unsigned int mode;
|
||||
|
||||
@@ -78,7 +78,7 @@ static bool check_kcov_mode(enum kcov_mode needed_mode, struct task_struct *t)
|
||||
return mode == needed_mode;
|
||||
}
|
||||
|
||||
static unsigned long canonicalize_ip(unsigned long ip)
|
||||
static notrace unsigned long canonicalize_ip(unsigned long ip)
|
||||
{
|
||||
#ifdef CONFIG_RANDOMIZE_BASE
|
||||
ip -= kaslr_offset();
|
||||
|
@@ -261,9 +261,6 @@ static int ptrace_check_attach(struct task_struct *child, bool ignore_state)
|
||||
|
||||
static int ptrace_has_cap(struct user_namespace *ns, unsigned int mode)
|
||||
{
|
||||
if (mode & PTRACE_MODE_SCHED)
|
||||
return false;
|
||||
|
||||
if (mode & PTRACE_MODE_NOAUDIT)
|
||||
return has_ns_capability_noaudit(current, ns, CAP_SYS_PTRACE);
|
||||
else
|
||||
@@ -331,16 +328,9 @@ ok:
|
||||
!ptrace_has_cap(mm->user_ns, mode)))
|
||||
return -EPERM;
|
||||
|
||||
if (mode & PTRACE_MODE_SCHED)
|
||||
return 0;
|
||||
return security_ptrace_access_check(task, mode);
|
||||
}
|
||||
|
||||
bool ptrace_may_access_sched(struct task_struct *task, unsigned int mode)
|
||||
{
|
||||
return __ptrace_may_access(task, mode | PTRACE_MODE_SCHED);
|
||||
}
|
||||
|
||||
bool ptrace_may_access(struct task_struct *task, unsigned int mode)
|
||||
{
|
||||
int err;
|
||||
|
@@ -319,16 +319,23 @@ int release_resource(struct resource *old)
|
||||
EXPORT_SYMBOL(release_resource);
|
||||
|
||||
/**
|
||||
* Finds the lowest iomem resource that covers part of [start..end]. The
|
||||
* caller must specify start, end, flags, and desc (which may be
|
||||
* Finds the lowest iomem resource that covers part of [@start..@end]. The
|
||||
* caller must specify @start, @end, @flags, and @desc (which may be
|
||||
* IORES_DESC_NONE).
|
||||
*
|
||||
* If a resource is found, returns 0 and *res is overwritten with the part
|
||||
* of the resource that's within [start..end]; if none is found, returns
|
||||
* -1.
|
||||
* If a resource is found, returns 0 and @*res is overwritten with the part
|
||||
* of the resource that's within [@start..@end]; if none is found, returns
|
||||
* -1 or -EINVAL for other invalid parameters.
|
||||
*
|
||||
* This function walks the whole tree and not just first level children
|
||||
* unless @first_lvl is true.
|
||||
*
|
||||
* @start: start address of the resource searched for
|
||||
* @end: end address of same resource
|
||||
* @flags: flags which the resource must have
|
||||
* @desc: descriptor the resource must have
|
||||
* @first_lvl: walk only the first level children, if set
|
||||
* @res: return ptr, if resource found
|
||||
*/
|
||||
static int find_next_iomem_res(resource_size_t start, resource_size_t end,
|
||||
unsigned long flags, unsigned long desc,
|
||||
@@ -399,6 +406,8 @@ static int __walk_iomem_res_desc(resource_size_t start, resource_size_t end,
|
||||
* @flags: I/O resource flags
|
||||
* @start: start addr
|
||||
* @end: end addr
|
||||
* @arg: function argument for the callback @func
|
||||
* @func: callback function that is called for each qualifying resource area
|
||||
*
|
||||
* NOTE: For a new descriptor search, define a new IORES_DESC in
|
||||
* <linux/ioport.h> and set it in 'desc' of a target resource entry.
|
||||
|
@@ -5738,15 +5738,10 @@ int sched_cpu_activate(unsigned int cpu)
|
||||
|
||||
#ifdef CONFIG_SCHED_SMT
|
||||
/*
|
||||
* The sched_smt_present static key needs to be evaluated on every
|
||||
* hotplug event because at boot time SMT might be disabled when
|
||||
* the number of booted CPUs is limited.
|
||||
*
|
||||
* If then later a sibling gets hotplugged, then the key would stay
|
||||
* off and SMT scheduling would never be functional.
|
||||
* When going up, increment the number of cores with SMT present.
|
||||
*/
|
||||
if (cpumask_weight(cpu_smt_mask(cpu)) > 1)
|
||||
static_branch_enable_cpuslocked(&sched_smt_present);
|
||||
if (cpumask_weight(cpu_smt_mask(cpu)) == 2)
|
||||
static_branch_inc_cpuslocked(&sched_smt_present);
|
||||
#endif
|
||||
set_cpu_active(cpu, true);
|
||||
|
||||
@@ -5790,6 +5785,14 @@ int sched_cpu_deactivate(unsigned int cpu)
|
||||
*/
|
||||
synchronize_rcu_mult(call_rcu, call_rcu_sched);
|
||||
|
||||
#ifdef CONFIG_SCHED_SMT
|
||||
/*
|
||||
* When going down, decrement the number of cores with SMT present.
|
||||
*/
|
||||
if (cpumask_weight(cpu_smt_mask(cpu)) == 2)
|
||||
static_branch_dec_cpuslocked(&sched_smt_present);
|
||||
#endif
|
||||
|
||||
if (!sched_smp_initialized)
|
||||
return 0;
|
||||
|
||||
@@ -5851,11 +5854,14 @@ void __init sched_init_smp(void)
|
||||
/*
|
||||
* There's no userspace yet to cause hotplug operations; hence all the
|
||||
* CPU masks are stable and all blatant races in the below code cannot
|
||||
* happen.
|
||||
* happen. The hotplug lock is nevertheless taken to satisfy lockdep,
|
||||
* but there won't be any contention on it.
|
||||
*/
|
||||
cpus_read_lock();
|
||||
mutex_lock(&sched_domains_mutex);
|
||||
sched_init_domains(cpu_active_mask);
|
||||
mutex_unlock(&sched_domains_mutex);
|
||||
cpus_read_unlock();
|
||||
|
||||
/* Move init over to a non-isolated CPU */
|
||||
if (set_cpus_allowed_ptr(current, housekeeping_cpumask(HK_FLAG_DOMAIN)) < 0)
|
||||
|
@@ -2400,8 +2400,8 @@ void task_numa_fault(int last_cpupid, int mem_node, int pages, int flags)
|
||||
local = 1;
|
||||
|
||||
/*
|
||||
* Retry task to preferred node migration periodically, in case it
|
||||
* case it previously failed, or the scheduler moved us.
|
||||
* Retry to migrate task to preferred node periodically, in case it
|
||||
* previously failed, or the scheduler moved us.
|
||||
*/
|
||||
if (time_after(jiffies, p->numa_migrate_retry)) {
|
||||
task_numa_placement(p);
|
||||
@@ -5674,11 +5674,11 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p,
|
||||
return target;
|
||||
}
|
||||
|
||||
static unsigned long cpu_util_wake(int cpu, struct task_struct *p);
|
||||
static unsigned long cpu_util_without(int cpu, struct task_struct *p);
|
||||
|
||||
static unsigned long capacity_spare_wake(int cpu, struct task_struct *p)
|
||||
static unsigned long capacity_spare_without(int cpu, struct task_struct *p)
|
||||
{
|
||||
return max_t(long, capacity_of(cpu) - cpu_util_wake(cpu, p), 0);
|
||||
return max_t(long, capacity_of(cpu) - cpu_util_without(cpu, p), 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -5738,7 +5738,7 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p,
|
||||
|
||||
avg_load += cfs_rq_load_avg(&cpu_rq(i)->cfs);
|
||||
|
||||
spare_cap = capacity_spare_wake(i, p);
|
||||
spare_cap = capacity_spare_without(i, p);
|
||||
|
||||
if (spare_cap > max_spare_cap)
|
||||
max_spare_cap = spare_cap;
|
||||
@@ -5889,8 +5889,8 @@ static inline int find_idlest_cpu(struct sched_domain *sd, struct task_struct *p
|
||||
return prev_cpu;
|
||||
|
||||
/*
|
||||
* We need task's util for capacity_spare_wake, sync it up to prev_cpu's
|
||||
* last_update_time.
|
||||
* We need task's util for capacity_spare_without, sync it up to
|
||||
* prev_cpu's last_update_time.
|
||||
*/
|
||||
if (!(sd_flag & SD_BALANCE_FORK))
|
||||
sync_entity_load_avg(&p->se);
|
||||
@@ -6216,10 +6216,19 @@ static inline unsigned long cpu_util(int cpu)
|
||||
}
|
||||
|
||||
/*
|
||||
* cpu_util_wake: Compute CPU utilization with any contributions from
|
||||
* the waking task p removed.
|
||||
* cpu_util_without: compute cpu utilization without any contributions from *p
|
||||
* @cpu: the CPU which utilization is requested
|
||||
* @p: the task which utilization should be discounted
|
||||
*
|
||||
* The utilization of a CPU is defined by the utilization of tasks currently
|
||||
* enqueued on that CPU as well as tasks which are currently sleeping after an
|
||||
* execution on that CPU.
|
||||
*
|
||||
* This method returns the utilization of the specified CPU by discounting the
|
||||
* utilization of the specified task, whenever the task is currently
|
||||
* contributing to the CPU utilization.
|
||||
*/
|
||||
static unsigned long cpu_util_wake(int cpu, struct task_struct *p)
|
||||
static unsigned long cpu_util_without(int cpu, struct task_struct *p)
|
||||
{
|
||||
struct cfs_rq *cfs_rq;
|
||||
unsigned int util;
|
||||
@@ -6231,7 +6240,7 @@ static unsigned long cpu_util_wake(int cpu, struct task_struct *p)
|
||||
cfs_rq = &cpu_rq(cpu)->cfs;
|
||||
util = READ_ONCE(cfs_rq->avg.util_avg);
|
||||
|
||||
/* Discount task's blocked util from CPU's util */
|
||||
/* Discount task's util from CPU's util */
|
||||
util -= min_t(unsigned int, util, task_util(p));
|
||||
|
||||
/*
|
||||
@@ -6240,14 +6249,14 @@ static unsigned long cpu_util_wake(int cpu, struct task_struct *p)
|
||||
* a) if *p is the only task sleeping on this CPU, then:
|
||||
* cpu_util (== task_util) > util_est (== 0)
|
||||
* and thus we return:
|
||||
* cpu_util_wake = (cpu_util - task_util) = 0
|
||||
* cpu_util_without = (cpu_util - task_util) = 0
|
||||
*
|
||||
* b) if other tasks are SLEEPING on this CPU, which is now exiting
|
||||
* IDLE, then:
|
||||
* cpu_util >= task_util
|
||||
* cpu_util > util_est (== 0)
|
||||
* and thus we discount *p's blocked utilization to return:
|
||||
* cpu_util_wake = (cpu_util - task_util) >= 0
|
||||
* cpu_util_without = (cpu_util - task_util) >= 0
|
||||
*
|
||||
* c) if other tasks are RUNNABLE on that CPU and
|
||||
* util_est > cpu_util
|
||||
@@ -6260,8 +6269,33 @@ static unsigned long cpu_util_wake(int cpu, struct task_struct *p)
|
||||
* covered by the following code when estimated utilization is
|
||||
* enabled.
|
||||
*/
|
||||
if (sched_feat(UTIL_EST))
|
||||
util = max(util, READ_ONCE(cfs_rq->avg.util_est.enqueued));
|
||||
if (sched_feat(UTIL_EST)) {
|
||||
unsigned int estimated =
|
||||
READ_ONCE(cfs_rq->avg.util_est.enqueued);
|
||||
|
||||
/*
|
||||
* Despite the following checks we still have a small window
|
||||
* for a possible race, when an execl's select_task_rq_fair()
|
||||
* races with LB's detach_task():
|
||||
*
|
||||
* detach_task()
|
||||
* p->on_rq = TASK_ON_RQ_MIGRATING;
|
||||
* ---------------------------------- A
|
||||
* deactivate_task() \
|
||||
* dequeue_task() + RaceTime
|
||||
* util_est_dequeue() /
|
||||
* ---------------------------------- B
|
||||
*
|
||||
* The additional check on "current == p" it's required to
|
||||
* properly fix the execl regression and it helps in further
|
||||
* reducing the chances for the above race.
|
||||
*/
|
||||
if (unlikely(task_on_rq_queued(p) || current == p)) {
|
||||
estimated -= min_t(unsigned int, estimated,
|
||||
(_task_util_est(p) | UTIL_AVG_UNCHANGED));
|
||||
}
|
||||
util = max(util, estimated);
|
||||
}
|
||||
|
||||
/*
|
||||
* Utilization (estimated) can exceed the CPU capacity, thus let's
|
||||
|
@@ -136,8 +136,18 @@
|
||||
|
||||
static int psi_bug __read_mostly;
|
||||
|
||||
bool psi_disabled __read_mostly;
|
||||
core_param(psi_disabled, psi_disabled, bool, 0644);
|
||||
DEFINE_STATIC_KEY_FALSE(psi_disabled);
|
||||
|
||||
#ifdef CONFIG_PSI_DEFAULT_DISABLED
|
||||
bool psi_enable;
|
||||
#else
|
||||
bool psi_enable = true;
|
||||
#endif
|
||||
static int __init setup_psi(char *str)
|
||||
{
|
||||
return kstrtobool(str, &psi_enable) == 0;
|
||||
}
|
||||
__setup("psi=", setup_psi);
|
||||
|
||||
/* Running averages - we need to be higher-res than loadavg */
|
||||
#define PSI_FREQ (2*HZ+1) /* 2 sec intervals */
|
||||
@@ -169,8 +179,10 @@ static void group_init(struct psi_group *group)
|
||||
|
||||
void __init psi_init(void)
|
||||
{
|
||||
if (psi_disabled)
|
||||
if (!psi_enable) {
|
||||
static_branch_enable(&psi_disabled);
|
||||
return;
|
||||
}
|
||||
|
||||
psi_period = jiffies_to_nsecs(PSI_FREQ);
|
||||
group_init(&psi_system);
|
||||
@@ -549,7 +561,7 @@ void psi_memstall_enter(unsigned long *flags)
|
||||
struct rq_flags rf;
|
||||
struct rq *rq;
|
||||
|
||||
if (psi_disabled)
|
||||
if (static_branch_likely(&psi_disabled))
|
||||
return;
|
||||
|
||||
*flags = current->flags & PF_MEMSTALL;
|
||||
@@ -579,7 +591,7 @@ void psi_memstall_leave(unsigned long *flags)
|
||||
struct rq_flags rf;
|
||||
struct rq *rq;
|
||||
|
||||
if (psi_disabled)
|
||||
if (static_branch_likely(&psi_disabled))
|
||||
return;
|
||||
|
||||
if (*flags)
|
||||
@@ -600,7 +612,7 @@ void psi_memstall_leave(unsigned long *flags)
|
||||
#ifdef CONFIG_CGROUPS
|
||||
int psi_cgroup_alloc(struct cgroup *cgroup)
|
||||
{
|
||||
if (psi_disabled)
|
||||
if (static_branch_likely(&psi_disabled))
|
||||
return 0;
|
||||
|
||||
cgroup->psi.pcpu = alloc_percpu(struct psi_group_cpu);
|
||||
@@ -612,7 +624,7 @@ int psi_cgroup_alloc(struct cgroup *cgroup)
|
||||
|
||||
void psi_cgroup_free(struct cgroup *cgroup)
|
||||
{
|
||||
if (psi_disabled)
|
||||
if (static_branch_likely(&psi_disabled))
|
||||
return;
|
||||
|
||||
cancel_delayed_work_sync(&cgroup->psi.clock_work);
|
||||
@@ -633,38 +645,39 @@ void psi_cgroup_free(struct cgroup *cgroup)
|
||||
*/
|
||||
void cgroup_move_task(struct task_struct *task, struct css_set *to)
|
||||
{
|
||||
bool move_psi = !psi_disabled;
|
||||
unsigned int task_flags = 0;
|
||||
struct rq_flags rf;
|
||||
struct rq *rq;
|
||||
|
||||
if (move_psi) {
|
||||
rq = task_rq_lock(task, &rf);
|
||||
|
||||
if (task_on_rq_queued(task))
|
||||
task_flags = TSK_RUNNING;
|
||||
else if (task->in_iowait)
|
||||
task_flags = TSK_IOWAIT;
|
||||
|
||||
if (task->flags & PF_MEMSTALL)
|
||||
task_flags |= TSK_MEMSTALL;
|
||||
|
||||
if (task_flags)
|
||||
psi_task_change(task, task_flags, 0);
|
||||
if (static_branch_likely(&psi_disabled)) {
|
||||
/*
|
||||
* Lame to do this here, but the scheduler cannot be locked
|
||||
* from the outside, so we move cgroups from inside sched/.
|
||||
*/
|
||||
rcu_assign_pointer(task->cgroups, to);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lame to do this here, but the scheduler cannot be locked
|
||||
* from the outside, so we move cgroups from inside sched/.
|
||||
*/
|
||||
rq = task_rq_lock(task, &rf);
|
||||
|
||||
if (task_on_rq_queued(task))
|
||||
task_flags = TSK_RUNNING;
|
||||
else if (task->in_iowait)
|
||||
task_flags = TSK_IOWAIT;
|
||||
|
||||
if (task->flags & PF_MEMSTALL)
|
||||
task_flags |= TSK_MEMSTALL;
|
||||
|
||||
if (task_flags)
|
||||
psi_task_change(task, task_flags, 0);
|
||||
|
||||
/* See comment above */
|
||||
rcu_assign_pointer(task->cgroups, to);
|
||||
|
||||
if (move_psi) {
|
||||
if (task_flags)
|
||||
psi_task_change(task, 0, task_flags);
|
||||
if (task_flags)
|
||||
psi_task_change(task, 0, task_flags);
|
||||
|
||||
task_rq_unlock(rq, task, &rf);
|
||||
}
|
||||
task_rq_unlock(rq, task, &rf);
|
||||
}
|
||||
#endif /* CONFIG_CGROUPS */
|
||||
|
||||
@@ -672,7 +685,7 @@ int psi_show(struct seq_file *m, struct psi_group *group, enum psi_res res)
|
||||
{
|
||||
int full;
|
||||
|
||||
if (psi_disabled)
|
||||
if (static_branch_likely(&psi_disabled))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
update_stats(group);
|
||||
|
@@ -23,6 +23,7 @@
|
||||
#include <linux/sched/prio.h>
|
||||
#include <linux/sched/rt.h>
|
||||
#include <linux/sched/signal.h>
|
||||
#include <linux/sched/smt.h>
|
||||
#include <linux/sched/stat.h>
|
||||
#include <linux/sched/sysctl.h>
|
||||
#include <linux/sched/task.h>
|
||||
@@ -936,9 +937,6 @@ static inline int cpu_of(struct rq *rq)
|
||||
|
||||
|
||||
#ifdef CONFIG_SCHED_SMT
|
||||
|
||||
extern struct static_key_false sched_smt_present;
|
||||
|
||||
extern void __update_idle_core(struct rq *rq);
|
||||
|
||||
static inline void update_idle_core(struct rq *rq)
|
||||
|
@@ -66,7 +66,7 @@ static inline void psi_enqueue(struct task_struct *p, bool wakeup)
|
||||
{
|
||||
int clear = 0, set = TSK_RUNNING;
|
||||
|
||||
if (psi_disabled)
|
||||
if (static_branch_likely(&psi_disabled))
|
||||
return;
|
||||
|
||||
if (!wakeup || p->sched_psi_wake_requeue) {
|
||||
@@ -86,7 +86,7 @@ static inline void psi_dequeue(struct task_struct *p, bool sleep)
|
||||
{
|
||||
int clear = TSK_RUNNING, set = 0;
|
||||
|
||||
if (psi_disabled)
|
||||
if (static_branch_likely(&psi_disabled))
|
||||
return;
|
||||
|
||||
if (!sleep) {
|
||||
@@ -102,7 +102,7 @@ static inline void psi_dequeue(struct task_struct *p, bool sleep)
|
||||
|
||||
static inline void psi_ttwu_dequeue(struct task_struct *p)
|
||||
{
|
||||
if (psi_disabled)
|
||||
if (static_branch_likely(&psi_disabled))
|
||||
return;
|
||||
/*
|
||||
* Is the task being migrated during a wakeup? Make sure to
|
||||
@@ -128,7 +128,7 @@ static inline void psi_ttwu_dequeue(struct task_struct *p)
|
||||
|
||||
static inline void psi_task_tick(struct rq *rq)
|
||||
{
|
||||
if (psi_disabled)
|
||||
if (static_branch_likely(&psi_disabled))
|
||||
return;
|
||||
|
||||
if (unlikely(rq->curr->flags & PF_MEMSTALL))
|
||||
|
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/stackleak.h>
|
||||
#include <linux/kprobes.h>
|
||||
|
||||
#ifdef CONFIG_STACKLEAK_RUNTIME_DISABLE
|
||||
#include <linux/jump_label.h>
|
||||
@@ -47,7 +48,7 @@ int stack_erasing_sysctl(struct ctl_table *table, int write,
|
||||
#define skip_erasing() false
|
||||
#endif /* CONFIG_STACKLEAK_RUNTIME_DISABLE */
|
||||
|
||||
asmlinkage void stackleak_erase(void)
|
||||
asmlinkage void notrace stackleak_erase(void)
|
||||
{
|
||||
/* It would be nice not to have 'kstack_ptr' and 'boundary' on stack */
|
||||
unsigned long kstack_ptr = current->lowest_stack;
|
||||
@@ -101,6 +102,7 @@ asmlinkage void stackleak_erase(void)
|
||||
/* Reset the 'lowest_stack' value for the next syscall */
|
||||
current->lowest_stack = current_top_of_stack() - THREAD_SIZE/64;
|
||||
}
|
||||
NOKPROBE_SYMBOL(stackleak_erase);
|
||||
|
||||
void __used stackleak_track_stack(void)
|
||||
{
|
||||
|
@@ -917,9 +917,6 @@ static void check_process_timers(struct task_struct *tsk,
|
||||
struct task_cputime cputime;
|
||||
unsigned long soft;
|
||||
|
||||
if (dl_task(tsk))
|
||||
check_dl_overrun(tsk);
|
||||
|
||||
/*
|
||||
* If cputimer is not running, then there are no active
|
||||
* process wide timers (POSIX 1.b, itimers, RLIMIT_CPU).
|
||||
|
@@ -196,11 +196,13 @@ BPF_CALL_5(bpf_trace_printk, char *, fmt, u32, fmt_size, u64, arg1,
|
||||
i++;
|
||||
} else if (fmt[i] == 'p' || fmt[i] == 's') {
|
||||
mod[fmt_cnt]++;
|
||||
i++;
|
||||
if (!isspace(fmt[i]) && !ispunct(fmt[i]) && fmt[i] != 0)
|
||||
/* disallow any further format extensions */
|
||||
if (fmt[i + 1] != 0 &&
|
||||
!isspace(fmt[i + 1]) &&
|
||||
!ispunct(fmt[i + 1]))
|
||||
return -EINVAL;
|
||||
fmt_cnt++;
|
||||
if (fmt[i - 1] == 's') {
|
||||
if (fmt[i] == 's') {
|
||||
if (str_seen)
|
||||
/* allow only one '%s' per fmt string */
|
||||
return -EINVAL;
|
||||
|
@@ -817,7 +817,7 @@ function_profile_call(unsigned long ip, unsigned long parent_ip,
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
static int profile_graph_entry(struct ftrace_graph_ent *trace)
|
||||
{
|
||||
int index = trace->depth;
|
||||
int index = current->curr_ret_stack;
|
||||
|
||||
function_profile_call(trace->func, 0, NULL, NULL);
|
||||
|
||||
@@ -852,7 +852,7 @@ static void profile_graph_return(struct ftrace_graph_ret *trace)
|
||||
if (!fgraph_graph_time) {
|
||||
int index;
|
||||
|
||||
index = trace->depth;
|
||||
index = current->curr_ret_stack;
|
||||
|
||||
/* Append this call time to the parent time to subtract */
|
||||
if (index)
|
||||
@@ -6814,6 +6814,7 @@ static int alloc_retstack_tasklist(struct ftrace_ret_stack **ret_stack_list)
|
||||
atomic_set(&t->tracing_graph_pause, 0);
|
||||
atomic_set(&t->trace_overrun, 0);
|
||||
t->curr_ret_stack = -1;
|
||||
t->curr_ret_depth = -1;
|
||||
/* Make sure the tasks see the -1 first: */
|
||||
smp_wmb();
|
||||
t->ret_stack = ret_stack_list[start++];
|
||||
@@ -7038,6 +7039,7 @@ graph_init_task(struct task_struct *t, struct ftrace_ret_stack *ret_stack)
|
||||
void ftrace_graph_init_idle_task(struct task_struct *t, int cpu)
|
||||
{
|
||||
t->curr_ret_stack = -1;
|
||||
t->curr_ret_depth = -1;
|
||||
/*
|
||||
* The idle task has no parent, it either has its own
|
||||
* stack or no stack at all.
|
||||
@@ -7068,6 +7070,7 @@ void ftrace_graph_init_task(struct task_struct *t)
|
||||
/* Make sure we do not use the parent ret_stack */
|
||||
t->ret_stack = NULL;
|
||||
t->curr_ret_stack = -1;
|
||||
t->curr_ret_depth = -1;
|
||||
|
||||
if (ftrace_graph_active) {
|
||||
struct ftrace_ret_stack *ret_stack;
|
||||
|
@@ -512,12 +512,44 @@ enum {
|
||||
* can only be modified by current, we can reuse trace_recursion.
|
||||
*/
|
||||
TRACE_IRQ_BIT,
|
||||
|
||||
/* Set if the function is in the set_graph_function file */
|
||||
TRACE_GRAPH_BIT,
|
||||
|
||||
/*
|
||||
* In the very unlikely case that an interrupt came in
|
||||
* at a start of graph tracing, and we want to trace
|
||||
* the function in that interrupt, the depth can be greater
|
||||
* than zero, because of the preempted start of a previous
|
||||
* trace. In an even more unlikely case, depth could be 2
|
||||
* if a softirq interrupted the start of graph tracing,
|
||||
* followed by an interrupt preempting a start of graph
|
||||
* tracing in the softirq, and depth can even be 3
|
||||
* if an NMI came in at the start of an interrupt function
|
||||
* that preempted a softirq start of a function that
|
||||
* preempted normal context!!!! Luckily, it can't be
|
||||
* greater than 3, so the next two bits are a mask
|
||||
* of what the depth is when we set TRACE_GRAPH_BIT
|
||||
*/
|
||||
|
||||
TRACE_GRAPH_DEPTH_START_BIT,
|
||||
TRACE_GRAPH_DEPTH_END_BIT,
|
||||
};
|
||||
|
||||
#define trace_recursion_set(bit) do { (current)->trace_recursion |= (1<<(bit)); } while (0)
|
||||
#define trace_recursion_clear(bit) do { (current)->trace_recursion &= ~(1<<(bit)); } while (0)
|
||||
#define trace_recursion_test(bit) ((current)->trace_recursion & (1<<(bit)))
|
||||
|
||||
#define trace_recursion_depth() \
|
||||
(((current)->trace_recursion >> TRACE_GRAPH_DEPTH_START_BIT) & 3)
|
||||
#define trace_recursion_set_depth(depth) \
|
||||
do { \
|
||||
current->trace_recursion &= \
|
||||
~(3 << TRACE_GRAPH_DEPTH_START_BIT); \
|
||||
current->trace_recursion |= \
|
||||
((depth) & 3) << TRACE_GRAPH_DEPTH_START_BIT; \
|
||||
} while (0)
|
||||
|
||||
#define TRACE_CONTEXT_BITS 4
|
||||
|
||||
#define TRACE_FTRACE_START TRACE_FTRACE_BIT
|
||||
@@ -843,8 +875,9 @@ extern void __trace_graph_return(struct trace_array *tr,
|
||||
extern struct ftrace_hash *ftrace_graph_hash;
|
||||
extern struct ftrace_hash *ftrace_graph_notrace_hash;
|
||||
|
||||
static inline int ftrace_graph_addr(unsigned long addr)
|
||||
static inline int ftrace_graph_addr(struct ftrace_graph_ent *trace)
|
||||
{
|
||||
unsigned long addr = trace->func;
|
||||
int ret = 0;
|
||||
|
||||
preempt_disable_notrace();
|
||||
@@ -855,6 +888,14 @@ static inline int ftrace_graph_addr(unsigned long addr)
|
||||
}
|
||||
|
||||
if (ftrace_lookup_ip(ftrace_graph_hash, addr)) {
|
||||
|
||||
/*
|
||||
* This needs to be cleared on the return functions
|
||||
* when the depth is zero.
|
||||
*/
|
||||
trace_recursion_set(TRACE_GRAPH_BIT);
|
||||
trace_recursion_set_depth(trace->depth);
|
||||
|
||||
/*
|
||||
* If no irqs are to be traced, but a set_graph_function
|
||||
* is set, and called by an interrupt handler, we still
|
||||
@@ -872,6 +913,13 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void ftrace_graph_addr_finish(struct ftrace_graph_ret *trace)
|
||||
{
|
||||
if (trace_recursion_test(TRACE_GRAPH_BIT) &&
|
||||
trace->depth == trace_recursion_depth())
|
||||
trace_recursion_clear(TRACE_GRAPH_BIT);
|
||||
}
|
||||
|
||||
static inline int ftrace_graph_notrace_addr(unsigned long addr)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -885,7 +933,7 @@ static inline int ftrace_graph_notrace_addr(unsigned long addr)
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
static inline int ftrace_graph_addr(unsigned long addr)
|
||||
static inline int ftrace_graph_addr(struct ftrace_graph_ent *trace)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@@ -894,6 +942,8 @@ static inline int ftrace_graph_notrace_addr(unsigned long addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void ftrace_graph_addr_finish(struct ftrace_graph_ret *trace)
|
||||
{ }
|
||||
#endif /* CONFIG_DYNAMIC_FTRACE */
|
||||
|
||||
extern unsigned int fgraph_max_depth;
|
||||
@@ -901,7 +951,8 @@ extern unsigned int fgraph_max_depth;
|
||||
static inline bool ftrace_graph_ignore_func(struct ftrace_graph_ent *trace)
|
||||
{
|
||||
/* trace it when it is-nested-in or is a function enabled. */
|
||||
return !(trace->depth || ftrace_graph_addr(trace->func)) ||
|
||||
return !(trace_recursion_test(TRACE_GRAPH_BIT) ||
|
||||
ftrace_graph_addr(trace)) ||
|
||||
(trace->depth < 0) ||
|
||||
(fgraph_max_depth && trace->depth >= fgraph_max_depth);
|
||||
}
|
||||
|
@@ -118,8 +118,8 @@ print_graph_duration(struct trace_array *tr, unsigned long long duration,
|
||||
struct trace_seq *s, u32 flags);
|
||||
|
||||
/* Add a function return address to the trace stack on thread info.*/
|
||||
int
|
||||
ftrace_push_return_trace(unsigned long ret, unsigned long func, int *depth,
|
||||
static int
|
||||
ftrace_push_return_trace(unsigned long ret, unsigned long func,
|
||||
unsigned long frame_pointer, unsigned long *retp)
|
||||
{
|
||||
unsigned long long calltime;
|
||||
@@ -177,9 +177,31 @@ ftrace_push_return_trace(unsigned long ret, unsigned long func, int *depth,
|
||||
#ifdef HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
|
||||
current->ret_stack[index].retp = retp;
|
||||
#endif
|
||||
*depth = current->curr_ret_stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int function_graph_enter(unsigned long ret, unsigned long func,
|
||||
unsigned long frame_pointer, unsigned long *retp)
|
||||
{
|
||||
struct ftrace_graph_ent trace;
|
||||
|
||||
trace.func = func;
|
||||
trace.depth = ++current->curr_ret_depth;
|
||||
|
||||
if (ftrace_push_return_trace(ret, func,
|
||||
frame_pointer, retp))
|
||||
goto out;
|
||||
|
||||
/* Only trace if the calling function expects to */
|
||||
if (!ftrace_graph_entry(&trace))
|
||||
goto out_ret;
|
||||
|
||||
return 0;
|
||||
out_ret:
|
||||
current->curr_ret_stack--;
|
||||
out:
|
||||
current->curr_ret_depth--;
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Retrieve a function return address to the trace stack on thread info.*/
|
||||
@@ -241,7 +263,13 @@ ftrace_pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret,
|
||||
trace->func = current->ret_stack[index].func;
|
||||
trace->calltime = current->ret_stack[index].calltime;
|
||||
trace->overrun = atomic_read(¤t->trace_overrun);
|
||||
trace->depth = index;
|
||||
trace->depth = current->curr_ret_depth--;
|
||||
/*
|
||||
* We still want to trace interrupts coming in if
|
||||
* max_depth is set to 1. Make sure the decrement is
|
||||
* seen before ftrace_graph_return.
|
||||
*/
|
||||
barrier();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -255,6 +283,12 @@ unsigned long ftrace_return_to_handler(unsigned long frame_pointer)
|
||||
|
||||
ftrace_pop_return_trace(&trace, &ret, frame_pointer);
|
||||
trace.rettime = trace_clock_local();
|
||||
ftrace_graph_return(&trace);
|
||||
/*
|
||||
* The ftrace_graph_return() may still access the current
|
||||
* ret_stack structure, we need to make sure the update of
|
||||
* curr_ret_stack is after that.
|
||||
*/
|
||||
barrier();
|
||||
current->curr_ret_stack--;
|
||||
/*
|
||||
@@ -267,13 +301,6 @@ unsigned long ftrace_return_to_handler(unsigned long frame_pointer)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* The trace should run after decrementing the ret counter
|
||||
* in case an interrupt were to come in. We don't want to
|
||||
* lose the interrupt if max_depth is set.
|
||||
*/
|
||||
ftrace_graph_return(&trace);
|
||||
|
||||
if (unlikely(!ret)) {
|
||||
ftrace_graph_stop();
|
||||
WARN_ON(1);
|
||||
@@ -482,6 +509,8 @@ void trace_graph_return(struct ftrace_graph_ret *trace)
|
||||
int cpu;
|
||||
int pc;
|
||||
|
||||
ftrace_graph_addr_finish(trace);
|
||||
|
||||
local_irq_save(flags);
|
||||
cpu = raw_smp_processor_id();
|
||||
data = per_cpu_ptr(tr->trace_buffer.data, cpu);
|
||||
@@ -505,6 +534,8 @@ void set_graph_array(struct trace_array *tr)
|
||||
|
||||
static void trace_graph_thresh_return(struct ftrace_graph_ret *trace)
|
||||
{
|
||||
ftrace_graph_addr_finish(trace);
|
||||
|
||||
if (tracing_thresh &&
|
||||
(trace->rettime - trace->calltime < tracing_thresh))
|
||||
return;
|
||||
|
@@ -208,6 +208,8 @@ static void irqsoff_graph_return(struct ftrace_graph_ret *trace)
|
||||
unsigned long flags;
|
||||
int pc;
|
||||
|
||||
ftrace_graph_addr_finish(trace);
|
||||
|
||||
if (!func_prolog_dec(tr, &data, &flags))
|
||||
return;
|
||||
|
||||
|
@@ -535,7 +535,7 @@ int traceprobe_update_arg(struct probe_arg *arg)
|
||||
if (code[1].op != FETCH_OP_IMM)
|
||||
return -EINVAL;
|
||||
|
||||
tmp = strpbrk("+-", code->data);
|
||||
tmp = strpbrk(code->data, "+-");
|
||||
if (tmp)
|
||||
c = *tmp;
|
||||
ret = traceprobe_split_symbol_offset(code->data,
|
||||
|
@@ -270,6 +270,8 @@ static void wakeup_graph_return(struct ftrace_graph_ret *trace)
|
||||
unsigned long flags;
|
||||
int pc;
|
||||
|
||||
ftrace_graph_addr_finish(trace);
|
||||
|
||||
if (!func_prolog_preempt_disable(tr, &data, &pc))
|
||||
return;
|
||||
|
||||
|
@@ -974,10 +974,6 @@ static ssize_t map_write(struct file *file, const char __user *buf,
|
||||
if (!new_idmap_permitted(file, ns, cap_setid, &new_map))
|
||||
goto out;
|
||||
|
||||
ret = sort_idmaps(&new_map);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = -EPERM;
|
||||
/* Map the lower ids from the parent user namespace to the
|
||||
* kernel global id space.
|
||||
@@ -1004,6 +1000,14 @@ static ssize_t map_write(struct file *file, const char __user *buf,
|
||||
e->lower_first = lower_first;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we want to use binary search for lookup, this clones the extent
|
||||
* array and sorts both copies.
|
||||
*/
|
||||
ret = sort_idmaps(&new_map);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
/* Install the map */
|
||||
if (new_map.nr_extents <= UID_GID_MAP_MAX_BASE_EXTENTS) {
|
||||
memcpy(map->extent, new_map.extent,
|
||||
|
Reference in New Issue
Block a user