]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/jdb/jdb_kern_info-bench.cpp
update
[l4.git] / kernel / fiasco / src / jdb / jdb_kern_info-bench.cpp
1 INTERFACE:
2
3 #include "jdb.h"
4
5 class Jdb_kern_info_bench : public Jdb_kern_info_module
6 {
7 private:
8   static Unsigned64 get_time_now();
9   static void show_arch();
10 };
11
12 //---------------------------------------------------------------------------
13 IMPLEMENTATION:
14
15 static Jdb_kern_info_bench k_a INIT_PRIORITY(JDB_MODULE_INIT_PRIO+1);
16
17 PUBLIC
18 Jdb_kern_info_bench::Jdb_kern_info_bench()
19   : Jdb_kern_info_module('b', "Benchmark privileged instructions")
20 {
21   Jdb_kern_info::register_subcmd(this);
22 }
23
24 PUBLIC
25 void
26 Jdb_kern_info_bench::show()
27 {
28   do_mp_benchmark();
29   show_arch();
30 }
31
32 //---------------------------------------------------------------------------
33 IMPLEMENTATION [!mp]:
34
35 PRIVATE
36 void
37 Jdb_kern_info_bench::do_mp_benchmark()
38 {}
39
40 //---------------------------------------------------------------------------
41 IMPLEMENTATION [mp && (ia32 || amd64)]:
42
43 #include "idt.h"
44
45 PRIVATE static inline
46 void
47 Jdb_kern_info_bench::stop_timer()
48 {
49   Timer_tick::set_vectors_stop();
50 }
51
52 //---------------------------------------------------------------------------
53 IMPLEMENTATION [mp && !(ia32 || amd64)]:
54
55 PRIVATE static inline
56 void
57 Jdb_kern_info_bench::stop_timer()
58 {}
59
60 //---------------------------------------------------------------------------
61 IMPLEMENTATION [mp]:
62
63 #include "ipi.h"
64
65 static int volatile ipi_bench_spin_done;
66 static int ipi_cnt;
67
68 PRIVATE static
69 void
70 Jdb_kern_info_bench::wait_for_ipi(Cpu_number cpu, void *)
71 {
72   Jdb::restore_irqs(cpu);
73   stop_timer();
74   Proc::sti();
75
76   while (!ipi_bench_spin_done)
77     Proc::pause();
78
79   Proc::cli();
80   Jdb::save_disable_irqs(cpu);
81 }
82
83 PRIVATE static
84 void
85 Jdb_kern_info_bench::empty_func(Cpu_number, void *)
86 {
87   ++ipi_cnt;
88 }
89
90 PRIVATE static
91 void
92 Jdb_kern_info_bench::do_ipi_bench(Cpu_number my_cpu, void *_partner)
93 {
94   Unsigned64 time;
95   Cpu_number partner = Cpu_number((unsigned long)_partner);
96   enum {
97     Runs2  = 3,
98     Warmup = 4,
99     Rounds = (1 << Runs2) + Warmup,
100   };
101   unsigned i;
102
103   ipi_cnt = 0;
104   Mem::barrier();
105
106   for (i = 0; i < Warmup; ++i)
107     Jdb::remote_work_ipi(my_cpu, partner, empty_func, 0, true);
108
109   time = get_time_now();
110   for (i = 0; i < (1 << Runs2); i++)
111     Jdb::remote_work_ipi(my_cpu, partner, empty_func, 0, true);
112
113   printf(" %2u:%8lld", cxx::int_value<Cpu_number>(partner),
114          (get_time_now() - time) >> Runs2);
115
116   if (ipi_cnt != Rounds)
117     printf("\nCounter mismatch: cnt=%d v %d\n", ipi_cnt, Rounds);
118
119   ipi_bench_spin_done = 1;
120   Mem::barrier();
121 }
122
123 PRIVATE
124 void
125 Jdb_kern_info_bench::do_mp_benchmark()
126 {
127   // IPI bench matrix
128   printf("IPI round-trips:\n");
129   for (Cpu_number u = Cpu_number::first(); u < Config::max_num_cpus(); ++u)
130     if (Cpu::online(u))
131       {
132         printf("l%2u: ", cxx::int_value<Cpu_number>(u));
133
134         for (Cpu_number v = Cpu_number::first(); v < Config::max_num_cpus(); ++v)
135           if (Cpu::online(v))
136             {
137               if (u == v)
138                 printf(" %2u:%8s", cxx::int_value<Cpu_number>(u), "X");
139               else
140                 {
141                   ipi_bench_spin_done = 0;
142
143                   // v is waiting for IPIs
144                   if (v != Cpu_number::boot_cpu())
145                     Jdb::remote_work(v, wait_for_ipi, 0, false);
146
147                   // u is doing benchmark
148                   if (u == Cpu_number::boot_cpu())
149                     do_ipi_bench(Cpu_number::boot_cpu(),
150                                  (void *)(long)cxx::int_value<Cpu_number>(v));
151                   else
152                     Jdb::remote_work(u, do_ipi_bench,
153                                     (void *)(long)cxx::int_value<Cpu_number>(v), false);
154
155                   // v is waiting for IPIs
156                   if (v == Cpu_number::boot_cpu())
157                     wait_for_ipi(Cpu_number::boot_cpu(), 0);
158
159                   Mem::barrier();
160
161                   while (!ipi_bench_spin_done)
162                     Proc::pause();
163                 }
164             }
165         printf("\n");
166       }
167 }