diff options
author | Hendiadyoin1 <leon2002.la@gmail.com> | 2021-04-10 23:29:32 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-04-23 22:50:53 +0200 |
commit | f1957bb86bd0535025bb9757b0b9f18a638e8d38 (patch) | |
tree | 5b91acaa1985dd4174e5409c2b4ad0dae99294d1 /Userland/DevTools | |
parent | a99812633bc0791c4f7bda99fc24240f9062ad55 (diff) | |
download | serenity-f1957bb86bd0535025bb9757b0b9f18a638e8d38.zip |
UE+LibX86: Support bigger reads and writes
Diffstat (limited to 'Userland/DevTools')
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/MmapRegion.cpp | 72 | ||||
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/MmapRegion.h | 4 | ||||
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/Region.h | 5 | ||||
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/SimpleRegion.cpp | 24 | ||||
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/SimpleRegion.h | 4 | ||||
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/SoftCPU.cpp | 37 | ||||
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/SoftCPU.h | 18 | ||||
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/SoftMMU.cpp | 72 | ||||
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/SoftMMU.h | 4 | ||||
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/ValueWithShadow.h | 38 |
10 files changed, 275 insertions, 3 deletions
diff --git a/Userland/DevTools/UserspaceEmulator/MmapRegion.cpp b/Userland/DevTools/UserspaceEmulator/MmapRegion.cpp index c7f4b3f8ad..a7056e47f0 100644 --- a/Userland/DevTools/UserspaceEmulator/MmapRegion.cpp +++ b/Userland/DevTools/UserspaceEmulator/MmapRegion.cpp @@ -129,6 +129,40 @@ ValueWithShadow<u64> MmapRegion::read64(u32 offset) return { *reinterpret_cast<const u64*>(m_data + offset), *reinterpret_cast<const u64*>(m_shadow_data + offset) }; } +ValueWithShadow<u128> MmapRegion::read128(u32 offset) +{ + if (!is_readable()) { + reportln("128-bit read from unreadable MmapRegion @ {:p}", base() + offset); + emulator().dump_backtrace(); + TODO(); + } + + if (is_malloc_block()) { + if (auto* tracer = emulator().malloc_tracer()) + tracer->audit_read(*this, base() + offset, 16); + } + + VERIFY(offset + 15 < size()); + return { *reinterpret_cast<const u128*>(m_data + offset), *reinterpret_cast<const u128*>(m_shadow_data + offset) }; +} + +ValueWithShadow<u256> MmapRegion::read256(u32 offset) +{ + if (!is_readable()) { + reportln("256-bit read from unreadable MmapRegion @ {:p}", base() + offset); + emulator().dump_backtrace(); + TODO(); + } + + if (is_malloc_block()) { + if (auto* tracer = emulator().malloc_tracer()) + tracer->audit_read(*this, base() + offset, 32); + } + + VERIFY(offset + 31 < size()); + return { *reinterpret_cast<const u256*>(m_data + offset), *reinterpret_cast<const u256*>(m_shadow_data + offset) }; +} + void MmapRegion::write8(u32 offset, ValueWithShadow<u8> value) { if (!is_writable()) { @@ -203,6 +237,44 @@ void MmapRegion::write64(u32 offset, ValueWithShadow<u64> value) *reinterpret_cast<u64*>(m_shadow_data + offset) = value.shadow(); } +void MmapRegion::write128(u32 offset, ValueWithShadow<u128> value) +{ + if (!is_writable()) { + reportln("128-bit write from unwritable MmapRegion @ {:p}", base() + offset); + emulator().dump_backtrace(); + TODO(); + } + + if (is_malloc_block()) { + if (auto* tracer = emulator().malloc_tracer()) + tracer->audit_write(*this, base() + offset, 16); + } + + VERIFY(offset + 15 < size()); + VERIFY(m_data != m_shadow_data); + *reinterpret_cast<u128*>(m_data + offset) = value.value(); + *reinterpret_cast<u128*>(m_shadow_data + offset) = value.shadow(); +} + +void MmapRegion::write256(u32 offset, ValueWithShadow<u256> value) +{ + if (!is_writable()) { + reportln("256-bit write from unwritable MmapRegion @ {:p}", base() + offset); + emulator().dump_backtrace(); + TODO(); + } + + if (is_malloc_block()) { + if (auto* tracer = emulator().malloc_tracer()) + tracer->audit_write(*this, base() + offset, 32); + } + + VERIFY(offset + 31 < size()); + VERIFY(m_data != m_shadow_data); + *reinterpret_cast<u256*>(m_data + offset) = value.value(); + *reinterpret_cast<u256*>(m_shadow_data + offset) = value.shadow(); +} + NonnullOwnPtr<MmapRegion> MmapRegion::split_at(VirtualAddress offset) { VERIFY(!m_malloc); diff --git a/Userland/DevTools/UserspaceEmulator/MmapRegion.h b/Userland/DevTools/UserspaceEmulator/MmapRegion.h index 366bd5b978..c535c80aea 100644 --- a/Userland/DevTools/UserspaceEmulator/MmapRegion.h +++ b/Userland/DevTools/UserspaceEmulator/MmapRegion.h @@ -24,11 +24,15 @@ public: virtual ValueWithShadow<u16> read16(u32 offset) override; virtual ValueWithShadow<u32> read32(u32 offset) override; virtual ValueWithShadow<u64> read64(u32 offset) override; + virtual ValueWithShadow<u128> read128(u32 offset) override; + virtual ValueWithShadow<u256> read256(u32 offset) override; virtual void write8(u32 offset, ValueWithShadow<u8>) override; virtual void write16(u32 offset, ValueWithShadow<u16>) override; virtual void write32(u32 offset, ValueWithShadow<u32>) override; virtual void write64(u32 offset, ValueWithShadow<u64>) override; + virtual void write128(u32 offset, ValueWithShadow<u128>) override; + virtual void write256(u32 offset, ValueWithShadow<u256>) override; virtual u8* data() override { return m_data; } virtual u8* shadow_data() override { return m_shadow_data; } diff --git a/Userland/DevTools/UserspaceEmulator/Region.h b/Userland/DevTools/UserspaceEmulator/Region.h index f33df7cca1..a027ccc553 100644 --- a/Userland/DevTools/UserspaceEmulator/Region.h +++ b/Userland/DevTools/UserspaceEmulator/Region.h @@ -10,6 +10,7 @@ #include "ValueWithShadow.h" #include <AK/TypeCasts.h> #include <AK/Types.h> +#include <LibX86/Types.h> namespace UserspaceEmulator { @@ -31,11 +32,15 @@ public: virtual void write16(u32 offset, ValueWithShadow<u16>) = 0; virtual void write32(u32 offset, ValueWithShadow<u32>) = 0; virtual void write64(u32 offset, ValueWithShadow<u64>) = 0; + virtual void write128(u32 offset, ValueWithShadow<u128>) = 0; + virtual void write256(u32 offset, ValueWithShadow<u256>) = 0; virtual ValueWithShadow<u8> read8(u32 offset) = 0; virtual ValueWithShadow<u16> read16(u32 offset) = 0; virtual ValueWithShadow<u32> read32(u32 offset) = 0; virtual ValueWithShadow<u64> read64(u32 offset) = 0; + virtual ValueWithShadow<u128> read128(u32 offset) = 0; + virtual ValueWithShadow<u256> read256(u32 offset) = 0; virtual u8* cacheable_ptr([[maybe_unused]] u32 offset) { return nullptr; } diff --git a/Userland/DevTools/UserspaceEmulator/SimpleRegion.cpp b/Userland/DevTools/UserspaceEmulator/SimpleRegion.cpp index b4a9415437..99f035c8c6 100644 --- a/Userland/DevTools/UserspaceEmulator/SimpleRegion.cpp +++ b/Userland/DevTools/UserspaceEmulator/SimpleRegion.cpp @@ -47,6 +47,18 @@ ValueWithShadow<u64> SimpleRegion::read64(u32 offset) return { *reinterpret_cast<const u64*>(m_data + offset), *reinterpret_cast<const u64*>(m_shadow_data + offset) }; } +ValueWithShadow<u128> SimpleRegion::read128(u32 offset) +{ + VERIFY(offset + 15 < size()); + return { *reinterpret_cast<const u128*>(m_data + offset), *reinterpret_cast<const u128*>(m_shadow_data + offset) }; +} + +ValueWithShadow<u256> SimpleRegion::read256(u32 offset) +{ + VERIFY(offset + 31 < size()); + return { *reinterpret_cast<const u256*>(m_data + offset), *reinterpret_cast<const u256*>(m_shadow_data + offset) }; +} + void SimpleRegion::write8(u32 offset, ValueWithShadow<u8> value) { VERIFY(offset < size()); @@ -74,6 +86,18 @@ void SimpleRegion::write64(u32 offset, ValueWithShadow<u64> value) *reinterpret_cast<u64*>(m_data + offset) = value.value(); *reinterpret_cast<u64*>(m_shadow_data + offset) = value.shadow(); } +void SimpleRegion::write128(u32 offset, ValueWithShadow<u128> value) +{ + VERIFY(offset + 15 < size()); + *reinterpret_cast<u128*>(m_data + offset) = value.value(); + *reinterpret_cast<u128*>(m_shadow_data + offset) = value.shadow(); +} +void SimpleRegion::write256(u32 offset, ValueWithShadow<u256> value) +{ + VERIFY(offset + 31 < size()); + *reinterpret_cast<u256*>(m_data + offset) = value.value(); + *reinterpret_cast<u256*>(m_shadow_data + offset) = value.shadow(); +} u8* SimpleRegion::cacheable_ptr(u32 offset) { diff --git a/Userland/DevTools/UserspaceEmulator/SimpleRegion.h b/Userland/DevTools/UserspaceEmulator/SimpleRegion.h index adad49dc65..4847d12bd4 100644 --- a/Userland/DevTools/UserspaceEmulator/SimpleRegion.h +++ b/Userland/DevTools/UserspaceEmulator/SimpleRegion.h @@ -19,11 +19,15 @@ public: virtual ValueWithShadow<u16> read16(u32 offset) override; virtual ValueWithShadow<u32> read32(u32 offset) override; virtual ValueWithShadow<u64> read64(u32 offset) override; + virtual ValueWithShadow<u128> read128(u32 offset) override; + virtual ValueWithShadow<u256> read256(u32 offset) override; virtual void write8(u32 offset, ValueWithShadow<u8>) override; virtual void write16(u32 offset, ValueWithShadow<u16>) override; virtual void write32(u32 offset, ValueWithShadow<u32>) override; virtual void write64(u32 offset, ValueWithShadow<u64>) override; + virtual void write128(u32 offset, ValueWithShadow<u128>) override; + virtual void write256(u32 offset, ValueWithShadow<u256>) override; virtual u8* data() override { return m_data; } virtual u8* shadow_data() override { return m_shadow_data; } diff --git a/Userland/DevTools/UserspaceEmulator/SoftCPU.cpp b/Userland/DevTools/UserspaceEmulator/SoftCPU.cpp index e88d3e6576..c41b6eaf40 100644 --- a/Userland/DevTools/UserspaceEmulator/SoftCPU.cpp +++ b/Userland/DevTools/UserspaceEmulator/SoftCPU.cpp @@ -133,6 +133,25 @@ ValueWithShadow<u64> SoftCPU::read_memory64(X86::LogicalAddress address) return value; } +ValueWithShadow<u128> SoftCPU::read_memory128(X86::LogicalAddress address) +{ + VERIFY(address.selector() == 0x1b || address.selector() == 0x23 || address.selector() == 0x2b); + auto value = m_emulator.mmu().read128(address); +#if MEMORY_DEBUG + outln("\033[36;1mread_memory128: @{:04x}:{:08x} -> {:032x} ({:032x})\033[0m", address.selector(), address.offset(), value, value.shadow()); +#endif + return value; +} +ValueWithShadow<u256> SoftCPU::read_memory256(X86::LogicalAddress address) +{ + VERIFY(address.selector() == 0x1b || address.selector() == 0x23 || address.selector() == 0x2b); + auto value = m_emulator.mmu().read256(address); +#if MEMORY_DEBUG + outln("\033[36;1mread_memory256: @{:04x}:{:08x} -> {:064x} ({:064x})\033[0m", address.selector(), address.offset(), value, value.shadow()); +#endif + return value; +} + void SoftCPU::write_memory8(X86::LogicalAddress address, ValueWithShadow<u8> value) { VERIFY(address.selector() == 0x23 || address.selector() == 0x2b); @@ -161,6 +180,24 @@ void SoftCPU::write_memory64(X86::LogicalAddress address, ValueWithShadow<u64> v m_emulator.mmu().write64(address, value); } +void SoftCPU::write_memory128(X86::LogicalAddress address, ValueWithShadow<u128> value) +{ + VERIFY(address.selector() == 0x23 || address.selector() == 0x2b); +#if MEMORY_DEBUG + outln("\033[36;1mwrite_memory128: @{:04x}:{:08x} <- {:032x} ({:032x})\033[0m", address.selector(), address.offset(), value, value.shadow()); +#endif + m_emulator.mmu().write128(address, value); +} + +void SoftCPU::write_memory256(X86::LogicalAddress address, ValueWithShadow<u256> value) +{ + VERIFY(address.selector() == 0x23 || address.selector() == 0x2b); +#if MEMORY_DEBUG + outln("\033[36;1mwrite_memory256: @{:04x}:{:08x} <- {:064x} ({:064x})\033[0m", address.selector(), address.offset(), value, value.shadow()); +#endif + m_emulator.mmu().write256(address, value); +} + void SoftCPU::push_string(const StringView& string) { size_t space_to_allocate = round_up_to_power_of_two(string.length() + 1, 16); diff --git a/Userland/DevTools/UserspaceEmulator/SoftCPU.h b/Userland/DevTools/UserspaceEmulator/SoftCPU.h index 7842b667df..1b6647861d 100644 --- a/Userland/DevTools/UserspaceEmulator/SoftCPU.h +++ b/Userland/DevTools/UserspaceEmulator/SoftCPU.h @@ -39,6 +39,8 @@ public: using ValueWithShadowType16 = ValueWithShadow<u16>; using ValueWithShadowType32 = ValueWithShadow<u32>; using ValueWithShadowType64 = ValueWithShadow<u64>; + using ValueWithShadowType128 = ValueWithShadow<u128>; + using ValueWithShadowType256 = ValueWithShadow<u256>; explicit SoftCPU(Emulator&); void dump() const; @@ -347,6 +349,8 @@ public: ValueWithShadow<u16> read_memory16(X86::LogicalAddress); ValueWithShadow<u32> read_memory32(X86::LogicalAddress); ValueWithShadow<u64> read_memory64(X86::LogicalAddress); + ValueWithShadow<u128> read_memory128(X86::LogicalAddress); + ValueWithShadow<u256> read_memory256(X86::LogicalAddress); template<typename T> ValueWithShadow<T> read_memory(X86::LogicalAddress address) @@ -357,12 +361,20 @@ public: return read_memory16(address); if constexpr (sizeof(T) == 4) return read_memory32(address); + if constexpr (sizeof(T) == 8) + return read_memory64(address); + if constexpr (sizeof(T) == 16) + return read_memory128(address); + if constexpr (sizeof(T) == 32) + return read_memory256(address); } void write_memory8(X86::LogicalAddress, ValueWithShadow<u8>); void write_memory16(X86::LogicalAddress, ValueWithShadow<u16>); void write_memory32(X86::LogicalAddress, ValueWithShadow<u32>); void write_memory64(X86::LogicalAddress, ValueWithShadow<u64>); + void write_memory128(X86::LogicalAddress, ValueWithShadow<u128>); + void write_memory256(X86::LogicalAddress, ValueWithShadow<u256>); template<typename T> void write_memory(X86::LogicalAddress address, ValueWithShadow<T> data) @@ -373,6 +385,12 @@ public: return write_memory16(address, data); if constexpr (sizeof(T) == 4) return write_memory32(address, data); + if constexpr (sizeof(T) == 8) + return write_memory64(address, data); + if constexpr (sizeof(T) == 16) + return write_memory128(address, data); + if constexpr (sizeof(T) == 32) + return write_memory256(address, data); } bool evaluate_condition(u8 condition) const diff --git a/Userland/DevTools/UserspaceEmulator/SoftMMU.cpp b/Userland/DevTools/UserspaceEmulator/SoftMMU.cpp index 430e3b93ee..67bc3a6e8f 100644 --- a/Userland/DevTools/UserspaceEmulator/SoftMMU.cpp +++ b/Userland/DevTools/UserspaceEmulator/SoftMMU.cpp @@ -163,6 +163,42 @@ ValueWithShadow<u64> SoftMMU::read64(X86::LogicalAddress address) return region->read64(address.offset() - region->base()); } +ValueWithShadow<u128> SoftMMU::read128(X86::LogicalAddress address) +{ + auto* region = find_region(address); + if (!region) { + reportln("SoftMMU::read128: No region for @ {:p}", address.offset()); + m_emulator.dump_backtrace(); + TODO(); + } + + if (!region->is_readable()) { + reportln("SoftMMU::read128: Non-readable region @ {:p}", address.offset()); + m_emulator.dump_backtrace(); + TODO(); + } + + return region->read128(address.offset() - region->base()); +} + +ValueWithShadow<u256> SoftMMU::read256(X86::LogicalAddress address) +{ + auto* region = find_region(address); + if (!region) { + reportln("SoftMMU::read256: No region for @ {:p}", address.offset()); + m_emulator.dump_backtrace(); + TODO(); + } + + if (!region->is_readable()) { + reportln("SoftMMU::read256: Non-readable region @ {:p}", address.offset()); + m_emulator.dump_backtrace(); + TODO(); + } + + return region->read256(address.offset() - region->base()); +} + void SoftMMU::write8(X86::LogicalAddress address, ValueWithShadow<u8> value) { auto* region = find_region(address); @@ -234,6 +270,42 @@ void SoftMMU::write64(X86::LogicalAddress address, ValueWithShadow<u64> value) region->write64(address.offset() - region->base(), value); } +void SoftMMU::write128(X86::LogicalAddress address, ValueWithShadow<u128> value) +{ + auto* region = find_region(address); + if (!region) { + reportln("SoftMMU::write128: No region for @ {:p}", address.offset()); + m_emulator.dump_backtrace(); + TODO(); + } + + if (!region->is_writable()) { + reportln("SoftMMU::write128: Non-writable region @ {:p}", address.offset()); + m_emulator.dump_backtrace(); + TODO(); + } + + region->write128(address.offset() - region->base(), value); +} + +void SoftMMU::write256(X86::LogicalAddress address, ValueWithShadow<u256> value) +{ + auto* region = find_region(address); + if (!region) { + reportln("SoftMMU::write256: No region for @ {:p}", address.offset()); + m_emulator.dump_backtrace(); + TODO(); + } + + if (!region->is_writable()) { + reportln("SoftMMU::write256: Non-writable region @ {:p}", address.offset()); + m_emulator.dump_backtrace(); + TODO(); + } + + region->write256(address.offset() - region->base(), value); +} + void SoftMMU::copy_to_vm(FlatPtr destination, const void* source, size_t size) { // FIXME: We should have a way to preserve the shadow data here as well. diff --git a/Userland/DevTools/UserspaceEmulator/SoftMMU.h b/Userland/DevTools/UserspaceEmulator/SoftMMU.h index 41ab0bafa5..8767fe2d87 100644 --- a/Userland/DevTools/UserspaceEmulator/SoftMMU.h +++ b/Userland/DevTools/UserspaceEmulator/SoftMMU.h @@ -26,11 +26,15 @@ public: ValueWithShadow<u16> read16(X86::LogicalAddress); ValueWithShadow<u32> read32(X86::LogicalAddress); ValueWithShadow<u64> read64(X86::LogicalAddress); + ValueWithShadow<u128> read128(X86::LogicalAddress); + ValueWithShadow<u256> read256(X86::LogicalAddress); void write8(X86::LogicalAddress, ValueWithShadow<u8>); void write16(X86::LogicalAddress, ValueWithShadow<u16>); void write32(X86::LogicalAddress, ValueWithShadow<u32>); void write64(X86::LogicalAddress, ValueWithShadow<u64>); + void write128(X86::LogicalAddress, ValueWithShadow<u128>); + void write256(X86::LogicalAddress, ValueWithShadow<u256>); ALWAYS_INLINE Region* find_region(X86::LogicalAddress address) { diff --git a/Userland/DevTools/UserspaceEmulator/ValueWithShadow.h b/Userland/DevTools/UserspaceEmulator/ValueWithShadow.h index 53fb760187..e1b65387ee 100644 --- a/Userland/DevTools/UserspaceEmulator/ValueWithShadow.h +++ b/Userland/DevTools/UserspaceEmulator/ValueWithShadow.h @@ -4,13 +4,19 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#pragma once + #include <AK/Format.h> #include <AK/Platform.h> - -#pragma once +#include <LibX86/Types.h> +#include <string.h> namespace UserspaceEmulator { +constexpr u64 _inititalized_64 = 0x01010101'01010101LLU; +constexpr u128 _initialized_128 = u128(_inititalized_64, _inititalized_64); +constexpr u256 _initialized_256 = u256(_initialized_128, _initialized_128); + template<typename T> class ValueAndShadowReference; @@ -32,6 +38,12 @@ public: bool is_uninitialized() const { + if constexpr (sizeof(T) == 32) + return (m_shadow & _initialized_256) != _initialized_256; + if constexpr (sizeof(T) == 16) + return (m_shadow & _initialized_128) != _initialized_128; + if constexpr (sizeof(T) == 8) + return (m_shadow & _inititalized_64) != _inititalized_64; if constexpr (sizeof(T) == 4) return (m_shadow & 0x01010101) != 0x01010101; if constexpr (sizeof(T) == 2) @@ -42,6 +54,12 @@ public: void set_initialized() { + if constexpr (sizeof(T) == 32) + m_shadow = _initialized_256; + if constexpr (sizeof(T) == 16) + m_shadow = _initialized_128; + if constexpr (sizeof(T) == 8) + m_shadow = _inititalized_64; if constexpr (sizeof(T) == 4) m_shadow = 0x01010101; if constexpr (sizeof(T) == 2) @@ -68,6 +86,12 @@ public: bool is_uninitialized() const { + if constexpr (sizeof(T) == 32) + return (m_shadow & _initialized_256) != _initialized_256; + if constexpr (sizeof(T) == 16) + return (m_shadow & _initialized_128) != _initialized_128; + if constexpr (sizeof(T) == 8) + return (m_shadow & _inititalized_64) != _inititalized_64; if constexpr (sizeof(T) == 4) return (m_shadow & 0x01010101) != 0x01010101; if constexpr (sizeof(T) == 2) @@ -92,8 +116,12 @@ private: template<typename T> ALWAYS_INLINE ValueWithShadow<T> shadow_wrap_as_initialized(T value) { + if constexpr (sizeof(T) == 32) + return { value, _initialized_256 }; + if constexpr (sizeof(T) == 16) + return { value, _initialized_128 }; if constexpr (sizeof(T) == 8) - return { value, 0x01010101'01010101LLU }; + return { value, _inititalized_64 }; if constexpr (sizeof(T) == 4) return { value, 0x01010101 }; if constexpr (sizeof(T) == 2) @@ -149,3 +177,7 @@ struct AK::Formatter<UserspaceEmulator::ValueWithShadow<T>> : AK::Formatter<T> { return Formatter<T>::format(builder, value.value()); } }; + +#undef INITIALIZED_64 +#undef INITIALIZED_128 +#undef INITIALIZED_256 |