hw: do not change x86 paging attributes on fly
Instead of changing the attributes (e.g., Xd bit) of the top-level page-tables, set them to allow everything. Only leafs of the paging hierarchy are set according to the paging attributes given by core. Otherwise, top-level page- table attributes are changed during lifetime, which requires a TLB flush operation (not intended in the semantic of the kernel/core). This led to problems when using the non-executable features introduced by issue #1723 in the recent past.
This commit is contained in:
parent
c365918b82
commit
d164cbac8c
|
@ -20,8 +20,6 @@
|
||||||
#include <hw/spec/x86_64/cpu.h>
|
#include <hw/spec/x86_64/cpu.h>
|
||||||
#include <hw/spec/x86_64/x86_64.h>
|
#include <hw/spec/x86_64/x86_64.h>
|
||||||
|
|
||||||
void Hw::Pml4_table::_invalidate_range(addr_t vo, size_t size) {}
|
|
||||||
|
|
||||||
namespace Bootstrap {
|
namespace Bootstrap {
|
||||||
struct Pic {};
|
struct Pic {};
|
||||||
using Cpu = Hw::X86_64_cpu;
|
using Cpu = Hw::X86_64_cpu;
|
||||||
|
|
|
@ -76,10 +76,10 @@ void Genode::Cpu::mmu_fault(Context & regs, Kernel::Thread_fault & fault)
|
||||||
};
|
};
|
||||||
|
|
||||||
auto fault_lambda = [] (addr_t err) {
|
auto fault_lambda = [] (addr_t err) {
|
||||||
if ((err & ERR_P) && (err & ERR_W)) return Fault::WRITE;
|
if (!(err & ERR_P)) return Fault::PAGE_MISSING;
|
||||||
if ((err & ERR_P) && (err & ERR_I)) return Fault::EXEC;
|
if (err & ERR_W) return Fault::WRITE;
|
||||||
if (err & ERR_P) return Fault::UNKNOWN;
|
if (err & ERR_I) return Fault::EXEC;
|
||||||
else return Fault::PAGE_MISSING;
|
else return Fault::UNKNOWN;
|
||||||
};
|
};
|
||||||
|
|
||||||
fault.addr = Genode::Cpu::Cr2::read();
|
fault.addr = Genode::Cpu::Cr2::read();
|
||||||
|
|
|
@ -25,7 +25,9 @@ void Kernel::Thread::_call_update_data_region() { }
|
||||||
void Kernel::Thread::_call_update_instr_region() { }
|
void Kernel::Thread::_call_update_instr_region() { }
|
||||||
|
|
||||||
|
|
||||||
void Kernel::Thread::_call_update_pd() { }
|
void Kernel::Thread::_call_update_pd() {
|
||||||
|
Genode::Cpu::Cr3::write(Genode::Cpu::Cr3::read());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
extern void * __tss_client_context_ptr;
|
extern void * __tss_client_context_ptr;
|
||||||
|
|
|
@ -15,13 +15,5 @@
|
||||||
#define _CORE__SPEC__X86_64__TRANSLATION_TABLE_H_
|
#define _CORE__SPEC__X86_64__TRANSLATION_TABLE_H_
|
||||||
|
|
||||||
#include <hw/spec/x86_64/page_table.h>
|
#include <hw/spec/x86_64/page_table.h>
|
||||||
#include <cpu.h>
|
|
||||||
|
|
||||||
void Hw::Pml4_table::_invalidate_range(addr_t vo, size_t size)
|
|
||||||
{
|
|
||||||
/* FIXME: do not necessarily flush the whole TLB */
|
|
||||||
Genode::Cpu::Cr3::write(Genode::Cpu::Cr3::read());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _CORE__SPEC__X86_64__TRANSLATION_TABLE_H_ */
|
#endif /* _CORE__SPEC__X86_64__TRANSLATION_TABLE_H_ */
|
||||||
|
|
|
@ -100,17 +100,6 @@ namespace Hw
|
||||||
D::clear(value);
|
D::clear(value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Merge access rights of descriptor with given flags.
|
|
||||||
*/
|
|
||||||
static void merge_access_rights(access_t &desc,
|
|
||||||
Page_flags const &flags)
|
|
||||||
{
|
|
||||||
Rw::set(desc, Rw::get(desc) | flags.writeable);
|
|
||||||
Us::set(desc, Us::get(desc) | !flags.privileged);
|
|
||||||
Xd::set(desc, Xd::get(desc) & !flags.executable);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,10 +330,11 @@ class Hw::Page_directory
|
||||||
struct Mt : Base::template Bitset_2<Base::Pwt,
|
struct Mt : Base::template Bitset_2<Base::Pwt,
|
||||||
Base::Pcd> { };
|
Base::Pcd> { };
|
||||||
|
|
||||||
static typename Base::access_t create(Page_flags const &flags,
|
static typename Base::access_t create(addr_t const pa)
|
||||||
addr_t const pa)
|
|
||||||
{
|
{
|
||||||
/* XXX: Set memory type depending on active PAT */
|
/* XXX: Set memory type depending on active PAT */
|
||||||
|
static Page_flags flags { RW, EXEC, USER, NO_GLOBAL,
|
||||||
|
RAM, Genode::CACHED };
|
||||||
return Base::create(flags) | Pa::masked(pa);
|
return Base::create(flags) | Pa::masked(pa);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -388,12 +378,10 @@ class Hw::Page_directory
|
||||||
|
|
||||||
/* create and link next level table */
|
/* create and link next level table */
|
||||||
ENTRY & table = alloc.construct<ENTRY>();
|
ENTRY & table = alloc.construct<ENTRY>();
|
||||||
desc = (access_t) Td::create(flags, alloc.phys_addr(table));
|
desc = (access_t) Td::create(alloc.phys_addr(table));
|
||||||
|
|
||||||
} else if (Descriptor::maps_page(desc)) {
|
} else if (Descriptor::maps_page(desc)) {
|
||||||
throw Double_insertion();
|
throw Double_insertion();
|
||||||
} else {
|
|
||||||
Descriptor::merge_access_rights(desc, flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* insert translation */
|
/* insert translation */
|
||||||
|
@ -528,9 +516,11 @@ class Hw::Pml4_table
|
||||||
struct Pa : Bitfield<12, SIZE_LOG2> { }; /* physical address */
|
struct Pa : Bitfield<12, SIZE_LOG2> { }; /* physical address */
|
||||||
struct Mt : Genode::Bitset_2<Pwt, Pcd> { }; /* memory type */
|
struct Mt : Genode::Bitset_2<Pwt, Pcd> { }; /* memory type */
|
||||||
|
|
||||||
static access_t create(Page_flags const &flags, addr_t const pa)
|
static access_t create(addr_t const pa)
|
||||||
{
|
{
|
||||||
/* XXX: Set memory type depending on active PAT */
|
/* XXX: Set memory type depending on active PAT */
|
||||||
|
static Page_flags flags { RW, EXEC, USER, NO_GLOBAL,
|
||||||
|
RAM, Genode::CACHED };
|
||||||
return Common_descriptor::create(flags) | Pa::masked(pa);
|
return Common_descriptor::create(flags) | Pa::masked(pa);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -556,9 +546,7 @@ class Hw::Pml4_table
|
||||||
if (!Descriptor::present(desc)) {
|
if (!Descriptor::present(desc)) {
|
||||||
/* create and link next level table */
|
/* create and link next level table */
|
||||||
ENTRY & table = alloc.construct<ENTRY>();
|
ENTRY & table = alloc.construct<ENTRY>();
|
||||||
desc = Descriptor::create(flags, alloc.phys_addr(table));
|
desc = Descriptor::create(alloc.phys_addr(table));
|
||||||
} else {
|
|
||||||
Descriptor::merge_access_rights(desc, flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* insert translation */
|
/* insert translation */
|
||||||
|
@ -622,8 +610,6 @@ class Hw::Pml4_table
|
||||||
/ (1UL << alignment);
|
/ (1UL << alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void _invalidate_range(addr_t vo, size_t size);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static constexpr size_t MIN_PAGE_SIZE_LOG2 = SIZE_LOG2_4KB;
|
static constexpr size_t MIN_PAGE_SIZE_LOG2 = SIZE_LOG2_4KB;
|
||||||
|
@ -680,7 +666,6 @@ class Hw::Pml4_table
|
||||||
void remove_translation(addr_t vo, size_t size, Allocator & alloc)
|
void remove_translation(addr_t vo, size_t size, Allocator & alloc)
|
||||||
{
|
{
|
||||||
_range_op(vo, 0, size, Remove_func(alloc));
|
_range_op(vo, 0, size, Remove_func(alloc));
|
||||||
_invalidate_range(vo, size);
|
|
||||||
}
|
}
|
||||||
} __attribute__((aligned(1 << ALIGNM_LOG2)));
|
} __attribute__((aligned(1 << ALIGNM_LOG2)));
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue