hw: cache maintainance on mapping removal too

Older ARM processors like ARMv6, or Cortex A8 need to write back changes
of the page-tables to physical ram because the MMU does not use the cache.
This naturally needs to be done not only when adding a mapping,
but on removal too.

Fix #3715
This commit is contained in:
Stefan Kalkowski 2020-04-06 20:44:29 +02:00 committed by Christian Helmuth
parent 03c3040a1d
commit ff378a8c5b
7 changed files with 17 additions and 12 deletions

View File

@ -21,6 +21,6 @@ constexpr unsigned Hw::Page_table::Descriptor_base::_device_tex() {
constexpr bool Hw::Page_table::Descriptor_base::_smp() { return false; }
void Hw::Page_table::_translation_added(unsigned long, unsigned long) { }
void Hw::Page_table::_table_changed(unsigned long, unsigned long) { }
#endif /* _SRC__BOOTSTRAP__SPEC__ARM__CORTEX_A8_PAGE_TABLE_H_ */

View File

@ -21,6 +21,6 @@ constexpr unsigned Hw::Page_table::Descriptor_base::_device_tex() {
constexpr bool Hw::Page_table::Descriptor_base::_smp() { return true; }
void Hw::Page_table::_translation_added(unsigned long, unsigned long) { }
void Hw::Page_table::_table_changed(unsigned long, unsigned long) { }
#endif /* _SRC__BOOTSTRAP__SPEC__ARM__CORTEX_A9_PAGE_TABLE_H_ */

View File

@ -28,7 +28,6 @@ constexpr unsigned Hw::Page_table::Descriptor_base::_device_tex() {
constexpr bool Hw::Page_table::Descriptor_base::_smp() { return false; }
void Hw::Page_table::_translation_added(unsigned long, unsigned long) {
Board::Cpu::clean_invalidate_data_cache(); }
void Hw::Page_table::_table_changed(unsigned long, unsigned long) { }
#endif /* _SRC__BOOTSTRAP__SPEC__RPI__BOARD_H_ */

View File

@ -24,7 +24,7 @@ constexpr unsigned Hw::Page_table::Descriptor_base::_device_tex() {
constexpr bool Hw::Page_table::Descriptor_base::_smp() { return false; }
void Hw::Page_table::_translation_added(unsigned long addr, unsigned long size)
void Hw::Page_table::_table_changed(unsigned long addr, unsigned long size)
{
Genode::Arm_cpu::clean_data_cache_by_virt_region(addr, size);
}

View File

@ -25,7 +25,7 @@ constexpr unsigned Hw::Page_table::Descriptor_base::_device_tex() {
constexpr bool Hw::Page_table::Descriptor_base::_smp() { return false; }
void Hw::Page_table::_translation_added(unsigned long addr, unsigned long size)
void Hw::Page_table::_table_changed(unsigned long addr, unsigned long size)
{
/*
* The Cortex-A8 CPU can't use the L1 cache on page-table

View File

@ -22,6 +22,6 @@ constexpr unsigned Hw::Page_table::Descriptor_base::_device_tex() {
constexpr bool Hw::Page_table::Descriptor_base::_smp() { return true; }
void Hw::Page_table::_translation_added(unsigned long, unsigned long) { }
void Hw::Page_table::_table_changed(unsigned long, unsigned long) { }
#endif /* _CORE__SPEC__CORTEX_A9__TRANSLATION_TABLE_H_ */

View File

@ -416,7 +416,7 @@ class Hw::Page_table
enum { MAX_INDEX = sizeof(_entries) / sizeof(_entries[0]) - 1 };
static inline void _translation_added(addr_t, size_t);
static inline void _table_changed(addr_t, size_t);
/**
* Try to get entry index in 'i' for virtual offset 'vo!
@ -457,7 +457,7 @@ class Hw::Page_table
/* create and link page table */
Pt & pt = alloc.construct<Pt>();
_entries[i] = Ptd::create(alloc.phys_addr(pt));
_translation_added((addr_t)&_entries[i], sizeof(Ptd));
_table_changed((addr_t)&_entries[i], sizeof(Ptd));
}
[[fallthrough]];
@ -465,7 +465,7 @@ class Hw::Page_table
{
Pt & pt = alloc.virt_addr<Pt>(Ptd::Pa::masked(_entries[i]));
pt.insert_translation(vo - Section::Pa::masked(vo), pa, size, flags);
_translation_added((addr_t)&pt, sizeof(Page_table_level_2));
_table_changed((addr_t)&pt, sizeof(Page_table_level_2));
break;
}
@ -532,7 +532,7 @@ class Hw::Page_table
_entries[i] = e;
/* some CPUs need to act on changed translations */
_translation_added((addr_t)&_entries[i], sizeof(Section));
_table_changed((addr_t)&_entries[i], sizeof(Section));
break;
}
@ -580,6 +580,7 @@ class Hw::Page_table
addr_t const pt_vo = vo - Section::Pa::masked(vo);
pt.remove_translation(pt_vo, Genode::min(size, end-vo));
_table_changed((addr_t)&pt, sizeof(Page_table_level_2));
if (pt.empty()) {
Descriptor::invalidate(_entries[i]);
@ -588,7 +589,12 @@ class Hw::Page_table
break;
}
default: Descriptor::invalidate(_entries[i]); }
default:
{
Descriptor::invalidate(_entries[i]);
_table_changed((addr_t)&_entries[i], sizeof(Section));
}
}
/* check whether we wrap */
if (end < vo) return;