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:
Stefan Kalkowski 2017-11-08 15:17:15 +01:00 committed by Christian Helmuth
parent c365918b82
commit d164cbac8c
5 changed files with 15 additions and 38 deletions

View File

@ -20,8 +20,6 @@
#include <hw/spec/x86_64/cpu.h>
#include <hw/spec/x86_64/x86_64.h>
void Hw::Pml4_table::_invalidate_range(addr_t vo, size_t size) {}
namespace Bootstrap {
struct Pic {};
using Cpu = Hw::X86_64_cpu;

View File

@ -76,10 +76,10 @@ void Genode::Cpu::mmu_fault(Context & regs, Kernel::Thread_fault & fault)
};
auto fault_lambda = [] (addr_t err) {
if ((err & ERR_P) && (err & ERR_W)) return Fault::WRITE;
if ((err & ERR_P) && (err & ERR_I)) return Fault::EXEC;
if (err & ERR_P) return Fault::UNKNOWN;
else return Fault::PAGE_MISSING;
if (!(err & ERR_P)) return Fault::PAGE_MISSING;
if (err & ERR_W) return Fault::WRITE;
if (err & ERR_I) return Fault::EXEC;
else return Fault::UNKNOWN;
};
fault.addr = Genode::Cpu::Cr2::read();

View File

@ -25,7 +25,9 @@ void Kernel::Thread::_call_update_data_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;

View File

@ -15,13 +15,5 @@
#define _CORE__SPEC__X86_64__TRANSLATION_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_ */

View File

@ -100,17 +100,6 @@ namespace Hw
D::clear(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,
Base::Pcd> { };
static typename Base::access_t create(Page_flags const &flags,
addr_t const pa)
static typename Base::access_t create(addr_t const pa)
{
/* 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);
}
};
@ -388,12 +378,10 @@ class Hw::Page_directory
/* create and link next level table */
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)) {
throw Double_insertion();
} else {
Descriptor::merge_access_rights(desc, flags);
}
/* insert translation */
@ -528,9 +516,11 @@ class Hw::Pml4_table
struct Pa : Bitfield<12, SIZE_LOG2> { }; /* physical address */
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 */
static Page_flags flags { RW, EXEC, USER, NO_GLOBAL,
RAM, Genode::CACHED };
return Common_descriptor::create(flags) | Pa::masked(pa);
}
};
@ -556,9 +546,7 @@ class Hw::Pml4_table
if (!Descriptor::present(desc)) {
/* create and link next level table */
ENTRY & table = alloc.construct<ENTRY>();
desc = Descriptor::create(flags, alloc.phys_addr(table));
} else {
Descriptor::merge_access_rights(desc, flags);
desc = Descriptor::create(alloc.phys_addr(table));
}
/* insert translation */
@ -622,8 +610,6 @@ class Hw::Pml4_table
/ (1UL << alignment);
}
inline void _invalidate_range(addr_t vo, size_t size);
public:
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)
{
_range_op(vo, 0, size, Remove_func(alloc));
_invalidate_range(vo, size);
}
} __attribute__((aligned(1 << ALIGNM_LOG2)));