Skip to content

Commit

Permalink
Use handlers to log unhandled accesses
Browse files Browse the repository at this point in the history
  • Loading branch information
ergo720 committed Feb 27, 2024
1 parent f713340 commit 5a7839a
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 30 deletions.
5 changes: 2 additions & 3 deletions lib86cpu/core/memory_management.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -576,8 +576,7 @@ T mem_read_helper(cpu_ctx_t *cpu_ctx, addr_t addr, uint32_t eip, uint8_t is_priv

default:
// because all other region types are cached, this should only happen with the unmapped region
LOG(log_level::warn, "Memory read to unmapped memory at address %#010x with size %d", addr, sizeof(T));
return std::numeric_limits<T>::max();
return log_unhandled_read<T, mem_type::unmapped>(addr);
}
}
}
Expand Down Expand Up @@ -659,7 +658,7 @@ void mem_write_helper(cpu_ctx_t *cpu_ctx, addr_t addr, T val, uint32_t eip, uint

default:
// because all other region types are cached, this should only happen with the unmapped region
LOG(log_level::warn, "Memory write to unmapped memory at address %#010x with size %d", addr, sizeof(T));
log_unhandled_write<T, mem_type::unmapped>(addr, val);
return;
}
}
Expand Down
10 changes: 4 additions & 6 deletions lib86cpu/core/memory_management.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,7 @@ T as_memory_dispatch_read(cpu_t *cpu, addr_t addr, const memory_region_t<addr_t>
break;

case mem_type::unmapped:
LOG(log_level::warn, "Memory read to unmapped memory at address %#010x with size %d", addr, sizeof(T));
return std::numeric_limits<T>::max();
return log_unhandled_read<T, mem_type::unmapped>(addr);

default:
LIB86CPU_ABORT();
Expand Down Expand Up @@ -152,7 +151,7 @@ void as_memory_dispatch_write(cpu_t *cpu, addr_t addr, T value, const memory_reg
break;

case mem_type::unmapped:
LOG(log_level::warn, "Memory write to unmapped memory at address %#010x with size %d", addr, sizeof(T));
log_unhandled_write<T, mem_type::unmapped>(addr, value);
break;

default:
Expand Down Expand Up @@ -180,8 +179,7 @@ T as_io_dispatch_read(cpu_t *cpu, port_t port, const memory_region_t<port_t> *re
}

case mem_type::unmapped:
LOG(log_level::warn, "Io read to unmapped memory at port %#06x with size %d", port, sizeof(T));
return std::numeric_limits<T>::max();
return log_unhandled_read<T, mem_type::unmapped>(port);

default:
LIB86CPU_ABORT();
Expand Down Expand Up @@ -209,7 +207,7 @@ void as_io_dispatch_write(cpu_t *cpu, port_t port, T value, const memory_region_
break;

case mem_type::unmapped:
LOG(log_level::warn, "Io write to unmapped memory at port %#06x with size %d", port, sizeof(T));
log_unhandled_write<T, mem_type::unmapped>(port, value);
return;

default:
Expand Down
35 changes: 14 additions & 21 deletions lib86cpu/interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,92 +17,85 @@
static uint8_t
default_mmio_read_handler8(addr_t addr, void *opaque)
{
LOG(log_level::warn, "Unhandled MMIO read at address %#010x with size 1", addr);
return std::numeric_limits<uint8_t>::max();
return log_unhandled_read<uint8_t, mem_type::mmio>(addr);
}

static uint16_t
default_mmio_read_handler16(addr_t addr, void *opaque)
{
LOG(log_level::warn, "Unhandled MMIO read at address %#010x with size 2", addr);
return std::numeric_limits<uint16_t>::max();
return log_unhandled_read<uint16_t, mem_type::mmio>(addr);
}

static uint32_t
default_mmio_read_handler32(addr_t addr, void *opaque)
{
LOG(log_level::warn, "Unhandled MMIO read at address %#010x with size 4", addr);
return std::numeric_limits<uint32_t>::max();
return log_unhandled_read<uint32_t, mem_type::mmio>(addr);
}

static uint64_t
default_mmio_read_handler64(addr_t addr, void *opaque)
{
LOG(log_level::warn, "Unhandled MMIO read at address %#010x with size 8", addr);
return std::numeric_limits<uint64_t>::max();
return log_unhandled_read<uint64_t, mem_type::mmio>(addr);
}

static void
default_mmio_write_handler8(addr_t addr, const uint8_t value, void *opaque)
{
LOG(log_level::warn, "Unhandled MMIO write at address %#010x with size 1", addr);
log_unhandled_write<uint8_t, mem_type::mmio>(addr, value);
}

static void
default_mmio_write_handler16(addr_t addr, const uint16_t value, void *opaque)
{
LOG(log_level::warn, "Unhandled MMIO write at address %#010x with size 2", addr);
log_unhandled_write<uint16_t, mem_type::mmio>(addr, value);
}

static void
default_mmio_write_handler32(addr_t addr, const uint32_t value, void *opaque)
{
LOG(log_level::warn, "Unhandled MMIO write at address %#010x with size 4", addr);
log_unhandled_write<uint32_t, mem_type::mmio>(addr, value);
}

static void
default_mmio_write_handler64(addr_t addr, const uint64_t value, void *opaque)
{
LOG(log_level::warn, "Unhandled MMIO write at address %#010x with size 8", addr);
log_unhandled_write<uint64_t, mem_type::mmio>(addr, value);
}

static uint8_t
default_pmio_read_handler8(addr_t addr, void *opaque)
{
LOG(log_level::warn, "Unhandled PMIO read at port %#06x with size 1", addr);
return std::numeric_limits<uint8_t>::max();
return log_unhandled_read<uint8_t, mem_type::pmio>(addr);
}

static uint16_t
default_pmio_read_handler16(addr_t addr, void *opaque)
{
LOG(log_level::warn, "Unhandled PMIO read at port %#06x with size 2", addr);
return std::numeric_limits<uint16_t>::max();
return log_unhandled_read<uint16_t, mem_type::pmio>(addr);
}

static uint32_t
default_pmio_read_handler32(addr_t addr, void *opaque)
{
LOG(log_level::warn, "Unhandled PMIO read at port %#06x with size 4", addr);
return std::numeric_limits<uint32_t>::max();
return log_unhandled_read<uint32_t, mem_type::pmio>(addr);
}

static void
default_pmio_write_handler8(addr_t addr, const uint8_t value, void *opaque)
{
LOG(log_level::warn, "Unhandled PMIO write at port %#06x with size 1", addr);
log_unhandled_write<uint8_t, mem_type::pmio>(addr, value);
}

static void
default_pmio_write_handler16(addr_t addr, const uint16_t value, void *opaque)
{
LOG(log_level::warn, "Unhandled PMIO write at port %#06x with size 2", addr);
log_unhandled_write<uint16_t, mem_type::pmio>(addr, value);
}

static void
default_pmio_write_handler32(addr_t addr, const uint32_t value, void *opaque)
{
LOG(log_level::warn, "Unhandled PMIO write at port %#06x with size 4", addr);
log_unhandled_write<uint32_t, mem_type::pmio>(addr, value);
}

// NOTE: lib86cpu runs entirely on the single thread that calls cpu_run, so calling the below functions from other threads is not safe. Only call them
Expand Down
81 changes: 81 additions & 0 deletions lib86cpu/support.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,84 @@ to_u64(auto val)

inline logfn_t logfn = &discard_log;
inline std::string last_error = "The operation completed successfully";

template<typename T>
consteval const char *get_prix_prefix()
{
if constexpr (sizeof(T) == 1) {
return PRIX8;
}
else if constexpr (sizeof(T) == 2) {
return PRIX16;
}
else if constexpr (sizeof(T) == 4) {
return PRIX32;
}
else if constexpr (sizeof(T) == 8) {
return PRIX64;
}
else {
return "";
}
}

template<typename T, mem_type type>
void log_unhandled_write(addr_t addr, T value)
{
if constexpr ((sizeof(T) == 10) || (sizeof(T) == 16)) {
constexpr size_t val_high_digits = sizeof(T) == 10 ? 4 : 16;
using type_high_digits = std::conditional_t<sizeof(T) == 10, uint16_t, uint64_t>;
if constexpr (type == mem_type::unmapped) {
LOG(log_level::warn, ("Memory write of value high=0x%0" + std::to_string(val_high_digits) + get_prix_prefix<type_high_digits>() + " and low=0x%016" PRIX64 " to \
unmapped memory at address 0x%08" PRIX32 " with size %" PRId32).c_str(),
value.high, value.low, addr, sizeof(T));
}
else {
LOG(log_level::warn, ("Unhandled mmio write of value high=0x%0" + std::to_string(val_high_digits) + get_prix_prefix<type_high_digits>() + " and low=0x%016" PRIX64 " at \
address 0x%08" PRIX32 " with size %" PRId32).c_str(),
value.high, value.low, addr, sizeof(T));
}
}
else {
constexpr size_t val_digits = sizeof(T) * 2;
if constexpr (type == mem_type::unmapped) {
LOG(log_level::warn, ("Memory write of value 0x%0" + std::to_string(val_digits) + get_prix_prefix<T>() + " to unmapped memory at address 0x%08" PRIX32 " with size %" PRId32).c_str(),
value, addr, sizeof(T));
}
else if constexpr (type == mem_type::mmio) {
LOG(log_level::warn, ("Unhandled mmio write of value 0x%0" + std::to_string(val_digits) + get_prix_prefix<T>() + " at address 0x%08" PRIX32 " with size %" PRId32).c_str(),
value, addr, sizeof(T));
}
else {
LOG(log_level::warn, ("Unhandled pmio write of value 0x%0" + std::to_string(val_digits) + get_prix_prefix<T>() + " at port 0x%04" PRIX16 " with size %" PRId32).c_str(),
value, addr, sizeof(T));
}
}
}

template<typename T, mem_type type>
T log_unhandled_read(addr_t addr)
{
if constexpr ((sizeof(T) == 10) || (sizeof(T) == 16)) {
if constexpr (type == mem_type::unmapped) {
LOG(log_level::warn, "Memory read to unmapped memory at address 0x%08" PRIX32 " with size %" PRId32, addr, sizeof(T));
}
else {
LOG(log_level::warn, "Unhandled mmio read at address 0x%08" PRIX32 " with size %" PRId32, addr, sizeof(T));
}
return T();
}
else {
constexpr size_t val_digits = sizeof(T) * 2 + 2;
if constexpr (type == mem_type::unmapped) {
LOG(log_level::warn, "Memory read to unmapped memory at address 0x%08" PRIX32 " with size %" PRId32, addr, sizeof(T));
}
else if constexpr (type == mem_type::mmio) {
LOG(log_level::warn, "Unhandled mmio read at address 0x%08" PRIX32 " with size %" PRId32, addr, sizeof(T));
}
else {
LOG(log_level::warn, "Unhandled pmio read at port 0x%04" PRIX16 " with size %" PRId32, addr, sizeof(T));
}
return 0;
}
}

0 comments on commit 5a7839a

Please sign in to comment.