Separate leaf page and directory pages USER flag

This is required for RISC-V. Privileged spec says:

> For non-leaf PTEs, the D, A, and U bits are reserved for future standard use.
> Until their use is defined by a standard extension, they must be cleared by software
> for forward compatibility.

QEMU fails address translation if it sees any of these flags set on non-leaf page entry.
This commit is contained in:
Andrey Turkin
2024-07-12 07:42:21 +03:00
parent bb27f57228
commit b7d3acf606
9 changed files with 13 additions and 10 deletions
+1 -1
View File
@@ -24,7 +24,7 @@ impl Arch for AArch64Arch {
const ENTRY_FLAG_PRESENT: usize = 1 << 0;
const ENTRY_FLAG_READONLY: usize = 1 << 7;
const ENTRY_FLAG_READWRITE: usize = 0;
const ENTRY_FLAG_USER: usize = 1 << 6;
const ENTRY_FLAG_PAGE_USER: usize = 1 << 6;
// This sets both userspace and privileged execute never
//TODO: Separate the two?
const ENTRY_FLAG_NO_EXEC: usize = 0b11 << 53;
+1 -1
View File
@@ -20,7 +20,7 @@ impl Arch for EmulateArch {
const ENTRY_FLAG_PRESENT: usize = X8664Arch::ENTRY_FLAG_PRESENT;
const ENTRY_FLAG_READONLY: usize = X8664Arch::ENTRY_FLAG_READONLY;
const ENTRY_FLAG_READWRITE: usize = X8664Arch::ENTRY_FLAG_READWRITE;
const ENTRY_FLAG_USER: usize = X8664Arch::ENTRY_FLAG_USER;
const ENTRY_FLAG_PAGE_USER: usize = X8664Arch::ENTRY_FLAG_PAGE_USER;
const ENTRY_FLAG_NO_EXEC: usize = X8664Arch::ENTRY_FLAG_NO_EXEC;
const ENTRY_FLAG_EXEC: usize = X8664Arch::ENTRY_FLAG_EXEC;
+2 -1
View File
@@ -36,7 +36,8 @@ pub trait Arch: Clone + Copy {
const ENTRY_FLAG_PRESENT: usize;
const ENTRY_FLAG_READONLY: usize;
const ENTRY_FLAG_READWRITE: usize;
const ENTRY_FLAG_USER: usize;
const ENTRY_FLAG_PAGE_USER: usize; // Leaf table user page flag
const ENTRY_FLAG_TABLE_USER: usize = Self::ENTRY_FLAG_PAGE_USER; // Directory user page table flag
const ENTRY_FLAG_NO_EXEC: usize;
const ENTRY_FLAG_EXEC: usize;
const ENTRY_FLAG_GLOBAL: usize;
+2 -1
View File
@@ -20,7 +20,8 @@ impl Arch for RiscV64Sv39Arch {
const ENTRY_FLAG_PRESENT: usize = 1 << 0;
const ENTRY_FLAG_READONLY: usize = 0;
const ENTRY_FLAG_READWRITE: usize = 1 << 2;
const ENTRY_FLAG_USER: usize = 1 << 4;
const ENTRY_FLAG_PAGE_USER: usize = 1 << 4;
const ENTRY_FLAG_TABLE_USER: usize = 0;
const ENTRY_FLAG_NO_EXEC: usize = 0;
const ENTRY_FLAG_EXEC: usize = 1 << 3;
const ENTRY_FLAG_GLOBAL: usize = 1 << 5;
+2 -1
View File
@@ -20,7 +20,8 @@ impl Arch for RiscV64Sv48Arch {
const ENTRY_FLAG_PRESENT: usize = 1 << 0;
const ENTRY_FLAG_READONLY: usize = 0;
const ENTRY_FLAG_READWRITE: usize = 1 << 2;
const ENTRY_FLAG_USER: usize = 1 << 4;
const ENTRY_FLAG_PAGE_USER: usize = 1 << 4;
const ENTRY_FLAG_TABLE_USER: usize = 0;
const ENTRY_FLAG_NO_EXEC: usize = 0;
const ENTRY_FLAG_EXEC: usize = 1 << 3;
const ENTRY_FLAG_GLOBAL: usize = 1 << 5;
+1 -1
View File
@@ -17,7 +17,7 @@ impl Arch for X86Arch {
const ENTRY_FLAG_PRESENT: usize = 1 << 0;
const ENTRY_FLAG_READONLY: usize = 0;
const ENTRY_FLAG_READWRITE: usize = 1 << 1;
const ENTRY_FLAG_USER: usize = 1 << 2;
const ENTRY_FLAG_PAGE_USER: usize = 1 << 2;
// Not used: const ENTRY_FLAG_HUGE: usize = 1 << 7;
const ENTRY_FLAG_GLOBAL: usize = 1 << 8;
const ENTRY_FLAG_NO_GLOBAL: usize = 0;
+1 -1
View File
@@ -16,7 +16,7 @@ impl Arch for X8664Arch {
const ENTRY_FLAG_PRESENT: usize = 1 << 0;
const ENTRY_FLAG_READONLY: usize = 0;
const ENTRY_FLAG_READWRITE: usize = 1 << 1;
const ENTRY_FLAG_USER: usize = 1 << 2;
const ENTRY_FLAG_PAGE_USER: usize = 1 << 2;
// Not used: const ENTRY_FLAG_HUGE: usize = 1 << 7;
const ENTRY_FLAG_GLOBAL: usize = 1 << 8;
const ENTRY_FLAG_NO_GLOBAL: usize = 0;
+2 -2
View File
@@ -72,12 +72,12 @@ impl<A: Arch> PageFlags<A> {
#[must_use]
#[inline(always)]
pub fn user(self, value: bool) -> Self {
self.custom_flag(A::ENTRY_FLAG_USER, value)
self.custom_flag(A::ENTRY_FLAG_PAGE_USER, value)
}
#[inline(always)]
pub fn has_user(&self) -> bool {
self.has_flag(A::ENTRY_FLAG_USER)
self.has_flag(A::ENTRY_FLAG_PAGE_USER)
}
#[must_use]
+1 -1
View File
@@ -123,7 +123,7 @@ impl<A: Arch, F: FrameAllocator> PageMapper<A, F> {
let flags = A::ENTRY_FLAG_READWRITE
| A::ENTRY_FLAG_DEFAULT_TABLE
| if virt.kind() == TableKind::User {
A::ENTRY_FLAG_USER
A::ENTRY_FLAG_TABLE_USER
} else {
0
};