diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2020-11-30 18:19:31 +0100 |
---|---|---|
committer | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2020-11-30 18:19:31 +0100 |
commit | 0162011ad222d71ed173bc3c32f847aa245555fa (patch) | |
tree | f05e7ed96fe6d7d5f31d973779f34be9305dfc89 | |
parent | 056c6e65e9f26f301c0bf066a5322cfeb0dae61a (diff) | |
download | linux-rt-0162011ad222d71ed173bc3c32f847aa245555fa.tar.gz |
[ANNOUNCE] v5.10-rc6-rt13v5.10-rc6-rt13-patches
Dear RT folks!
I'm pleased to announce the v5.10-rc6-rt13 patch set.
Changes since v5.10-rc6-rt12:
- John's printk series was updated to his current status.
- The notifier lock has been made a raw_spinlock_t to avoid a
acquiring a sleeping lock in atomic context. Patch by Valentin
Schneider.
- The lock-lock in zswap lock was not properly initialized since
v5.9-RT. This was noticed during the investigation of a z3fold
related failure report Oleksandr Natalenko. According to Mike
Galbraith this is still broken.
Known issues
- It has been pointed out that due to changes to the printk code the
internal buffer representation changed. This is only an issue if tools
like `crash' are used to extract the printk buffer from a kernel memory
image.
The delta patch against v5.10-rc6-rt12 is appended below and can be found here:
https://cdn.kernel.org/pub/linux/kernel/projects/rt/5.10/incr/patch-5.10-rc6-rt12-rt13.patch.xz
You can get this release via the git tree at:
git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git v5.10-rc6-rt13
The RT patch against v5.10-rc6 can be found here:
https://cdn.kernel.org/pub/linux/kernel/projects/rt/5.10/older/patch-5.10-rc6-rt13.patch.xz
The split quilt queue is available at:
https://cdn.kernel.org/pub/linux/kernel/projects/rt/5.10/older/patches-5.10-rc6-rt13.tar.xz
Sebastian
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
23 files changed, 1182 insertions, 866 deletions
diff --git a/patches/0001-printk-refactor-kmsg_dump_get_buffer.patch b/patches/0001-printk-refactor-kmsg_dump_get_buffer.patch index 53fabc5d9437..219f71ec5104 100644 --- a/patches/0001-printk-refactor-kmsg_dump_get_buffer.patch +++ b/patches/0001-printk-refactor-kmsg_dump_get_buffer.patch @@ -1,6 +1,6 @@ From: John Ogness <john.ogness@linutronix.de> -Date: Wed, 14 Oct 2020 19:09:15 +0200 -Subject: [PATCH 01/15] printk: refactor kmsg_dump_get_buffer() +Date: Mon, 30 Nov 2020 01:41:56 +0106 +Subject: [PATCH 01/16] printk: refactor kmsg_dump_get_buffer() kmsg_dump_get_buffer() requires nearly the same logic as syslog_print_all(), but uses different variable names and @@ -85,7 +85,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> } - /* last message in next interation */ -+ /* Keep track of the last message for the next interation. */ ++ /* Keep track of the last message for the next iteration. */ next_seq = seq; - /* actually read text into the buffer now */ diff --git a/patches/0008-printk-inline-log_output-log_store-in-vprintk_store.patch b/patches/0002-printk-inline-log_output-log_store-in-vprintk_store.patch index f4cebbc4ca8f..0af56e5c7288 100644 --- a/patches/0008-printk-inline-log_output-log_store-in-vprintk_store.patch +++ b/patches/0002-printk-inline-log_output-log_store-in-vprintk_store.patch @@ -1,22 +1,21 @@ From: John Ogness <john.ogness@linutronix.de> -Date: Mon, 19 Oct 2020 16:40:26 +0206 -Subject: [PATCH 08/15] printk: inline log_output(),log_store() in +Date: Mon, 30 Nov 2020 01:41:57 +0106 +Subject: [PATCH 02/16] printk: inline log_output(),log_store() in vprintk_store() -In preparation for supporting atomic printing, inline log_output() -and log_store() into vprintk_store(). This allows these -sub-functions to more easily communicate if they have performed -a finalized commit as well as the sequence number of that commit. +In preparation for removing logbuf_lock, inline log_output() +and log_store() into vprintk_store(). This will simplify dealing +with the various code branches and fallbacks that are possible. Signed-off-by: John Ogness <john.ogness@linutronix.de> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> --- - kernel/printk/printk.c | 141 +++++++++++++++++++++---------------------------- - 1 file changed, 63 insertions(+), 78 deletions(-) + kernel/printk/printk.c | 134 ++++++++++++++++++++----------------------------- + 1 file changed, 56 insertions(+), 78 deletions(-) --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c -@@ -465,52 +465,6 @@ static void truncate_msg(u16 *text_len, +@@ -491,52 +491,6 @@ static void truncate_msg(u16 *text_len, *trunc_msg_len = 0; } @@ -69,7 +68,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> int dmesg_restrict = IS_ENABLED(CONFIG_SECURITY_DMESG_RESTRICT); static int syslog_action_restricted(int type) -@@ -2001,45 +1955,24 @@ static inline u32 printk_caller_id(void) +@@ -1907,44 +1861,22 @@ static inline u32 printk_caller_id(void) 0x80000000 + raw_smp_processor_id(); } @@ -102,66 +101,59 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> - dev_info, text, text_len); -} - + /* Must be called under logbuf_lock. */ int vprintk_store(int facility, int level, const struct dev_printk_info *dev_info, const char *fmt, va_list args) { -- size_t text_len; + const u32 caller_id = printk_caller_id(); + static char textbuf[LOG_LINE_MAX]; +- char *text = textbuf; +- size_t text_len; + struct prb_reserved_entry e; enum log_flags lflags = 0; - unsigned long irqflags; + struct printk_record r; + u16 trunc_msg_len = 0; - int sprint_id; ++ char *text = textbuf; + u16 text_len; + u64 ts_nsec; -+ int ret = 0; - char *text; -- int ret; -+ u64 seq; + + ts_nsec = local_clock(); - /* No buffer is available if printk has recursed too much. */ - text = get_sprint_buf(&sprint_id, &irqflags); -@@ -2083,8 +2016,60 @@ int vprintk_store(int facility, int leve + /* + * The printf needs to come first; we need the syslog +@@ -1983,7 +1915,53 @@ int vprintk_store(int facility, int leve if (dev_info) lflags |= LOG_NEWLINE; -- ret = log_output(facility, level, lflags, dev_info, text, text_len); +- return log_output(facility, level, lflags, dev_info, text, text_len); + if (lflags & LOG_CONT) { + prb_rec_init_wr(&r, text_len); + if (prb_reserve_in_last(&e, prb, &r, caller_id, LOG_LINE_MAX)) { -+ seq = r.info->seq; + memcpy(&r.text_buf[r.info->text_len], text, text_len); + r.info->text_len += text_len; ++ + if (lflags & LOG_NEWLINE) { + r.info->flags |= LOG_NEWLINE; + prb_final_commit(&e); + } else { + prb_commit(&e); + } -+ ret = text_len; -+ goto out; ++ ++ return text_len; + } + } + -+ /* Store it in the record log */ -+ + prb_rec_init_wr(&r, text_len); -+ + if (!prb_reserve(&e, prb, &r)) { + /* truncate the message if it is too long for empty buffer */ + truncate_msg(&text_len, &trunc_msg_len); ++ + prb_rec_init_wr(&r, text_len + trunc_msg_len); -+ /* survive when the log buffer is too small for trunc_msg */ + if (!prb_reserve(&e, prb, &r)) -+ goto out; ++ return 0; + } + -+ seq = r.info->seq; -+ + /* fill message */ + memcpy(&r.text_buf[0], text, text_len); + if (trunc_msg_len) @@ -174,16 +166,14 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> + r.info->caller_id = caller_id; + if (dev_info) + memcpy(&r.info->dev_info, dev_info, sizeof(r.info->dev_info)); - -+ /* insert message */ -+ if ((lflags & LOG_CONT) || !(lflags & LOG_NEWLINE)) { ++ ++ /* A message without a trailing newline can be continued. */ ++ if (!(lflags & LOG_NEWLINE)) + prb_commit(&e); -+ } else { ++ else + prb_final_commit(&e); -+ } + -+ ret = text_len + trunc_msg_len; -+out: - put_sprint_buf(sprint_id, irqflags); - return ret; ++ return (text_len + trunc_msg_len); } + + asmlinkage int vprintk_emit(int facility, int level, diff --git a/patches/0002-printk-use-buffer-pools-for-sprint-buffers.patch b/patches/0002-printk-use-buffer-pools-for-sprint-buffers.patch deleted file mode 100644 index ee4c41875be3..000000000000 --- a/patches/0002-printk-use-buffer-pools-for-sprint-buffers.patch +++ /dev/null @@ -1,193 +0,0 @@ -From: John Ogness <john.ogness@linutronix.de> -Date: Tue, 13 Oct 2020 22:57:55 +0200 -Subject: [PATCH 02/15] printk: use buffer pools for sprint buffers - -vprintk_store() is using a single static buffer as a temporary -sprint buffer for the message text. This will not work once -@logbuf_lock is removed. Replace the single static buffer with -per-cpu and global pools. - -Each per-cpu pool is large enough to support a worse case of 2 -contexts (non-NMI and NMI). - -To support printk() recursion and printk() calls before per-cpu -variables are ready, an extra/fallback global pool of 2 contexts is -available. - -Signed-off-by: John Ogness <john.ogness@linutronix.de> -Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> ---- - kernel/printk/printk.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 137 insertions(+), 4 deletions(-) - ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -1704,6 +1704,129 @@ SYSCALL_DEFINE3(syslog, int, type, char - } - - /* -+ * The per-cpu sprint buffers are used with interrupts disabled, so each CPU -+ * only requires 2 buffers: for non-NMI and NMI contexts. Recursive printk() -+ * calls are handled by the global sprint buffers. -+ */ -+#define SPRINT_CTX_DEPTH 2 -+ -+/* Static sprint buffers for early boot (only 1 CPU) and recursion. */ -+static DECLARE_BITMAP(sprint_global_buffer_map, SPRINT_CTX_DEPTH); -+static char sprint_global_buffer[SPRINT_CTX_DEPTH][PREFIX_MAX + LOG_LINE_MAX]; -+ -+struct sprint_buffers { -+ char buf[SPRINT_CTX_DEPTH][PREFIX_MAX + LOG_LINE_MAX]; -+ atomic_t index; -+}; -+ -+static DEFINE_PER_CPU(struct sprint_buffers, percpu_sprint_buffers); -+ -+/* -+ * Acquire an unused buffer, returning its index. If no buffer is -+ * available, @count is returned. -+ */ -+static int _get_sprint_buf(unsigned long *map, int count) -+{ -+ int index; -+ -+ do { -+ index = find_first_zero_bit(map, count); -+ if (index == count) -+ break; -+ /* -+ * Guarantee map changes are ordered for the other CPUs. -+ * Pairs with clear_bit() in _put_sprint_buf(). -+ */ -+ } while (test_and_set_bit(index, map)); -+ -+ return index; -+} -+ -+/* Mark the buffer @index as unused. */ -+static void _put_sprint_buf(unsigned long *map, unsigned int count, unsigned int index) -+{ -+ /* -+ * Guarantee map changes are ordered for the other CPUs. -+ * Pairs with test_and_set_bit() in _get_sprint_buf(). -+ */ -+ clear_bit(index, map); -+} -+ -+/* -+ * Get a buffer sized PREFIX_MAX+LOG_LINE_MAX for sprinting. On success, @id -+ * is set and interrupts are disabled. @id is used to put back the buffer. -+ * -+ * @id is non-negative for per-cpu buffers, negative for global buffers. -+ */ -+static char *get_sprint_buf(int *id, unsigned long *flags) -+{ -+ struct sprint_buffers *bufs; -+ unsigned int index; -+ unsigned int cpu; -+ -+ local_irq_save(*flags); -+ cpu = get_cpu(); -+ -+ if (printk_percpu_data_ready()) { -+ -+ /* -+ * First try with per-cpu pool. Note that the last -+ * buffer is reserved for NMI context. -+ */ -+ bufs = per_cpu_ptr(&percpu_sprint_buffers, cpu); -+ index = atomic_read(&bufs->index); -+ if (index < (SPRINT_CTX_DEPTH - 1) || -+ (in_nmi() && index < SPRINT_CTX_DEPTH)) { -+ atomic_set(&bufs->index, index + 1); -+ *id = cpu; -+ return &bufs->buf[index][0]; -+ } -+ } -+ -+ /* -+ * Fallback to global pool. -+ * -+ * The global pool will only ever be used if per-cpu data is not ready -+ * yet or printk recurses. Recursion will not occur unless printk is -+ * having internal issues. -+ */ -+ index = _get_sprint_buf(sprint_global_buffer_map, SPRINT_CTX_DEPTH); -+ if (index != SPRINT_CTX_DEPTH) { -+ /* Convert to global buffer representation. */ -+ *id = -index - 1; -+ return &sprint_global_buffer[index][0]; -+ } -+ -+ /* Failed to get a buffer. */ -+ put_cpu(); -+ local_irq_restore(*flags); -+ return NULL; -+} -+ -+/* Put back an sprint buffer and restore interrupts. */ -+static void put_sprint_buf(int id, unsigned long flags) -+{ -+ struct sprint_buffers *bufs; -+ unsigned int index; -+ unsigned int cpu; -+ -+ if (id >= 0) { -+ cpu = id; -+ bufs = per_cpu_ptr(&percpu_sprint_buffers, cpu); -+ index = atomic_read(&bufs->index); -+ atomic_set(&bufs->index, index - 1); -+ } else { -+ /* Convert from global buffer representation. */ -+ index = -id - 1; -+ _put_sprint_buf(sprint_global_buffer_map, -+ SPRINT_CTX_DEPTH, index); -+ } -+ -+ put_cpu(); -+ local_irq_restore(flags); -+} -+ -+/* - * Special console_lock variants that help to reduce the risk of soft-lockups. - * They allow to pass console_lock to another printk() call using a busy wait. - */ -@@ -1941,16 +2064,23 @@ int vprintk_store(int facility, int leve - const struct dev_printk_info *dev_info, - const char *fmt, va_list args) - { -- static char textbuf[LOG_LINE_MAX]; -- char *text = textbuf; - size_t text_len; - enum log_flags lflags = 0; -+ unsigned long irqflags; -+ int sprint_id; -+ char *text; -+ int ret; -+ -+ /* No buffer is available if printk has recursed too much. */ -+ text = get_sprint_buf(&sprint_id, &irqflags); -+ if (!text) -+ return 0; - - /* - * The printf needs to come first; we need the syslog - * prefix which might be passed-in as a parameter. - */ -- text_len = vscnprintf(text, sizeof(textbuf), fmt, args); -+ text_len = vscnprintf(text, LOG_LINE_MAX, fmt, args); - - /* mark and strip a trailing newline */ - if (text_len && text[text_len-1] == '\n') { -@@ -1983,7 +2113,10 @@ int vprintk_store(int facility, int leve - if (dev_info) - lflags |= LOG_NEWLINE; - -- return log_output(facility, level, lflags, dev_info, text, text_len); -+ ret = log_output(facility, level, lflags, dev_info, text, text_len); -+ -+ put_sprint_buf(sprint_id, irqflags); -+ return ret; - } - - asmlinkage int vprintk_emit(int facility, int level, diff --git a/patches/0003-printk-change-clear_seq-to-atomic64_t.patch b/patches/0003-printk-change-clear_seq-to-atomic64_t.patch index d29d83360af9..0eaf077e7e1d 100644 --- a/patches/0003-printk-change-clear_seq-to-atomic64_t.patch +++ b/patches/0003-printk-change-clear_seq-to-atomic64_t.patch @@ -1,6 +1,6 @@ From: John Ogness <john.ogness@linutronix.de> -Date: Tue, 13 Oct 2020 23:19:35 +0200 -Subject: [PATCH 03/15] printk: change @clear_seq to atomic64_t +Date: Mon, 30 Nov 2020 01:41:58 +0106 +Subject: [PATCH 03/16] printk: change @clear_seq to atomic64_t Currently @clear_seq access is protected by @logbuf_lock. Once @logbuf_lock is removed some other form of synchronization will be @@ -24,7 +24,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> #ifdef CONFIG_PRINTK_CALLER #define PREFIX_MAX 48 -@@ -843,7 +843,7 @@ static loff_t devkmsg_llseek(struct file +@@ -797,7 +797,7 @@ static loff_t devkmsg_llseek(struct file * like issued by 'dmesg -c'. Reading /dev/kmsg itself * changes no global state, and does not clear anything. */ @@ -33,7 +33,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> break; case SEEK_END: /* after the last record */ -@@ -960,6 +960,9 @@ void log_buf_vmcoreinfo_setup(void) +@@ -914,6 +914,9 @@ void log_buf_vmcoreinfo_setup(void) * parse it and detect any changes to structure down the line. */ @@ -43,7 +43,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> VMCOREINFO_STRUCT_SIZE(printk_ringbuffer); VMCOREINFO_OFFSET(printk_ringbuffer, desc_ring); VMCOREINFO_OFFSET(printk_ringbuffer, text_data_ring); -@@ -1522,6 +1525,7 @@ static int syslog_print_all(char __user +@@ -1476,6 +1479,7 @@ static int syslog_print_all(char __user struct printk_info info; unsigned int line_count; struct printk_record r; @@ -51,7 +51,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> char *text; int len = 0; u64 seq; -@@ -1533,15 +1537,17 @@ static int syslog_print_all(char __user +@@ -1487,15 +1491,17 @@ static int syslog_print_all(char __user time = printk_time; logbuf_lock_irq(); @@ -71,7 +71,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> if (len <= size) break; len -= get_record_print_text_size(&info, line_count, true, time); -@@ -1572,7 +1578,7 @@ static int syslog_print_all(char __user +@@ -1526,7 +1532,7 @@ static int syslog_print_all(char __user } if (clear) @@ -80,7 +80,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> logbuf_unlock_irq(); kfree(text); -@@ -1582,7 +1588,7 @@ static int syslog_print_all(char __user +@@ -1536,7 +1542,7 @@ static int syslog_print_all(char __user static void syslog_clear(void) { logbuf_lock_irq(); @@ -89,7 +89,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> logbuf_unlock_irq(); } -@@ -3355,7 +3361,7 @@ void kmsg_dump(enum kmsg_dump_reason rea +@@ -3200,7 +3206,7 @@ void kmsg_dump(enum kmsg_dump_reason rea dumper->active = true; logbuf_lock_irqsave(flags); @@ -98,7 +98,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> dumper->next_seq = prb_next_seq(prb); logbuf_unlock_irqrestore(flags); -@@ -3563,7 +3569,7 @@ EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer); +@@ -3408,7 +3414,7 @@ EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer); */ void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper) { diff --git a/patches/0004-printk-remove-logbuf_lock-add-syslog_lock.patch b/patches/0004-printk-remove-logbuf_lock-add-syslog_lock.patch index 2ee099289033..b9cd36838148 100644 --- a/patches/0004-printk-remove-logbuf_lock-add-syslog_lock.patch +++ b/patches/0004-printk-remove-logbuf_lock-add-syslog_lock.patch @@ -1,6 +1,6 @@ From: John Ogness <john.ogness@linutronix.de> -Date: Wed, 14 Oct 2020 19:06:12 +0200 -Subject: [PATCH 04/15] printk: remove logbuf_lock, add syslog_lock +Date: Mon, 30 Nov 2020 01:41:59 +0106 +Subject: [PATCH 04/16] printk: remove logbuf_lock, add syslog_lock Since the ringbuffer is lockless, there is no need for it to be protected by @logbuf_lock. Remove @logbuf_lock. @@ -15,14 +15,33 @@ protect these. @console_seq, @exclusive_console_stop_seq, @console_dropped are protected by @console_lock. +Without @logbuf_lock it is no longer possible to use the single +static buffer for temporarily sprint'ing the message. Instead, +use vsnprintf() to determine the length and perform the real +vscnprintf() using the area reserved from the ringbuffer. This +leads to suboptimal packing of the message data, but will +result in less wasted storage than multiple per-cpu buffers to +support lockless temporary sprint'ing. + Signed-off-by: John Ogness <john.ogness@linutronix.de> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> --- - kernel/printk/internal.h | 4 - - kernel/printk/printk.c | 151 +++++++++++--------------------------------- - kernel/printk/printk_safe.c | 18 ----- - 3 files changed, 42 insertions(+), 131 deletions(-) + include/linux/printk.h | 1 + kernel/printk/internal.h | 4 + kernel/printk/printk.c | 285 +++++++++++++++++++++++--------------------- + kernel/printk/printk_safe.c | 18 -- + 4 files changed, 157 insertions(+), 151 deletions(-) +--- a/include/linux/printk.h ++++ b/include/linux/printk.h +@@ -45,6 +45,7 @@ static inline const char *printk_skip_he + } + + #define CONSOLE_EXT_LOG_MAX 8192 ++#define CONSOLE_LOG_MAX 1024 + + /* printk's without a loglevel use this.. */ + #define MESSAGE_LOGLEVEL_DEFAULT CONFIG_MESSAGE_LOGLEVEL_DEFAULT --- a/kernel/printk/internal.h +++ b/kernel/printk/internal.h @@ -12,8 +12,6 @@ @@ -45,7 +64,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> */ --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c -@@ -355,48 +355,22 @@ enum log_flags { +@@ -355,48 +355,18 @@ enum log_flags { LOG_CONT = 8, /* text is a fragment of a continuation line */ }; @@ -84,11 +103,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> - printk_safe_exit_irqrestore(flags); \ - } while (0) +/* The syslog_lock protects syslog_* variables. */ -+DEFINE_RAW_SPINLOCK(syslog_lock); -+#define syslog_lock_irq() raw_spin_lock_irq(&syslog_lock) -+#define syslog_unlock_irq() raw_spin_unlock_irq(&syslog_lock) -+#define syslog_lock_irqsave(flags) raw_spin_lock_irqsave(&syslog_lock, flags) -+#define syslog_unlock_irqrestore(flags) raw_spin_unlock_irqrestore(&syslog_lock, flags) ++static DEFINE_SPINLOCK(syslog_lock); #ifdef CONFIG_PRINTK DECLARE_WAIT_QUEUE_HEAD(log_wait); @@ -102,7 +117,16 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> /* the next printk record to write to the console */ static u64 console_seq; static u64 exclusive_console_stop_seq; -@@ -766,27 +740,22 @@ static ssize_t devkmsg_read(struct file +@@ -410,7 +380,7 @@ static atomic64_t clear_seq = ATOMIC64_I + #else + #define PREFIX_MAX 32 + #endif +-#define LOG_LINE_MAX (1024 - PREFIX_MAX) ++#define LOG_LINE_MAX (CONSOLE_LOG_MAX - PREFIX_MAX) + + #define LOG_LEVEL(v) ((v) & 0x07) + #define LOG_FACILITY(v) ((v) >> 3 & 0xff) +@@ -720,27 +690,22 @@ static ssize_t devkmsg_read(struct file if (ret) return ret; @@ -130,7 +154,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> goto out; } -@@ -796,7 +765,6 @@ static ssize_t devkmsg_read(struct file +@@ -750,7 +715,6 @@ static ssize_t devkmsg_read(struct file &r->info->dev_info); user->seq = r->info->seq + 1; @@ -138,7 +162,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> if (len > count) { ret = -EINVAL; -@@ -831,7 +799,6 @@ static loff_t devkmsg_llseek(struct file +@@ -785,7 +749,6 @@ static loff_t devkmsg_llseek(struct file if (offset) return -ESPIPE; @@ -146,7 +170,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> switch (whence) { case SEEK_SET: /* the first record */ -@@ -852,7 +819,6 @@ static loff_t devkmsg_llseek(struct file +@@ -806,7 +769,6 @@ static loff_t devkmsg_llseek(struct file default: ret = -EINVAL; } @@ -154,7 +178,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> return ret; } -@@ -866,7 +832,6 @@ static __poll_t devkmsg_poll(struct file +@@ -820,7 +782,6 @@ static __poll_t devkmsg_poll(struct file poll_wait(file, &log_wait, wait); @@ -162,7 +186,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> if (prb_read_valid(prb, user->seq, NULL)) { /* return error when data has vanished underneath us */ if (user->seq < prb_first_valid_seq(prb)) -@@ -874,7 +839,6 @@ static __poll_t devkmsg_poll(struct file +@@ -828,7 +789,6 @@ static __poll_t devkmsg_poll(struct file else ret = EPOLLIN|EPOLLRDNORM; } @@ -170,7 +194,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> return ret; } -@@ -907,9 +871,7 @@ static int devkmsg_open(struct inode *in +@@ -861,9 +821,7 @@ static int devkmsg_open(struct inode *in prb_rec_init_rd(&user->record, &user->info, &user->text_buf[0], sizeof(user->text_buf)); @@ -180,7 +204,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> file->private_data = user; return 0; -@@ -1117,7 +1079,6 @@ void __init setup_log_buf(int early) +@@ -1071,7 +1029,6 @@ void __init setup_log_buf(int early) struct printk_record r; size_t new_descs_size; size_t new_infos_size; @@ -188,7 +212,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> char *new_log_buf; unsigned int free; u64 seq; -@@ -1175,8 +1136,6 @@ void __init setup_log_buf(int early) +@@ -1129,8 +1086,6 @@ void __init setup_log_buf(int early) new_descs, ilog2(new_descs_count), new_infos); @@ -197,7 +221,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> log_buf_len = new_log_buf_len; log_buf = new_log_buf; new_log_buf_len = 0; -@@ -1192,8 +1151,6 @@ void __init setup_log_buf(int early) +@@ -1146,8 +1101,6 @@ void __init setup_log_buf(int early) */ prb = &printk_rb_dynamic; @@ -206,28 +230,28 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> if (seq != prb_next_seq(&printk_rb_static)) { pr_err("dropped %llu messages\n", prb_next_seq(&printk_rb_static) - seq); -@@ -1469,9 +1426,9 @@ static int syslog_print(char __user *buf +@@ -1423,9 +1376,9 @@ static int syslog_print(char __user *buf size_t n; size_t skip; - logbuf_lock_irq(); -+ syslog_lock_irq(); ++ spin_lock_irq(&syslog_lock); if (!prb_read_valid(prb, syslog_seq, &r)) { - logbuf_unlock_irq(); -+ syslog_unlock_irq(); ++ spin_unlock_irq(&syslog_lock); break; } if (r.info->seq != syslog_seq) { -@@ -1500,7 +1457,7 @@ static int syslog_print(char __user *buf +@@ -1454,7 +1407,7 @@ static int syslog_print(char __user *buf syslog_partial += n; } else n = 0; - logbuf_unlock_irq(); -+ syslog_unlock_irq(); ++ spin_unlock_irq(&syslog_lock); if (!n) break; -@@ -1525,6 +1482,7 @@ static int syslog_print_all(char __user +@@ -1479,6 +1432,7 @@ static int syslog_print_all(char __user struct printk_info info; unsigned int line_count; struct printk_record r; @@ -235,7 +259,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> u64 clr_seq; char *text; int len = 0; -@@ -1536,19 +1494,30 @@ static int syslog_print_all(char __user +@@ -1490,19 +1444,30 @@ static int syslog_print_all(char __user return -ENOMEM; time = printk_time; @@ -269,7 +293,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> break; len -= get_record_print_text_size(&info, line_count, true, time); } -@@ -1566,12 +1535,10 @@ static int syslog_print_all(char __user +@@ -1520,12 +1485,10 @@ static int syslog_print_all(char __user break; } @@ -282,7 +306,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> if (len < 0) break; -@@ -1579,7 +1546,6 @@ static int syslog_print_all(char __user +@@ -1533,7 +1496,6 @@ static int syslog_print_all(char __user if (clear) atomic64_set(&clear_seq, seq); @@ -290,7 +314,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> kfree(text); return len; -@@ -1587,9 +1553,7 @@ static int syslog_print_all(char __user +@@ -1541,9 +1503,7 @@ static int syslog_print_all(char __user static void syslog_clear(void) { @@ -300,7 +324,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> } int do_syslog(int type, char __user *buf, int len, int source) -@@ -1597,6 +1561,7 @@ int do_syslog(int type, char __user *buf +@@ -1551,6 +1511,7 @@ int do_syslog(int type, char __user *buf bool clear = false; static int saved_console_loglevel = LOGLEVEL_DEFAULT; int error; @@ -308,46 +332,249 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> error = check_syslog_permissions(type, source); if (error) -@@ -1614,8 +1579,11 @@ int do_syslog(int type, char __user *buf +@@ -1568,8 +1529,11 @@ int do_syslog(int type, char __user *buf return 0; if (!access_ok(buf, len)) return -EFAULT; -+ syslog_lock_irq(); ++ spin_lock_irq(&syslog_lock); + seq = syslog_seq; -+ syslog_unlock_irq(); ++ spin_unlock_irq(&syslog_lock); error = wait_event_interruptible(log_wait, - prb_read_valid(prb, syslog_seq, NULL)); + prb_read_valid(prb, seq, NULL)); if (error) return error; error = syslog_print(buf, len); -@@ -1663,7 +1631,7 @@ int do_syslog(int type, char __user *buf +@@ -1617,7 +1581,7 @@ int do_syslog(int type, char __user *buf break; /* Number of chars in the log buffer */ case SYSLOG_ACTION_SIZE_UNREAD: - logbuf_lock_irq(); -+ syslog_lock_irq(); ++ spin_lock_irq(&syslog_lock); if (syslog_seq < prb_first_valid_seq(prb)) { /* messages are gone, move to first one */ syslog_seq = prb_first_valid_seq(prb); -@@ -1690,7 +1658,7 @@ int do_syslog(int type, char __user *buf +@@ -1644,7 +1608,7 @@ int do_syslog(int type, char __user *buf } error -= syslog_partial; } - logbuf_unlock_irq(); -+ syslog_unlock_irq(); ++ spin_unlock_irq(&syslog_lock); break; /* Size of the log buffer */ case SYSLOG_ACTION_SIZE_BUFFER: -@@ -2065,7 +2033,6 @@ static size_t log_output(int facility, i - dev_info, text, text_len); +@@ -1847,6 +1811,65 @@ static void call_console_drivers(const c + } + } + ++#ifdef CONFIG_PRINTK_NMI ++#define NUM_RECURSION_CTX 2 ++#else ++#define NUM_RECURSION_CTX 1 ++#endif ++ ++struct printk_recursion { ++ char count[NUM_RECURSION_CTX]; ++}; ++ ++static DEFINE_PER_CPU(struct printk_recursion, percpu_printk_recursion); ++static char printk_recursion_count[NUM_RECURSION_CTX]; ++ ++static char *get_printk_count(void) ++{ ++ struct printk_recursion *rec; ++ char *count; ++ ++ if (!printk_percpu_data_ready()) { ++ count = &printk_recursion_count[0]; ++ } else { ++ rec = this_cpu_ptr(&percpu_printk_recursion); ++ ++ count = &rec->count[0]; ++ } ++ ++#ifdef CONFIG_PRINTK_NMI ++ if (in_nmi()) ++ count++; ++#endif ++ ++ return count; ++} ++ ++static bool printk_enter(unsigned long *flags) ++{ ++ char *count; ++ ++ local_irq_save(*flags); ++ count = get_printk_count(); ++ /* Only 1 level of recursion allowed. */ ++ if (*count > 1) { ++ local_irq_restore(*flags); ++ return false; ++ } ++ (*count)++; ++ ++ return true; ++} ++ ++static void printk_exit(unsigned long flags) ++{ ++ char *count; ++ ++ count = get_printk_count(); ++ (*count)--; ++ local_irq_restore(flags); ++} ++ + int printk_delay_msec __read_mostly; + + static inline void printk_delay(void) +@@ -1867,40 +1890,75 @@ static inline u32 printk_caller_id(void) + 0x80000000 + raw_smp_processor_id(); } -/* Must be called under logbuf_lock. */ ++static u16 printk_sprint(char *text, u16 size, int facility, enum log_flags *lflags, ++ const char *fmt, va_list args) ++{ ++ char *orig_text = text; ++ u16 text_len; ++ ++ text_len = vscnprintf(text, size, fmt, args); ++ ++ /* Mark and strip a trailing newline. */ ++ if (text_len && text[text_len - 1] == '\n') { ++ text_len--; ++ *lflags |= LOG_NEWLINE; ++ } ++ ++ /* Strip kernel syslog prefix. */ ++ if (facility == 0) { ++ while (text_len >= 2 && printk_get_level(text)) { ++ text_len -= 2; ++ text += 2; ++ } ++ ++ if (text != orig_text) ++ memmove(orig_text, text, text_len); ++ } ++ ++ return text_len; ++} ++ ++__printf(4, 0) int vprintk_store(int facility, int level, const struct dev_printk_info *dev_info, const char *fmt, va_list args) -@@ -2131,7 +2098,6 @@ asmlinkage int vprintk_emit(int facility + { + const u32 caller_id = printk_caller_id(); +- static char textbuf[LOG_LINE_MAX]; + struct prb_reserved_entry e; + enum log_flags lflags = 0; + struct printk_record r; ++ unsigned long irqflags; + u16 trunc_msg_len = 0; +- char *text = textbuf; ++ char lvlbuf[8]; ++ va_list args2; + u16 text_len; ++ int ret = 0; + u64 ts_nsec; + + ts_nsec = local_clock(); + ++ if (!printk_enter(&irqflags)) ++ return 0; ++ ++ va_copy(args2, args); ++ + /* + * The printf needs to come first; we need the syslog + * prefix which might be passed-in as a parameter. + */ +- text_len = vscnprintf(text, sizeof(textbuf), fmt, args); ++ text_len = vsnprintf(&lvlbuf[0], sizeof(lvlbuf), fmt, args) + 1; ++ if (text_len > CONSOLE_LOG_MAX) ++ text_len = CONSOLE_LOG_MAX; + +- /* mark and strip a trailing newline */ +- if (text_len && text[text_len-1] == '\n') { +- text_len--; +- lflags |= LOG_NEWLINE; +- } +- +- /* strip kernel syslog prefix and extract log level or control flags */ ++ /* Extract log level or control flags. */ + if (facility == 0) { + int kern_level; ++ int i; + +- while ((kern_level = printk_get_level(text)) != 0) { ++ for (i = 0; i < sizeof(lvlbuf); i += 2) { ++ kern_level = printk_get_level(&lvlbuf[i]); ++ if (!kern_level) ++ break; + switch (kern_level) { + case '0' ... '7': + if (level == LOGLEVEL_DEFAULT) +@@ -1909,9 +1967,6 @@ int vprintk_store(int facility, int leve + case 'c': /* KERN_CONT */ + lflags |= LOG_CONT; + } +- +- text_len -= 2; +- text += 2; + } + } + +@@ -1924,7 +1979,8 @@ int vprintk_store(int facility, int leve + if (lflags & LOG_CONT) { + prb_rec_init_wr(&r, text_len); + if (prb_reserve_in_last(&e, prb, &r, caller_id, LOG_LINE_MAX)) { +- memcpy(&r.text_buf[r.info->text_len], text, text_len); ++ text_len = printk_sprint(&r.text_buf[r.info->text_len], text_len, ++ facility, &lflags, fmt, args2); + r.info->text_len += text_len; + + if (lflags & LOG_NEWLINE) { +@@ -1934,7 +1990,8 @@ int vprintk_store(int facility, int leve + prb_commit(&e); + } + +- return text_len; ++ ret = text_len; ++ goto out; + } + } + +@@ -1945,11 +2002,11 @@ int vprintk_store(int facility, int leve + + prb_rec_init_wr(&r, text_len + trunc_msg_len); + if (!prb_reserve(&e, prb, &r)) +- return 0; ++ goto out; + } + + /* fill message */ +- memcpy(&r.text_buf[0], text, text_len); ++ text_len = printk_sprint(&r.text_buf[0], text_len, facility, &lflags, fmt, args2); + if (trunc_msg_len) + memcpy(&r.text_buf[text_len], trunc_msg, trunc_msg_len); + r.info->text_len = text_len + trunc_msg_len; +@@ -1967,7 +2024,11 @@ int vprintk_store(int facility, int leve + else + prb_final_commit(&e); + +- return (text_len + trunc_msg_len); ++ ret = text_len + trunc_msg_len; ++out: ++ va_end(args2); ++ printk_exit(irqflags); ++ return ret; + } + + asmlinkage int vprintk_emit(int facility, int level, +@@ -1976,7 +2037,6 @@ asmlinkage int vprintk_emit(int facility { int printed_len; bool in_sched = false; @@ -355,7 +582,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> /* Suppress unimportant messages after panic happens */ if (unlikely(suppress_printk)) -@@ -2146,9 +2112,7 @@ asmlinkage int vprintk_emit(int facility +@@ -1991,9 +2051,7 @@ asmlinkage int vprintk_emit(int facility printk_delay(); /* This stops the holder of console_sem just where we want him */ @@ -365,7 +592,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> /* If called from the scheduler, we can not call up(). */ if (!in_sched) { -@@ -2580,7 +2544,6 @@ void console_unlock(void) +@@ -2425,7 +2483,6 @@ void console_unlock(void) size_t len; printk_safe_enter_irqsave(flags); @@ -373,7 +600,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> skip: if (!prb_read_valid(prb, console_seq, &r)) break; -@@ -2624,7 +2587,6 @@ void console_unlock(void) +@@ -2469,7 +2526,6 @@ void console_unlock(void) console_msg_format & MSG_FORMAT_SYSLOG, printk_time); console_seq++; @@ -381,7 +608,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> /* * While actively printing out messages, if another printk() -@@ -2651,8 +2613,6 @@ void console_unlock(void) +@@ -2496,8 +2552,6 @@ void console_unlock(void) console_locked = 0; @@ -390,7 +617,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> up_console_sem(); /* -@@ -2661,9 +2621,7 @@ void console_unlock(void) +@@ -2506,9 +2560,7 @@ void console_unlock(void) * there's a new owner and the console_unlock() from them will do the * flush, no worries. */ @@ -400,7 +627,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> printk_safe_exit_irqrestore(flags); if (retry && console_trylock()) -@@ -2727,13 +2685,8 @@ void console_flush_on_panic(enum con_flu +@@ -2572,13 +2624,8 @@ void console_flush_on_panic(enum con_flu console_trylock(); console_may_schedule = 0; @@ -415,7 +642,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> console_unlock(); } -@@ -2957,11 +2910,7 @@ void register_console(struct console *ne +@@ -2802,11 +2849,7 @@ void register_console(struct console *ne nr_ext_console_drivers++; if (newcon->flags & CON_PRINTBUFFER) { @@ -424,20 +651,20 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> - * for us. - */ - logbuf_lock_irqsave(flags); -+ syslog_lock_irqsave(flags); ++ spin_lock_irqsave(&syslog_lock, flags); /* * We're about to replay the log buffer. Only do this to the * just-registered console to avoid excessive message spam to -@@ -2974,7 +2923,7 @@ void register_console(struct console *ne +@@ -2819,7 +2862,7 @@ void register_console(struct console *ne exclusive_console = newcon; exclusive_console_stop_seq = console_seq; console_seq = syslog_seq; - logbuf_unlock_irqrestore(flags); -+ syslog_unlock_irqrestore(flags); ++ spin_unlock_irqrestore(&syslog_lock, flags); } console_unlock(); console_sysfs_notify(); -@@ -3340,7 +3289,6 @@ EXPORT_SYMBOL_GPL(kmsg_dump_reason_str); +@@ -3185,7 +3228,6 @@ EXPORT_SYMBOL_GPL(kmsg_dump_reason_str); void kmsg_dump(enum kmsg_dump_reason reason) { struct kmsg_dumper *dumper; @@ -445,7 +672,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> rcu_read_lock(); list_for_each_entry_rcu(dumper, &dump_list, list) { -@@ -3360,10 +3308,7 @@ void kmsg_dump(enum kmsg_dump_reason rea +@@ -3205,10 +3247,7 @@ void kmsg_dump(enum kmsg_dump_reason rea /* initialize iterator with data about the stored records */ dumper->active = true; @@ -457,7 +684,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> /* invoke dumper which will iterate over records */ dumper->dump(dumper, reason); -@@ -3450,14 +3395,7 @@ bool kmsg_dump_get_line_nolock(struct km +@@ -3295,14 +3334,7 @@ bool kmsg_dump_get_line_nolock(struct km bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog, char *line, size_t size, size_t *len) { @@ -473,7 +700,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> } EXPORT_SYMBOL_GPL(kmsg_dump_get_line); -@@ -3486,7 +3424,6 @@ bool kmsg_dump_get_buffer(struct kmsg_du +@@ -3331,7 +3363,6 @@ bool kmsg_dump_get_buffer(struct kmsg_du struct printk_info info; unsigned int line_count; struct printk_record r; @@ -481,7 +708,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> u64 seq; u64 next_seq; size_t len = 0; -@@ -3496,17 +3433,14 @@ bool kmsg_dump_get_buffer(struct kmsg_du +@@ -3341,17 +3372,14 @@ bool kmsg_dump_get_buffer(struct kmsg_du if (!dumper->active || !buf || !size) goto out; @@ -500,7 +727,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> /* * Find first record that fits, including all following records, -@@ -3549,7 +3483,6 @@ bool kmsg_dump_get_buffer(struct kmsg_du +@@ -3394,7 +3422,6 @@ bool kmsg_dump_get_buffer(struct kmsg_du dumper->next_seq = next_seq; ret = true; @@ -508,7 +735,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> out: if (len_out) *len_out = len; -@@ -3564,8 +3497,6 @@ EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer); +@@ -3409,8 +3436,6 @@ EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer); * Reset the dumper's iterator so that kmsg_dump_get_line() and * kmsg_dump_get_buffer() can be called again and used multiple * times within the same dumper.dump() callback. @@ -517,7 +744,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> */ void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper) { -@@ -3583,11 +3514,7 @@ void kmsg_dump_rewind_nolock(struct kmsg +@@ -3428,11 +3453,7 @@ void kmsg_dump_rewind_nolock(struct kmsg */ void kmsg_dump_rewind(struct kmsg_dumper *dumper) { diff --git a/patches/0005-printk-remove-safe-buffers.patch b/patches/0005-printk-remove-safe-buffers.patch index ba8805748b07..874938b4efeb 100644 --- a/patches/0005-printk-remove-safe-buffers.patch +++ b/patches/0005-printk-remove-safe-buffers.patch @@ -1,6 +1,6 @@ From: John Ogness <john.ogness@linutronix.de> -Date: Wed, 14 Oct 2020 20:00:11 +0200 -Subject: [PATCH 05/15] printk: remove safe buffers +Date: Mon, 30 Nov 2020 01:42:00 +0106 +Subject: [PATCH 05/16] printk: remove safe buffers With @logbuf_lock removed, the high level printk functions for storing messages are lockless. Messages can be stored from any @@ -50,7 +50,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> --- a/include/linux/printk.h +++ b/include/linux/printk.h -@@ -207,8 +207,6 @@ void __init setup_log_buf(int early); +@@ -208,8 +208,6 @@ void __init setup_log_buf(int early); void dump_stack_print_info(const char *log_lvl); void show_regs_print_info(const char *log_lvl); extern asmlinkage void dump_stack(void) __cold; @@ -59,7 +59,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> #else static inline __printf(1, 0) int vprintk(const char *s, va_list args) -@@ -272,14 +270,6 @@ static inline void show_regs_print_info( +@@ -273,14 +271,6 @@ static inline void show_regs_print_info( static inline void dump_stack(void) { } @@ -122,7 +122,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> #endif /* CONFIG_PRINTK */ --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c -@@ -1037,9 +1037,6 @@ static inline void log_buf_add_cpu(void) +@@ -987,9 +987,6 @@ static inline void log_buf_add_cpu(void) static void __init set_percpu_data_ready(void) { diff --git a/patches/0006-console-add-write_atomic-interface.patch b/patches/0006-console-add-write_atomic-interface.patch index 0c25e4ae99c2..b1d6bdd94f72 100644 --- a/patches/0006-console-add-write_atomic-interface.patch +++ b/patches/0006-console-add-write_atomic-interface.patch @@ -1,6 +1,6 @@ From: John Ogness <john.ogness@linutronix.de> -Date: Wed, 14 Oct 2020 20:26:35 +0200 -Subject: [PATCH 06/15] console: add write_atomic interface +Date: Mon, 30 Nov 2020 01:42:01 +0106 +Subject: [PATCH 06/16] console: add write_atomic interface Add a write_atomic() callback to the console. This is an optional function for console drivers. The function must be atomic (including @@ -34,7 +34,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> struct console { char name[16]; void (*write)(struct console *, const char *, unsigned); -+ void (*write_atomic)(struct console *, const char *, unsigned); ++ void (*write_atomic)(struct console *co, const char *s, unsigned int count); int (*read)(struct console *, char *, unsigned); struct tty_driver *(*device)(struct console *, int *); void (*unblank)(void); @@ -48,7 +48,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> #endif /* _LINUX_CONSOLE_H */ --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c -@@ -3516,3 +3516,103 @@ void kmsg_dump_rewind(struct kmsg_dumper +@@ -3455,3 +3455,103 @@ void kmsg_dump_rewind(struct kmsg_dumper EXPORT_SYMBOL_GPL(kmsg_dump_rewind); #endif @@ -105,7 +105,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> + * + * It is safe to call this function from any context and state. + */ -+void prb_lock(struct prb_cpulock *cpu_lock, unsigned int *cpu_store) ++static void prb_lock(struct prb_cpulock *cpu_lock, unsigned int *cpu_store) +{ + for (;;) { + if (__prb_trylock(cpu_lock, cpu_store)) @@ -123,7 +123,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> + * + * It is safe to call this function from any context and state. + */ -+void prb_unlock(struct prb_cpulock *cpu_lock, unsigned int cpu_store) ++static void prb_unlock(struct prb_cpulock *cpu_lock, unsigned int cpu_store) +{ + unsigned long *flags; + unsigned int cpu; diff --git a/patches/0007-serial-8250-implement-write_atomic.patch b/patches/0007-serial-8250-implement-write_atomic.patch index 1b88e78b4d7c..b1aef776d287 100644 --- a/patches/0007-serial-8250-implement-write_atomic.patch +++ b/patches/0007-serial-8250-implement-write_atomic.patch @@ -1,6 +1,6 @@ From: John Ogness <john.ogness@linutronix.de> -Date: Wed, 14 Oct 2020 20:31:46 +0200 -Subject: [PATCH 07/15] serial: 8250: implement write_atomic +Date: Mon, 30 Nov 2020 01:42:02 +0106 +Subject: [PATCH 07/16] serial: 8250: implement write_atomic Implement a non-sleeping NMI-safe write_atomic() console function in order to support emergency console printing. diff --git a/patches/0009-printk-relocate-printk_delay-and-vprintk_default.patch b/patches/0008-printk-relocate-printk_delay-and-vprintk_default.patch index ffd29dfd11af..89139600b8fd 100644 --- a/patches/0009-printk-relocate-printk_delay-and-vprintk_default.patch +++ b/patches/0008-printk-relocate-printk_delay-and-vprintk_default.patch @@ -1,11 +1,11 @@ From: John Ogness <john.ogness@linutronix.de> -Date: Mon, 19 Oct 2020 21:02:40 +0206 -Subject: [PATCH 09/15] printk: relocate printk_delay() and vprintk_default() +Date: Mon, 30 Nov 2020 01:42:03 +0106 +Subject: [PATCH 08/16] printk: relocate printk_delay() and vprintk_default() Move printk_delay() and vprintk_default() "as is" further up so that they can be used by new functions in an upcoming commit. -Signed-off-by: John Ogness <john.ogness@linutornix.de> +Signed-off-by: John Ogness <john.ogness@linutronix.de> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> --- kernel/printk/printk.c | 40 ++++++++++++++++++++-------------------- @@ -13,8 +13,8 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c -@@ -1751,6 +1751,20 @@ static void put_sprint_buf(int id, unsig - local_irq_restore(flags); +@@ -1624,6 +1624,20 @@ SYSCALL_DEFINE3(syslog, int, type, char + return do_syslog(type, buf, len, SYSLOG_FROM_READER); } +int printk_delay_msec __read_mostly; @@ -34,8 +34,8 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> /* * Special console_lock variants that help to reduce the risk of soft-lockups. * They allow to pass console_lock to another printk() call using a busy wait. -@@ -1935,20 +1949,6 @@ static void call_console_drivers(const c - } +@@ -1867,20 +1881,6 @@ static void printk_exit(unsigned long fl + local_irq_restore(flags); } -int printk_delay_msec __read_mostly; @@ -55,7 +55,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> static inline u32 printk_caller_id(void) { return in_task() ? task_pid_nr(current) : -@@ -2119,18 +2119,18 @@ asmlinkage int vprintk_emit(int facility +@@ -2073,18 +2073,18 @@ asmlinkage int vprintk_emit(int facility } EXPORT_SYMBOL(vprintk_emit); diff --git a/patches/0010-printk-combine-boot_delay_msec-into-printk_delay.patch b/patches/0009-printk-combine-boot_delay_msec-into-printk_delay.patch index 54892f3d062f..ed47f9da8faf 100644 --- a/patches/0010-printk-combine-boot_delay_msec-into-printk_delay.patch +++ b/patches/0009-printk-combine-boot_delay_msec-into-printk_delay.patch @@ -1,6 +1,6 @@ From: John Ogness <john.ogness@linutronix.de> -Date: Mon, 19 Oct 2020 22:11:31 +0206 -Subject: [PATCH 10/15] printk: combine boot_delay_msec() into printk_delay() +Date: Mon, 30 Nov 2020 01:42:04 +0106 +Subject: [PATCH 09/16] printk: combine boot_delay_msec() into printk_delay() boot_delay_msec() is always called immediately before printk_delay() so just combine the two. @@ -13,7 +13,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c -@@ -1753,8 +1753,10 @@ static void put_sprint_buf(int id, unsig +@@ -1626,8 +1626,10 @@ SYSCALL_DEFINE3(syslog, int, type, char int printk_delay_msec __read_mostly; @@ -25,7 +25,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> if (unlikely(printk_delay_msec)) { int m = printk_delay_msec; -@@ -2090,8 +2092,7 @@ asmlinkage int vprintk_emit(int facility +@@ -2044,8 +2046,7 @@ asmlinkage int vprintk_emit(int facility in_sched = true; } diff --git a/patches/0010-printk-change-console_seq-to-atomic64_t.patch b/patches/0010-printk-change-console_seq-to-atomic64_t.patch new file mode 100644 index 000000000000..5299e29eecca --- /dev/null +++ b/patches/0010-printk-change-console_seq-to-atomic64_t.patch @@ -0,0 +1,122 @@ +From: John Ogness <john.ogness@linutronix.de> +Date: Mon, 30 Nov 2020 01:42:05 +0106 +Subject: [PATCH 10/16] printk: change @console_seq to atomic64_t + +In preparation for atomic printing, change @console_seq to atomic +so that it can be accessed without requiring @console_sem. + +Signed-off-by: John Ogness <john.ogness@linutronix.de> +Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +--- + kernel/printk/printk.c | 34 +++++++++++++++++++--------------- + 1 file changed, 19 insertions(+), 15 deletions(-) + +--- a/kernel/printk/printk.c ++++ b/kernel/printk/printk.c +@@ -366,12 +366,13 @@ static u64 syslog_seq; + static size_t syslog_partial; + static bool syslog_time; + +-/* All 3 protected by @console_sem. */ +-/* the next printk record to write to the console */ +-static u64 console_seq; ++/* Both protected by @console_sem. */ + static u64 exclusive_console_stop_seq; + static unsigned long console_dropped; + ++/* the next printk record to write to the console */ ++static atomic64_t console_seq = ATOMIC64_INIT(0); ++ + /* the next printk record to read after the last 'clear' command */ + static atomic64_t clear_seq = ATOMIC64_INIT(0); + +@@ -2130,7 +2131,7 @@ EXPORT_SYMBOL(printk); + #define prb_first_valid_seq(rb) 0 + + static u64 syslog_seq; +-static u64 console_seq; ++static atomic64_t console_seq = ATOMIC64_INIT(0); + static u64 exclusive_console_stop_seq; + static unsigned long console_dropped; + +@@ -2439,6 +2440,7 @@ void console_unlock(void) + bool do_cond_resched, retry; + struct printk_info info; + struct printk_record r; ++ u64 seq; + + if (console_suspended) { + up_console_sem(); +@@ -2482,12 +2484,14 @@ void console_unlock(void) + + printk_safe_enter_irqsave(flags); + skip: +- if (!prb_read_valid(prb, console_seq, &r)) ++ seq = atomic64_read(&console_seq); ++ if (!prb_read_valid(prb, seq, &r)) + break; + +- if (console_seq != r.info->seq) { +- console_dropped += r.info->seq - console_seq; +- console_seq = r.info->seq; ++ if (seq != r.info->seq) { ++ console_dropped += r.info->seq - seq; ++ atomic64_set(&console_seq, r.info->seq); ++ seq = r.info->seq; + } + + if (suppress_message_printing(r.info->level)) { +@@ -2496,13 +2500,13 @@ void console_unlock(void) + * directly to the console when we received it, and + * record that has level above the console loglevel. + */ +- console_seq++; ++ atomic64_set(&console_seq, seq + 1); + goto skip; + } + + /* Output to all consoles once old messages replayed. */ + if (unlikely(exclusive_console && +- console_seq >= exclusive_console_stop_seq)) { ++ seq >= exclusive_console_stop_seq)) { + exclusive_console = NULL; + } + +@@ -2523,7 +2527,7 @@ void console_unlock(void) + len = record_print_text(&r, + console_msg_format & MSG_FORMAT_SYSLOG, + printk_time); +- console_seq++; ++ atomic64_set(&console_seq, seq + 1); + + /* + * While actively printing out messages, if another printk() +@@ -2558,7 +2562,7 @@ void console_unlock(void) + * there's a new owner and the console_unlock() from them will do the + * flush, no worries. + */ +- retry = prb_read_valid(prb, console_seq, NULL); ++ retry = prb_read_valid(prb, atomic64_read(&console_seq), NULL); + printk_safe_exit_irqrestore(flags); + + if (retry && console_trylock()) +@@ -2623,7 +2627,7 @@ void console_flush_on_panic(enum con_flu + console_may_schedule = 0; + + if (mode == CONSOLE_REPLAY_ALL) +- console_seq = prb_first_valid_seq(prb); ++ atomic64_set(&console_seq, prb_first_valid_seq(prb)); + console_unlock(); + } + +@@ -2858,8 +2862,8 @@ void register_console(struct console *ne + * ignores console_lock. + */ + exclusive_console = newcon; +- exclusive_console_stop_seq = console_seq; +- console_seq = syslog_seq; ++ exclusive_console_stop_seq = atomic64_read(&console_seq); ++ atomic64_set(&console_seq, syslog_seq); + spin_unlock_irqrestore(&syslog_lock, flags); + } + console_unlock(); diff --git a/patches/0011-printk-introduce-kernel-sync-mode.patch b/patches/0011-printk-introduce-kernel-sync-mode.patch index 8d7107ee3df0..efcc95736dd9 100644 --- a/patches/0011-printk-introduce-kernel-sync-mode.patch +++ b/patches/0011-printk-introduce-kernel-sync-mode.patch @@ -1,20 +1,39 @@ From: John Ogness <john.ogness@linutronix.de> -Date: Wed, 14 Oct 2020 20:40:05 +0200 -Subject: [PATCH 11/15] printk: introduce kernel sync mode +Date: Mon, 30 Nov 2020 01:42:06 +0106 +Subject: [PATCH 11/16] printk: introduce kernel sync mode When the kernel performs an OOPS, enter into "sync mode": - only atomic consoles (write_atomic() callback) will print - printing occurs within vprintk_store() instead of console_unlock() -Change @console_seq to atomic64_t for atomic access. - Signed-off-by: John Ogness <john.ogness@linutronix.de> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> --- - kernel/printk/printk.c | 165 ++++++++++++++++++++++++++++++++++++++++++++----- - 1 file changed, 150 insertions(+), 15 deletions(-) + include/linux/console.h | 4 + + kernel/printk/printk.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 144 insertions(+), 2 deletions(-) +--- a/include/linux/console.h ++++ b/include/linux/console.h +@@ -16,6 +16,7 @@ + + #include <linux/atomic.h> + #include <linux/types.h> ++#include <linux/printk.h> + + struct vc_data; + struct console_font_op; +@@ -151,6 +152,9 @@ struct console { + short flags; + short index; + int cflag; ++#ifdef CONFIG_PRINTK ++ char sync_buf[CONSOLE_LOG_MAX]; ++#endif + void *data; + struct console *next; + }; --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -44,6 +44,7 @@ @@ -25,34 +44,17 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> #include <linux/sched/clock.h> #include <linux/sched/debug.h> #include <linux/sched/task_stack.h> -@@ -78,6 +79,9 @@ EXPORT_SYMBOL(ignore_console_lock_warnin - int oops_in_progress; - EXPORT_SYMBOL(oops_in_progress); +@@ -359,6 +360,9 @@ enum log_flags { + static DEFINE_SPINLOCK(syslog_lock); + #ifdef CONFIG_PRINTK +/* Set to enable sync mode. Once set, it is never cleared. */ +static bool sync_mode; + - /* - * console_sem protects the console_drivers list, and also - * provides serialisation for access to the entire console -@@ -370,12 +374,13 @@ static u64 syslog_seq; - static size_t syslog_partial; - static bool syslog_time; - --/* All 3 protected by @console_sem. */ --/* the next printk record to write to the console */ --static u64 console_seq; -+/* Both protected by @console_sem. */ - static u64 exclusive_console_stop_seq; - static unsigned long console_dropped; - -+/* the next printk record to write to the console */ -+static atomic64_t console_seq = ATOMIC64_INIT(0); -+ - /* the next printk record to read after the last 'clear' command */ - static atomic64_t clear_seq = ATOMIC64_INIT(0); - -@@ -1767,6 +1772,110 @@ static inline void printk_delay(int leve + DECLARE_WAIT_QUEUE_HEAD(log_wait); + /* All 3 protected by @syslog_lock. */ + /* the next printk record to read by syslog(READ) or /proc/kmsg */ +@@ -1641,6 +1645,110 @@ static inline void printk_delay(int leve } } @@ -106,20 +108,20 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> + return false; +} + -+static bool print_sync(struct console *con, char *buf, size_t buf_size, u64 *seq) ++static bool print_sync(struct console *con, u64 *seq) +{ + struct printk_info info; + struct printk_record r; + size_t text_len; + -+ prb_rec_init_rd(&r, &info, buf, buf_size); ++ prb_rec_init_rd(&r, &info, &con->sync_buf[0], sizeof(con->sync_buf)); + + if (!prb_read_valid(prb, *seq, &r)) + return false; + + text_len = record_print_text(&r, console_msg_format & MSG_FORMAT_SYSLOG, printk_time); + -+ if (!call_sync_console_driver(con, buf, text_len)) ++ if (!call_sync_console_driver(con, &con->sync_buf[0], text_len)) + return false; + + *seq = r.info->seq; @@ -135,7 +137,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> + return true; +} + -+static void print_sync_until(u64 seq, struct console *con, char *buf, size_t buf_size) ++static void print_sync_until(struct console *con, u64 seq) +{ + unsigned int flags; + u64 printk_seq; @@ -143,7 +145,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> + if (!con) { + for_each_console(con) { + if (console_can_sync(con)) -+ print_sync_until(seq, con, buf, buf_size); ++ print_sync_until(con, seq); + } + return; + } @@ -153,7 +155,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> + printk_seq = atomic64_read(&console_seq); + if (printk_seq >= seq) + break; -+ if (!print_sync(con, buf, buf_size, &printk_seq)) ++ if (!print_sync(con, &printk_seq)) + break; + atomic64_set(&console_seq, printk_seq + 1); + } @@ -163,7 +165,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> /* * Special console_lock variants that help to reduce the risk of soft-lockups. * They allow to pass console_lock to another printk() call using a busy wait. -@@ -1941,6 +2050,8 @@ static void call_console_drivers(const c +@@ -1815,6 +1923,8 @@ static void call_console_drivers(const c if (!cpu_online(smp_processor_id()) && !(con->flags & CON_ANYTIME)) continue; @@ -172,15 +174,31 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> if (con->flags & CON_EXTENDED) con->write(con, ext_text, ext_len); else { -@@ -1964,6 +2075,7 @@ int vprintk_store(int facility, int leve +@@ -1926,6 +2036,7 @@ int vprintk_store(int facility, int leve const u32 caller_id = printk_caller_id(); struct prb_reserved_entry e; enum log_flags lflags = 0; + bool final_commit = false; - unsigned long irqflags; struct printk_record r; + unsigned long irqflags; u16 trunc_msg_len = 0; -@@ -2027,6 +2139,7 @@ int vprintk_store(int facility, int leve +@@ -1934,6 +2045,7 @@ int vprintk_store(int facility, int leve + u16 text_len; + int ret = 0; + u64 ts_nsec; ++ u64 seq; + + ts_nsec = local_clock(); + +@@ -1979,6 +2091,7 @@ int vprintk_store(int facility, int leve + if (lflags & LOG_CONT) { + prb_rec_init_wr(&r, text_len); + if (prb_reserve_in_last(&e, prb, &r, caller_id, LOG_LINE_MAX)) { ++ seq = r.info->seq; + text_len = printk_sprint(&r.text_buf[r.info->text_len], text_len, + facility, &lflags, fmt, args2); + r.info->text_len += text_len; +@@ -1986,6 +2099,7 @@ int vprintk_store(int facility, int leve if (lflags & LOG_NEWLINE) { r.info->flags |= LOG_NEWLINE; prb_final_commit(&e); @@ -188,32 +206,47 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> } else { prb_commit(&e); } -@@ -2068,10 +2181,15 @@ int vprintk_store(int facility, int leve +@@ -2005,6 +2119,8 @@ int vprintk_store(int facility, int leve + goto out; + } + ++ seq = r.info->seq; ++ + /* fill message */ + text_len = printk_sprint(&r.text_buf[0], text_len, facility, &lflags, fmt, args2); + if (trunc_msg_len) +@@ -2019,13 +2135,19 @@ int vprintk_store(int facility, int leve + memcpy(&r.info->dev_info, dev_info, sizeof(r.info->dev_info)); + + /* A message without a trailing newline can be continued. */ +- if (!(lflags & LOG_NEWLINE)) ++ if (!(lflags & LOG_NEWLINE)) { prb_commit(&e); - } else { +- else ++ } else { prb_final_commit(&e); + final_commit = true; - } ++ } ret = text_len + trunc_msg_len; out: + /* only the kernel may perform synchronous printing */ + if (facility == 0 && final_commit && any_console_can_sync()) -+ print_sync_until(seq + 1, NULL, text, PREFIX_MAX + LOG_LINE_MAX); ++ print_sync_until(NULL, seq + 1); + - put_sprint_buf(sprint_id, irqflags); + va_end(args2); + printk_exit(irqflags); return ret; - } -@@ -2176,7 +2294,7 @@ EXPORT_SYMBOL(printk); +@@ -2130,6 +2252,8 @@ EXPORT_SYMBOL(printk); + #define prb_read_valid(rb, seq, r) false #define prb_first_valid_seq(rb) 0 ++#define kernel_sync_mode() false ++ static u64 syslog_seq; --static u64 console_seq; -+static atomic64_t console_seq = ATOMI64_INIT(0); + static atomic64_t console_seq = ATOMIC64_INIT(0); static u64 exclusive_console_stop_seq; - static unsigned long console_dropped; - -@@ -2460,6 +2578,8 @@ static int have_callable_console(void) +@@ -2415,6 +2539,8 @@ static int have_callable_console(void) */ static inline int can_use_console(void) { @@ -222,88 +255,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> return cpu_online(raw_smp_processor_id()) || have_callable_console(); } -@@ -2485,6 +2605,7 @@ void console_unlock(void) - bool do_cond_resched, retry; - struct printk_info info; - struct printk_record r; -+ u64 seq; - - if (console_suspended) { - up_console_sem(); -@@ -2528,12 +2649,14 @@ void console_unlock(void) - - printk_safe_enter_irqsave(flags); - skip: -- if (!prb_read_valid(prb, console_seq, &r)) -+ seq = atomic64_read(&console_seq); -+ if (!prb_read_valid(prb, seq, &r)) - break; - -- if (console_seq != r.info->seq) { -- console_dropped += r.info->seq - console_seq; -- console_seq = r.info->seq; -+ if (seq != r.info->seq) { -+ console_dropped += r.info->seq - seq; -+ atomic64_set(&console_seq, r.info->seq); -+ seq = r.info->seq; - } - - if (suppress_message_printing(r.info->level)) { -@@ -2542,13 +2665,13 @@ void console_unlock(void) - * directly to the console when we received it, and - * record that has level above the console loglevel. - */ -- console_seq++; -+ atomic64_set(&console_seq, seq + 1); - goto skip; - } - - /* Output to all consoles once old messages replayed. */ - if (unlikely(exclusive_console && -- console_seq >= exclusive_console_stop_seq)) { -+ seq >= exclusive_console_stop_seq)) { - exclusive_console = NULL; - } - -@@ -2569,7 +2692,7 @@ void console_unlock(void) - len = record_print_text(&r, - console_msg_format & MSG_FORMAT_SYSLOG, - printk_time); -- console_seq++; -+ atomic64_set(&console_seq, seq + 1); - - /* - * While actively printing out messages, if another printk() -@@ -2604,7 +2727,7 @@ void console_unlock(void) - * there's a new owner and the console_unlock() from them will do the - * flush, no worries. - */ -- retry = prb_read_valid(prb, console_seq, NULL); -+ retry = prb_read_valid(prb, atomic64_read(&console_seq), NULL); - printk_safe_exit_irqrestore(flags); - - if (retry && console_trylock()) -@@ -2669,7 +2792,7 @@ void console_flush_on_panic(enum con_flu - console_may_schedule = 0; - - if (mode == CONSOLE_REPLAY_ALL) -- console_seq = prb_first_valid_seq(prb); -+ atomic64_set(&console_seq, prb_first_valid_seq(prb)); - console_unlock(); - } - -@@ -2904,8 +3027,8 @@ void register_console(struct console *ne - * ignores console_lock. - */ - exclusive_console = newcon; -- exclusive_console_stop_seq = console_seq; -- console_seq = syslog_seq; -+ exclusive_console_stop_seq = atomic64_read(&console_seq); -+ atomic64_set(&console_seq, syslog_seq); - syslog_unlock_irqrestore(flags); - } - console_unlock(); -@@ -3273,6 +3396,18 @@ void kmsg_dump(enum kmsg_dump_reason rea +@@ -3231,6 +3357,18 @@ void kmsg_dump(enum kmsg_dump_reason rea { struct kmsg_dumper *dumper; diff --git a/patches/0012-printk-move-console-printing-to-kthreads.patch b/patches/0012-printk-move-console-printing-to-kthreads.patch index 39df8851ff79..4f3310e13ed0 100644 --- a/patches/0012-printk-move-console-printing-to-kthreads.patch +++ b/patches/0012-printk-move-console-printing-to-kthreads.patch @@ -1,6 +1,6 @@ From: John Ogness <john.ogness@linutronix.de> -Date: Mon, 19 Oct 2020 22:30:38 +0206 -Subject: [PATCH 12/15] printk: move console printing to kthreads +Date: Mon, 30 Nov 2020 01:42:07 +0106 +Subject: [PATCH 12/16] printk: move console printing to kthreads Create a kthread for each console to perform console printing. Now all console printing is fully asynchronous except for the boot @@ -14,15 +14,15 @@ Signed-off-by: John Ogness <john.ogness@linutronix.de> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> --- include/linux/console.h | 2 - kernel/printk/printk.c | 586 +++++++++++++++--------------------------------- - 2 files changed, 190 insertions(+), 398 deletions(-) + kernel/printk/printk.c | 635 ++++++++++++++---------------------------------- + 2 files changed, 192 insertions(+), 445 deletions(-) --- a/include/linux/console.h +++ b/include/linux/console.h -@@ -151,6 +151,8 @@ struct console { - short flags; - short index; - int cflag; +@@ -155,6 +155,8 @@ struct console { + #ifdef CONFIG_PRINTK + char sync_buf[CONSOLE_LOG_MAX]; + #endif + atomic64_t printk_seq; + struct task_struct *thread; void *data; @@ -38,7 +38,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> #include <linux/clocksource.h> #include <linux/sched/clock.h> #include <linux/sched/debug.h> -@@ -271,11 +272,6 @@ static void __up_console_sem(unsigned lo +@@ -268,11 +269,6 @@ static void __up_console_sem(unsigned lo static int console_locked, console_suspended; /* @@ -50,7 +50,19 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> * Array of consoles built from command line options (console=) */ -@@ -374,13 +370,6 @@ static u64 syslog_seq; +@@ -356,10 +352,10 @@ enum log_flags { + LOG_CONT = 8, /* text is a fragment of a continuation line */ + }; + ++#ifdef CONFIG_PRINTK + /* The syslog_lock protects syslog_* variables. */ + static DEFINE_SPINLOCK(syslog_lock); + +-#ifdef CONFIG_PRINTK + /* Set to enable sync mode. Once set, it is never cleared. */ + static bool sync_mode; + +@@ -370,13 +366,6 @@ static u64 syslog_seq; static size_t syslog_partial; static bool syslog_time; @@ -64,7 +76,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> /* the next printk record to read after the last 'clear' command */ static atomic64_t clear_seq = ATOMIC64_INIT(0); -@@ -1783,6 +1772,8 @@ static bool console_can_sync(struct cons +@@ -1656,6 +1645,8 @@ static bool console_can_sync(struct cons return false; if (con->write_atomic && kernel_sync_mode()) return true; @@ -73,7 +85,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> return false; } -@@ -1792,6 +1783,8 @@ static bool call_sync_console_driver(str +@@ -1665,6 +1656,8 @@ static bool call_sync_console_driver(str return false; if (con->write_atomic && kernel_sync_mode()) con->write_atomic(con, text, text_len); @@ -82,7 +94,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> else return false; -@@ -1866,202 +1859,16 @@ static void print_sync_until(u64 seq, st +@@ -1739,202 +1732,16 @@ static void print_sync_until(struct cons console_atomic_lock(&flags); for (;;) { @@ -90,7 +102,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> + printk_seq = atomic64_read(&con->printk_seq); if (printk_seq >= seq) break; - if (!print_sync(con, buf, buf_size, &printk_seq)) + if (!print_sync(con, &printk_seq)) break; - atomic64_set(&console_seq, printk_seq + 1); + atomic64_set(&con->printk_seq, printk_seq + 1); @@ -284,10 +296,10 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> - } -} - - static inline u32 printk_caller_id(void) - { - return in_task() ? task_pid_nr(current) : -@@ -2199,40 +2006,16 @@ asmlinkage int vprintk_emit(int facility + #ifdef CONFIG_PRINTK_NMI + #define NUM_RECURSION_CTX 2 + #else +@@ -2158,40 +1965,16 @@ asmlinkage int vprintk_emit(int facility const char *fmt, va_list args) { int printed_len; @@ -302,9 +314,9 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> level = LOGLEVEL_DEFAULT; - in_sched = true; - } -- -- printk_delay(level); +- printk_delay(level); +- - /* This stops the holder of console_sem just where we want him */ printed_len = vprintk_store(facility, level, dev_info, fmt, args); @@ -329,35 +341,233 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> wake_up_klogd(); return printed_len; } -@@ -2294,9 +2077,6 @@ EXPORT_SYMBOL(printk); +@@ -2243,6 +2026,153 @@ asmlinkage __visible int printk(const ch + } + EXPORT_SYMBOL(printk); + ++static int printk_kthread_func(void *data) ++{ ++ struct console *con = data; ++ unsigned long dropped = 0; ++ char *dropped_text = NULL; ++ struct printk_info info; ++ struct printk_record r; ++ char *ext_text = NULL; ++ size_t dropped_len; ++ int ret = -ENOMEM; ++ char *text = NULL; ++ char *write_text; ++ u64 printk_seq; ++ size_t len; ++ int error; ++ u64 seq; ++ ++ if (con->flags & CON_EXTENDED) { ++ ext_text = kmalloc(CONSOLE_EXT_LOG_MAX, GFP_KERNEL); ++ if (!ext_text) ++ goto out; ++ } ++ text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL); ++ dropped_text = kmalloc(64, GFP_KERNEL); ++ if (!text || !dropped_text) ++ goto out; ++ ++ if (con->flags & CON_EXTENDED) ++ write_text = ext_text; ++ else ++ write_text = text; ++ ++ seq = atomic64_read(&con->printk_seq); ++ ++ prb_rec_init_rd(&r, &info, text, LOG_LINE_MAX + PREFIX_MAX); ++ ++ for (;;) { ++ error = wait_event_interruptible(log_wait, ++ prb_read_valid(prb, seq, &r) || kthread_should_stop()); ++ ++ if (kthread_should_stop()) ++ break; ++ ++ if (error) ++ continue; ++ ++ if (seq != r.info->seq) { ++ dropped += r.info->seq - seq; ++ seq = r.info->seq; ++ } ++ ++ seq++; ++ ++ if (!(con->flags & CON_ENABLED)) ++ continue; ++ ++ if (suppress_message_printing(r.info->level)) ++ continue; ++ ++ if (con->flags & CON_EXTENDED) { ++ len = info_print_ext_header(ext_text, ++ CONSOLE_EXT_LOG_MAX, ++ r.info); ++ len += msg_print_ext_body(ext_text + len, ++ CONSOLE_EXT_LOG_MAX - len, ++ &r.text_buf[0], r.info->text_len, ++ &r.info->dev_info); ++ } else { ++ len = record_print_text(&r, ++ console_msg_format & MSG_FORMAT_SYSLOG, ++ printk_time); ++ } ++ ++ printk_seq = atomic64_read(&con->printk_seq); ++ ++ console_lock(); ++ console_may_schedule = 0; ++ ++ if (kernel_sync_mode() && con->write_atomic) { ++ console_unlock(); ++ break; ++ } ++ ++ if (!(con->flags & CON_EXTENDED) && dropped) { ++ dropped_len = snprintf(dropped_text, 64, ++ "** %lu printk messages dropped **\n", ++ dropped); ++ dropped = 0; ++ ++ con->write(con, dropped_text, dropped_len); ++ printk_delay(r.info->level); ++ } ++ ++ con->write(con, write_text, len); ++ if (len) ++ printk_delay(r.info->level); ++ ++ atomic64_cmpxchg_relaxed(&con->printk_seq, printk_seq, seq); ++ ++ console_unlock(); ++ } ++out: ++ kfree(dropped_text); ++ kfree(text); ++ kfree(ext_text); ++ pr_info("%sconsole [%s%d]: printing thread stopped\n", ++ (con->flags & CON_BOOT) ? "boot" : "", ++ con->name, con->index); ++ return ret; ++} ++ ++/* Must be called within console_lock(). */ ++static void start_printk_kthread(struct console *con) ++{ ++ con->thread = kthread_run(printk_kthread_func, con, ++ "pr/%s%d", con->name, con->index); ++ if (IS_ERR(con->thread)) { ++ pr_err("%sconsole [%s%d]: unable to start printing thread\n", ++ (con->flags & CON_BOOT) ? "boot" : "", ++ con->name, con->index); ++ return; ++ } ++ pr_info("%sconsole [%s%d]: printing thread started\n", ++ (con->flags & CON_BOOT) ? "boot" : "", ++ con->name, con->index); ++} ++ ++/* protected by console_lock */ ++static bool kthreads_started; ++ ++/* Must be called within console_lock(). */ ++static void console_try_thread(struct console *con) ++{ ++ if (kthreads_started) { ++ start_printk_kthread(con); ++ return; ++ } ++ ++ /* ++ * The printing threads have not been started yet. If this console ++ * can print synchronously, print all unprinted messages. ++ */ ++ ++ if (console_can_sync(con)) ++ print_sync_until(con, prb_next_seq(prb)); ++} ++ + #else /* CONFIG_PRINTK */ + + #define LOG_LINE_MAX 0 +@@ -2251,32 +2181,11 @@ EXPORT_SYMBOL(printk); + + #define prb_read_valid(rb, seq, r) false #define prb_first_valid_seq(rb) 0 ++#define prb_next_seq(rb) 0 - static u64 syslog_seq; --static atomic64_t console_seq = ATOMI64_INIT(0); + #define kernel_sync_mode() false + +-static u64 syslog_seq; +-static atomic64_t console_seq = ATOMIC64_INIT(0); -static u64 exclusive_console_stop_seq; -static unsigned long console_dropped; - - static size_t record_print_text(const struct printk_record *r, - bool syslog, bool time) -@@ -2311,8 +2091,6 @@ static ssize_t info_print_ext_header(cha - static ssize_t msg_print_ext_body(char *buf, size_t size, - char *text, size_t text_len, - struct dev_printk_info *dev_info) { return 0; } +- +-static size_t record_print_text(const struct printk_record *r, +- bool syslog, bool time) +-{ +- return 0; +-} +-static ssize_t info_print_ext_header(char *buf, size_t size, +- struct printk_info *info) +-{ +- return 0; +-} +-static ssize_t msg_print_ext_body(char *buf, size_t size, +- char *text, size_t text_len, +- struct dev_printk_info *dev_info) { return 0; } -static void console_lock_spinning_enable(void) { } -static int console_lock_spinning_disable_and_check(void) { return 0; } - static void call_console_drivers(const char *ext_text, size_t ext_len, - const char *text, size_t len) {} - static bool suppress_message_printing(int level) { return false; } -@@ -2578,8 +2356,6 @@ static int have_callable_console(void) - */ - static inline int can_use_console(void) - { -- if (kernel_sync_mode()) -- return false; - return cpu_online(raw_smp_processor_id()) || have_callable_console(); +-static void call_console_drivers(const char *ext_text, size_t ext_len, +- const char *text, size_t len) {} +-static bool suppress_message_printing(int level) { return false; } ++#define console_try_thread(con) + + #endif /* CONFIG_PRINTK */ + +@@ -2514,36 +2423,6 @@ int is_console_locked(void) } + EXPORT_SYMBOL(is_console_locked); -@@ -2599,139 +2375,14 @@ static inline int can_use_console(void) +-/* +- * Check if we have any console that is capable of printing while cpu is +- * booting or shutting down. Requires console_sem. +- */ +-static int have_callable_console(void) +-{ +- struct console *con; +- +- for_each_console(con) +- if ((con->flags & CON_ENABLED) && +- (con->flags & CON_ANYTIME)) +- return 1; +- +- return 0; +-} +- +-/* +- * Can we actually use the console at this time on this cpu? +- * +- * Console drivers may assume that per-cpu resources have been allocated. So +- * unless they're explicitly marked as being able to cope (CON_ANYTIME) don't +- * call them until this CPU is officially up. +- */ +-static inline int can_use_console(void) +-{ +- if (kernel_sync_mode()) +- return false; +- return cpu_online(raw_smp_processor_id()) || have_callable_console(); +-} +- + /** + * console_unlock - unlock the console system + * +@@ -2560,139 +2439,14 @@ static inline int can_use_console(void) */ void console_unlock(void) { @@ -497,7 +707,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> } EXPORT_SYMBOL(console_unlock); -@@ -2781,18 +2432,20 @@ void console_unblank(void) +@@ -2742,18 +2496,20 @@ void console_unblank(void) */ void console_flush_on_panic(enum con_flush_mode mode) { @@ -528,16 +738,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> console_unlock(); } -@@ -2906,6 +2559,8 @@ static int try_enable_new_console(struct - return -ENOENT; - } - -+static void console_try_thread(struct console *con); -+ - /* - * The console driver calls this routine during kernel initialization - * to register the console printing procedure with printk() and to -@@ -2927,7 +2582,6 @@ static int try_enable_new_console(struct +@@ -2888,7 +2644,6 @@ static int try_enable_new_console(struct */ void register_console(struct console *newcon) { @@ -545,7 +746,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> struct console *bcon = NULL; int err; -@@ -2951,6 +2605,8 @@ void register_console(struct console *ne +@@ -2912,6 +2667,8 @@ void register_console(struct console *ne } } @@ -554,12 +755,12 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> if (console_drivers && console_drivers->flags & CON_BOOT) bcon = console_drivers; -@@ -3015,22 +2671,12 @@ void register_console(struct console *ne +@@ -2976,22 +2733,12 @@ void register_console(struct console *ne if (newcon->flags & CON_EXTENDED) nr_ext_console_drivers++; - if (newcon->flags & CON_PRINTBUFFER) { -- syslog_lock_irqsave(flags); +- spin_lock_irqsave(&syslog_lock, flags); - /* - * We're about to replay the log buffer. Only do this to the - * just-registered console to avoid excessive message spam to @@ -572,7 +773,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> - exclusive_console = newcon; - exclusive_console_stop_seq = atomic64_read(&console_seq); - atomic64_set(&console_seq, syslog_seq); -- syslog_unlock_irqrestore(flags); +- spin_unlock_irqrestore(&syslog_lock, flags); - } + if (newcon->flags & CON_PRINTBUFFER) + atomic64_set(&newcon->printk_seq, 0); @@ -583,7 +784,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> console_unlock(); console_sysfs_notify(); -@@ -3104,6 +2750,9 @@ int unregister_console(struct console *c +@@ -3065,6 +2812,9 @@ int unregister_console(struct console *c console_unlock(); console_sysfs_notify(); @@ -593,176 +794,23 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> if (console->exit) res = console->exit(console); -@@ -3147,6 +2796,154 @@ void __init console_init(void) - } - } - -+static int printk_kthread_func(void *data) -+{ -+ struct console *con = data; -+ unsigned long dropped = 0; -+ struct printk_info info; -+ struct printk_record r; -+ char *ext_text = NULL; -+ size_t dropped_len; -+ char *dropped_text; -+ int ret = -ENOMEM; -+ char *write_text; -+ u64 printk_seq; -+ size_t len; -+ char *text; -+ int error; -+ u64 seq; -+ -+ if (con->flags & CON_EXTENDED) { -+ ext_text = kmalloc(CONSOLE_EXT_LOG_MAX, GFP_KERNEL); -+ if (!ext_text) -+ return ret; -+ } -+ text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL); -+ dropped_text = kmalloc(64, GFP_KERNEL); -+ if (!text || !dropped_text) -+ goto out; -+ -+ if (con->flags & CON_EXTENDED) -+ write_text = ext_text; -+ else -+ write_text = text; -+ -+ seq = atomic64_read(&con->printk_seq); -+ -+ prb_rec_init_rd(&r, &info, text, LOG_LINE_MAX + PREFIX_MAX); -+ -+ for (;;) { -+ error = wait_event_interruptible(log_wait, -+ prb_read_valid(prb, seq, &r) || kthread_should_stop()); -+ -+ if (kthread_should_stop()) -+ break; -+ -+ if (error) -+ continue; -+ -+ if (seq != r.info->seq) { -+ dropped += r.info->seq - seq; -+ seq = r.info->seq; -+ } -+ -+ seq++; -+ -+ if (!(con->flags & CON_ENABLED)) -+ continue; -+ -+ if (suppress_message_printing(r.info->level)) -+ continue; -+ -+ if (con->flags & CON_EXTENDED) { -+ len = info_print_ext_header(ext_text, -+ CONSOLE_EXT_LOG_MAX, -+ r.info); -+ len += msg_print_ext_body(ext_text + len, -+ CONSOLE_EXT_LOG_MAX - len, -+ &r.text_buf[0], r.info->text_len, -+ &r.info->dev_info); -+ } else { -+ len = record_print_text(&r, -+ console_msg_format & MSG_FORMAT_SYSLOG, -+ printk_time); -+ } -+ -+ printk_seq = atomic64_read(&con->printk_seq); -+ -+ console_lock(); -+ console_may_schedule = 0; -+ -+ if (kernel_sync_mode() && con->write_atomic) { -+ console_unlock(); -+ break; -+ } -+ -+ if (!(con->flags & CON_EXTENDED) && dropped) { -+ dropped_len = snprintf(dropped_text, 64, -+ "** %lu printk messages dropped **\n", -+ dropped); -+ dropped = 0; -+ -+ con->write(con, dropped_text, dropped_len); -+ printk_delay(r.info->level); -+ } -+ -+ con->write(con, write_text, len); -+ if (len) -+ printk_delay(r.info->level); -+ -+ atomic64_cmpxchg_relaxed(&con->printk_seq, printk_seq, seq); -+ -+ console_unlock(); -+ } -+out: -+ kfree(dropped_text); -+ kfree(text); -+ kfree(ext_text); -+ pr_info("%sconsole [%s%d]: printing thread stopped\n", -+ (con->flags & CON_BOOT) ? "boot" : "" , -+ con->name, con->index); -+ return ret; -+} -+ -+static void start_printk_kthread(struct console *con) -+{ -+ con->thread = kthread_run(printk_kthread_func, con, -+ "pr/%s%d", con->name, con->index); -+ if (IS_ERR(con->thread)) { -+ pr_err("%sconsole [%s%d]: unable to start printing thread\n", -+ (con->flags & CON_BOOT) ? "boot" : "" , -+ con->name, con->index); -+ return; -+ } -+ pr_info("%sconsole [%s%d]: printing thread started\n", -+ (con->flags & CON_BOOT) ? "boot" : "" , -+ con->name, con->index); -+} -+ -+static bool kthreads_started; -+ -+static void console_try_thread(struct console *con) -+{ -+ unsigned long irqflags; -+ int sprint_id; -+ char *buf; -+ -+ if (kthreads_started) { -+ start_printk_kthread(con); -+ return; -+ } -+ -+ buf = get_sprint_buf(&sprint_id, &irqflags); -+ if (!buf) -+ return; -+ -+ print_sync_until(prb_next_seq(prb), con, buf, PREFIX_MAX + LOG_LINE_MAX); -+ -+ put_sprint_buf(sprint_id, irqflags); -+} -+ - /* - * Some boot consoles access data that is in the init section and which will - * be discarded after the initcalls have been run. To make sure that no code -@@ -3186,6 +2983,13 @@ static int __init printk_late_init(void) +@@ -3147,6 +2897,15 @@ static int __init printk_late_init(void) unregister_console(con); } } + ++#ifdef CONFIG_PRINTK + console_lock(); + for_each_console(con) + start_printk_kthread(con); + kthreads_started = true; + console_unlock(); ++#endif + ret = cpuhp_setup_state_nocalls(CPUHP_PRINTK_DEAD, "printk:dead", NULL, console_cpu_notify); WARN_ON(ret < 0); -@@ -3201,7 +3005,6 @@ late_initcall(printk_late_init); +@@ -3162,7 +2921,6 @@ late_initcall(printk_late_init); * Delayed printk version, for scheduler-internal messages: */ #define PRINTK_PENDING_WAKEUP 0x01 @@ -770,7 +818,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> static DEFINE_PER_CPU(int, printk_pending); -@@ -3209,12 +3012,6 @@ static void wake_up_klogd_work_func(stru +@@ -3170,12 +2928,6 @@ static void wake_up_klogd_work_func(stru { int pending = __this_cpu_xchg(printk_pending, 0); @@ -783,7 +831,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> if (pending & PRINTK_PENDING_WAKEUP) wake_up_interruptible(&log_wait); } -@@ -3239,13 +3036,6 @@ void wake_up_klogd(void) +@@ -3200,13 +2952,6 @@ void wake_up_klogd(void) void defer_console_output(void) { diff --git a/patches/0013-printk-remove-deferred-printing.patch b/patches/0013-printk-remove-deferred-printing.patch index d0e55876f372..ca30c73593dd 100644 --- a/patches/0013-printk-remove-deferred-printing.patch +++ b/patches/0013-printk-remove-deferred-printing.patch @@ -1,6 +1,6 @@ From: John Ogness <john.ogness@linutronix.de> -Date: Mon, 19 Oct 2020 22:53:30 +0206 -Subject: [PATCH 13/15] printk: remove deferred printing +Date: Mon, 30 Nov 2020 01:42:08 +0106 +Subject: [PATCH 13/16] printk: remove deferred printing Since printing occurs either atomically or from the printing kthread, there is no need for any deferring or tracking possible @@ -15,10 +15,10 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> include/linux/printk.h | 12 ------ kernel/printk/Makefile | 1 kernel/printk/internal.h | 70 ----------------------------------- - kernel/printk/printk.c | 40 ++++++-------------- + kernel/printk/printk.c | 57 +++++++++++------------------ kernel/printk/printk_safe.c | 86 -------------------------------------------- kernel/trace/trace.c | 2 - - 9 files changed, 12 insertions(+), 206 deletions(-) + 9 files changed, 22 insertions(+), 213 deletions(-) delete mode 100644 kernel/printk/internal.h delete mode 100644 kernel/printk/printk_safe.c @@ -66,7 +66,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> } while (0) --- a/include/linux/printk.h +++ b/include/linux/printk.h -@@ -149,18 +149,6 @@ static inline __printf(1, 2) __cold +@@ -150,18 +150,6 @@ static inline __printf(1, 2) __cold void early_printk(const char *s, ...) { } #endif @@ -168,7 +168,15 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> -#endif /* CONFIG_PRINTK */ --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c -@@ -60,7 +60,6 @@ +@@ -45,6 +45,7 @@ + #include <linux/ctype.h> + #include <linux/uio.h> + #include <linux/kthread.h> ++#include <linux/kdb.h> + #include <linux/clocksource.h> + #include <linux/sched/clock.h> + #include <linux/sched/debug.h> +@@ -60,7 +61,6 @@ #include "printk_ringbuffer.h" #include "console_cmdline.h" #include "braille.h" @@ -176,7 +184,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> int console_printk[4] = { CONSOLE_LOGLEVEL_DEFAULT, /* console_loglevel */ -@@ -230,19 +229,7 @@ static int nr_ext_console_drivers; +@@ -227,19 +227,7 @@ static int nr_ext_console_drivers; static int __down_trylock_console_sem(unsigned long ip) { @@ -197,7 +205,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> return 1; mutex_acquire(&console_lock_dep_map, 0, 1, ip); return 0; -@@ -251,13 +238,9 @@ static int __down_trylock_console_sem(un +@@ -248,13 +236,9 @@ static int __down_trylock_console_sem(un static void __up_console_sem(unsigned long ip) { @@ -211,11 +219,42 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> } #define up_console_sem() __up_console_sem(_RET_IP_) -@@ -2027,6 +2010,16 @@ int vprintk_default(const char *fmt, va_ +@@ -411,7 +395,7 @@ static struct printk_ringbuffer *prb = & + */ + static bool __printk_percpu_data_ready __read_mostly; + +-bool printk_percpu_data_ready(void) ++static bool printk_percpu_data_ready(void) + { + return __printk_percpu_data_ready; + } +@@ -1836,9 +1820,9 @@ static u16 printk_sprint(char *text, u16 } - EXPORT_SYMBOL_GPL(vprintk_default); -+__printf(1, 0) int vprintk_func(const char *fmt, va_list args) + __printf(4, 0) +-int vprintk_store(int facility, int level, +- const struct dev_printk_info *dev_info, +- const char *fmt, va_list args) ++static int vprintk_store(int facility, int level, ++ const struct dev_printk_info *dev_info, ++ const char *fmt, va_list args) + { + const u32 caller_id = printk_caller_id(); + struct prb_reserved_entry e; +@@ -1980,11 +1964,22 @@ asmlinkage int vprintk_emit(int facility + } + EXPORT_SYMBOL(vprintk_emit); + +-int vprintk_default(const char *fmt, va_list args) ++__printf(1, 0) ++static int vprintk_default(const char *fmt, va_list args) + { + return vprintk_emit(0, LOGLEVEL_DEFAULT, NULL, fmt, args); + } +-EXPORT_SYMBOL_GPL(vprintk_default); ++ ++__printf(1, 0) ++static int vprintk_func(const char *fmt, va_list args) +{ +#ifdef CONFIG_KGDB_KDB + /* Allow to pass printk() to kdb but avoid a recursion. */ @@ -224,20 +263,21 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +#endif + return vprintk_default(fmt, args); +} -+ + asmlinkage int vprintk(const char *fmt, va_list args) { - return vprintk_func(fmt, args); -@@ -3034,18 +3027,9 @@ void wake_up_klogd(void) +@@ -2950,18 +2945,10 @@ void wake_up_klogd(void) preempt_enable(); } -void defer_console_output(void) --{ ++__printf(1, 0) ++static int vprintk_deferred(const char *fmt, va_list args) + { -} - - int vprintk_deferred(const char *fmt, va_list args) - { +-int vprintk_deferred(const char *fmt, va_list args) +-{ - int r; - - r = vprintk_emit(0, LOGLEVEL_SCHED, NULL, fmt, args); diff --git a/patches/0014-printk-add-console-handover.patch b/patches/0014-printk-add-console-handover.patch index be2dfc39c3e2..20fc3125a4ce 100644 --- a/patches/0014-printk-add-console-handover.patch +++ b/patches/0014-printk-add-console-handover.patch @@ -1,6 +1,6 @@ From: John Ogness <john.ogness@linutronix.de> -Date: Mon, 19 Oct 2020 23:03:44 +0206 -Subject: [PATCH 14/15] printk: add console handover +Date: Mon, 30 Nov 2020 01:42:09 +0106 +Subject: [PATCH 14/16] printk: add console handover If earlyprintk is used, a boot console will print directly to the console immediately. The boot console will unregister itself as soon @@ -25,7 +25,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> --- a/include/linux/console.h +++ b/include/linux/console.h -@@ -137,6 +137,7 @@ static inline int con_debug_leave(void) +@@ -138,6 +138,7 @@ static inline int con_debug_leave(void) #define CON_ANYTIME (16) /* Safe to call when cpu is offline */ #define CON_BRL (32) /* Used for a braille device */ #define CON_EXTENDED (64) /* Use the extended output format a la /dev/kmsg */ @@ -35,7 +35,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> char name[16]; --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c -@@ -1755,6 +1755,8 @@ static bool console_can_sync(struct cons +@@ -1629,6 +1629,8 @@ static bool console_can_sync(struct cons return false; if (con->write_atomic && kernel_sync_mode()) return true; @@ -44,7 +44,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> if (con->write && (con->flags & CON_BOOT) && !con->thread) return true; return false; -@@ -1766,6 +1768,8 @@ static bool call_sync_console_driver(str +@@ -1640,6 +1642,8 @@ static bool call_sync_console_driver(str return false; if (con->write_atomic && kernel_sync_mode()) con->write_atomic(con, text, text_len); @@ -53,7 +53,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> else if (con->write && (con->flags & CON_BOOT) && !con->thread) con->write(con, text, text_len); else -@@ -2641,8 +2645,10 @@ void register_console(struct console *ne +@@ -2705,8 +2709,10 @@ void register_console(struct console *ne * the real console are the same physical device, it's annoying to * see the beginning boot messages twice */ diff --git a/patches/0015-printk-add-pr_flush.patch b/patches/0015-printk-add-pr_flush.patch new file mode 100644 index 000000000000..26a704450f72 --- /dev/null +++ b/patches/0015-printk-add-pr_flush.patch @@ -0,0 +1,103 @@ +From: John Ogness <john.ogness@linutronix.de> +Date: Mon, 30 Nov 2020 01:42:10 +0106 +Subject: [PATCH 15/16] printk: add pr_flush() + +Provide a function to allow waiting for console printers to catch +up to the latest logged message. + +Signed-off-by: John Ogness <john.ogness@linutronix.de> +Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +--- + include/linux/printk.h | 2 + + kernel/printk/printk.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 74 insertions(+) + +--- a/include/linux/printk.h ++++ b/include/linux/printk.h +@@ -476,6 +476,8 @@ extern int kptr_restrict; + no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) + #endif + ++bool pr_flush(bool may_sleep, int timeout_ms, bool reset_on_progress); ++ + /* + * ratelimited messages with local ratelimit_state, + * no local ratelimit_state used in the !PRINTK case +--- a/kernel/printk/printk.c ++++ b/kernel/printk/printk.c +@@ -3436,3 +3436,75 @@ void console_atomic_unlock(unsigned int + prb_unlock(&printk_cpulock, flags); + } + EXPORT_SYMBOL(console_atomic_unlock); ++ ++static void pr_msleep(bool may_sleep, int ms) ++{ ++ if (may_sleep) { ++ msleep(ms); ++ } else { ++ while (ms--) ++ udelay(1000); ++ } ++} ++ ++/** ++ * pr_flush() - Wait for printing threads to catch up. ++ * ++ * @may_sleep: Context allows msleep() calls. ++ * @timeout_ms: The maximum time (in ms) to wait. ++ * @reset_on_progress: Reset the timeout if forward progress is seen. ++ * ++ * A value of 0 for @timeout_ms means no waiting will occur. A value of -1 ++ * represents infinite waiting. ++ * ++ * If @reset_on_progress is true, the timeout will be reset whenever any ++ * printer has been seen to make some forward progress. ++ * ++ * Context: Any context if @timeout_ms is 0 or @may_sleep is false. Otherwise ++ * process context. ++ * Return: true if all enabled printers are caught up. ++ */ ++bool pr_flush(bool may_sleep, int timeout_ms, bool reset_on_progress) ++{ ++ int remaining = timeout_ms; ++ struct console *con; ++ u64 last_diff = 0; ++ u64 printk_seq; ++ u64 diff; ++ u64 seq; ++ ++ seq = prb_next_seq(prb); ++ ++ for (;;) { ++ diff = 0; ++ ++ for_each_console(con) { ++ if (!(con->flags & CON_ENABLED)) ++ continue; ++ printk_seq = atomic64_read(&con->printk_seq); ++ if (printk_seq < seq) ++ diff += seq - printk_seq; ++ } ++ ++ if (diff != last_diff && reset_on_progress) ++ remaining = timeout_ms; ++ ++ if (!diff || remaining == 0) ++ break; ++ ++ if (remaining < 0) { ++ pr_msleep(may_sleep, 100); ++ } else if (remaining < 100) { ++ pr_msleep(may_sleep, remaining); ++ remaining = 0; ++ } else { ++ pr_msleep(may_sleep, 100); ++ remaining -= 100; ++ } ++ ++ last_diff = diff; ++ } ++ ++ return (diff == 0); ++} ++EXPORT_SYMBOL(pr_flush); diff --git a/patches/0016-printk-kmsg_dump-do_mounts-wait-for-printers.patch b/patches/0016-printk-kmsg_dump-do_mounts-wait-for-printers.patch new file mode 100644 index 000000000000..1479af403f58 --- /dev/null +++ b/patches/0016-printk-kmsg_dump-do_mounts-wait-for-printers.patch @@ -0,0 +1,43 @@ +From: John Ogness <john.ogness@linutronix.de> +Date: Mon, 30 Nov 2020 01:42:11 +0106 +Subject: [PATCH 16/16] printk: kmsg_dump,do_mounts wait for printers + +Use pr_flush() to give console printers a chance to finish if no +atomic console is available. This should probably be implemented +inside panic(), giving panic() an additional @may_sleep argument. +But that would require evaluating every panic() caller. For now +just call pr_flush() for kmsg_dump and when failing to mount the +root filesystem, since these are both common error paths. + +Signed-off-by: John Ogness <john.ogness@linutronix.de> +Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +--- + init/do_mounts.c | 1 + + kernel/printk/printk.c | 6 ++++++ + 2 files changed, 7 insertions(+) + +--- a/init/do_mounts.c ++++ b/init/do_mounts.c +@@ -457,6 +457,7 @@ void __init mount_block_root(char *name, + printk("DEBUG_BLOCK_EXT_DEVT is enabled, you need to specify " + "explicit textual name for \"root=\" boot option.\n"); + #endif ++ pr_flush(true, 1000, true); + panic("VFS: Unable to mount root fs on %s", b); + } + if (!(flags & SB_RDONLY)) { +--- a/kernel/printk/printk.c ++++ b/kernel/printk/printk.c +@@ -3105,6 +3105,12 @@ void kmsg_dump(enum kmsg_dump_reason rea + sync_mode = true; + pr_info("enabled sync mode\n"); + } ++ ++ /* ++ * Give the printing threads time to flush, allowing up to 1 ++ * second of no printing forward progress before giving up. ++ */ ++ pr_flush(false, 100, true); + } + + rcu_read_lock(); diff --git a/patches/localversion.patch b/patches/localversion.patch index 12bd473a33f5..25e5fadbaae8 100644 --- a/patches/localversion.patch +++ b/patches/localversion.patch @@ -10,4 +10,4 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de> --- /dev/null +++ b/localversion-rt @@ -0,0 +1 @@ -+-rt12 ++-rt13 diff --git a/patches/mm-zswap-Use-local-lock-to-protect-per-CPU-data.patch b/patches/mm-zswap-Use-local-lock-to-protect-per-CPU-data.patch index 7d7180d74b41..0b624ecb1c9d 100644 --- a/patches/mm-zswap-Use-local-lock-to-protect-per-CPU-data.patch +++ b/patches/mm-zswap-Use-local-lock-to-protect-per-CPU-data.patch @@ -23,8 +23,8 @@ Cc: linux-mm@kvack.org Signed-off-by: Luis Claudio R. Goncalves <lgoncalv@redhat.com> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> --- - mm/zswap.c | 41 ++++++++++++++++++++++++++--------------- - 1 file changed, 26 insertions(+), 15 deletions(-) + mm/zswap.c | 43 ++++++++++++++++++++++++++++--------------- + 1 file changed, 28 insertions(+), 15 deletions(-) --- a/mm/zswap.c +++ b/mm/zswap.c @@ -36,7 +36,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> #include <linux/types.h> #include <linux/atomic.h> #include <linux/frontswap.h> -@@ -387,27 +388,35 @@ static struct zswap_entry *zswap_entry_f +@@ -387,27 +388,37 @@ static struct zswap_entry *zswap_entry_f /********************************* * per-cpu code **********************************/ @@ -47,7 +47,9 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> + u8 *dstmem; +}; + -+static DEFINE_PER_CPU(struct zswap_comp, zswap_comp); ++static DEFINE_PER_CPU(struct zswap_comp, zswap_comp) = { ++ .lock = INIT_LOCAL_LOCK(lock), ++}; static int zswap_dstmem_prepare(unsigned int cpu) { @@ -78,7 +80,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> return 0; } -@@ -919,10 +928,11 @@ static int zswap_writeback_entry(struct +@@ -919,10 +930,11 @@ static int zswap_writeback_entry(struct dlen = PAGE_SIZE; src = (u8 *)zhdr + sizeof(struct zswap_header); dst = kmap_atomic(page); @@ -92,7 +94,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> kunmap_atomic(dst); BUG_ON(ret); BUG_ON(dlen != PAGE_SIZE); -@@ -1074,12 +1084,12 @@ static int zswap_frontswap_store(unsigne +@@ -1074,12 +1086,12 @@ static int zswap_frontswap_store(unsigne } /* compress */ @@ -108,7 +110,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> if (ret) { ret = -EINVAL; goto put_dstmem; -@@ -1103,7 +1113,7 @@ static int zswap_frontswap_store(unsigne +@@ -1103,7 +1115,7 @@ static int zswap_frontswap_store(unsigne memcpy(buf, &zhdr, hlen); memcpy(buf + hlen, dst, dlen); zpool_unmap_handle(entry->pool->zpool, handle); @@ -117,7 +119,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> /* populate entry */ entry->offset = offset; -@@ -1131,7 +1141,7 @@ static int zswap_frontswap_store(unsigne +@@ -1131,7 +1143,7 @@ static int zswap_frontswap_store(unsigne return 0; put_dstmem: @@ -126,7 +128,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> zswap_pool_put(entry->pool); freepage: zswap_entry_cache_free(entry); -@@ -1176,9 +1186,10 @@ static int zswap_frontswap_load(unsigned +@@ -1176,9 +1188,10 @@ static int zswap_frontswap_load(unsigned if (zpool_evictable(entry->pool->zpool)) src += sizeof(struct zswap_header); dst = kmap_atomic(page); diff --git a/patches/notifier-Make-atomic_notifiers-use-raw_spinlock.patch b/patches/notifier-Make-atomic_notifiers-use-raw_spinlock.patch new file mode 100644 index 000000000000..3ef97ac3f0d1 --- /dev/null +++ b/patches/notifier-Make-atomic_notifiers-use-raw_spinlock.patch @@ -0,0 +1,123 @@ +From: Valentin Schneider <valentin.schneider@arm.com> +Date: Sun, 22 Nov 2020 20:19:04 +0000 +Subject: [PATCH] notifier: Make atomic_notifiers use raw_spinlock + +Booting a recent PREEMPT_RT kernel (v5.10-rc3-rt7-rebase) on my arm64 Juno +leads to the idle task blocking on an RT sleeping spinlock down some +notifier path: + + [ 1.809101] BUG: scheduling while atomic: swapper/5/0/0x00000002 + [ 1.809116] Modules linked in: + [ 1.809123] Preemption disabled at: + [ 1.809125] secondary_start_kernel (arch/arm64/kernel/smp.c:227) + [ 1.809146] CPU: 5 PID: 0 Comm: swapper/5 Tainted: G W 5.10.0-rc3-rt7 #168 + [ 1.809153] Hardware name: ARM Juno development board (r0) (DT) + [ 1.809158] Call trace: + [ 1.809160] dump_backtrace (arch/arm64/kernel/stacktrace.c:100 (discriminator 1)) + [ 1.809170] show_stack (arch/arm64/kernel/stacktrace.c:198) + [ 1.809178] dump_stack (lib/dump_stack.c:122) + [ 1.809188] __schedule_bug (kernel/sched/core.c:4886) + [ 1.809197] __schedule (./arch/arm64/include/asm/preempt.h:18 kernel/sched/core.c:4913 kernel/sched/core.c:5040) + [ 1.809204] preempt_schedule_lock (kernel/sched/core.c:5365 (discriminator 1)) + [ 1.809210] rt_spin_lock_slowlock_locked (kernel/locking/rtmutex.c:1072) + [ 1.809217] rt_spin_lock_slowlock (kernel/locking/rtmutex.c:1110) + [ 1.809224] rt_spin_lock (./include/linux/rcupdate.h:647 kernel/locking/rtmutex.c:1139) + [ 1.809231] atomic_notifier_call_chain_robust (kernel/notifier.c:71 kernel/notifier.c:118 kernel/notifier.c:186) + [ 1.809240] cpu_pm_enter (kernel/cpu_pm.c:39 kernel/cpu_pm.c:93) + [ 1.809249] psci_enter_idle_state (drivers/cpuidle/cpuidle-psci.c:52 drivers/cpuidle/cpuidle-psci.c:129) + [ 1.809258] cpuidle_enter_state (drivers/cpuidle/cpuidle.c:238) + [ 1.809267] cpuidle_enter (drivers/cpuidle/cpuidle.c:353) + [ 1.809275] do_idle (kernel/sched/idle.c:132 kernel/sched/idle.c:213 kernel/sched/idle.c:273) + [ 1.809282] cpu_startup_entry (kernel/sched/idle.c:368 (discriminator 1)) + [ 1.809288] secondary_start_kernel (arch/arm64/kernel/smp.c:273) + +Two points worth noting: + +1) That this is conceptually the same issue as pointed out in: + 313c8c16ee62 ("PM / CPU: replace raw_notifier with atomic_notifier") +2) Only the _robust() variant of atomic_notifier callchains suffer from + this + +AFAICT only the cpu_pm_notifier_chain really needs to be changed, but +singling it out would mean introducing a new (truly) non-blocking API. At +the same time, callers that are fine with any blocking within the call +chain should use blocking notifiers, so patching up all atomic_notifier's +doesn't seem *too* crazy to me. + +Fixes: 70d932985757 ("notifier: Fix broken error handling pattern") +Signed-off-by: Valentin Schneider <valentin.schneider@arm.com> +Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com> +Link: https://lkml.kernel.org/r/20201122201904.30940-1-valentin.schneider@arm.com +Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +--- + include/linux/notifier.h | 6 +++--- + kernel/notifier.c | 12 ++++++------ + 2 files changed, 9 insertions(+), 9 deletions(-) + +--- a/include/linux/notifier.h ++++ b/include/linux/notifier.h +@@ -58,7 +58,7 @@ struct notifier_block { + }; + + struct atomic_notifier_head { +- spinlock_t lock; ++ raw_spinlock_t lock; + struct notifier_block __rcu *head; + }; + +@@ -78,7 +78,7 @@ struct srcu_notifier_head { + }; + + #define ATOMIC_INIT_NOTIFIER_HEAD(name) do { \ +- spin_lock_init(&(name)->lock); \ ++ raw_spin_lock_init(&(name)->lock); \ + (name)->head = NULL; \ + } while (0) + #define BLOCKING_INIT_NOTIFIER_HEAD(name) do { \ +@@ -95,7 +95,7 @@ extern void srcu_init_notifier_head(stru + cleanup_srcu_struct(&(name)->srcu); + + #define ATOMIC_NOTIFIER_INIT(name) { \ +- .lock = __SPIN_LOCK_UNLOCKED(name.lock), \ ++ .lock = __RAW_SPIN_LOCK_UNLOCKED(name.lock), \ + .head = NULL } + #define BLOCKING_NOTIFIER_INIT(name) { \ + .rwsem = __RWSEM_INITIALIZER((name).rwsem), \ +--- a/kernel/notifier.c ++++ b/kernel/notifier.c +@@ -142,9 +142,9 @@ int atomic_notifier_chain_register(struc + unsigned long flags; + int ret; + +- spin_lock_irqsave(&nh->lock, flags); ++ raw_spin_lock_irqsave(&nh->lock, flags); + ret = notifier_chain_register(&nh->head, n); +- spin_unlock_irqrestore(&nh->lock, flags); ++ raw_spin_unlock_irqrestore(&nh->lock, flags); + return ret; + } + EXPORT_SYMBOL_GPL(atomic_notifier_chain_register); +@@ -164,9 +164,9 @@ int atomic_notifier_chain_unregister(str + unsigned long flags; + int ret; + +- spin_lock_irqsave(&nh->lock, flags); ++ raw_spin_lock_irqsave(&nh->lock, flags); + ret = notifier_chain_unregister(&nh->head, n); +- spin_unlock_irqrestore(&nh->lock, flags); ++ raw_spin_unlock_irqrestore(&nh->lock, flags); + synchronize_rcu(); + return ret; + } +@@ -182,9 +182,9 @@ int atomic_notifier_call_chain_robust(st + * Musn't use RCU; because then the notifier list can + * change between the up and down traversal. + */ +- spin_lock_irqsave(&nh->lock, flags); ++ raw_spin_lock_irqsave(&nh->lock, flags); + ret = notifier_call_chain_robust(&nh->head, val_up, val_down, v); +- spin_unlock_irqrestore(&nh->lock, flags); ++ raw_spin_unlock_irqrestore(&nh->lock, flags); + + return ret; + } diff --git a/patches/printk-Tiny-cleanup.patch b/patches/printk-Tiny-cleanup.patch deleted file mode 100644 index 7408f2a7f869..000000000000 --- a/patches/printk-Tiny-cleanup.patch +++ /dev/null @@ -1,145 +0,0 @@ -From: Sebastian Andrzej Siewior <bigeasy@linutronix.de> -Date: Tue, 20 Oct 2020 18:48:16 +0200 -Subject: [PATCH] printk: Tiny cleanup - -- mark functions and variables static which are used only in this file. -- add printf annotation where appropriate -- remove static functions without caller -- add kdb header file for kgdb builds. - -Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> ---- - kernel/printk/printk.c | 62 +++++++++++++++---------------------------------- - 1 file changed, 19 insertions(+), 43 deletions(-) - ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -49,6 +49,7 @@ - #include <linux/sched/clock.h> - #include <linux/sched/debug.h> - #include <linux/sched/task_stack.h> -+#include <linux/kdb.h> - - #include <linux/uaccess.h> - #include <asm/sections.h> -@@ -339,11 +340,11 @@ enum log_flags { - }; - - /* The syslog_lock protects syslog_* variables. */ --DEFINE_RAW_SPINLOCK(syslog_lock); --#define syslog_lock_irq() raw_spin_lock_irq(&syslog_lock) --#define syslog_unlock_irq() raw_spin_unlock_irq(&syslog_lock) --#define syslog_lock_irqsave(flags) raw_spin_lock_irqsave(&syslog_lock, flags) --#define syslog_unlock_irqrestore(flags) raw_spin_unlock_irqrestore(&syslog_lock, flags) -+static DEFINE_SPINLOCK(syslog_lock); -+#define syslog_lock_irq() spin_lock_irq(&syslog_lock) -+#define syslog_unlock_irq() spin_unlock_irq(&syslog_lock) -+#define syslog_lock_irqsave(flags) spin_lock_irqsave(&syslog_lock, flags) -+#define syslog_unlock_irqrestore(flags) spin_unlock_irqrestore(&syslog_lock, flags) - - #ifdef CONFIG_PRINTK - DECLARE_WAIT_QUEUE_HEAD(log_wait); -@@ -398,7 +399,7 @@ static struct printk_ringbuffer *prb = & - */ - static bool __printk_percpu_data_ready __read_mostly; - --bool printk_percpu_data_ready(void) -+static bool printk_percpu_data_ready(void) - { - return __printk_percpu_data_ready; - } -@@ -1862,9 +1863,10 @@ static inline u32 printk_caller_id(void) - 0x80000000 + raw_smp_processor_id(); - } - --int vprintk_store(int facility, int level, -- const struct dev_printk_info *dev_info, -- const char *fmt, va_list args) -+__printf(4, 0) -+static int vprintk_store(int facility, int level, -+ const struct dev_printk_info *dev_info, -+ const char *fmt, va_list args) - { - const u32 caller_id = printk_caller_id(); - struct prb_reserved_entry e; -@@ -2008,13 +2010,14 @@ asmlinkage int vprintk_emit(int facility - } - EXPORT_SYMBOL(vprintk_emit); - --int vprintk_default(const char *fmt, va_list args) -+ __printf(1, 0) -+static int vprintk_default(const char *fmt, va_list args) - { - return vprintk_emit(0, LOGLEVEL_DEFAULT, NULL, fmt, args); - } --EXPORT_SYMBOL_GPL(vprintk_default); - --__printf(1, 0) int vprintk_func(const char *fmt, va_list args) -+__printf(1, 0) -+static int vprintk_func(const char *fmt, va_list args) - { - #ifdef CONFIG_KGDB_KDB - /* Allow to pass printk() to kdb but avoid a recursion. */ -@@ -2328,34 +2331,6 @@ int is_console_locked(void) - } - EXPORT_SYMBOL(is_console_locked); - --/* -- * Check if we have any console that is capable of printing while cpu is -- * booting or shutting down. Requires console_sem. -- */ --static int have_callable_console(void) --{ -- struct console *con; -- -- for_each_console(con) -- if ((con->flags & CON_ENABLED) && -- (con->flags & CON_ANYTIME)) -- return 1; -- -- return 0; --} -- --/* -- * Can we actually use the console at this time on this cpu? -- * -- * Console drivers may assume that per-cpu resources have been allocated. So -- * unless they're explicitly marked as being able to cope (CON_ANYTIME) don't -- * call them until this CPU is officially up. -- */ --static inline int can_use_console(void) --{ -- return cpu_online(raw_smp_processor_id()) || have_callable_console(); --} -- - /** - * console_unlock - unlock the console system - * -@@ -3033,7 +3008,8 @@ void wake_up_klogd(void) - preempt_enable(); - } - --int vprintk_deferred(const char *fmt, va_list args) -+__printf(1, 0) -+static int vprintk_deferred(const char *fmt, va_list args) - { - return vprintk_emit(0, LOGLEVEL_DEFAULT, NULL, fmt, args); - } -@@ -3470,7 +3446,7 @@ static bool __prb_trylock(struct prb_cpu - * - * It is safe to call this function from any context and state. - */ --void prb_lock(struct prb_cpulock *cpu_lock, unsigned int *cpu_store) -+static void prb_lock(struct prb_cpulock *cpu_lock, unsigned int *cpu_store) - { - for (;;) { - if (__prb_trylock(cpu_lock, cpu_store)) -@@ -3488,7 +3464,7 @@ void prb_lock(struct prb_cpulock *cpu_lo - * - * It is safe to call this function from any context and state. - */ --void prb_unlock(struct prb_cpulock *cpu_lock, unsigned int cpu_store) -+static void prb_unlock(struct prb_cpulock *cpu_lock, unsigned int cpu_store) - { - unsigned long *flags; - unsigned int cpu; diff --git a/patches/series b/patches/series index e65af8c36ba9..b2b8ba0b94bb 100644 --- a/patches/series +++ b/patches/series @@ -106,26 +106,30 @@ timers-Don-t-block-on-expiry_lock-for-TIMER_IRQSAFE.patch 0001-kthread-Move-prio-affinite-change-into-the-newly-cre.patch 0002-genirq-Move-prio-assignment-into-the-newly-created-t.patch +# 20201122201904.30940-1-valentin.schneider@arm.com +notifier-Make-atomic_notifiers-use-raw_spinlock.patch + ############################################################ # Ready for posting ############################################################ # John's printk series. 0001-printk-refactor-kmsg_dump_get_buffer.patch -0002-printk-use-buffer-pools-for-sprint-buffers.patch +0002-printk-inline-log_output-log_store-in-vprintk_store.patch 0003-printk-change-clear_seq-to-atomic64_t.patch 0004-printk-remove-logbuf_lock-add-syslog_lock.patch 0005-printk-remove-safe-buffers.patch 0006-console-add-write_atomic-interface.patch 0007-serial-8250-implement-write_atomic.patch -0008-printk-inline-log_output-log_store-in-vprintk_store.patch -0009-printk-relocate-printk_delay-and-vprintk_default.patch -0010-printk-combine-boot_delay_msec-into-printk_delay.patch +0008-printk-relocate-printk_delay-and-vprintk_default.patch +0009-printk-combine-boot_delay_msec-into-printk_delay.patch +0010-printk-change-console_seq-to-atomic64_t.patch 0011-printk-introduce-kernel-sync-mode.patch 0012-printk-move-console-printing-to-kthreads.patch 0013-printk-remove-deferred-printing.patch 0014-printk-add-console-handover.patch -printk-Tiny-cleanup.patch +0015-printk-add-pr_flush.patch +0016-printk-kmsg_dump-do_mounts-wait-for-printers.patch ############################################################ # Needs to address review feedback diff --git a/patches/x86-kvm-require-const-tsc-for-rt.patch b/patches/x86-kvm-require-const-tsc-for-rt.patch index 0f7b158d2a09..c7cd925d4339 100644 --- a/patches/x86-kvm-require-const-tsc-for-rt.patch +++ b/patches/x86-kvm-require-const-tsc-for-rt.patch @@ -14,7 +14,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de> --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c -@@ -7870,6 +7870,14 @@ int kvm_arch_init(void *opaque) +@@ -7872,6 +7872,14 @@ int kvm_arch_init(void *opaque) goto out; } |