diff options
author | Luke <luke.wilde@live.co.uk> | 2020-12-30 17:31:25 +0000 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-12-30 20:33:15 +0100 |
commit | 865f5ed4f6bb6f6a756946f6b3ef3f021ac9554c (patch) | |
tree | 730c3b41a5c81f78b37f2b793524d726e48f7bec /Kernel/Arch/i386/CPU.h | |
parent | d0142779730d118cd3982239407bedc6103e2baa (diff) | |
download | serenity-865f5ed4f6bb6f6a756946f6b3ef3f021ac9554c.zip |
Kernel: Prevent sign bit extension when creating a PDPTE
When doing the cast to u64 on the page directory physical address,
the sign bit was being extended. This only beomes an issue when
crossing the 2 GiB boundary. At >= 2 GiB, the physical address
has the sign bit set. For example, 0x80000000.
This set all the reserved bits in the PDPTE, causing a GPF
when loading the PDPT pointer into CR3. The reserved bits are
presumably there to stop you writing out a physical address that
the CPU physically cannot handle, as the size of the reserved bits
is determined by the physical address width of the CPU.
This fixes this by casting to FlatPtr instead. I believe the sign
extension only happens when casting to a bigger type. I'm also using
FlatPtr because it's a pointer we're writing into the PDPTE.
sizeof(FlatPtr) will always be the same size as sizeof(void*).
This also now asserts that the physical address in the PDPTE is
within the max physical address the CPU supports. This is better
than getting a GPF, because CPU::handle_crash tries to do the same
operation that caused the GPF in the first place. That would cause
an infinite loop of GPFs until the stack was exhausted, causing a
triple fault.
As far as I know and tested, I believe we can now use the full 32-bit
physical range without crashing.
Fixes #4584. See that issue for the full debugging story.
Diffstat (limited to 'Kernel/Arch/i386/CPU.h')
-rw-r--r-- | Kernel/Arch/i386/CPU.h | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/Kernel/Arch/i386/CPU.h b/Kernel/Arch/i386/CPU.h index c5883caa51..d9a36f5c32 100644 --- a/Kernel/Arch/i386/CPU.h +++ b/Kernel/Arch/i386/CPU.h @@ -721,6 +721,7 @@ class Processor { static FPUState s_clean_fpu_state; CPUFeature m_features; static volatile u32 g_total_processors; // atomic + u8 m_physical_address_bit_width; ProcessorInfo* m_info; MemoryManagerData* m_mm_data; @@ -812,6 +813,8 @@ public: return IterationDecision::Continue; } + ALWAYS_INLINE u8 physical_address_bit_width() const { return m_physical_address_bit_width; } + ALWAYS_INLINE ProcessorInfo& info() { return *m_info; } ALWAYS_INLINE static Processor& current() |