printk changes for 6.17
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEESH4wyp42V4tXvYsjUqAMR0iAlPIFAmiQpykACgkQUqAMR0iA lPJcrg/9Hez6+zO7LECCn5VkuK5oJWR5CyCfwx14ki8UF38djQGU2frckI5837rE MnVoEBexZunK5SXy4MAy7bTCitzR+lMqNtP5uq9J2ovlSPtNlfuJRDr7uGQLDtSS M5KZ1qsZnhgwLYeNhfVVToHgp+OwIQb2GcgYmYc8k03fUI1NQpdxIM46DzoTj+06 x6qgrNsmmJbm8E73VWBByJAEFoq9ugjny8Rt+tYMi/CmhgZpp0ZyF1r5dYfYX/KS VS8UQY//aZOFhNsQUAXwP7Ym00CYRgTg7Na+MHivYLXmYGH2gF6tWQhX/eEgHKcJ RTmUbLFx70fdBbjJMxv2k8vyMk2sy6sTfJHPqM/NS/Fb0tSPBXQJG/EexzfoqiBc wcjgOPkeALIosVdFdTqXxjoIGOP8rqsU4t6Y6WFjJlWK04SBVjxBUofytRdQSxkG 5Sb0rFVGKrKIkXaVkt4byPa1/BDpfNhfKMYPtQ56pv2VNUgzfye4prUAZHE5pLnK 8nixeeMtKDFFCBpn6rG5wZW7k2mK5FrWGZUfdfxdK1gWQ1y0kqGy5wa3lNZLcxlH l3AtOYoDeWM2DjDVO6WCj8ambEWkbjbGg7tC9TI3F0NvRJSYytTb6npMqb3Gwhcb U4NgT+Ho0GJ/5BLUye8HMfhvrGoCfRCeptHtEFXAK7pzKyjc0+c= =Mocd -----END PGP SIGNATURE----- Merge tag 'printk-for-6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux Pull printk updates from Petr Mladek: - Add new "hash_pointers=[auto|always|never]" boot parameter to force the hashing even with "slab_debug" enabled - Allow to stop CPU, after losing nbcon console ownership during panic(), even without proper NMI - Allow to use the printk kthread immediately even for the 1st registered nbcon - Compiler warning removal * tag 'printk-for-6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux: printk: nbcon: Allow reacquire during panic printk: Allow to use the printk kthread immediately even for 1st nbcon slab: Decouple slab_debug and no_hash_pointers vsprintf: Use __diag macros to disable '-Wsuggest-attribute=format' compiler-gcc.h: Introduce __diag_GCC_allpull/1314/head
commit
35a813e010
|
|
@ -1828,6 +1828,27 @@
|
||||||
backtraces on all cpus.
|
backtraces on all cpus.
|
||||||
Format: 0 | 1
|
Format: 0 | 1
|
||||||
|
|
||||||
|
hash_pointers=
|
||||||
|
[KNL,EARLY]
|
||||||
|
By default, when pointers are printed to the console
|
||||||
|
or buffers via the %p format string, that pointer is
|
||||||
|
"hashed", i.e. obscured by hashing the pointer value.
|
||||||
|
This is a security feature that hides actual kernel
|
||||||
|
addresses from unprivileged users, but it also makes
|
||||||
|
debugging the kernel more difficult since unequal
|
||||||
|
pointers can no longer be compared. The choices are:
|
||||||
|
Format: { auto | always | never }
|
||||||
|
Default: auto
|
||||||
|
|
||||||
|
auto - Hash pointers unless slab_debug is enabled.
|
||||||
|
always - Always hash pointers (even if slab_debug is
|
||||||
|
enabled).
|
||||||
|
never - Never hash pointers. This option should only
|
||||||
|
be specified when debugging the kernel. Do
|
||||||
|
not use on production kernels. The boot
|
||||||
|
param "no_hash_pointers" is an alias for
|
||||||
|
this mode.
|
||||||
|
|
||||||
hashdist= [KNL,NUMA] Large hashes allocated during boot
|
hashdist= [KNL,NUMA] Large hashes allocated during boot
|
||||||
are distributed across NUMA nodes. Defaults on
|
are distributed across NUMA nodes. Defaults on
|
||||||
for 64-bit NUMA, off otherwise.
|
for 64-bit NUMA, off otherwise.
|
||||||
|
|
@ -4216,18 +4237,7 @@
|
||||||
|
|
||||||
no_hash_pointers
|
no_hash_pointers
|
||||||
[KNL,EARLY]
|
[KNL,EARLY]
|
||||||
Force pointers printed to the console or buffers to be
|
Alias for "hash_pointers=never".
|
||||||
unhashed. By default, when a pointer is printed via %p
|
|
||||||
format string, that pointer is "hashed", i.e. obscured
|
|
||||||
by hashing the pointer value. This is a security feature
|
|
||||||
that hides actual kernel addresses from unprivileged
|
|
||||||
users, but it also makes debugging the kernel more
|
|
||||||
difficult since unequal pointers can no longer be
|
|
||||||
compared. However, if this command-line option is
|
|
||||||
specified, then all normal pointers will have their true
|
|
||||||
value printed. This option should only be specified when
|
|
||||||
debugging the kernel. Please do not use on production
|
|
||||||
kernels.
|
|
||||||
|
|
||||||
nohibernate [HIBERNATION] Disable hibernation and resume.
|
nohibernate [HIBERNATION] Disable hibernation and resume.
|
||||||
|
|
||||||
|
|
@ -6644,6 +6654,10 @@
|
||||||
Documentation/admin-guide/mm/slab.rst.
|
Documentation/admin-guide/mm/slab.rst.
|
||||||
(slub_debug legacy name also accepted for now)
|
(slub_debug legacy name also accepted for now)
|
||||||
|
|
||||||
|
Using this option implies the "no_hash_pointers"
|
||||||
|
option which can be undone by adding the
|
||||||
|
"hash_pointers=always" option.
|
||||||
|
|
||||||
slab_max_order= [MM]
|
slab_max_order= [MM]
|
||||||
Determines the maximum allowed order for slabs.
|
Determines the maximum allowed order for slabs.
|
||||||
A high setting may cause OOMs due to memory
|
A high setting may cause OOMs due to memory
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,8 @@
|
||||||
#define __diag_GCC_8(s)
|
#define __diag_GCC_8(s)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define __diag_GCC_all(s) __diag(s)
|
||||||
|
|
||||||
#define __diag_ignore_all(option, comment) \
|
#define __diag_ignore_all(option, comment) \
|
||||||
__diag(__diag_GCC_ignore option)
|
__diag(__diag_GCC_ignore option)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ __scanf(2, 0) int vsscanf(const char *, const char *, va_list);
|
||||||
|
|
||||||
/* These are for specific cases, do not use without real need */
|
/* These are for specific cases, do not use without real need */
|
||||||
extern bool no_hash_pointers;
|
extern bool no_hash_pointers;
|
||||||
int no_hash_pointers_enable(char *str);
|
void hash_pointers_finalize(bool slub_debug);
|
||||||
|
|
||||||
/* Used for Rust formatting ('%pA') */
|
/* Used for Rust formatting ('%pA') */
|
||||||
char *rust_fmt_argument(char *buf, char *end, const void *ptr);
|
char *rust_fmt_argument(char *buf, char *end, const void *ptr);
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ struct dev_printk_info;
|
||||||
|
|
||||||
extern struct printk_ringbuffer *prb;
|
extern struct printk_ringbuffer *prb;
|
||||||
extern bool printk_kthreads_running;
|
extern bool printk_kthreads_running;
|
||||||
|
extern bool printk_kthreads_ready;
|
||||||
extern bool debug_non_panic_cpus;
|
extern bool debug_non_panic_cpus;
|
||||||
|
|
||||||
__printf(4, 0)
|
__printf(4, 0)
|
||||||
|
|
@ -179,6 +180,7 @@ static inline void nbcon_kthread_wake(struct console *con)
|
||||||
#define PRINTKRB_RECORD_MAX 0
|
#define PRINTKRB_RECORD_MAX 0
|
||||||
|
|
||||||
#define printk_kthreads_running (false)
|
#define printk_kthreads_running (false)
|
||||||
|
#define printk_kthreads_ready (false)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In !PRINTK builds we still export console_sem
|
* In !PRINTK builds we still export console_sem
|
||||||
|
|
|
||||||
|
|
@ -214,8 +214,9 @@ static void nbcon_seq_try_update(struct nbcon_context *ctxt, u64 new_seq)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nbcon_context_try_acquire_direct - Try to acquire directly
|
* nbcon_context_try_acquire_direct - Try to acquire directly
|
||||||
* @ctxt: The context of the caller
|
* @ctxt: The context of the caller
|
||||||
* @cur: The current console state
|
* @cur: The current console state
|
||||||
|
* @is_reacquire: This acquire is a reacquire
|
||||||
*
|
*
|
||||||
* Acquire the console when it is released. Also acquire the console when
|
* Acquire the console when it is released. Also acquire the console when
|
||||||
* the current owner has a lower priority and the console is in a safe state.
|
* the current owner has a lower priority and the console is in a safe state.
|
||||||
|
|
@ -225,17 +226,17 @@ static void nbcon_seq_try_update(struct nbcon_context *ctxt, u64 new_seq)
|
||||||
*
|
*
|
||||||
* Errors:
|
* Errors:
|
||||||
*
|
*
|
||||||
* -EPERM: A panic is in progress and this is not the panic CPU.
|
* -EPERM: A panic is in progress and this is neither the panic
|
||||||
* Or the current owner or waiter has the same or higher
|
* CPU nor is this a reacquire. Or the current owner or
|
||||||
* priority. No acquire method can be successful in
|
* waiter has the same or higher priority. No acquire
|
||||||
* this case.
|
* method can be successful in these cases.
|
||||||
*
|
*
|
||||||
* -EBUSY: The current owner has a lower priority but the console
|
* -EBUSY: The current owner has a lower priority but the console
|
||||||
* in an unsafe state. The caller should try using
|
* in an unsafe state. The caller should try using
|
||||||
* the handover acquire method.
|
* the handover acquire method.
|
||||||
*/
|
*/
|
||||||
static int nbcon_context_try_acquire_direct(struct nbcon_context *ctxt,
|
static int nbcon_context_try_acquire_direct(struct nbcon_context *ctxt,
|
||||||
struct nbcon_state *cur)
|
struct nbcon_state *cur, bool is_reacquire)
|
||||||
{
|
{
|
||||||
unsigned int cpu = smp_processor_id();
|
unsigned int cpu = smp_processor_id();
|
||||||
struct console *con = ctxt->console;
|
struct console *con = ctxt->console;
|
||||||
|
|
@ -243,14 +244,20 @@ static int nbcon_context_try_acquire_direct(struct nbcon_context *ctxt,
|
||||||
|
|
||||||
do {
|
do {
|
||||||
/*
|
/*
|
||||||
* Panic does not imply that the console is owned. However, it
|
* Panic does not imply that the console is owned. However,
|
||||||
* is critical that non-panic CPUs during panic are unable to
|
* since all non-panic CPUs are stopped during panic(), it
|
||||||
* acquire ownership in order to satisfy the assumptions of
|
* is safer to have them avoid gaining console ownership.
|
||||||
* nbcon_waiter_matches(). In particular, the assumption that
|
*
|
||||||
* lower priorities are ignored during panic.
|
* If this acquire is a reacquire (and an unsafe takeover
|
||||||
|
* has not previously occurred) then it is allowed to attempt
|
||||||
|
* a direct acquire in panic. This gives console drivers an
|
||||||
|
* opportunity to perform any necessary cleanup if they were
|
||||||
|
* interrupted by the panic CPU while printing.
|
||||||
*/
|
*/
|
||||||
if (other_cpu_in_panic())
|
if (other_cpu_in_panic() &&
|
||||||
|
(!is_reacquire || cur->unsafe_takeover)) {
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
}
|
||||||
|
|
||||||
if (ctxt->prio <= cur->prio || ctxt->prio <= cur->req_prio)
|
if (ctxt->prio <= cur->prio || ctxt->prio <= cur->req_prio)
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
@ -301,8 +308,9 @@ static bool nbcon_waiter_matches(struct nbcon_state *cur, int expected_prio)
|
||||||
* Event #1 implies this context is EMERGENCY.
|
* Event #1 implies this context is EMERGENCY.
|
||||||
* Event #2 implies the new context is PANIC.
|
* Event #2 implies the new context is PANIC.
|
||||||
* Event #3 occurs when panic() has flushed the console.
|
* Event #3 occurs when panic() has flushed the console.
|
||||||
* Events #4 and #5 are not possible due to the other_cpu_in_panic()
|
* Event #4 occurs when a non-panic CPU reacquires.
|
||||||
* check in nbcon_context_try_acquire_direct().
|
* Event #5 is not possible due to the other_cpu_in_panic() check
|
||||||
|
* in nbcon_context_try_acquire_handover().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return (cur->req_prio == expected_prio);
|
return (cur->req_prio == expected_prio);
|
||||||
|
|
@ -431,6 +439,16 @@ static int nbcon_context_try_acquire_handover(struct nbcon_context *ctxt,
|
||||||
WARN_ON_ONCE(ctxt->prio <= cur->prio || ctxt->prio <= cur->req_prio);
|
WARN_ON_ONCE(ctxt->prio <= cur->prio || ctxt->prio <= cur->req_prio);
|
||||||
WARN_ON_ONCE(!cur->unsafe);
|
WARN_ON_ONCE(!cur->unsafe);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Panic does not imply that the console is owned. However, it
|
||||||
|
* is critical that non-panic CPUs during panic are unable to
|
||||||
|
* wait for a handover in order to satisfy the assumptions of
|
||||||
|
* nbcon_waiter_matches(). In particular, the assumption that
|
||||||
|
* lower priorities are ignored during panic.
|
||||||
|
*/
|
||||||
|
if (other_cpu_in_panic())
|
||||||
|
return -EPERM;
|
||||||
|
|
||||||
/* Handover is not possible on the same CPU. */
|
/* Handover is not possible on the same CPU. */
|
||||||
if (cur->cpu == cpu)
|
if (cur->cpu == cpu)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
@ -558,7 +576,8 @@ static struct printk_buffers panic_nbcon_pbufs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nbcon_context_try_acquire - Try to acquire nbcon console
|
* nbcon_context_try_acquire - Try to acquire nbcon console
|
||||||
* @ctxt: The context of the caller
|
* @ctxt: The context of the caller
|
||||||
|
* @is_reacquire: This acquire is a reacquire
|
||||||
*
|
*
|
||||||
* Context: Under @ctxt->con->device_lock() or local_irq_save().
|
* Context: Under @ctxt->con->device_lock() or local_irq_save().
|
||||||
* Return: True if the console was acquired. False otherwise.
|
* Return: True if the console was acquired. False otherwise.
|
||||||
|
|
@ -568,7 +587,7 @@ static struct printk_buffers panic_nbcon_pbufs;
|
||||||
* in an unsafe state. Otherwise, on success the caller may assume
|
* in an unsafe state. Otherwise, on success the caller may assume
|
||||||
* the console is not in an unsafe state.
|
* the console is not in an unsafe state.
|
||||||
*/
|
*/
|
||||||
static bool nbcon_context_try_acquire(struct nbcon_context *ctxt)
|
static bool nbcon_context_try_acquire(struct nbcon_context *ctxt, bool is_reacquire)
|
||||||
{
|
{
|
||||||
unsigned int cpu = smp_processor_id();
|
unsigned int cpu = smp_processor_id();
|
||||||
struct console *con = ctxt->console;
|
struct console *con = ctxt->console;
|
||||||
|
|
@ -577,7 +596,7 @@ static bool nbcon_context_try_acquire(struct nbcon_context *ctxt)
|
||||||
|
|
||||||
nbcon_state_read(con, &cur);
|
nbcon_state_read(con, &cur);
|
||||||
try_again:
|
try_again:
|
||||||
err = nbcon_context_try_acquire_direct(ctxt, &cur);
|
err = nbcon_context_try_acquire_direct(ctxt, &cur, is_reacquire);
|
||||||
if (err != -EBUSY)
|
if (err != -EBUSY)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
|
@ -913,7 +932,7 @@ void nbcon_reacquire_nobuf(struct nbcon_write_context *wctxt)
|
||||||
{
|
{
|
||||||
struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt);
|
struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt);
|
||||||
|
|
||||||
while (!nbcon_context_try_acquire(ctxt))
|
while (!nbcon_context_try_acquire(ctxt, true))
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
|
|
||||||
nbcon_write_context_set_buf(wctxt, NULL, 0);
|
nbcon_write_context_set_buf(wctxt, NULL, 0);
|
||||||
|
|
@ -1101,7 +1120,7 @@ static bool nbcon_emit_one(struct nbcon_write_context *wctxt, bool use_atomic)
|
||||||
cant_migrate();
|
cant_migrate();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nbcon_context_try_acquire(ctxt))
|
if (!nbcon_context_try_acquire(ctxt, false))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1486,7 +1505,7 @@ static int __nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq,
|
||||||
ctxt->prio = nbcon_get_default_prio();
|
ctxt->prio = nbcon_get_default_prio();
|
||||||
ctxt->allow_unsafe_takeover = allow_unsafe_takeover;
|
ctxt->allow_unsafe_takeover = allow_unsafe_takeover;
|
||||||
|
|
||||||
if (!nbcon_context_try_acquire(ctxt))
|
if (!nbcon_context_try_acquire(ctxt, false))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
while (nbcon_seq_read(con) < stop_seq) {
|
while (nbcon_seq_read(con) < stop_seq) {
|
||||||
|
|
@ -1671,6 +1690,9 @@ bool nbcon_alloc(struct console *con)
|
||||||
{
|
{
|
||||||
struct nbcon_state state = { };
|
struct nbcon_state state = { };
|
||||||
|
|
||||||
|
/* Synchronize the kthread start. */
|
||||||
|
lockdep_assert_console_list_lock_held();
|
||||||
|
|
||||||
/* The write_thread() callback is mandatory. */
|
/* The write_thread() callback is mandatory. */
|
||||||
if (WARN_ON(!con->write_thread))
|
if (WARN_ON(!con->write_thread))
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1701,12 +1723,15 @@ bool nbcon_alloc(struct console *con)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (printk_kthreads_running) {
|
if (printk_kthreads_ready && !have_boot_console) {
|
||||||
if (!nbcon_kthread_create(con)) {
|
if (!nbcon_kthread_create(con)) {
|
||||||
kfree(con->pbufs);
|
kfree(con->pbufs);
|
||||||
con->pbufs = NULL;
|
con->pbufs = NULL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Might be the first kthread. */
|
||||||
|
printk_kthreads_running = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1716,14 +1741,30 @@ bool nbcon_alloc(struct console *con)
|
||||||
/**
|
/**
|
||||||
* nbcon_free - Free and cleanup the nbcon console specific data
|
* nbcon_free - Free and cleanup the nbcon console specific data
|
||||||
* @con: Console to free/cleanup nbcon data
|
* @con: Console to free/cleanup nbcon data
|
||||||
|
*
|
||||||
|
* Important: @have_nbcon_console must be updated before calling
|
||||||
|
* this function. In particular, it can be set only when there
|
||||||
|
* is still another nbcon console registered.
|
||||||
*/
|
*/
|
||||||
void nbcon_free(struct console *con)
|
void nbcon_free(struct console *con)
|
||||||
{
|
{
|
||||||
struct nbcon_state state = { };
|
struct nbcon_state state = { };
|
||||||
|
|
||||||
if (printk_kthreads_running)
|
/* Synchronize the kthread stop. */
|
||||||
|
lockdep_assert_console_list_lock_held();
|
||||||
|
|
||||||
|
if (printk_kthreads_running) {
|
||||||
nbcon_kthread_stop(con);
|
nbcon_kthread_stop(con);
|
||||||
|
|
||||||
|
/* Might be the last nbcon console.
|
||||||
|
*
|
||||||
|
* Do not rely on printk_kthreads_check_locked(). It is not
|
||||||
|
* called in some code paths, see nbcon_free() callers.
|
||||||
|
*/
|
||||||
|
if (!have_nbcon_console)
|
||||||
|
printk_kthreads_running = false;
|
||||||
|
}
|
||||||
|
|
||||||
nbcon_state_set(con, &state);
|
nbcon_state_set(con, &state);
|
||||||
|
|
||||||
/* Boot consoles share global printk buffers. */
|
/* Boot consoles share global printk buffers. */
|
||||||
|
|
@ -1762,7 +1803,7 @@ bool nbcon_device_try_acquire(struct console *con)
|
||||||
ctxt->console = con;
|
ctxt->console = con;
|
||||||
ctxt->prio = NBCON_PRIO_NORMAL;
|
ctxt->prio = NBCON_PRIO_NORMAL;
|
||||||
|
|
||||||
if (!nbcon_context_try_acquire(ctxt))
|
if (!nbcon_context_try_acquire(ctxt, false))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!nbcon_context_enter_unsafe(ctxt))
|
if (!nbcon_context_enter_unsafe(ctxt))
|
||||||
|
|
|
||||||
|
|
@ -3574,7 +3574,7 @@ EXPORT_SYMBOL(console_resume);
|
||||||
static int unregister_console_locked(struct console *console);
|
static int unregister_console_locked(struct console *console);
|
||||||
|
|
||||||
/* True when system boot is far enough to create printer threads. */
|
/* True when system boot is far enough to create printer threads. */
|
||||||
static bool printk_kthreads_ready __ro_after_init;
|
bool printk_kthreads_ready __ro_after_init;
|
||||||
|
|
||||||
static struct task_struct *printk_legacy_kthread;
|
static struct task_struct *printk_legacy_kthread;
|
||||||
|
|
||||||
|
|
@ -3713,6 +3713,7 @@ static void printk_kthreads_check_locked(void)
|
||||||
if (!printk_kthreads_ready)
|
if (!printk_kthreads_ready)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Start or stop the legacy kthread when needed. */
|
||||||
if (have_legacy_console || have_boot_console) {
|
if (have_legacy_console || have_boot_console) {
|
||||||
if (!printk_legacy_kthread &&
|
if (!printk_legacy_kthread &&
|
||||||
force_legacy_kthread() &&
|
force_legacy_kthread() &&
|
||||||
|
|
@ -4204,14 +4205,6 @@ static int unregister_console_locked(struct console *console)
|
||||||
*/
|
*/
|
||||||
synchronize_srcu(&console_srcu);
|
synchronize_srcu(&console_srcu);
|
||||||
|
|
||||||
if (console->flags & CON_NBCON)
|
|
||||||
nbcon_free(console);
|
|
||||||
|
|
||||||
console_sysfs_notify();
|
|
||||||
|
|
||||||
if (console->exit)
|
|
||||||
res = console->exit(console);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* With this console gone, the global flags tracking registered
|
* With this console gone, the global flags tracking registered
|
||||||
* console types may have changed. Update them.
|
* console types may have changed. Update them.
|
||||||
|
|
@ -4232,6 +4225,15 @@ static int unregister_console_locked(struct console *console)
|
||||||
if (!found_nbcon_con)
|
if (!found_nbcon_con)
|
||||||
have_nbcon_console = found_nbcon_con;
|
have_nbcon_console = found_nbcon_con;
|
||||||
|
|
||||||
|
/* @have_nbcon_console must be updated before calling nbcon_free(). */
|
||||||
|
if (console->flags & CON_NBCON)
|
||||||
|
nbcon_free(console);
|
||||||
|
|
||||||
|
console_sysfs_notify();
|
||||||
|
|
||||||
|
if (console->exit)
|
||||||
|
res = console->exit(console);
|
||||||
|
|
||||||
/* Changed console list, may require printer threads to start/stop. */
|
/* Changed console list, may require printer threads to start/stop. */
|
||||||
printk_kthreads_check_locked();
|
printk_kthreads_check_locked();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,20 @@
|
||||||
bool no_hash_pointers __ro_after_init;
|
bool no_hash_pointers __ro_after_init;
|
||||||
EXPORT_SYMBOL_GPL(no_hash_pointers);
|
EXPORT_SYMBOL_GPL(no_hash_pointers);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hashed pointers policy selected by "hash_pointers=..." boot param
|
||||||
|
*
|
||||||
|
* `auto` - Hashed pointers enabled unless disabled by slub_debug_enabled=true
|
||||||
|
* `always` - Hashed pointers enabled unconditionally
|
||||||
|
* `never` - Hashed pointers disabled unconditionally
|
||||||
|
*/
|
||||||
|
enum hash_pointers_policy {
|
||||||
|
HASH_PTR_AUTO = 0,
|
||||||
|
HASH_PTR_ALWAYS,
|
||||||
|
HASH_PTR_NEVER
|
||||||
|
};
|
||||||
|
static enum hash_pointers_policy hash_pointers_mode __initdata;
|
||||||
|
|
||||||
noinline
|
noinline
|
||||||
static unsigned long long simple_strntoull(const char *startp, char **endp, unsigned int base, size_t max_chars)
|
static unsigned long long simple_strntoull(const char *startp, char **endp, unsigned int base, size_t max_chars)
|
||||||
{
|
{
|
||||||
|
|
@ -1699,10 +1713,9 @@ char *escaped_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
__diag_push();
|
||||||
#ifndef __clang__
|
__diag_ignore(GCC, all, "-Wsuggest-attribute=format",
|
||||||
#pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
|
"Not a valid __printf() conversion candidate.");
|
||||||
#endif
|
|
||||||
static char *va_format(char *buf, char *end, struct va_format *va_fmt,
|
static char *va_format(char *buf, char *end, struct va_format *va_fmt,
|
||||||
struct printf_spec spec)
|
struct printf_spec spec)
|
||||||
{
|
{
|
||||||
|
|
@ -1717,7 +1730,7 @@ static char *va_format(char *buf, char *end, struct va_format *va_fmt,
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
#pragma GCC diagnostic pop
|
__diag_pop();
|
||||||
|
|
||||||
static noinline_for_stack
|
static noinline_for_stack
|
||||||
char *uuid_string(char *buf, char *end, const u8 *addr,
|
char *uuid_string(char *buf, char *end, const u8 *addr,
|
||||||
|
|
@ -2289,12 +2302,23 @@ char *resource_or_range(const char *fmt, char *buf, char *end, void *ptr,
|
||||||
return resource_string(buf, end, ptr, spec, fmt);
|
return resource_string(buf, end, ptr, spec, fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
int __init no_hash_pointers_enable(char *str)
|
void __init hash_pointers_finalize(bool slub_debug)
|
||||||
{
|
{
|
||||||
if (no_hash_pointers)
|
switch (hash_pointers_mode) {
|
||||||
return 0;
|
case HASH_PTR_ALWAYS:
|
||||||
|
no_hash_pointers = false;
|
||||||
|
break;
|
||||||
|
case HASH_PTR_NEVER:
|
||||||
|
no_hash_pointers = true;
|
||||||
|
break;
|
||||||
|
case HASH_PTR_AUTO:
|
||||||
|
default:
|
||||||
|
no_hash_pointers = slub_debug;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
no_hash_pointers = true;
|
if (!no_hash_pointers)
|
||||||
|
return;
|
||||||
|
|
||||||
pr_warn("**********************************************************\n");
|
pr_warn("**********************************************************\n");
|
||||||
pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
|
pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
|
||||||
|
|
@ -2307,11 +2331,39 @@ int __init no_hash_pointers_enable(char *str)
|
||||||
pr_warn("** the kernel, report this immediately to your system **\n");
|
pr_warn("** the kernel, report this immediately to your system **\n");
|
||||||
pr_warn("** administrator! **\n");
|
pr_warn("** administrator! **\n");
|
||||||
pr_warn("** **\n");
|
pr_warn("** **\n");
|
||||||
|
pr_warn("** Use hash_pointers=always to force this mode off **\n");
|
||||||
|
pr_warn("** **\n");
|
||||||
pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
|
pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
|
||||||
pr_warn("**********************************************************\n");
|
pr_warn("**********************************************************\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __init hash_pointers_mode_parse(char *str)
|
||||||
|
{
|
||||||
|
if (!str) {
|
||||||
|
pr_warn("Hash pointers mode empty; falling back to auto.\n");
|
||||||
|
hash_pointers_mode = HASH_PTR_AUTO;
|
||||||
|
} else if (strncmp(str, "auto", 4) == 0) {
|
||||||
|
pr_info("Hash pointers mode set to auto.\n");
|
||||||
|
hash_pointers_mode = HASH_PTR_AUTO;
|
||||||
|
} else if (strncmp(str, "never", 5) == 0) {
|
||||||
|
pr_info("Hash pointers mode set to never.\n");
|
||||||
|
hash_pointers_mode = HASH_PTR_NEVER;
|
||||||
|
} else if (strncmp(str, "always", 6) == 0) {
|
||||||
|
pr_info("Hash pointers mode set to always.\n");
|
||||||
|
hash_pointers_mode = HASH_PTR_ALWAYS;
|
||||||
|
} else {
|
||||||
|
pr_warn("Unknown hash_pointers mode '%s' specified; assuming auto.\n", str);
|
||||||
|
hash_pointers_mode = HASH_PTR_AUTO;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
early_param("hash_pointers", hash_pointers_mode_parse);
|
||||||
|
|
||||||
|
static int __init no_hash_pointers_enable(char *str)
|
||||||
|
{
|
||||||
|
return hash_pointers_mode_parse("never");
|
||||||
|
}
|
||||||
early_param("no_hash_pointers", no_hash_pointers_enable);
|
early_param("no_hash_pointers", no_hash_pointers_enable);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -6312,9 +6312,8 @@ void __init kmem_cache_init(void)
|
||||||
if (debug_guardpage_minorder())
|
if (debug_guardpage_minorder())
|
||||||
slub_max_order = 0;
|
slub_max_order = 0;
|
||||||
|
|
||||||
/* Print slub debugging pointers without hashing */
|
/* Inform pointer hashing choice about slub debugging state. */
|
||||||
if (__slub_debug_enabled())
|
hash_pointers_finalize(__slub_debug_enabled());
|
||||||
no_hash_pointers_enable(NULL);
|
|
||||||
|
|
||||||
kmem_cache_node = &boot_kmem_cache_node;
|
kmem_cache_node = &boot_kmem_cache_node;
|
||||||
kmem_cache = &boot_kmem_cache;
|
kmem_cache = &boot_kmem_cache;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue