From ff378a8c5bda3f6d7585ca25a446d726a0ad82c0 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Mon, 6 Apr 2020 20:44:29 +0200 Subject: [PATCH] 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 --- .../bootstrap/spec/arm/cortex_a8_page_table.h | 2 +- .../bootstrap/spec/arm/cortex_a9_page_table.h | 2 +- repos/base-hw/src/bootstrap/spec/rpi/board.h | 3 +-- .../src/core/spec/arm_v6/translation_table.h | 2 +- .../src/core/spec/cortex_a8/translation_table.h | 2 +- .../src/core/spec/cortex_a9/translation_table.h | 2 +- .../base-hw/src/include/hw/spec/arm/page_table.h | 16 +++++++++++----- 7 files changed, 17 insertions(+), 12 deletions(-) diff --git a/repos/base-hw/src/bootstrap/spec/arm/cortex_a8_page_table.h b/repos/base-hw/src/bootstrap/spec/arm/cortex_a8_page_table.h index fb6f9c5fe..2b9faf99e 100644 --- a/repos/base-hw/src/bootstrap/spec/arm/cortex_a8_page_table.h +++ b/repos/base-hw/src/bootstrap/spec/arm/cortex_a8_page_table.h @@ -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_ */ diff --git a/repos/base-hw/src/bootstrap/spec/arm/cortex_a9_page_table.h b/repos/base-hw/src/bootstrap/spec/arm/cortex_a9_page_table.h index 3ec85c660..78ae9461e 100644 --- a/repos/base-hw/src/bootstrap/spec/arm/cortex_a9_page_table.h +++ b/repos/base-hw/src/bootstrap/spec/arm/cortex_a9_page_table.h @@ -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_ */ diff --git a/repos/base-hw/src/bootstrap/spec/rpi/board.h b/repos/base-hw/src/bootstrap/spec/rpi/board.h index f81f52192..002147d4b 100644 --- a/repos/base-hw/src/bootstrap/spec/rpi/board.h +++ b/repos/base-hw/src/bootstrap/spec/rpi/board.h @@ -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_ */ diff --git a/repos/base-hw/src/core/spec/arm_v6/translation_table.h b/repos/base-hw/src/core/spec/arm_v6/translation_table.h index bb283c584..300fd0657 100644 --- a/repos/base-hw/src/core/spec/arm_v6/translation_table.h +++ b/repos/base-hw/src/core/spec/arm_v6/translation_table.h @@ -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); } diff --git a/repos/base-hw/src/core/spec/cortex_a8/translation_table.h b/repos/base-hw/src/core/spec/cortex_a8/translation_table.h index 2bb87e730..16ccccca5 100644 --- a/repos/base-hw/src/core/spec/cortex_a8/translation_table.h +++ b/repos/base-hw/src/core/spec/cortex_a8/translation_table.h @@ -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 diff --git a/repos/base-hw/src/core/spec/cortex_a9/translation_table.h b/repos/base-hw/src/core/spec/cortex_a9/translation_table.h index c29bdfdaf..89d97b834 100644 --- a/repos/base-hw/src/core/spec/cortex_a9/translation_table.h +++ b/repos/base-hw/src/core/spec/cortex_a9/translation_table.h @@ -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_ */ diff --git a/repos/base-hw/src/include/hw/spec/arm/page_table.h b/repos/base-hw/src/include/hw/spec/arm/page_table.h index 9ed857977..bec2d84b2 100644 --- a/repos/base-hw/src/include/hw/spec/arm/page_table.h +++ b/repos/base-hw/src/include/hw/spec/arm/page_table.h @@ -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(); _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(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;