1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <linux/cpuhplock.h> 4 #include <linux/cpumask.h> 5 #include <linux/init.h> 6 #include <linux/kthread.h> 7 #include <linux/module.h> 8 #include <linux/moduleparam.h> 9 #include <linux/random.h> 10 #include <linux/slab.h> 11 #include <linux/timer.h> 12 #include <linux/wait.h> 13 14 #include <kunit/resource.h> 15 #include <kunit/test.h> 16 17 #include "printk_ringbuffer.h" 18 19 /* 20 * This KUnit tests the data integrity of the lockless printk_ringbuffer. 21 * From multiple CPUs it writes messages of varying length and content while 22 * a reader validates the correctness of the messages. 23 * 24 * IMPORTANT: The more CPUs you can use for this KUnit, the better! 25 * 26 * The test works by starting "num_online_cpus() - 1" writer threads, each 27 * pinned to their own CPU. Each writer thread loops, writing data of varying 28 * length into a printk_ringbuffer as fast as possible. The data content is 29 * an embedded data struct followed by string content repeating the byte: 30 * 31 * 'A' + CPUID 32 * 33 * The reader is running on the remaining online CPU, or if there is only one 34 * CPU on the same as the writer. 35 * It ensures that the embedded struct content is consistent with the string 36 * and that the string * is terminated and is composed of the same repeating 37 * byte as its first byte. 38 * 39 * Because the threads are running in such tight loops, they will call 40 * cond_resched() from time to time so the system stays functional. 41 * 42 * If the reader encounters an error, the test is aborted and some 43 * information about the error is reported. 44 * The runtime of the test can be configured with the runtime_ms module parameter. 45 * 46 * Note that the test is performed on a separate printk_ringbuffer instance 47 * and not the instance used by printk(). 48 */ 49 50 static unsigned long runtime_ms = 10 * MSEC_PER_SEC; 51 module_param(runtime_ms, ulong, 0400); 52 53 /* test data structure */ 54 struct prbtest_rbdata { 55 unsigned int size; 56 char text[] __counted_by(size); 57 }; 58 59 #define MAX_RBDATA_TEXT_SIZE 0x80 60 #define MAX_PRB_RECORD_SIZE (sizeof(struct prbtest_rbdata) + MAX_RBDATA_TEXT_SIZE) 61 62 struct prbtest_data { 63 struct kunit *test; 64 struct printk_ringbuffer *ringbuffer; 65 /* used by writers to signal reader of new records */ 66 wait_queue_head_t new_record_wait; 67 }; 68 69 struct prbtest_thread_data { 70 unsigned long num; 71 struct prbtest_data *test_data; 72 }; 73 74 static void prbtest_fail_record(struct kunit *test, const struct prbtest_rbdata *dat, u64 seq) 75 { 76 unsigned int len; 77 78 len = dat->size - 1; 79 80 KUNIT_FAIL(test, "BAD RECORD: seq=%llu size=%u text=%.*s\n", 81 seq, dat->size, 82 len < MAX_RBDATA_TEXT_SIZE ? len : -1, 83 len < MAX_RBDATA_TEXT_SIZE ? dat->text : "<invalid>"); 84 } 85 86 static bool prbtest_check_data(const struct prbtest_rbdata *dat) 87 { 88 unsigned int len; 89 90 /* Sane size? At least one character + trailing '\0' */ 91 if (dat->size < 2 || dat->size > MAX_RBDATA_TEXT_SIZE) 92 return false; 93 94 len = dat->size - 1; 95 if (dat->text[len] != '\0') 96 return false; 97 98 /* String repeats with the same character? */ 99 while (len--) { 100 if (dat->text[len] != dat->text[0]) 101 return false; 102 } 103 104 return true; 105 } 106 107 static int prbtest_writer(void *data) 108 { 109 struct prbtest_thread_data *tr = data; 110 char text_id = 'A' + tr->num; 111 struct prb_reserved_entry e; 112 struct prbtest_rbdata *dat; 113 u32 record_size, text_size; 114 unsigned long count = 0; 115 struct printk_record r; 116 117 kunit_info(tr->test_data->test, "start thread %03lu (writer)\n", tr->num); 118 119 for (;;) { 120 /* ensure at least 1 character + trailing '\0' */ 121 text_size = get_random_u32_inclusive(2, MAX_RBDATA_TEXT_SIZE); 122 if (WARN_ON_ONCE(text_size < 2)) 123 text_size = 2; 124 if (WARN_ON_ONCE(text_size > MAX_RBDATA_TEXT_SIZE)) 125 text_size = MAX_RBDATA_TEXT_SIZE; 126 127 record_size = sizeof(struct prbtest_rbdata) + text_size; 128 WARN_ON_ONCE(record_size > MAX_PRB_RECORD_SIZE); 129 130 /* specify the text sizes for reservation */ 131 prb_rec_init_wr(&r, record_size); 132 133 /* 134 * Reservation can fail if: 135 * 136 * - No free descriptor is available. 137 * - The buffer is full, and the oldest record is reserved 138 * but not yet committed. 139 * 140 * It actually happens in this test because all CPUs are trying 141 * to write an unbounded number of messages in a tight loop. 142 * These failures are intentionally ignored because this test 143 * focuses on races, ringbuffer consistency, and pushing system 144 * usability limits. 145 */ 146 if (prb_reserve(&e, tr->test_data->ringbuffer, &r)) { 147 r.info->text_len = record_size; 148 149 dat = (struct prbtest_rbdata *)r.text_buf; 150 dat->size = text_size; 151 memset(dat->text, text_id, text_size - 1); 152 dat->text[text_size - 1] = '\0'; 153 154 prb_commit(&e); 155 156 wake_up_interruptible(&tr->test_data->new_record_wait); 157 } 158 159 if ((count++ & 0x3fff) == 0) 160 cond_resched(); 161 162 if (kthread_should_stop()) 163 break; 164 } 165 166 kunit_info(tr->test_data->test, "end thread %03lu: wrote=%lu\n", tr->num, count); 167 168 return 0; 169 } 170 171 struct prbtest_wakeup_timer { 172 struct timer_list timer; 173 struct task_struct *task; 174 }; 175 176 static void prbtest_wakeup_callback(struct timer_list *timer) 177 { 178 struct prbtest_wakeup_timer *wakeup = timer_container_of(wakeup, timer, timer); 179 180 set_tsk_thread_flag(wakeup->task, TIF_NOTIFY_SIGNAL); 181 wake_up_process(wakeup->task); 182 } 183 184 static int prbtest_reader(struct prbtest_data *test_data, unsigned long timeout_ms) 185 { 186 struct prbtest_wakeup_timer wakeup; 187 char text_buf[MAX_PRB_RECORD_SIZE]; 188 unsigned long count = 0; 189 struct printk_info info; 190 struct printk_record r; 191 u64 seq = 0; 192 193 wakeup.task = current; 194 timer_setup_on_stack(&wakeup.timer, prbtest_wakeup_callback, 0); 195 mod_timer(&wakeup.timer, jiffies + msecs_to_jiffies(timeout_ms)); 196 197 prb_rec_init_rd(&r, &info, text_buf, sizeof(text_buf)); 198 199 kunit_info(test_data->test, "start reader\n"); 200 201 while (!wait_event_interruptible(test_data->new_record_wait, 202 prb_read_valid(test_data->ringbuffer, seq, &r))) { 203 /* check/track the sequence */ 204 if (info.seq < seq) 205 KUNIT_FAIL(test_data->test, "BAD SEQ READ: request=%llu read=%llu\n", 206 seq, info.seq); 207 208 if (!prbtest_check_data((struct prbtest_rbdata *)r.text_buf)) 209 prbtest_fail_record(test_data->test, 210 (struct prbtest_rbdata *)r.text_buf, info.seq); 211 212 if ((count++ & 0x3fff) == 0) 213 cond_resched(); 214 215 seq = info.seq + 1; 216 } 217 218 timer_delete_sync(&wakeup.timer); 219 timer_destroy_on_stack(&wakeup.timer); 220 221 kunit_info(test_data->test, "end reader: read=%lu seq=%llu\n", count, info.seq); 222 223 return 0; 224 } 225 226 KUNIT_DEFINE_ACTION_WRAPPER(prbtest_cpumask_cleanup, free_cpumask_var, struct cpumask *); 227 KUNIT_DEFINE_ACTION_WRAPPER(prbtest_kthread_cleanup, kthread_stop, struct task_struct *); 228 229 static void prbtest_add_cpumask_cleanup(struct kunit *test, cpumask_var_t mask) 230 { 231 int err; 232 233 err = kunit_add_action_or_reset(test, prbtest_cpumask_cleanup, mask); 234 KUNIT_ASSERT_EQ(test, err, 0); 235 } 236 237 static void prbtest_add_kthread_cleanup(struct kunit *test, struct task_struct *kthread) 238 { 239 int err; 240 241 err = kunit_add_action_or_reset(test, prbtest_kthread_cleanup, kthread); 242 KUNIT_ASSERT_EQ(test, err, 0); 243 } 244 245 static inline void prbtest_prb_reinit(struct printk_ringbuffer *rb) 246 { 247 prb_init(rb, rb->text_data_ring.data, rb->text_data_ring.size_bits, rb->desc_ring.descs, 248 rb->desc_ring.count_bits, rb->desc_ring.infos); 249 } 250 251 static void test_readerwriter(struct kunit *test) 252 { 253 /* Equivalent to CONFIG_LOG_BUF_SHIFT=13 */ 254 DEFINE_PRINTKRB(test_rb, 8, 5); 255 256 struct prbtest_thread_data *thread_data; 257 struct prbtest_data *test_data; 258 struct task_struct *thread; 259 cpumask_var_t test_cpus; 260 int cpu, reader_cpu; 261 262 KUNIT_ASSERT_TRUE(test, alloc_cpumask_var(&test_cpus, GFP_KERNEL)); 263 prbtest_add_cpumask_cleanup(test, test_cpus); 264 265 cpus_read_lock(); 266 /* 267 * Failure of KUNIT_ASSERT() kills the current task 268 * so it can not be called while the CPU hotplug lock is held. 269 * Instead use a snapshot of the online CPUs. 270 * If they change during test execution it is unfortunate but not a grave error. 271 */ 272 cpumask_copy(test_cpus, cpu_online_mask); 273 cpus_read_unlock(); 274 275 /* One CPU is for the reader, all others are writers */ 276 reader_cpu = cpumask_first(test_cpus); 277 if (cpumask_weight(test_cpus) == 1) 278 kunit_warn(test, "more than one CPU is recommended"); 279 else 280 cpumask_clear_cpu(reader_cpu, test_cpus); 281 282 /* KUnit test can get restarted more times. */ 283 prbtest_prb_reinit(&test_rb); 284 285 test_data = kunit_kmalloc(test, sizeof(*test_data), GFP_KERNEL); 286 KUNIT_ASSERT_NOT_NULL(test, test_data); 287 test_data->test = test; 288 test_data->ringbuffer = &test_rb; 289 init_waitqueue_head(&test_data->new_record_wait); 290 291 kunit_info(test, "running for %lu ms\n", runtime_ms); 292 293 for_each_cpu(cpu, test_cpus) { 294 thread_data = kunit_kmalloc(test, sizeof(*thread_data), GFP_KERNEL); 295 KUNIT_ASSERT_NOT_NULL(test, thread_data); 296 thread_data->test_data = test_data; 297 thread_data->num = cpu; 298 299 thread = kthread_run_on_cpu(prbtest_writer, thread_data, cpu, 300 "prbtest writer %u"); 301 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, thread); 302 prbtest_add_kthread_cleanup(test, thread); 303 } 304 305 kunit_info(test, "starting test\n"); 306 307 set_cpus_allowed_ptr(current, cpumask_of(reader_cpu)); 308 prbtest_reader(test_data, runtime_ms); 309 310 kunit_info(test, "completed test\n"); 311 } 312 313 static struct kunit_case prb_test_cases[] = { 314 KUNIT_CASE_SLOW(test_readerwriter), 315 {} 316 }; 317 318 static struct kunit_suite prb_test_suite = { 319 .name = "printk-ringbuffer", 320 .test_cases = prb_test_cases, 321 }; 322 kunit_test_suite(prb_test_suite); 323 324 MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING"); 325 MODULE_AUTHOR("John Ogness <john.ogness@linutronix.de>"); 326 MODULE_DESCRIPTION("printk_ringbuffer KUnit test"); 327 MODULE_LICENSE("GPL"); 328