Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit e6b4d47

Browse files
Tudor AmbarusTreehugger Robot
authored andcommitted
Merge 0c182ac ("Merge tag 'objtool-core-2024-07-16' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip") into android-mainline
Steps on the way to v6.11-rc1 Change-Id: I3a934f3ef3373311b33a9eb50ef65852bae58de8 Signed-off-by: Tudor Ambarus <tudordana@google.com>
2 parents 831f010 + 0c182ac commit e6b4d47

File tree

7 files changed

+148
-63
lines changed

7 files changed

+148
-63
lines changed

arch/x86/events/core.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2547,6 +2547,7 @@ static ssize_t set_attr_rdpmc(struct device *cdev,
25472547
struct device_attribute *attr,
25482548
const char *buf, size_t count)
25492549
{
2550+
static DEFINE_MUTEX(rdpmc_mutex);
25502551
unsigned long val;
25512552
ssize_t ret;
25522553

@@ -2560,6 +2561,8 @@ static ssize_t set_attr_rdpmc(struct device *cdev,
25602561
if (x86_pmu.attr_rdpmc_broken)
25612562
return -ENOTSUPP;
25622563

2564+
guard(mutex)(&rdpmc_mutex);
2565+
25632566
if (val != x86_pmu.attr_rdpmc) {
25642567
/*
25652568
* Changing into or out of never available or always available,

include/linux/cleanup.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* SPDX-License-Identifier: GPL-2.0 */
2-
#ifndef __LINUX_GUARDS_H
3-
#define __LINUX_GUARDS_H
2+
#ifndef _LINUX_CLEANUP_H
3+
#define _LINUX_CLEANUP_H
44

55
#include <linux/compiler.h>
66

@@ -250,4 +250,4 @@ __DEFINE_LOCK_GUARD_0(_name, _lock)
250250
{ return class_##_name##_lock_ptr(_T); }
251251

252252

253-
#endif /* __LINUX_GUARDS_H */
253+
#endif /* _LINUX_CLEANUP_H */

kernel/jump_label.c

Lines changed: 46 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,16 @@ bool static_key_fast_inc_not_disabled(struct static_key *key)
131131
STATIC_KEY_CHECK_USE(key);
132132
/*
133133
* Negative key->enabled has a special meaning: it sends
134-
* static_key_slow_inc() down the slow path, and it is non-zero
135-
* so it counts as "enabled" in jump_label_update(). Note that
136-
* atomic_inc_unless_negative() checks >= 0, so roll our own.
134+
* static_key_slow_inc/dec() down the slow path, and it is non-zero
135+
* so it counts as "enabled" in jump_label_update().
136+
*
137+
* The INT_MAX overflow condition is either used by the networking
138+
* code to reset or detected in the slow path of
139+
* static_key_slow_inc_cpuslocked().
137140
*/
138141
v = atomic_read(&key->enabled);
139142
do {
140-
if (v <= 0 || (v + 1) < 0)
143+
if (v <= 0 || v == INT_MAX)
141144
return false;
142145
} while (!likely(atomic_try_cmpxchg(&key->enabled, &v, v + 1)));
143146

@@ -150,7 +153,7 @@ bool static_key_slow_inc_cpuslocked(struct static_key *key)
150153
lockdep_assert_cpus_held();
151154

152155
/*
153-
* Careful if we get concurrent static_key_slow_inc() calls;
156+
* Careful if we get concurrent static_key_slow_inc/dec() calls;
154157
* later calls must wait for the first one to _finish_ the
155158
* jump_label_update() process. At the same time, however,
156159
* the jump_label_update() call below wants to see
@@ -159,22 +162,24 @@ bool static_key_slow_inc_cpuslocked(struct static_key *key)
159162
if (static_key_fast_inc_not_disabled(key))
160163
return true;
161164

162-
jump_label_lock();
163-
if (atomic_read(&key->enabled) == 0) {
164-
atomic_set(&key->enabled, -1);
165+
guard(mutex)(&jump_label_mutex);
166+
/* Try to mark it as 'enabling in progress. */
167+
if (!atomic_cmpxchg(&key->enabled, 0, -1)) {
165168
jump_label_update(key);
166169
/*
167-
* Ensure that if the above cmpxchg loop observes our positive
168-
* value, it must also observe all the text changes.
170+
* Ensure that when static_key_fast_inc_not_disabled() or
171+
* static_key_slow_try_dec() observe the positive value,
172+
* they must also observe all the text changes.
169173
*/
170174
atomic_set_release(&key->enabled, 1);
171175
} else {
172-
if (WARN_ON_ONCE(!static_key_fast_inc_not_disabled(key))) {
173-
jump_label_unlock();
176+
/*
177+
* While holding the mutex this should never observe
178+
* anything else than a value >= 1 and succeed
179+
*/
180+
if (WARN_ON_ONCE(!static_key_fast_inc_not_disabled(key)))
174181
return false;
175-
}
176182
}
177-
jump_label_unlock();
178183
return true;
179184
}
180185

@@ -247,20 +252,32 @@ EXPORT_SYMBOL_GPL(static_key_disable);
247252

248253
static bool static_key_slow_try_dec(struct static_key *key)
249254
{
250-
int val;
251-
252-
val = atomic_fetch_add_unless(&key->enabled, -1, 1);
253-
if (val == 1)
254-
return false;
255+
int v;
255256

256257
/*
257-
* The negative count check is valid even when a negative
258-
* key->enabled is in use by static_key_slow_inc(); a
259-
* __static_key_slow_dec() before the first static_key_slow_inc()
260-
* returns is unbalanced, because all other static_key_slow_inc()
261-
* instances block while the update is in progress.
258+
* Go into the slow path if key::enabled is less than or equal than
259+
* one. One is valid to shut down the key, anything less than one
260+
* is an imbalance, which is handled at the call site.
261+
*
262+
* That includes the special case of '-1' which is set in
263+
* static_key_slow_inc_cpuslocked(), but that's harmless as it is
264+
* fully serialized in the slow path below. By the time this task
265+
* acquires the jump label lock the value is back to one and the
266+
* retry under the lock must succeed.
262267
*/
263-
WARN(val < 0, "jump label: negative count!\n");
268+
v = atomic_read(&key->enabled);
269+
do {
270+
/*
271+
* Warn about the '-1' case though; since that means a
272+
* decrement is concurrent with a first (0->1) increment. IOW
273+
* people are trying to disable something that wasn't yet fully
274+
* enabled. This suggests an ordering problem on the user side.
275+
*/
276+
WARN_ON_ONCE(v < 0);
277+
if (v <= 1)
278+
return false;
279+
} while (!likely(atomic_try_cmpxchg(&key->enabled, &v, v - 1)));
280+
264281
return true;
265282
}
266283

@@ -271,10 +288,11 @@ static void __static_key_slow_dec_cpuslocked(struct static_key *key)
271288
if (static_key_slow_try_dec(key))
272289
return;
273290

274-
jump_label_lock();
275-
if (atomic_dec_and_test(&key->enabled))
291+
guard(mutex)(&jump_label_mutex);
292+
if (atomic_cmpxchg(&key->enabled, 1, 0))
276293
jump_label_update(key);
277-
jump_label_unlock();
294+
else
295+
WARN_ON_ONCE(!static_key_slow_try_dec(key));
278296
}
279297

280298
static void __static_key_slow_dec(struct static_key *key)

kernel/locking/rwsem.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,7 +1297,7 @@ static inline int __down_read_trylock(struct rw_semaphore *sem)
12971297
/*
12981298
* lock for writing
12991299
*/
1300-
static inline int __down_write_common(struct rw_semaphore *sem, int state)
1300+
static __always_inline int __down_write_common(struct rw_semaphore *sem, int state)
13011301
{
13021302
int ret = 0;
13031303

@@ -1310,12 +1310,12 @@ static inline int __down_write_common(struct rw_semaphore *sem, int state)
13101310
return ret;
13111311
}
13121312

1313-
static inline void __down_write(struct rw_semaphore *sem)
1313+
static __always_inline void __down_write(struct rw_semaphore *sem)
13141314
{
13151315
__down_write_common(sem, TASK_UNINTERRUPTIBLE);
13161316
}
13171317

1318-
static inline int __down_write_killable(struct rw_semaphore *sem)
1318+
static __always_inline int __down_write_killable(struct rw_semaphore *sem)
13191319
{
13201320
return __down_write_common(sem, TASK_KILLABLE);
13211321
}

scripts/faddr2line

Lines changed: 84 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,17 @@ command -v ${ADDR2LINE} >/dev/null 2>&1 || die "${ADDR2LINE} isn't installed"
8585
# init/main.c! This only works for vmlinux. Otherwise it falls back to
8686
# printing the absolute path.
8787
find_dir_prefix() {
88-
local objfile=$1
89-
90-
local start_kernel_addr=$(${READELF} --symbols --wide $objfile | sed 's/\[.*\]//' |
88+
local start_kernel_addr=$(echo "${ELF_SYMS}" | sed 's/\[.*\]//' |
9189
${AWK} '$8 == "start_kernel" {printf "0x%s", $2}')
9290
[[ -z $start_kernel_addr ]] && return
9391

94-
local file_line=$(${ADDR2LINE} -e $objfile $start_kernel_addr)
95-
[[ -z $file_line ]] && return
92+
run_addr2line ${start_kernel_addr} ""
93+
[[ -z $ADDR2LINE_OUT ]] && return
9694

95+
local file_line=${ADDR2LINE_OUT#* at }
96+
if [[ -z $file_line ]] || [[ $file_line = $ADDR2LINE_OUT ]]; then
97+
return
98+
fi
9799
local prefix=${file_line%init/main.c:*}
98100
if [[ -z $prefix ]] || [[ $prefix = $file_line ]]; then
99101
return
@@ -103,6 +105,71 @@ find_dir_prefix() {
103105
return 0
104106
}
105107

108+
run_readelf() {
109+
local objfile=$1
110+
local out=$(${READELF} --file-header --section-headers --symbols --wide $objfile)
111+
112+
# This assumes that readelf first prints the file header, then the section headers, then the symbols.
113+
# Note: It seems that GNU readelf does not prefix section headers with the "There are X section headers"
114+
# line when multiple options are given, so let's also match with the "Section Headers:" line.
115+
ELF_FILEHEADER=$(echo "${out}" | sed -n '/There are [0-9]* section headers, starting at offset\|Section Headers:/q;p')
116+
ELF_SECHEADERS=$(echo "${out}" | sed -n '/There are [0-9]* section headers, starting at offset\|Section Headers:/,$p' | sed -n '/Symbol table .* contains [0-9]* entries:/q;p')
117+
ELF_SYMS=$(echo "${out}" | sed -n '/Symbol table .* contains [0-9]* entries:/,$p')
118+
}
119+
120+
check_vmlinux() {
121+
# vmlinux uses absolute addresses in the section table rather than
122+
# section offsets.
123+
IS_VMLINUX=0
124+
local file_type=$(echo "${ELF_FILEHEADER}" |
125+
${AWK} '$1 == "Type:" { print $2; exit }')
126+
if [[ $file_type = "EXEC" ]] || [[ $file_type == "DYN" ]]; then
127+
IS_VMLINUX=1
128+
fi
129+
}
130+
131+
init_addr2line() {
132+
local objfile=$1
133+
134+
check_vmlinux
135+
136+
ADDR2LINE_ARGS="--functions --pretty-print --inlines --addresses --exe=$objfile"
137+
if [[ $IS_VMLINUX = 1 ]]; then
138+
# If the executable file is vmlinux, we don't pass section names to
139+
# addr2line, so we can launch it now as a single long-running process.
140+
coproc ADDR2LINE_PROC (${ADDR2LINE} ${ADDR2LINE_ARGS})
141+
fi
142+
}
143+
144+
run_addr2line() {
145+
local addr=$1
146+
local sec_name=$2
147+
148+
if [[ $IS_VMLINUX = 1 ]]; then
149+
# We send to the addr2line process: (1) the address, then (2) a sentinel
150+
# value, i.e., something that can't be interpreted as a valid address
151+
# (i.e., ","). This causes addr2line to write out: (1) the answer for
152+
# our address, then (2) either "?? ??:0" or "0x0...0: ..." (if
153+
# using binutils' addr2line), or "," (if using LLVM's addr2line).
154+
echo ${addr} >& "${ADDR2LINE_PROC[1]}"
155+
echo "," >& "${ADDR2LINE_PROC[1]}"
156+
local first_line
157+
read -r first_line <& "${ADDR2LINE_PROC[0]}"
158+
ADDR2LINE_OUT=$(echo "${first_line}" | sed 's/^0x[0-9a-fA-F]*: //')
159+
while read -r line <& "${ADDR2LINE_PROC[0]}"; do
160+
if [[ "$line" == "?? ??:0" ]] || [[ "$line" == "," ]] || [[ $(echo "$line" | ${GREP} "^0x00*: ") ]]; then
161+
break
162+
fi
163+
ADDR2LINE_OUT+=$'\n'$(echo "$line" | sed 's/^0x[0-9a-fA-F]*: //')
164+
done
165+
else
166+
# Run addr2line as a single invocation.
167+
local sec_arg
168+
[[ -z $sec_name ]] && sec_arg="" || sec_arg="--section=${sec_name}"
169+
ADDR2LINE_OUT=$(${ADDR2LINE} ${ADDR2LINE_ARGS} ${sec_arg} ${addr} | sed 's/^0x[0-9a-fA-F]*: //')
170+
fi
171+
}
172+
106173
__faddr2line() {
107174
local objfile=$1
108175
local func_addr=$2
@@ -113,8 +180,6 @@ __faddr2line() {
113180
local func_offset=${func_addr#*+}
114181
func_offset=${func_offset%/*}
115182
local user_size=
116-
local file_type
117-
local is_vmlinux=0
118183
[[ $func_addr =~ "/" ]] && user_size=${func_addr#*/}
119184

120185
if [[ -z $sym_name ]] || [[ -z $func_offset ]] || [[ $sym_name = $func_addr ]]; then
@@ -123,14 +188,6 @@ __faddr2line() {
123188
return
124189
fi
125190

126-
# vmlinux uses absolute addresses in the section table rather than
127-
# section offsets.
128-
local file_type=$(${READELF} --file-header $objfile |
129-
${AWK} '$1 == "Type:" { print $2; exit }')
130-
if [[ $file_type = "EXEC" ]] || [[ $file_type == "DYN" ]]; then
131-
is_vmlinux=1
132-
fi
133-
134191
# Go through each of the object's symbols which match the func name.
135192
# In rare cases there might be duplicates, in which case we print all
136193
# matches.
@@ -143,8 +200,7 @@ __faddr2line() {
143200
local sec_name
144201

145202
# Get the section size:
146-
sec_size=$(${READELF} --section-headers --wide $objfile |
147-
sed 's/\[ /\[/' |
203+
sec_size=$(echo "${ELF_SECHEADERS}" | sed 's/\[ /\[/' |
148204
${AWK} -v sec=$sym_sec '$1 == "[" sec "]" { print "0x" $6; exit }')
149205

150206
if [[ -z $sec_size ]]; then
@@ -154,8 +210,7 @@ __faddr2line() {
154210
fi
155211

156212
# Get the section name:
157-
sec_name=$(${READELF} --section-headers --wide $objfile |
158-
sed 's/\[ /\[/' |
213+
sec_name=$(echo "${ELF_SECHEADERS}" | sed 's/\[ /\[/' |
159214
${AWK} -v sec=$sym_sec '$1 == "[" sec "]" { print $2; exit }')
160215

161216
if [[ -z $sec_name ]]; then
@@ -197,7 +252,7 @@ __faddr2line() {
197252
found=2
198253
break
199254
fi
200-
done < <(${READELF} --symbols --wide $objfile | sed 's/\[.*\]//' | ${AWK} -v sec=$sym_sec '$7 == sec' | sort --key=2)
255+
done < <(echo "${ELF_SYMS}" | sed 's/\[.*\]//' | ${AWK} -v sec=$sym_sec '$7 == sec' | sort --key=2 | ${GREP} -A1 --no-group-separator " ${sym_name}$")
201256

202257
if [[ $found = 0 ]]; then
203258
warn "can't find symbol: sym_name: $sym_name sym_sec: $sym_sec sym_addr: $sym_addr sym_elf_size: $sym_elf_size"
@@ -249,9 +304,8 @@ __faddr2line() {
249304

250305
# Pass section address to addr2line and strip absolute paths
251306
# from the output:
252-
local args="--functions --pretty-print --inlines --exe=$objfile"
253-
[[ $is_vmlinux = 0 ]] && args="$args --section=$sec_name"
254-
local output=$(${ADDR2LINE} $args $addr | sed "s; $dir_prefix\(\./\)*; ;")
307+
run_addr2line $addr $sec_name
308+
local output=$(echo "${ADDR2LINE_OUT}" | sed "s; $dir_prefix\(\./\)*; ;")
255309
[[ -z $output ]] && continue
256310

257311
# Default output (non --list):
@@ -278,7 +332,7 @@ __faddr2line() {
278332

279333
DONE=1
280334

281-
done < <(${READELF} --symbols --wide $objfile | sed 's/\[.*\]//' | ${AWK} -v fn=$sym_name '$8 == fn')
335+
done < <(echo "${ELF_SYMS}" | sed 's/\[.*\]//' | ${AWK} -v fn=$sym_name '$8 == fn')
282336
}
283337

284338
[[ $# -lt 2 ]] && usage
@@ -291,10 +345,14 @@ LIST=0
291345
[[ ! -f $objfile ]] && die "can't find objfile $objfile"
292346
shift
293347

294-
${READELF} --section-headers --wide $objfile | ${GREP} -q '\.debug_info' || die "CONFIG_DEBUG_INFO not enabled"
348+
run_readelf $objfile
349+
350+
echo "${ELF_SECHEADERS}" | ${GREP} -q '\.debug_info' || die "CONFIG_DEBUG_INFO not enabled"
351+
352+
init_addr2line $objfile
295353

296354
DIR_PREFIX=supercalifragilisticexpialidocious
297-
find_dir_prefix $objfile
355+
find_dir_prefix
298356

299357
FIRST=1
300358
while [[ $# -gt 0 ]]; do

tools/objtool/arch/x86/decode.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,14 @@ bool arch_pc_relative_reloc(struct reloc *reloc)
125125
#define is_RIP() ((modrm_rm & 7) == CFI_BP && modrm_mod == 0)
126126
#define have_SIB() ((modrm_rm & 7) == CFI_SP && mod_is_mem())
127127

128+
/*
129+
* Check the ModRM register. If there is a SIB byte then check with
130+
* the SIB base register. But if the SIB base is 5 (i.e. CFI_BP) and
131+
* ModRM mod is 0 then there is no base register.
132+
*/
128133
#define rm_is(reg) (have_SIB() ? \
129-
sib_base == (reg) && sib_index == CFI_SP : \
134+
sib_base == (reg) && sib_index == CFI_SP && \
135+
(sib_base != CFI_BP || modrm_mod != 0) : \
130136
modrm_rm == (reg))
131137

132138
#define rm_is_mem(reg) (mod_is_mem() && !is_RIP() && rm_is(reg))

tools/objtool/builtin-check.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ static bool opts_valid(void)
144144
opts.static_call ||
145145
opts.uaccess) {
146146
if (opts.dump_orc) {
147-
ERROR("--dump can't be combined with other options");
147+
ERROR("--dump can't be combined with other actions");
148148
return false;
149149
}
150150

@@ -159,7 +159,7 @@ static bool opts_valid(void)
159159
if (opts.dump_orc)
160160
return true;
161161

162-
ERROR("At least one command required");
162+
ERROR("At least one action required");
163163
return false;
164164
}
165165

0 commit comments

Comments
 (0)