40 #include <type_traits>
71 dumpDmesgEntry(
const uint8_t *
base,
const uint8_t *end,
75 const size_t max_length = end -
base;
78 if (max_length <
sizeof(
de)) {
79 warn(
"Malformed dmesg entry\n");
88 if (
de.len <
sizeof(
de) ||
89 max_length <
de.len ||
90 max_length <
sizeof(DmesgEntry) +
de.text_len) {
92 warn(
"Malformed dmesg entry:\n");
93 warn(
"\tMax length: %i\n", max_length);
94 warn(
"\tde.len: %i\n",
de.len);
95 warn(
"\tde.text_len: %i\n",
de.text_len);
100 os.write((
char *)
base +
sizeof(
de),
de.text_len);
110 System *
system = tc->getSystemPtr();
111 const ByteOrder
bo =
system->getGuestByteOrder();
112 const auto &symtab =
system->workload->symtab(tc);
113 TranslatingPortProxy proxy(tc);
115 auto lb = symtab.find(
"__log_buf");
116 auto lb_len = symtab.find(
"log_buf_len");
117 auto first = symtab.find(
"log_first_idx");
118 auto next = symtab.find(
"log_next_idx");
120 auto end_it = symtab.end();
122 if (lb == end_it || lb_len == end_it ||
123 first == end_it || next == end_it) {
124 warn(
"Failed to find kernel dmesg symbols.\n");
128 uint32_t log_buf_len = proxy.read<uint32_t>(lb_len->address,
bo);
129 uint32_t log_first_idx = proxy.read<uint32_t>(first->address,
bo);
130 uint32_t log_next_idx = proxy.read<uint32_t>(next->address,
bo);
132 if (log_first_idx >= log_buf_len || log_next_idx >= log_buf_len) {
133 warn(
"dmesg pointers/length corrupted\n");
140 if (log_first_idx < log_next_idx) {
141 length = log_next_idx - log_first_idx;
142 if (length < 0 || length > log_buf.size()) {
143 warn(
"Unexpected dmesg buffer length\n");
146 proxy.readBlob(lb->address + log_first_idx, log_buf.data(), length);
148 const int length_2 = log_buf_len - log_first_idx;
149 if (length_2 < 0 || length_2 + log_next_idx > log_buf.size()) {
150 warn(
"Unexpected dmesg buffer length\n");
153 length = log_buf_len;
154 proxy.readBlob(lb->address + log_first_idx, log_buf.data(), length_2);
155 proxy.readBlob(lb->address, log_buf.data() + length_2, log_next_idx);
159 const uint8_t *cur = log_buf.data(), *end = log_buf.data() + length;
161 int ret = dumpDmesgEntry(cur, end,
bo,
os);
182 template<
typename atomic_var_t>
185 using guest_ptr_t =
typename std::make_unsigned_t<atomic_var_t>;
196 static DmesgMetadataRecord
197 read(
const TranslatingPortProxy & proxy,
199 guest_ptr_t data_offset_mask,
200 const ByteOrder &
bo)
214 metadata.data_buffer.curr_offset & data_offset_mask;
216 metadata.data_buffer.next_offset & data_offset_mask;
232 struct GEM5_PACKED DmesgInfoRecord
248 static DmesgInfoRecord
249 read(
const TranslatingPortProxy & proxy,
251 const ByteOrder &
bo)
253 DmesgInfoRecord info;
254 proxy.readBlob(address, &info,
sizeof(info));
257 info.ts_nsec =
gtoh(info.ts_nsec,
bo);
258 info.message_size =
gtoh(info.message_size,
bo);
274 template<
typename AtomicVarType>
275 struct GEM5_PACKED DmesgRingbuffer
279 std::is_same<AtomicVarType, int32_t>,
280 std::is_same<AtomicVarType, int64_t>
282 "AtomicVarType must be int32_t or int64_t");
284 using atomic_var_t = AtomicVarType;
285 using guest_ptr_t =
typename std::make_unsigned_t<atomic_var_t>;
286 using metadata_record_t = DmesgMetadataRecord<atomic_var_t>;
307 static DmesgRingbuffer
308 read(
const TranslatingPortProxy & proxy,
310 const ByteOrder &
bo)
313 proxy.readBlob(address, &rb,
sizeof(rb));
316 rb.metadata.mask_bits =
317 gtoh(rb.metadata.mask_bits,
bo);
318 rb.metadata.metadata_ring_ptr =
319 gtoh(rb.metadata.metadata_ring_ptr,
bo);
320 rb.metadata.info_ring_ptr =
321 gtoh(rb.metadata.info_ring_ptr,
bo);
323 rb.data.mask_bits =
gtoh(rb.data.mask_bits,
bo);
324 rb.data.data_ring_ptr =
gtoh(rb.data.data_ring_ptr,
bo);
325 rb.data.head_offset =
gtoh(rb.data.head_offset,
bo);
326 rb.data.tail_offset =
gtoh(rb.data.tail_offset,
bo);
329 rb.data.head_offset =
330 rb.mask_data_offset(rb.data.head_offset);
331 rb.data.tail_offset =
332 rb.mask_data_offset(rb.data.tail_offset);
340 template<
typename as_type>
342 make_offset_mask_as(
const unsigned int mask_bits)
344 using unsigned_atomic_var_t =
346 const atomic_var_t offset_mask =
347 static_cast<atomic_var_t
>(
348 (
static_cast<unsigned_atomic_var_t
>(1) <<
mask_bits) - 1);
349 return static_cast<as_type
>(offset_mask);
353 template<
typename metadata_offset_t>
355 make_metadata_offset_mask()
const
357 return make_offset_mask_as<metadata_offset_t>(
metadata.mask_bits);
361 template<
typename data_offset_t>
363 make_data_offset_mask()
const
365 return make_offset_mask_as<data_offset_t>(
data.mask_bits);
370 template<
typename metadata_offset_t>
372 mask_metadata_offset(
const metadata_offset_t metadata_offset)
const
374 const atomic_var_t MASK =
375 make_metadata_offset_mask<metadata_offset_t>();
376 return metadata_offset & MASK;
380 template<
typename data_offset_t>
382 mask_data_offset(
const data_offset_t data_offset)
const
384 const atomic_var_t MASK = make_data_offset_mask<data_offset_t>();
385 return data_offset & MASK;
390 using Linux64_Ringbuffer = DmesgRingbuffer<int64_t>;
391 using Linux32_Ringbuffer = DmesgRingbuffer<int32_t>;
406 template <
typename ringbuffer_t,
407 typename atomic_var_t=
typename ringbuffer_t::atomic_var_t,
408 typename guest_ptr_t=
typename ringbuffer_t::guest_ptr_t>
410 iterateDataRingbuffer(std::ostream &
os,
411 const TranslatingPortProxy & proxy,
412 const ringbuffer_t & rb,
413 const atomic_var_t
offset,
414 const guest_ptr_t first_metadata_offset,
417 using metadata_record_t =
typename ringbuffer_t::metadata_record_t;
419 constexpr
size_t METADATA_RECORD_SIZE =
420 sizeof(
typename ringbuffer_t::metadata_record_t);
421 constexpr
size_t INFO_RECORD_SIZE =
sizeof(DmesgInfoRecord);
423 const guest_ptr_t DATA_OFFSET_MASK =
424 rb.template make_data_offset_mask<guest_ptr_t>();
428 guest_ptr_t metadata_info_offset = rb.mask_metadata_offset(
429 proxy.read<guest_ptr_t>(rb.data.data_ring_ptr +
offset,
bo));
435 if (metadata_info_offset == first_metadata_offset) {
436 return static_cast<atomic_var_t
>(0);
440 guest_ptr_t metadata_address =
441 rb.metadata.metadata_ring_ptr +
442 (metadata_info_offset * METADATA_RECORD_SIZE);
444 metadata_record_t::read(proxy, metadata_address, DATA_OFFSET_MASK,
bo);
447 guest_ptr_t info_address =
448 rb.metadata.info_ring_ptr +
449 (metadata_info_offset * INFO_RECORD_SIZE);
450 DmesgInfoRecord info =
451 DmesgInfoRecord::read(proxy, info_address,
bo);
456 warn_once(
"Dmesg dump: metadata record (at 0x%08x) does not point "
457 "back to the correponding data record (at 0x%08x). Dmesg "
458 "buffer may be corrupted",
466 proxy.readBlob(rb.data.data_ring_ptr +
offset +
sizeof(guest_ptr_t),
467 message.data(), info.message_size);
471 os.write((
char *)message.data(), info.message_size);
476 return metadata.data_buffer.next_offset;
483 template <
typename ringbuffer_t>
485 dumpDmesgImpl(ThreadContext *tc, std::ostream &
os)
487 using atomic_var_t =
typename ringbuffer_t::atomic_var_t;
488 using guest_ptr_t =
typename ringbuffer_t::guest_ptr_t;
490 System *
system = tc->getSystemPtr();
491 const ByteOrder
bo =
system->getGuestByteOrder();
492 const auto &symtab =
system->workload->symtab(tc);
493 TranslatingPortProxy proxy(tc);
495 auto symtab_end_it = symtab.end();
498 ringbuffer_t dynamic_rb;
499 auto dynamic_rb_symbol = symtab.find(
"printk_rb_dynamic");
500 if (dynamic_rb_symbol != symtab_end_it) {
501 dynamic_rb = ringbuffer_t::read(proxy, dynamic_rb_symbol->address,
bo);
503 warn(
"Failed to find required dmesg symbols.\n");
508 ringbuffer_t static_rb;
509 auto static_rb_symbol = symtab.find(
"printk_rb_static");
510 if (static_rb_symbol != symtab_end_it) {
511 static_rb = ringbuffer_t::read(proxy, static_rb_symbol->address,
bo);
513 warn(
"Failed to find required dmesg symbols.\n");
520 guest_ptr_t active_ringbuffer_ptr = 0x0;
521 auto active_ringbuffer_ptr_symbol = symtab.find(
"prb");
522 if (active_ringbuffer_ptr_symbol != symtab_end_it) {
523 active_ringbuffer_ptr =
524 proxy.read<guest_ptr_t>(active_ringbuffer_ptr_symbol->address,
bo);
526 warn(
"Failed to find required dmesg symbols.\n");
530 if (active_ringbuffer_ptr == 0 ||
531 (active_ringbuffer_ptr != dynamic_rb_symbol->address &&
532 active_ringbuffer_ptr != static_rb_symbol->address)) {
533 warn(
"Kernel Dmesg ringbuffer appears to be invalid.\n");
538 (active_ringbuffer_ptr == dynamic_rb_symbol->address)
539 ? dynamic_rb : static_rb;
546 const guest_ptr_t first_metadata_offset = rb.mask_metadata_offset(
547 proxy.read<guest_ptr_t>(rb.data.data_ring_ptr,
bo));
548 const guest_ptr_t invalid_metadata_offset =
549 rb.template make_metadata_offset_mask<guest_ptr_t>() + 1;
565 guest_ptr_t
count = 0;
568 iterateDataRingbuffer<ringbuffer_t>(
578 iterateDataRingbuffer<ringbuffer_t>(
592 System *
system = tc->getSystemPtr();
596 dumpDmesgImpl<Linux64_Ringbuffer>(tc,
os);
598 dumpDmesgImpl<Linux32_Ringbuffer>(tc,
os);
610 const auto &symtab =
system->workload->symtab(tc);
612 auto end_it = symtab.end();
616 auto lb = symtab.find(
"__log_buf");
617 auto lb_len = symtab.find(
"log_buf_len");
618 auto first = symtab.find(
"log_first_idx");
619 auto next = symtab.find(
"log_next_idx");
621 if (lb != end_it && lb_len != end_it &&
622 first != end_it && next != end_it) {
629 auto printk_rb_static = symtab.find(
"printk_rb_static");
630 auto printk_rb_dynamic = symtab.find(
"printk_rb_dynamic");
632 if (printk_rb_dynamic != end_it || printk_rb_static != end_it) {
639 warn(
"Failed to find kernel dmesg symbols.\n");