LCOV - code coverage report
Current view: top level - core/test - run-trace.c (source / functions) Hit Total Coverage
Test: skiboot.info Lines: 195 198 98.5 %
Date: 2024-09-10 18:37:41 Functions: 11 12 91.7 %
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
       2                 :            : /*
       3                 :            :  * Copyright 2013-2019 IBM Corp.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include <config.h>
       7                 :            : #include <stdlib.h>
       8                 :            : #include <assert.h>
       9                 :            : #include <sched.h>
      10                 :            : #include <stdlib.h>
      11                 :            : #include <stdint.h>
      12                 :            : #include <unistd.h>
      13                 :            : #include <stdio.h>
      14                 :            : #include <stdbool.h>
      15                 :            : #include <sys/types.h>
      16                 :            : #include <sys/wait.h>
      17                 :            : 
      18                 :            : #include <skiboot-valgrind.h>
      19                 :            : 
      20                 :            : /* Don't include these: PPC-specific */
      21                 :            : #define __CPU_H
      22                 :            : #define __TIME_H
      23                 :            : #define __PROCESSOR_H
      24                 :            : 
      25                 :            : #if defined(__i386__) || defined(__x86_64__)
      26                 :            : /* This is more than a lwsync, but it'll work */
      27                 :   10850485 : static void full_barrier(void)
      28                 :            : {
      29                 :   10850485 :         asm volatile("mfence" : : : "memory");
      30                 :   10850485 : }
      31                 :            : #define lwsync full_barrier
      32                 :            : #elif defined(__powerpc__) || defined(__powerpc64__)
      33                 :            : static inline void lwsync(void)
      34                 :            : {
      35                 :            :         asm volatile("lwsync" : : : "memory");
      36                 :            : }
      37                 :            : #else
      38                 :            : #error "Define lwsync for this arch"
      39                 :            : #endif
      40                 :            : 
      41                 :            : #define zalloc(size) calloc((size), 1)
      42                 :            : 
      43                 :            : struct cpu_thread {
      44                 :            :         uint32_t pir;
      45                 :            :         uint32_t chip_id;
      46                 :            :         struct trace_info *trace;
      47                 :            :         uint32_t server_no;
      48                 :            :         bool is_secondary;
      49                 :            :         struct cpu_thread *primary;
      50                 :            : };
      51                 :            : static struct cpu_thread *this_cpu(void);
      52                 :            : 
      53                 :            : #define CPUS 4
      54                 :            : 
      55                 :            : static struct cpu_thread fake_cpus[CPUS];
      56                 :            : 
      57                 :         15 : static inline struct cpu_thread *next_cpu(struct cpu_thread *cpu)
      58                 :            : {
      59                 :         15 :         if (cpu == NULL)
      60                 :          3 :                 return &fake_cpus[0];
      61                 :         12 :         cpu++;
      62                 :         12 :         if (cpu == &fake_cpus[CPUS])
      63                 :          3 :                 return NULL;
      64                 :          9 :         return cpu;
      65                 :            : }
      66                 :            : 
      67                 :            : #define first_cpu() next_cpu(NULL)
      68                 :            : 
      69                 :            : #define for_each_cpu(cpu)       \
      70                 :            :         for (cpu = first_cpu(); cpu; cpu = next_cpu(cpu))
      71                 :            : 
      72                 :            : static unsigned long timestamp;
      73                 :    6418116 : static unsigned long mftb(void)
      74                 :            : {
      75                 :    6418116 :         return timestamp;
      76                 :            : }
      77                 :            : 
      78                 :          2 : static void *local_alloc(unsigned int chip_id,
      79                 :            :                          size_t size, size_t align)
      80                 :            : {
      81                 :            :         void *p;
      82                 :            : 
      83                 :            :         (void)chip_id;
      84                 :          2 :         if (posix_memalign(&p, align, size))
      85                 :          0 :                 p = NULL;
      86                 :          2 :         return p;
      87                 :            : }
      88                 :            : 
      89                 :            : struct dt_node;
      90                 :            : extern struct dt_node *opal_node;
      91                 :            : 
      92                 :            : #include "../trace.c"
      93                 :            : 
      94                 :            : #include "../external/trace/trace.c"
      95                 :            : static struct trace_reader trace_readers[CPUS];
      96                 :            : struct trace_reader *my_trace_reader;
      97                 :            : #include "../device.c"
      98                 :            : 
      99                 :            : char __rodata_start[1], __rodata_end[1];
     100                 :            : struct dt_node *opal_node;
     101                 :            : struct debug_descriptor debug_descriptor = {
     102                 :            :         .trace_mask = -1
     103                 :            : };
     104                 :            : 
     105                 :          0 : const char *nvram_query_safe(const char *key __unused)
     106                 :            : {
     107                 :          0 :         return NULL;
     108                 :            : }
     109                 :            : 
     110                 :    6418116 : void lock_caller(struct lock *l, const char *caller)
     111                 :            : {
     112                 :            :         (void)caller;
     113                 :    6418116 :         assert(!l->lock_val);
     114                 :    6418116 :         l->lock_val = 1;
     115                 :    6418116 : }
     116                 :            : 
     117                 :    6418116 : void unlock(struct lock *l)
     118                 :            : {
     119                 :    6418116 :         assert(l->lock_val);
     120                 :    6418116 :         l->lock_val = 0;
     121                 :    6418116 : }
     122                 :            : 
     123                 :            : struct cpu_thread *my_fake_cpu;
     124                 :   12836233 : static struct cpu_thread *this_cpu(void)
     125                 :            : {
     126                 :   12836233 :         return my_fake_cpu;
     127                 :            : }
     128                 :            : 
     129                 :            : #include <sys/mman.h>
     130                 :            : #define PER_CHILD_TRACES ((RUNNING_ON_VALGRIND) ? (1024*16) : (1024*1024))
     131                 :            : 
     132                 :          4 : static void write_trace_entries(int id)
     133                 :            : {
     134                 :            :         void exit(int);
     135                 :            :         unsigned int i;
     136                 :            :         union trace trace;
     137                 :            : 
     138                 :          4 :         timestamp = id;
     139                 :    4194308 :         for (i = 0; i < PER_CHILD_TRACES; i++) {
     140                 :    4194304 :                 timestamp = i * CPUS + id;
     141                 :            :                 assert(sizeof(trace.hdr) % 8 == 0);
     142                 :            :                 /* First child never repeats, second repeats once, etc. */
     143                 :    4194304 :                 trace_add(&trace, 3 + ((i / (id + 1)) % 0x40),
     144                 :            :                           sizeof(trace.hdr));
     145                 :            :         }
     146                 :            : 
     147                 :            :         /* Final entry has special type, so parent knows it's over. */
     148                 :          4 :         trace_add(&trace, 0x70, sizeof(trace.hdr));
     149                 :          4 :         exit(0);
     150                 :            : }
     151                 :            : 
     152                 :    2093313 : static bool all_done(const bool done[])
     153                 :            : {
     154                 :            :         unsigned int i;
     155                 :            : 
     156                 :    2972555 :         for (i = 0; i < CPUS; i++)
     157                 :    2972554 :                 if (!done[i])
     158                 :    2093312 :                         return false;
     159                 :          1 :         return true;
     160                 :            : }
     161                 :            : 
     162                 :          1 : static void test_parallel(void)
     163                 :            : {
     164                 :            :         void *p;
     165                 :            :         unsigned int cpu;
     166                 :          1 :         unsigned int i, counts[CPUS] = { 0 }, overflows[CPUS] = { 0 };
     167                 :          1 :         unsigned int repeats[CPUS] = { 0 }, num_overflows[CPUS] = { 0 };
     168                 :          1 :         bool done[CPUS] = { false };
     169                 :          1 :         size_t len = sizeof(struct trace_info) + TBUF_SZ + sizeof(union trace);
     170                 :          1 :         int last = 0;
     171                 :            : 
     172                 :            :         /* Use a shared mmap to test actual parallel buffers. */
     173                 :          1 :         i = (CPUS*len + getpagesize()-1)&~(getpagesize()-1);
     174                 :          1 :         p = mmap(NULL, i, PROT_READ|PROT_WRITE,
     175                 :            :                  MAP_ANONYMOUS|MAP_SHARED, -1, 0);
     176                 :            : 
     177                 :          5 :         for (i = 0; i < CPUS; i++) {
     178                 :          4 :                 fake_cpus[i].trace = p + i * len;
     179                 :          4 :                 fake_cpus[i].trace->tb.buf_size = cpu_to_be64(TBUF_SZ);
     180                 :          4 :                 fake_cpus[i].trace->tb.max_size = cpu_to_be32(sizeof(union trace));
     181                 :          4 :                 fake_cpus[i].is_secondary = false;
     182                 :          4 :                 memset(&trace_readers[i], 0, sizeof(struct trace_reader));
     183                 :          4 :                 trace_readers[i].tb = &fake_cpus[i].trace->tb;
     184                 :            :         }
     185                 :            : 
     186                 :          5 :         for (i = 0; i < CPUS; i++) {
     187                 :          4 :                 if (!fork()) {
     188                 :            :                         /* Child. */
     189                 :          4 :                         my_fake_cpu = &fake_cpus[i];
     190                 :          4 :                         write_trace_entries(i);
     191                 :            :                 }
     192                 :            :         }
     193                 :            : 
     194                 :    2093313 :         while (!all_done(done)) {
     195                 :            :                 union trace t;
     196                 :            : 
     197                 :    2241991 :                 for (i = 0; i < CPUS; i++) {
     198                 :    2204827 :                         if (trace_get(&t, &trace_readers[(i+last) % CPUS]))
     199                 :    2056148 :                                 break;
     200                 :            :                 }
     201                 :            : 
     202                 :    2093312 :                 if (i == CPUS) {
     203                 :      37164 :                         sched_yield();
     204                 :      37193 :                         continue;
     205                 :            :                 }
     206                 :    2056148 :                 i = (i + last) % CPUS;
     207                 :    2056148 :                 last = i;
     208                 :            : 
     209                 :    2056148 :                 if (t.hdr.type == TRACE_OVERFLOW) {
     210                 :            :                         /* Conveniently, each record is 16 bytes here. */
     211                 :         29 :                         assert(be64_to_cpu(t.overflow.bytes_missed) % 16 == 0);
     212                 :         29 :                         overflows[i] += be64_to_cpu(t.overflow.bytes_missed) / 16;
     213                 :         29 :                         num_overflows[i]++;
     214                 :         29 :                         continue;
     215                 :            :                 }
     216                 :            : 
     217                 :    2056119 :                 assert(be16_to_cpu(t.hdr.cpu) < CPUS);
     218                 :    2056119 :                 assert(!done[be16_to_cpu(t.hdr.cpu)]);
     219                 :    2056119 :                 assert(be64_to_cpu(t.hdr.timestamp) % CPUS == be16_to_cpu(t.hdr.cpu));
     220                 :    2056119 :                 if (t.hdr.type == TRACE_REPEAT) {
     221                 :     838957 :                         assert(t.hdr.len_div_8 * 8 == sizeof(t.repeat));
     222                 :     838957 :                         assert(be16_to_cpu(t.repeat.num) != 0);
     223                 :     838957 :                         assert(be16_to_cpu(t.repeat.num) <= be16_to_cpu(t.hdr.cpu));
     224                 :     838957 :                         repeats[be16_to_cpu(t.hdr.cpu)] += be16_to_cpu(t.repeat.num);
     225                 :    1217162 :                 } else if (t.hdr.type == 0x70) {
     226                 :          4 :                         cpu = be16_to_cpu(t.hdr.cpu);
     227                 :          4 :                         assert(cpu < CPUS);
     228                 :          4 :                         done[cpu] = true;
     229                 :            :                 } else {
     230                 :    1217158 :                         cpu = be16_to_cpu(t.hdr.cpu);
     231                 :    1217158 :                         assert(cpu < CPUS);
     232                 :    1217158 :                         counts[cpu]++;
     233                 :            :                 }
     234                 :            :         }
     235                 :            : 
     236                 :            :         /* Gather children. */
     237                 :          5 :         for (i = 0; i < CPUS; i++) {
     238                 :            :                 int status;
     239                 :          4 :                 wait(&status);
     240                 :            :         }
     241                 :            : 
     242                 :          5 :         for (i = 0; i < CPUS; i++) {
     243                 :          4 :                 printf("Child %i: %u produced, %u overflows, %llu total\n", i,
     244                 :            :                        counts[i], overflows[i],
     245                 :          4 :                        (long long)be64_to_cpu(fake_cpus[i].trace->tb.end));
     246                 :          4 :                 assert(counts[i] + repeats[i] <= PER_CHILD_TRACES);
     247                 :            :         }
     248                 :            :         /* Child 0 never repeats. */
     249                 :          1 :         assert(repeats[0] == 0);
     250                 :          1 :         assert(counts[0] + overflows[0] == PER_CHILD_TRACES);
     251                 :            : 
     252                 :            :         /*
     253                 :            :          * FIXME: Other children have some fuzz, since overflows may
     254                 :            :          * include repeat record we already read.  And odd-numbered
     255                 :            :          * overflows may include more repeat records than normal
     256                 :            :          * records (they alternate).
     257                 :            :          */
     258                 :          1 : }
     259                 :            : 
     260                 :          1 : int main(void)
     261                 :            : {
     262                 :            :         union trace minimal;
     263                 :            :         union trace large;
     264                 :            :         union trace trace;
     265                 :            :         unsigned int i, j;
     266                 :            : 
     267                 :          1 :         opal_node = dt_new_root("opal");
     268                 :          1 :         dt_new(dt_new(opal_node, "firmware"), "exports");
     269                 :          5 :         for (i = 0; i < CPUS; i++) {
     270                 :          4 :                 fake_cpus[i].server_no = i;
     271                 :          4 :                 fake_cpus[i].pir = i;
     272                 :          4 :                 fake_cpus[i].is_secondary = (i & 0x1);
     273                 :          4 :                 fake_cpus[i].primary = &fake_cpus[i & ~0x1];
     274                 :            :         }
     275                 :          1 :         my_fake_cpu = &fake_cpus[0];
     276                 :          1 :         my_trace_reader = &trace_readers[0];
     277                 :          1 :         init_trace_buffers();
     278                 :            : 
     279                 :          5 :         for (i = 0; i < CPUS; i++) {
     280                 :          4 :                 trace_readers[i].tb = &fake_cpus[i].trace->tb;
     281                 :          4 :                 assert(trace_empty(&trace_readers[i]));
     282                 :          4 :                 assert(!trace_get(&trace, &trace_readers[i]));
     283                 :            :         }
     284                 :            : 
     285                 :            :         assert(sizeof(trace.hdr) % 8 == 0);
     286                 :          1 :         timestamp = 1;
     287                 :          1 :         trace_add(&minimal, 100, sizeof(trace.hdr));
     288                 :          1 :         assert(trace_get(&trace, my_trace_reader));
     289                 :          1 :         assert(trace.hdr.len_div_8 == minimal.hdr.len_div_8);
     290                 :          1 :         assert(be64_to_cpu(trace.hdr.timestamp) == timestamp);
     291                 :            : 
     292                 :            :         /* Make it wrap once. */
     293                 :      65404 :         for (i = 0; i < TBUF_SZ / (minimal.hdr.len_div_8 * 8) + 1; i++) {
     294                 :      65403 :                 timestamp = i;
     295                 :      65403 :                 trace_add(&minimal, 99 + (i%2), sizeof(trace.hdr));
     296                 :            :         }
     297                 :            : 
     298                 :          1 :         assert(trace_get(&trace, my_trace_reader));
     299                 :            :         /* First one must be overflow marker. */
     300                 :          1 :         assert(trace.hdr.type == TRACE_OVERFLOW);
     301                 :          1 :         assert(trace.hdr.len_div_8 * 8 == sizeof(trace.overflow));
     302                 :          1 :         assert(be64_to_cpu(trace.overflow.bytes_missed) == minimal.hdr.len_div_8 * 8);
     303                 :            : 
     304                 :      65403 :         for (i = 0; i < TBUF_SZ / (minimal.hdr.len_div_8 * 8); i++) {
     305                 :      65402 :                 assert(trace_get(&trace, my_trace_reader));
     306                 :      65402 :                 assert(trace.hdr.len_div_8 == minimal.hdr.len_div_8);
     307                 :      65402 :                 assert(be64_to_cpu(trace.hdr.timestamp) == i+1);
     308                 :      65402 :                 assert(trace.hdr.type == 99 + ((i+1)%2));
     309                 :            :         }
     310                 :          1 :         assert(!trace_get(&trace, my_trace_reader));
     311                 :            : 
     312                 :            :         /* Now put in some weird-length ones, to test overlap.
     313                 :            :          * Last power of 2, minus 8. */
     314                 :          8 :         for (j = 0; (1 << j) < sizeof(large); j++);
     315                 :    1046433 :         for (i = 0; i < TBUF_SZ; i++) {
     316                 :    1046432 :                 timestamp = i;
     317                 :    1046432 :                 trace_add(&large, 100 + (i%2), (1 << (j-1)));
     318                 :            :         }
     319                 :          1 :         assert(trace_get(&trace, my_trace_reader));
     320                 :          1 :         assert(trace.hdr.type == TRACE_OVERFLOW);
     321                 :          1 :         assert(trace_get(&trace, my_trace_reader));
     322                 :          1 :         assert(trace.hdr.len_div_8 == large.hdr.len_div_8);
     323                 :          1 :         i = be64_to_cpu(trace.hdr.timestamp);
     324                 :      16350 :         while (trace_get(&trace, my_trace_reader))
     325                 :      16349 :                 assert(be64_to_cpu(trace.hdr.timestamp) == ++i);
     326                 :            : 
     327                 :            :         /* Test repeats. */
     328                 :      65539 :         for (i = 0; i < 65538; i++) {
     329                 :      65538 :                 timestamp = i;
     330                 :      65538 :                 trace_add(&minimal, 100, sizeof(trace.hdr));
     331                 :            :         }
     332                 :          1 :         timestamp = i;
     333                 :          1 :         trace_add(&minimal, 101, sizeof(trace.hdr));
     334                 :          1 :         timestamp = i+1;
     335                 :          1 :         trace_add(&minimal, 101, sizeof(trace.hdr));
     336                 :            : 
     337                 :          1 :         assert(trace_get(&trace, my_trace_reader));
     338                 :          1 :         assert(trace.hdr.timestamp == 0);
     339                 :          1 :         assert(trace.hdr.len_div_8 == minimal.hdr.len_div_8);
     340                 :          1 :         assert(trace.hdr.type == 100);
     341                 :          1 :         assert(trace_get(&trace, my_trace_reader));
     342                 :          1 :         assert(trace.hdr.type == TRACE_REPEAT);
     343                 :          1 :         assert(trace.hdr.len_div_8 * 8 == sizeof(trace.repeat));
     344                 :          1 :         assert(be16_to_cpu(trace.repeat.num) == 65535);
     345                 :          1 :         assert(be64_to_cpu(trace.repeat.timestamp) == 65535);
     346                 :          1 :         assert(trace_get(&trace, my_trace_reader));
     347                 :          1 :         assert(be64_to_cpu(trace.hdr.timestamp) == 65536);
     348                 :          1 :         assert(trace.hdr.len_div_8 == minimal.hdr.len_div_8);
     349                 :          1 :         assert(trace.hdr.type == 100);
     350                 :          1 :         assert(trace_get(&trace, my_trace_reader));
     351                 :          1 :         assert(trace.hdr.type == TRACE_REPEAT);
     352                 :          1 :         assert(trace.hdr.len_div_8 * 8 == sizeof(trace.repeat));
     353                 :          1 :         assert(be16_to_cpu(trace.repeat.num) == 1);
     354                 :          1 :         assert(be64_to_cpu(trace.repeat.timestamp) == 65537);
     355                 :            : 
     356                 :          1 :         assert(trace_get(&trace, my_trace_reader));
     357                 :          1 :         assert(be64_to_cpu(trace.hdr.timestamp) == 65538);
     358                 :          1 :         assert(trace.hdr.len_div_8 == minimal.hdr.len_div_8);
     359                 :          1 :         assert(trace.hdr.type == 101);
     360                 :          1 :         assert(trace_get(&trace, my_trace_reader));
     361                 :          1 :         assert(trace.hdr.type == TRACE_REPEAT);
     362                 :          1 :         assert(trace.hdr.len_div_8 * 8 == sizeof(trace.repeat));
     363                 :          1 :         assert(be16_to_cpu(trace.repeat.num) == 1);
     364                 :          1 :         assert(be64_to_cpu(trace.repeat.timestamp) == 65539);
     365                 :            : 
     366                 :            :         /* Now, test adding repeat while we're reading... */
     367                 :          1 :         timestamp = 0;
     368                 :          1 :         trace_add(&minimal, 100, sizeof(trace.hdr));
     369                 :          1 :         assert(trace_get(&trace, my_trace_reader));
     370                 :          1 :         assert(be64_to_cpu(trace.hdr.timestamp) == 0);
     371                 :          1 :         assert(trace.hdr.len_div_8 == minimal.hdr.len_div_8);
     372                 :          1 :         assert(trace.hdr.type == 100);
     373                 :            : 
     374                 :    1046432 :         for (i = 1; i < TBUF_SZ; i++) {
     375                 :    1046431 :                 timestamp = i;
     376                 :    1046431 :                 trace_add(&minimal, 100, sizeof(trace.hdr));
     377                 :    1046431 :                 assert(trace_get(&trace, my_trace_reader));
     378                 :    1046431 :                 if (i % 65536 == 0) {
     379                 :         15 :                         assert(trace.hdr.type == 100);
     380                 :         15 :                         assert(trace.hdr.len_div_8 == minimal.hdr.len_div_8);
     381                 :            :                 } else {
     382                 :    1046416 :                         assert(trace.hdr.type == TRACE_REPEAT);
     383                 :    1046416 :                         assert(trace.hdr.len_div_8 * 8 == sizeof(trace.repeat));
     384                 :    1046416 :                         assert(be16_to_cpu(trace.repeat.num) == 1);
     385                 :            :                 }
     386                 :    1046431 :                 assert(be64_to_cpu(trace.repeat.timestamp) == i);
     387                 :    1046431 :                 assert(!trace_get(&trace, my_trace_reader));
     388                 :            :         }
     389                 :            : 
     390                 :          5 :         for (i = 0; i < CPUS; i++)
     391                 :          4 :                 if (!fake_cpus[i].is_secondary)
     392                 :          2 :                         free(fake_cpus[i].trace);
     393                 :            : 
     394                 :          1 :         test_parallel();
     395                 :            : 
     396                 :          1 :         return 0;
     397                 :            : }

Generated by: LCOV version 1.14