1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
/*
* 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/ExecutionMode.h>
#include <Kernel/VirtualAddress.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,
};
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;
Access m_access;
ExecutionMode m_execution_mode;
bool m_is_reserved_bit_violation { false };
bool m_is_instruction_fetch { false };
VirtualAddress m_vaddr;
};
}
|