hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/arch/s390/kernel/debug.c
....@@ -2,7 +2,7 @@
22 /*
33 * S/390 debug facility
44 *
5
- * Copyright IBM Corp. 1999, 2012
5
+ * Copyright IBM Corp. 1999, 2020
66 *
77 * Author(s): Michael Holzheu (holzheu@de.ibm.com),
88 * Holger Smolinski (Holger.Smolinski@de.ibm.com)
....@@ -24,6 +24,7 @@
2424 #include <linux/export.h>
2525 #include <linux/init.h>
2626 #include <linux/fs.h>
27
+#include <linux/minmax.h>
2728 #include <linux/debugfs.h>
2829
2930 #include <asm/debug.h>
....@@ -90,26 +91,12 @@
9091 size_t user_buf_size, loff_t *offset);
9192 static int debug_hex_ascii_format_fn(debug_info_t *id, struct debug_view *view,
9293 char *out_buf, const char *in_buf);
93
-static int debug_raw_format_fn(debug_info_t *id,
94
- struct debug_view *view, char *out_buf,
95
- const char *in_buf);
96
-static int debug_raw_header_fn(debug_info_t *id, struct debug_view *view,
97
- int area, debug_entry_t *entry, char *out_buf);
98
-
9994 static int debug_sprintf_format_fn(debug_info_t *id, struct debug_view *view,
10095 char *out_buf, debug_sprintf_entry_t *curr_event);
96
+static void debug_areas_swap(debug_info_t *a, debug_info_t *b);
97
+static void debug_events_append(debug_info_t *dest, debug_info_t *src);
10198
10299 /* globals */
103
-
104
-struct debug_view debug_raw_view = {
105
- "raw",
106
- NULL,
107
- &debug_raw_header_fn,
108
- &debug_raw_format_fn,
109
- NULL,
110
- NULL
111
-};
112
-EXPORT_SYMBOL(debug_raw_view);
113100
114101 struct debug_view debug_hex_ascii_view = {
115102 "hex_ascii",
....@@ -327,24 +314,6 @@
327314 goto out;
328315
329316 rc->mode = mode & ~S_IFMT;
330
-
331
- /* create root directory */
332
- rc->debugfs_root_entry = debugfs_create_dir(rc->name,
333
- debug_debugfs_root_entry);
334
-
335
- /* append new element to linked list */
336
- if (!debug_area_first) {
337
- /* first element in list */
338
- debug_area_first = rc;
339
- rc->prev = NULL;
340
- } else {
341
- /* append element to end of list */
342
- debug_area_last->next = rc;
343
- rc->prev = debug_area_last;
344
- }
345
- debug_area_last = rc;
346
- rc->next = NULL;
347
-
348317 refcount_set(&rc->ref_count, 1);
349318 out:
350319 return rc;
....@@ -404,27 +373,10 @@
404373 */
405374 static void debug_info_put(debug_info_t *db_info)
406375 {
407
- int i;
408
-
409376 if (!db_info)
410377 return;
411
- if (refcount_dec_and_test(&db_info->ref_count)) {
412
- for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
413
- if (!db_info->views[i])
414
- continue;
415
- debugfs_remove(db_info->debugfs_entries[i]);
416
- }
417
- debugfs_remove(db_info->debugfs_root_entry);
418
- if (db_info == debug_area_first)
419
- debug_area_first = db_info->next;
420
- if (db_info == debug_area_last)
421
- debug_area_last = db_info->prev;
422
- if (db_info->prev)
423
- db_info->prev->next = db_info->next;
424
- if (db_info->next)
425
- db_info->next->prev = db_info->prev;
378
+ if (refcount_dec_and_test(&db_info->ref_count))
426379 debug_info_free(db_info);
427
- }
428380 }
429381
430382 /*
....@@ -449,7 +401,7 @@
449401 act_entry = (debug_entry_t *) ((char *)id_snap->areas[p_info->act_area]
450402 [p_info->act_page] + p_info->act_entry);
451403
452
- if (act_entry->id.stck == 0LL)
404
+ if (act_entry->clock == 0LL)
453405 goto out; /* empty entry */
454406 if (view->header_proc)
455407 len += view->header_proc(id_snap, view, p_info->act_area,
....@@ -648,11 +600,48 @@
648600 return 0; /* success */
649601 }
650602
651
-/*
652
- * debug_register_mode:
653
- * - Creates and initializes debug area for the caller
654
- * The mode parameter allows to specify access rights for the s390dbf files
655
- * - Returns handle for debug area
603
+/* Create debugfs entries and add to internal list. */
604
+static void _debug_register(debug_info_t *id)
605
+{
606
+ /* create root directory */
607
+ id->debugfs_root_entry = debugfs_create_dir(id->name,
608
+ debug_debugfs_root_entry);
609
+
610
+ /* append new element to linked list */
611
+ if (!debug_area_first) {
612
+ /* first element in list */
613
+ debug_area_first = id;
614
+ id->prev = NULL;
615
+ } else {
616
+ /* append element to end of list */
617
+ debug_area_last->next = id;
618
+ id->prev = debug_area_last;
619
+ }
620
+ debug_area_last = id;
621
+ id->next = NULL;
622
+
623
+ debug_register_view(id, &debug_level_view);
624
+ debug_register_view(id, &debug_flush_view);
625
+ debug_register_view(id, &debug_pages_view);
626
+}
627
+
628
+/**
629
+ * debug_register_mode() - creates and initializes debug area.
630
+ *
631
+ * @name: Name of debug log (e.g. used for debugfs entry)
632
+ * @pages_per_area: Number of pages, which will be allocated per area
633
+ * @nr_areas: Number of debug areas
634
+ * @buf_size: Size of data area in each debug entry
635
+ * @mode: File mode for debugfs files. E.g. S_IRWXUGO
636
+ * @uid: User ID for debugfs files. Currently only 0 is supported.
637
+ * @gid: Group ID for debugfs files. Currently only 0 is supported.
638
+ *
639
+ * Return:
640
+ * - Handle for generated debug area
641
+ * - %NULL if register failed
642
+ *
643
+ * Allocates memory for a debug log.
644
+ * Must not be called within an interrupt handler.
656645 */
657646 debug_info_t *debug_register_mode(const char *name, int pages_per_area,
658647 int nr_areas, int buf_size, umode_t mode,
....@@ -665,27 +654,35 @@
665654 if ((uid != 0) || (gid != 0))
666655 pr_warn("Root becomes the owner of all s390dbf files in sysfs\n");
667656 BUG_ON(!initialized);
668
- mutex_lock(&debug_mutex);
669657
670658 /* create new debug_info */
671659 rc = debug_info_create(name, pages_per_area, nr_areas, buf_size, mode);
672
- if (!rc)
673
- goto out;
674
- debug_register_view(rc, &debug_level_view);
675
- debug_register_view(rc, &debug_flush_view);
676
- debug_register_view(rc, &debug_pages_view);
677
-out:
678
- if (!rc)
660
+ if (rc) {
661
+ mutex_lock(&debug_mutex);
662
+ _debug_register(rc);
663
+ mutex_unlock(&debug_mutex);
664
+ } else {
679665 pr_err("Registering debug feature %s failed\n", name);
680
- mutex_unlock(&debug_mutex);
666
+ }
681667 return rc;
682668 }
683669 EXPORT_SYMBOL(debug_register_mode);
684670
685
-/*
686
- * debug_register:
687
- * - creates and initializes debug area for the caller
688
- * - returns handle for debug area
671
+/**
672
+ * debug_register() - creates and initializes debug area with default file mode.
673
+ *
674
+ * @name: Name of debug log (e.g. used for debugfs entry)
675
+ * @pages_per_area: Number of pages, which will be allocated per area
676
+ * @nr_areas: Number of debug areas
677
+ * @buf_size: Size of data area in each debug entry
678
+ *
679
+ * Return:
680
+ * - Handle for generated debug area
681
+ * - %NULL if register failed
682
+ *
683
+ * Allocates memory for a debug log.
684
+ * The debugfs file mode access permissions are read and write for user.
685
+ * Must not be called within an interrupt handler.
689686 */
690687 debug_info_t *debug_register(const char *name, int pages_per_area,
691688 int nr_areas, int buf_size)
....@@ -695,17 +692,44 @@
695692 }
696693 EXPORT_SYMBOL(debug_register);
697694
698
-/*
699
- * debug_unregister:
700
- * - give back debug area
695
+/* Remove debugfs entries and remove from internal list. */
696
+static void _debug_unregister(debug_info_t *id)
697
+{
698
+ int i;
699
+
700
+ for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
701
+ if (!id->views[i])
702
+ continue;
703
+ debugfs_remove(id->debugfs_entries[i]);
704
+ }
705
+ debugfs_remove(id->debugfs_root_entry);
706
+ if (id == debug_area_first)
707
+ debug_area_first = id->next;
708
+ if (id == debug_area_last)
709
+ debug_area_last = id->prev;
710
+ if (id->prev)
711
+ id->prev->next = id->next;
712
+ if (id->next)
713
+ id->next->prev = id->prev;
714
+}
715
+
716
+/**
717
+ * debug_unregister() - give back debug area.
718
+ *
719
+ * @id: handle for debug log
720
+ *
721
+ * Return:
722
+ * none
701723 */
702724 void debug_unregister(debug_info_t *id)
703725 {
704726 if (!id)
705727 return;
706728 mutex_lock(&debug_mutex);
707
- debug_info_put(id);
729
+ _debug_unregister(id);
708730 mutex_unlock(&debug_mutex);
731
+
732
+ debug_info_put(id);
709733 }
710734 EXPORT_SYMBOL(debug_unregister);
711735
....@@ -715,40 +739,38 @@
715739 */
716740 static int debug_set_size(debug_info_t *id, int nr_areas, int pages_per_area)
717741 {
718
- debug_entry_t ***new_areas;
742
+ debug_info_t *new_id;
719743 unsigned long flags;
720
- int rc = 0;
721744
722745 if (!id || (nr_areas <= 0) || (pages_per_area < 0))
723746 return -EINVAL;
724
- if (pages_per_area > 0) {
725
- new_areas = debug_areas_alloc(pages_per_area, nr_areas);
726
- if (!new_areas) {
727
- pr_info("Allocating memory for %i pages failed\n",
728
- pages_per_area);
729
- rc = -ENOMEM;
730
- goto out;
731
- }
732
- } else {
733
- new_areas = NULL;
747
+
748
+ new_id = debug_info_alloc("", pages_per_area, nr_areas, id->buf_size,
749
+ id->level, ALL_AREAS);
750
+ if (!new_id) {
751
+ pr_info("Allocating memory for %i pages failed\n",
752
+ pages_per_area);
753
+ return -ENOMEM;
734754 }
755
+
735756 spin_lock_irqsave(&id->lock, flags);
736
- debug_areas_free(id);
737
- id->areas = new_areas;
738
- id->nr_areas = nr_areas;
739
- id->pages_per_area = pages_per_area;
740
- id->active_area = 0;
741
- memset(id->active_entries, 0, sizeof(int)*id->nr_areas);
742
- memset(id->active_pages, 0, sizeof(int)*id->nr_areas);
757
+ debug_events_append(new_id, id);
758
+ debug_areas_swap(new_id, id);
759
+ debug_info_free(new_id);
743760 spin_unlock_irqrestore(&id->lock, flags);
744761 pr_info("%s: set new size (%i pages)\n", id->name, pages_per_area);
745
-out:
746
- return rc;
762
+
763
+ return 0;
747764 }
748765
749
-/*
750
- * debug_set_level:
751
- * - set actual debug level
766
+/**
767
+ * debug_set_level() - Sets new actual debug level if new_level is valid.
768
+ *
769
+ * @id: handle for debug log
770
+ * @new_level: new debug level
771
+ *
772
+ * Return:
773
+ * none
752774 */
753775 void debug_set_level(debug_info_t *id, int new_level)
754776 {
....@@ -805,6 +827,42 @@
805827 id->active_entries[id->active_area]);
806828 }
807829
830
+/* Swap debug areas of a and b. */
831
+static void debug_areas_swap(debug_info_t *a, debug_info_t *b)
832
+{
833
+ swap(a->nr_areas, b->nr_areas);
834
+ swap(a->pages_per_area, b->pages_per_area);
835
+ swap(a->areas, b->areas);
836
+ swap(a->active_area, b->active_area);
837
+ swap(a->active_pages, b->active_pages);
838
+ swap(a->active_entries, b->active_entries);
839
+}
840
+
841
+/* Append all debug events in active area from source to destination log. */
842
+static void debug_events_append(debug_info_t *dest, debug_info_t *src)
843
+{
844
+ debug_entry_t *from, *to, *last;
845
+
846
+ if (!src->areas || !dest->areas)
847
+ return;
848
+
849
+ /* Loop over all entries in src, starting with oldest. */
850
+ from = get_active_entry(src);
851
+ last = from;
852
+ do {
853
+ if (from->clock != 0LL) {
854
+ to = get_active_entry(dest);
855
+ memset(to, 0, dest->entry_size);
856
+ memcpy(to, from, min(src->entry_size,
857
+ dest->entry_size));
858
+ proceed_active_entry(dest);
859
+ }
860
+
861
+ proceed_active_entry(src);
862
+ from = get_active_entry(src);
863
+ } while (from != last);
864
+}
865
+
808866 /*
809867 * debug_finish_entry:
810868 * - set timestamp, caller address, cpu number etc.
....@@ -813,12 +871,17 @@
813871 static inline void debug_finish_entry(debug_info_t *id, debug_entry_t *active,
814872 int level, int exception)
815873 {
816
- active->id.stck = get_tod_clock_fast() -
817
- *(unsigned long long *) &tod_clock_base[1];
818
- active->id.fields.cpuid = smp_processor_id();
874
+ unsigned char clk[STORE_CLOCK_EXT_SIZE];
875
+ unsigned long timestamp;
876
+
877
+ get_tod_clock_ext(clk);
878
+ timestamp = *(unsigned long *) &clk[0] >> 4;
879
+ timestamp -= TOD_UNIX_EPOCH >> 12;
880
+ active->clock = timestamp;
881
+ active->cpu = smp_processor_id();
819882 active->caller = __builtin_return_address(0);
820
- active->id.fields.exception = exception;
821
- active->id.fields.level = level;
883
+ active->exception = exception;
884
+ active->level = level;
822885 proceed_active_entry(id);
823886 if (exception)
824887 proceed_active_area(id);
....@@ -836,7 +899,7 @@
836899 * if debug_active is already off
837900 */
838901 static int s390dbf_procactive(struct ctl_table *table, int write,
839
- void __user *buffer, size_t *lenp, loff_t *ppos)
902
+ void *buffer, size_t *lenp, loff_t *ppos)
840903 {
841904 if (!write || debug_stoppable || !debug_active)
842905 return proc_dointvec(table, write, buffer, lenp, ppos);
....@@ -874,6 +937,14 @@
874937
875938 static struct ctl_table_header *s390dbf_sysctl_header;
876939
940
+/**
941
+ * debug_stop_all() - stops the debug feature if stopping is allowed.
942
+ *
943
+ * Return:
944
+ * - none
945
+ *
946
+ * Currently used in case of a kernel oops.
947
+ */
877948 void debug_stop_all(void)
878949 {
879950 if (debug_stoppable)
....@@ -881,6 +952,17 @@
881952 }
882953 EXPORT_SYMBOL(debug_stop_all);
883954
955
+/**
956
+ * debug_set_critical() - event/exception functions try lock instead of spin.
957
+ *
958
+ * Return:
959
+ * - none
960
+ *
961
+ * Currently used in case of stopping all CPUs but the current one.
962
+ * Once in this state, functions to write a debug entry for an
963
+ * event or exception no longer spin on the debug area lock,
964
+ * but only try to get it and fail if they do not get the lock.
965
+ */
884966 void debug_set_critical(void)
885967 {
886968 debug_critical = 1;
....@@ -1037,8 +1119,16 @@
10371119 }
10381120 EXPORT_SYMBOL(__debug_sprintf_exception);
10391121
1040
-/*
1041
- * debug_register_view:
1122
+/**
1123
+ * debug_register_view() - registers new debug view and creates debugfs
1124
+ * dir entry
1125
+ *
1126
+ * @id: handle for debug log
1127
+ * @view: pointer to debug view struct
1128
+ *
1129
+ * Return:
1130
+ * - 0 : ok
1131
+ * - < 0: Error
10421132 */
10431133 int debug_register_view(debug_info_t *id, struct debug_view *view)
10441134 {
....@@ -1057,12 +1147,6 @@
10571147 mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
10581148 pde = debugfs_create_file(view->name, mode, id->debugfs_root_entry,
10591149 id, &debug_file_ops);
1060
- if (!pde) {
1061
- pr_err("Registering view %s/%s failed due to out of "
1062
- "memory\n", id->name, view->name);
1063
- rc = -1;
1064
- goto out;
1065
- }
10661150 spin_lock_irqsave(&id->lock, flags);
10671151 for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
10681152 if (!id->views[i])
....@@ -1084,8 +1168,16 @@
10841168 }
10851169 EXPORT_SYMBOL(debug_register_view);
10861170
1087
-/*
1088
- * debug_unregister_view:
1171
+/**
1172
+ * debug_unregister_view() - unregisters debug view and removes debugfs
1173
+ * dir entry
1174
+ *
1175
+ * @id: handle for debug log
1176
+ * @view: pointer to debug view struct
1177
+ *
1178
+ * Return:
1179
+ * - 0 : ok
1180
+ * - < 0: Error
10891181 */
10901182 int debug_unregister_view(debug_info_t *id, struct debug_view *view)
10911183 {
....@@ -1325,32 +1417,6 @@
13251417 }
13261418
13271419 /*
1328
- * prints debug header in raw format
1329
- */
1330
-static int debug_raw_header_fn(debug_info_t *id, struct debug_view *view,
1331
- int area, debug_entry_t *entry, char *out_buf)
1332
-{
1333
- int rc;
1334
-
1335
- rc = sizeof(debug_entry_t);
1336
- memcpy(out_buf, entry, sizeof(debug_entry_t));
1337
- return rc;
1338
-}
1339
-
1340
-/*
1341
- * prints debug data in raw format
1342
- */
1343
-static int debug_raw_format_fn(debug_info_t *id, struct debug_view *view,
1344
- char *out_buf, const char *in_buf)
1345
-{
1346
- int rc;
1347
-
1348
- rc = id->buf_size;
1349
- memcpy(out_buf, in_buf, id->buf_size);
1350
- return rc;
1351
-}
1352
-
1353
-/*
13541420 * prints debug data in hex/ascii format
13551421 */
13561422 static int debug_hex_ascii_format_fn(debug_info_t *id, struct debug_view *view,
....@@ -1379,25 +1445,24 @@
13791445 int debug_dflt_header_fn(debug_info_t *id, struct debug_view *view,
13801446 int area, debug_entry_t *entry, char *out_buf)
13811447 {
1382
- unsigned long base, sec, usec;
1448
+ unsigned long sec, usec;
13831449 unsigned long caller;
13841450 unsigned int level;
13851451 char *except_str;
13861452 int rc = 0;
13871453
1388
- level = entry->id.fields.level;
1389
- base = (*(unsigned long *) &tod_clock_base[0]) >> 4;
1390
- sec = (entry->id.stck >> 12) + base - (TOD_UNIX_EPOCH >> 12);
1454
+ level = entry->level;
1455
+ sec = entry->clock;
13911456 usec = do_div(sec, USEC_PER_SEC);
13921457
1393
- if (entry->id.fields.exception)
1458
+ if (entry->exception)
13941459 except_str = "*";
13951460 else
13961461 except_str = "-";
13971462 caller = (unsigned long) entry->caller;
1398
- rc += sprintf(out_buf, "%02i %011ld:%06lu %1u %1s %02i %pK ",
1463
+ rc += sprintf(out_buf, "%02i %011ld:%06lu %1u %1s %04u %pK ",
13991464 area, sec, usec, level, except_str,
1400
- entry->id.fields.cpuid, (void *)caller);
1465
+ entry->cpu, (void *)caller);
14011466 return rc;
14021467 }
14031468 EXPORT_SYMBOL(debug_dflt_header_fn);