mirror of
https://github.com/SerenityOS/serenity
synced 2024-09-06 17:06:31 +00:00
![Sönke Holz](/assets/img/avatar_default.png)
Instead, rewrite the region page fault handling code to not use PageFault::type() on RISC-V. I split Region::handle_fault into having a RISC-V-specific implementation, as I am not sure if I cover all page fault handling edge cases by solely relying on MM's own region metadata. We should probably also take the processor-provided page fault reason into account, if we decide to merge these two implementations in the future.
104 lines
3.2 KiB
C++
104 lines
3.2 KiB
C++
/*
|
|
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/Platform.h>
|
|
#include <AK/Types.h>
|
|
#include <Kernel/Arch/RegisterState.h>
|
|
#include <Kernel/Memory/VirtualAddress.h>
|
|
#include <Kernel/Security/ExecutionMode.h>
|
|
|
|
namespace Kernel {
|
|
|
|
// NOTE: These flags are x86_64 specific.
|
|
struct PageFaultFlags {
|
|
enum Flags {
|
|
NotPresent = 0x00,
|
|
ProtectionViolation = 0x01,
|
|
Read = 0x00,
|
|
Write = 0x02,
|
|
UserMode = 0x04,
|
|
SupervisorMode = 0x00,
|
|
ReservedBitViolation = 0x08,
|
|
InstructionFetch = 0x10,
|
|
};
|
|
};
|
|
|
|
class PageFault {
|
|
public:
|
|
PageFault(u16 code, VirtualAddress vaddr)
|
|
: m_vaddr(vaddr)
|
|
{
|
|
m_type = (Type)(code & PageFaultFlags::ProtectionViolation);
|
|
m_access = (Access)(code & PageFaultFlags::Write);
|
|
m_execution_mode = (code & PageFaultFlags::UserMode) != 0 ? ExecutionMode::User : ExecutionMode::Kernel;
|
|
m_is_reserved_bit_violation = (code & PageFaultFlags::ReservedBitViolation) != 0;
|
|
m_is_instruction_fetch = (code & PageFaultFlags::InstructionFetch) != 0;
|
|
}
|
|
|
|
explicit PageFault(VirtualAddress vaddr)
|
|
: m_vaddr(vaddr)
|
|
{
|
|
}
|
|
|
|
void handle(RegisterState& regs);
|
|
|
|
enum class Type {
|
|
PageNotPresent = PageFaultFlags::NotPresent,
|
|
ProtectionViolation = PageFaultFlags::ProtectionViolation,
|
|
Unknown,
|
|
};
|
|
|
|
enum class Access {
|
|
Read = PageFaultFlags::Read,
|
|
Write = PageFaultFlags::Write,
|
|
};
|
|
|
|
VirtualAddress vaddr() const { return m_vaddr; }
|
|
u16 code() const
|
|
{
|
|
u16 code = 0;
|
|
code |= (u16)m_type;
|
|
code |= (u16)m_access;
|
|
code |= m_execution_mode == ExecutionMode::User ? PageFaultFlags::UserMode : 0;
|
|
code |= m_is_reserved_bit_violation ? PageFaultFlags::ReservedBitViolation : 0;
|
|
code |= m_is_instruction_fetch ? PageFaultFlags::InstructionFetch : 0;
|
|
return code;
|
|
}
|
|
|
|
void set_type(Type type) { m_type = type; }
|
|
Type type() const { return m_type; }
|
|
|
|
void set_access(Access access) { m_access = access; }
|
|
Access access() const { return m_access; }
|
|
|
|
void set_mode(ExecutionMode execution_mode) { m_execution_mode = execution_mode; }
|
|
ExecutionMode mode() const { return m_execution_mode; }
|
|
|
|
void set_instruction_fetch(bool b) { m_is_instruction_fetch = b; }
|
|
|
|
bool is_not_present() const { return m_type == Type::PageNotPresent; }
|
|
bool is_protection_violation() const { return m_type == Type::ProtectionViolation; }
|
|
bool is_read() const { return m_access == Access::Read; }
|
|
bool is_write() const { return m_access == Access::Write; }
|
|
bool is_user() const { return m_execution_mode == ExecutionMode::User; }
|
|
bool is_kernel() const { return m_execution_mode == ExecutionMode::Kernel; }
|
|
bool is_reserved_bit_violation() const { return m_is_reserved_bit_violation; }
|
|
bool is_instruction_fetch() const { return m_is_instruction_fetch; }
|
|
|
|
private:
|
|
Type m_type = Type::Unknown;
|
|
Access m_access;
|
|
ExecutionMode m_execution_mode;
|
|
bool m_is_reserved_bit_violation { false };
|
|
bool m_is_instruction_fetch { false };
|
|
|
|
VirtualAddress m_vaddr;
|
|
};
|
|
|
|
}
|