/*
 * Copyright (c) 2016, 2022 Arm Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "kern/linux/helpers.hh"

#include <type_traits>

#include "base/compiler.hh"
#include "base/loader/object_file.hh"
#include "cpu/thread_context.hh"
#include "mem/port_proxy.hh"
#include "mem/translating_port_proxy.hh"
#include "sim/byteswap.hh"
#include "sim/system.hh"

namespace gem5 {

namespace linux {

namespace {

namespace pre5_10 {

/** Dmesg entry for Linux versions pre-v5.10 */
struct GEM5_PACKED DmesgEntry
{
    uint64_t ts_nsec;
    uint16_t len;
    uint16_t text_len;
    uint16_t dict_len;
    uint8_t facility;
    uint8_t flags;
};

/** Dump a Linux Demsg entry, pre-v5.10. */
static int
dumpDmesgEntry(const uint8_t *base, const uint8_t *end,
               const ByteOrder bo,
               std::ostream &os)
{
    const size_t max_length = end - base;
    DmesgEntry de;

    if (max_length < sizeof(de)) {
        warn("Malformed dmesg entry\n");
        return -1;
    }

    memcpy(&de, base, sizeof(de));
    de.ts_nsec = gtoh(de.ts_nsec, bo);
    de.len = gtoh(de.len, bo);
    de.text_len = gtoh(de.text_len, bo);

    if (de.len < sizeof(de) ||
        max_length < de.len ||
        max_length < sizeof(DmesgEntry) + de.text_len) {

        warn("Malformed dmesg entry:\n");
        warn("\tMax length: %i\n", max_length);
        warn("\tde.len: %i\n", de.len);
        warn("\tde.text_len: %i\n", de.text_len);
        return -1;
    }

    ccprintf(os, "[%.6f] ", de.ts_nsec * 10e-9);
    os.write((char *)base + sizeof(de), de.text_len);
    os << std::endl;

    return de.len;
}

/** Dump the kernel Dmesg ringbuffer for Linux versions pre-v5.10 */
void
dumpDmesg(ThreadContext *tc, std::ostream &os)
{
    System *system = tc->getSystemPtr();
    const ByteOrder bo = system->getGuestByteOrder();
    const auto &symtab = system->workload->symtab(tc);
    TranslatingPortProxy proxy(tc);

    auto lb = symtab.find("__log_buf");
    auto lb_len = symtab.find("log_buf_len");
    auto first = symtab.find("log_first_idx");
    auto next = symtab.find("log_next_idx");

    auto end_it = symtab.end();

    if (lb == end_it || lb_len == end_it ||
            first == end_it || next == end_it) {
        warn("Failed to find kernel dmesg symbols.\n");
        return;
    }

    uint32_t log_buf_len = proxy.read<uint32_t>(lb_len->address, bo);
    uint32_t log_first_idx = proxy.read<uint32_t>(first->address, bo);
    uint32_t log_next_idx = proxy.read<uint32_t>(next->address, bo);

    if (log_first_idx >= log_buf_len || log_next_idx >= log_buf_len) {
        warn("dmesg pointers/length corrupted\n");
        return;
    }

    // Normalize and read the dmesg ring buffer
    std::vector<uint8_t> log_buf(log_buf_len);
    int length;
    if (log_first_idx < log_next_idx) {
        length = log_next_idx - log_first_idx;
        if (length < 0 || length > log_buf.size()) {
            warn("Unexpected dmesg buffer length\n");
            return;
        }
        proxy.readBlob(lb->address + log_first_idx, log_buf.data(), length);
    } else {
        const int length_2 = log_buf_len - log_first_idx;
        if (length_2 < 0 || length_2 + log_next_idx > log_buf.size()) {
            warn("Unexpected dmesg buffer length\n");
            return;
        }
        length = log_buf_len;
        proxy.readBlob(lb->address + log_first_idx, log_buf.data(), length_2);
        proxy.readBlob(lb->address, log_buf.data() + length_2, log_next_idx);
    }

    // Print dmesg buffer content
    const uint8_t *cur = log_buf.data(), *end = log_buf.data() + length;
    while (cur < end) {
        int ret = dumpDmesgEntry(cur, end, bo, os);
        if (ret < 0)
            return;
        cur += ret;
    }
}

} // namespace pre5_10

namespace post5_10 {

/** Metadata record for the Linux dmesg ringbuffer, post-v5.10.
 *
 *  Struct data members are compatible with the equivalent Linux data
 *  structure. Should be templated on atomic_var_t=int32_t for 32-bit
 *  Linux and atomic_var_t=int64_t for 64-bit Linux.
 *
 *  Also includes helper methods for reading the data structure into
 *  the gem5 world.
 *
 */
template<typename atomic_var_t>
struct GEM5_PACKED DmesgMetadataRecord
{
    using guest_ptr_t = typename std::make_unsigned_t<atomic_var_t>;

    // Struct data members
    atomic_var_t state;
    struct
    {
        guest_ptr_t curr_offset;
        guest_ptr_t next_offset;
    } data_buffer;

    /** Read a DmesgMetadataRecord from guest memory. */
    static DmesgMetadataRecord
    read(const TranslatingPortProxy & proxy,
         Addr address,
         guest_ptr_t data_offset_mask,
         const ByteOrder & bo)
    {
        DmesgMetadataRecord metadata;
        proxy.readBlob(address, &metadata, sizeof(metadata));

        // Convert members to host byte order
        metadata.state = gtoh(metadata.state, bo);
        metadata.data_buffer.curr_offset =
            gtoh(metadata.data_buffer.curr_offset, bo);
        metadata.data_buffer.next_offset =
            gtoh(metadata.data_buffer.next_offset, bo);

        // Mask the offsets
        metadata.data_buffer.curr_offset =
            metadata.data_buffer.curr_offset & data_offset_mask;
        metadata.data_buffer.next_offset =
            metadata.data_buffer.next_offset & data_offset_mask;

        return metadata;
    }
};

/** Info record for the Linux dmesg ringbuffer, post-v5.10.
 *
 *  Struct data members are compatible with the equivalent Linux data
 *  structure. Should be templated on atomic_var_t=int32_t for 32-bit
 *  Linux and atomic_var_t=int64_t for 64-bit Linux.
 *
 *  Also includes helper methods for reading the data structure into
 *  the gem5 world.
 *
 */
struct GEM5_PACKED DmesgInfoRecord
{
    // Struct data members
    uint64_t unused1;
    uint64_t ts_nsec;
    uint16_t message_size;
    uint8_t unused2;
    uint8_t unused3;
    uint32_t unused4;
    struct
    {
        char unused5_1[16];
        char unused5_2[48];
    } unused5;

    /** Read a DmesgInfoRecord from guest memory. */
    static DmesgInfoRecord
    read(const TranslatingPortProxy & proxy,
         Addr address,
         const ByteOrder & bo)
    {
        DmesgInfoRecord info;
        proxy.readBlob(address, &info, sizeof(info));

        // Convert members to host byte order
        info.ts_nsec = gtoh(info.ts_nsec, bo);
        info.message_size = gtoh(info.message_size, bo);

        return info;
    }
};

/** Top-level ringbuffer record for the Linux dmesg ringbuffer, post-v5.10.
 *
 *  Struct data members are compatible with the equivalent Linux data
 *  structure. Should be templated on AtomicVarType=int32_t for 32-bit
 *  Linux and AtomicVarType=int64_t for 64-bit Linux.
 *
 *  Also includes helper methods for reading the data structure into
 *  the gem5 world, and reading/generating appropriate masks.
 *
 */
template<typename AtomicVarType>
struct GEM5_PACKED DmesgRingbuffer
{
    static_assert(
        std::disjunction<
            std::is_same<AtomicVarType, int32_t>,
            std::is_same<AtomicVarType, int64_t>
        >::value,
        "AtomicVarType must be int32_t or int64_t");

    using atomic_var_t = AtomicVarType;
    using guest_ptr_t = typename std::make_unsigned_t<atomic_var_t>;
    using metadata_record_t = DmesgMetadataRecord<atomic_var_t>;

    // Struct data members
    struct
    {
        unsigned int mask_bits;
        guest_ptr_t metadata_ring_ptr;
        guest_ptr_t info_ring_ptr;
        atomic_var_t unused1;
        atomic_var_t unused2;
    } metadata;
    struct
    {
        unsigned int mask_bits;
        guest_ptr_t data_ring_ptr;
        atomic_var_t head_offset;
        atomic_var_t tail_offset;
    } data;
    atomic_var_t fail;

    /** Read a DmesgRingbuffer from guest memory. */
    static DmesgRingbuffer
    read(const TranslatingPortProxy & proxy,
         const Addr address,
         const ByteOrder & bo)
    {
        DmesgRingbuffer rb;
        proxy.readBlob(address, &rb, sizeof(rb));

        // Convert members to host byte order
        rb.metadata.mask_bits =
            gtoh(rb.metadata.mask_bits, bo);
        rb.metadata.metadata_ring_ptr =
            gtoh(rb.metadata.metadata_ring_ptr, bo);
        rb.metadata.info_ring_ptr =
            gtoh(rb.metadata.info_ring_ptr, bo);

        rb.data.mask_bits = gtoh(rb.data.mask_bits, bo);
        rb.data.data_ring_ptr = gtoh(rb.data.data_ring_ptr, bo);
        rb.data.head_offset = gtoh(rb.data.head_offset, bo);
        rb.data.tail_offset = gtoh(rb.data.tail_offset, bo);

        // Mask offsets to the correct number of bits
        rb.data.head_offset =
            rb.mask_data_offset(rb.data.head_offset);
        rb.data.tail_offset =
            rb.mask_data_offset(rb.data.tail_offset);

        return rb;
    }

    /** Make a mask for the bottom mask_bits of an `atomic_var_t`, then
     *  cast it to the required `as_type`.
     */
    template<typename as_type>
    static as_type
    make_offset_mask_as(const unsigned int mask_bits)
    {
        using unsigned_atomic_var_t =
            typename std::make_unsigned<atomic_var_t>::type;
        const atomic_var_t offset_mask =
            static_cast<atomic_var_t>(
                (static_cast<unsigned_atomic_var_t>(1) << mask_bits) - 1);
        return static_cast<as_type>(offset_mask);
    }

    /** Make a mask for an offset into the metadata or info ringbuffers. */
    template<typename metadata_offset_t>
    metadata_offset_t
    make_metadata_offset_mask() const
    {
        return make_offset_mask_as<metadata_offset_t>(metadata.mask_bits);
    }

    /** Make a mask for an offset into the data ringbuffer. */
    template<typename data_offset_t>
    data_offset_t
    make_data_offset_mask() const
    {
        return make_offset_mask_as<data_offset_t>(data.mask_bits);
    }

    /** Apply the correct masking to an offset into the metadata or info
        ringbuffers. */
    template<typename metadata_offset_t>
    metadata_offset_t
    mask_metadata_offset(const metadata_offset_t metadata_offset) const
    {
        const atomic_var_t MASK =
            make_metadata_offset_mask<metadata_offset_t>();
        return metadata_offset & MASK;
    }

    /** Apply the correct masking to an offset into the data ringbuffer. */
    template<typename data_offset_t>
    data_offset_t
    mask_data_offset(const data_offset_t data_offset) const
    {
        const atomic_var_t MASK = make_data_offset_mask<data_offset_t>();
        return data_offset & MASK;
    }
};

// Aliases for the two types of Ringbuffer that could be used.
using Linux64_Ringbuffer = DmesgRingbuffer<int64_t>;
using Linux32_Ringbuffer = DmesgRingbuffer<int32_t>;

/** Print the record at the specified offset into the data ringbuffer,
 *  and return the offset of the next entry in the data ringbuffer,
 *  post-v5.10.
 *
 * The `first_metadata_offset` argument is used to check for
 * wraparound. If the final data record of the ringbuffer is not large
 * enough to hold the message, the record will be left empty and
 * repeated at the beginning of the data ringbuffer. In this case the
 * metadata offset at the beginning of the last record will match the
 * metadata offset of the first record of the ringbuffer, and the last
 * record of the ring buffer should be skipped.
 *
 */
template <typename ringbuffer_t,
          typename atomic_var_t=typename ringbuffer_t::atomic_var_t,
          typename guest_ptr_t=typename ringbuffer_t::guest_ptr_t>
atomic_var_t
iterateDataRingbuffer(std::ostream & os,
                      const TranslatingPortProxy & proxy,
                      const ringbuffer_t & rb,
                      const atomic_var_t offset,
                      const guest_ptr_t first_metadata_offset,
                      const ByteOrder bo)
{
    using metadata_record_t = typename ringbuffer_t::metadata_record_t;

    constexpr size_t METADATA_RECORD_SIZE =
        sizeof(typename ringbuffer_t::metadata_record_t);
    constexpr size_t INFO_RECORD_SIZE = sizeof(DmesgInfoRecord);

    const guest_ptr_t DATA_OFFSET_MASK =
        rb.template make_data_offset_mask<guest_ptr_t>();

    // Read the offset of the metadata record from the beginning of
    // the data record.
    guest_ptr_t metadata_info_offset = rb.mask_metadata_offset(
        proxy.read<guest_ptr_t>(rb.data.data_ring_ptr + offset, bo));

    // If the metadata offset of the block is the same as the metadata
    // offset of the first block of the data ringbuffer, then this
    // data block is unsused (padding), and the iteration can wrap
    // around to the beginning of the data ringbuffer (offset == 0).
    if (metadata_info_offset == first_metadata_offset) {
        return static_cast<atomic_var_t>(0);
    }

    // Read the metadata record from the metadata ringbuffer.
    guest_ptr_t metadata_address =
        rb.metadata.metadata_ring_ptr +
        (metadata_info_offset * METADATA_RECORD_SIZE);
    metadata_record_t metadata =
        metadata_record_t::read(proxy, metadata_address, DATA_OFFSET_MASK, bo);

    // Read the info record from the info ringbuffer.
    guest_ptr_t info_address =
        rb.metadata.info_ring_ptr +
        (metadata_info_offset * INFO_RECORD_SIZE);
    DmesgInfoRecord info =
        DmesgInfoRecord::read(proxy, info_address, bo);

    // The metadata record should point back to the same data record
    // in the data ringbuffer.
    if (metadata.data_buffer.curr_offset != offset) {
        warn_once("Dmesg dump: metadata record (at 0x%08x) does not point "
                  "back to the correponding data record (at 0x%08x). Dmesg "
                  "buffer may be corrupted",
             metadata.data_buffer.next_offset, offset);
    }

    // Read the message from the data record. This is placed
    // immediately after the `guest_ptr_t` sized metadata offset at
    // the beginning of the record.
    std::vector<uint8_t> message(info.message_size);
    proxy.readBlob(rb.data.data_ring_ptr + offset + sizeof(guest_ptr_t),
                   message.data(), info.message_size);

    // Print the record
    ccprintf(os, "[%.6f] ", info.ts_nsec * 10e-9);
    os.write((char *)message.data(), info.message_size);
    os << "\n";

    // Return the offset of the next data record in the data
    // ringbuffer.
    return metadata.data_buffer.next_offset;
}

/** Dump the kernel Dmesg ringbuffer for Linux versions post-v5.10.

    Templated implementation specific to 32-bit or 64-bit Linux.
*/
template <typename ringbuffer_t>
void
dumpDmesgImpl(ThreadContext *tc, std::ostream &os)
{
    using atomic_var_t = typename ringbuffer_t::atomic_var_t;
    using guest_ptr_t = typename ringbuffer_t::guest_ptr_t;

    System *system = tc->getSystemPtr();
    const ByteOrder bo = system->getGuestByteOrder();
    const auto &symtab = system->workload->symtab(tc);
    TranslatingPortProxy proxy(tc);

    auto symtab_end_it = symtab.end();

    // Read the dynamic ringbuffer structure from guest memory, if present.
    ringbuffer_t dynamic_rb;
    auto dynamic_rb_symbol = symtab.find("printk_rb_dynamic");
    if (dynamic_rb_symbol != symtab_end_it) {
        dynamic_rb = ringbuffer_t::read(proxy, dynamic_rb_symbol->address, bo);
    } else {
        warn("Failed to find required dmesg symbols.\n");
        return;
    }

    // Read the static ringbuffer structure from guest memory, if present.
    ringbuffer_t static_rb;
    auto static_rb_symbol = symtab.find("printk_rb_static");
    if (static_rb_symbol != symtab_end_it) {
        static_rb = ringbuffer_t::read(proxy, static_rb_symbol->address, bo);
    } else {
        warn("Failed to find required dmesg symbols.\n");
        return;
    }

    // Read the pointer to the active ringbuffer structure from guest
    // memory. This should point to one of the two ringbuffer
    // structures already read from guest memory.
    guest_ptr_t active_ringbuffer_ptr = 0x0;
    auto active_ringbuffer_ptr_symbol = symtab.find("prb");
    if (active_ringbuffer_ptr_symbol != symtab_end_it) {
        active_ringbuffer_ptr =
            proxy.read<guest_ptr_t>(active_ringbuffer_ptr_symbol->address, bo);
    } else {
        warn("Failed to find required dmesg symbols.\n");
        return;
    }

    if (active_ringbuffer_ptr == 0 ||
        (active_ringbuffer_ptr != dynamic_rb_symbol->address &&
         active_ringbuffer_ptr != static_rb_symbol->address)) {
        warn("Kernel Dmesg ringbuffer appears to be invalid.\n");
        return;
    }

    ringbuffer_t & rb =
        (active_ringbuffer_ptr == dynamic_rb_symbol->address)
        ? dynamic_rb : static_rb;

    atomic_var_t head_offset = rb.data.head_offset;
    atomic_var_t tail_offset = rb.data.tail_offset;

    // Get some marker offsets into the data ringbuffer which will be
    // used as end values to control the iteration.
    const guest_ptr_t first_metadata_offset = rb.mask_metadata_offset(
        proxy.read<guest_ptr_t>(rb.data.data_ring_ptr, bo));
    const guest_ptr_t invalid_metadata_offset =
        rb.template make_metadata_offset_mask<guest_ptr_t>() + 1;

    // Iterate over the active ringbuffer, printing each message to
    // `os`. Use the maximum number of possible info records plus one
    // (invalid_metadata_offset) as an escape counter to make sure the
    // process doesn't iterate infinitely if the kernel data
    // structures have been corrupted.

    // When head is behind tail, read to the end of the ringbuffer,
    // then loop back to the begining.
    //
    // iterateDataRingbuffer will return offset at the beginning of
    // the data ringbuffer when it loops back.
    //
    // `first_metadata_offset` is used to detect cases where the final data
    // block is unused.
    guest_ptr_t count = 0;
    while (head_offset < tail_offset && count < invalid_metadata_offset) {
        tail_offset =
            iterateDataRingbuffer<ringbuffer_t>(
                os, proxy, rb, tail_offset, first_metadata_offset, bo);
        ++count;
    }

    // When tail is behind head, read forwards from the tail offset to
    // the head offset.
    count = 0;
    while (tail_offset < head_offset && count < invalid_metadata_offset) {
        tail_offset =
            iterateDataRingbuffer<ringbuffer_t>(
                os, proxy, rb, tail_offset, invalid_metadata_offset, bo);
        ++count;
    }
}

/** Dump the kernel Dmesg ringbuffer for Linux versions post-v5.10.
 *
 *  Delegates to an architecture specific template funtion instance.
 *
 */
void
dumpDmesg(ThreadContext *tc, std::ostream &os)
{
    System *system = tc->getSystemPtr();
    const bool os_is_64_bit = loader::archIs64Bit(system->workload->getArch());

    if (os_is_64_bit) {
        dumpDmesgImpl<Linux64_Ringbuffer>(tc, os);
    } else {
        dumpDmesgImpl<Linux32_Ringbuffer>(tc, os);
    }
}

} // namespace post5_10

} // anonymous namespace

void
dumpDmesg(ThreadContext *tc, std::ostream &os)
{
    System *system = tc->getSystemPtr();
    const auto &symtab = system->workload->symtab(tc);

    auto end_it = symtab.end();

    // Search for symbols associated with the Kernel Dmesg ringbuffer,
    // pre-v5.10.
    auto lb = symtab.find("__log_buf");
    auto lb_len = symtab.find("log_buf_len");
    auto first = symtab.find("log_first_idx");
    auto next = symtab.find("log_next_idx");

    if (lb != end_it && lb_len != end_it &&
            first != end_it && next != end_it) {
        linux::pre5_10::dumpDmesg(tc, os);
        return;
    }

    // Search for symbols associated with the Kernel Dmesg ringbuffer,
    // post-v5.10.
    auto printk_rb_static = symtab.find("printk_rb_static");
    auto printk_rb_dynamic = symtab.find("printk_rb_dynamic");

    if (printk_rb_dynamic != end_it || printk_rb_static != end_it) {
        linux::post5_10::dumpDmesg(tc, os);
        return;
    }

    // Required symbols relating to the Kernel Dmesg buffer were not
    // found for any supported version of Linux.
    warn("Failed to find kernel dmesg symbols.\n");
}

} // namespace linux

} // namespace gem5
