From 58c4f1585bc3056bb9713dd5cf37a01f2cb89fcb Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Thu, 17 Apr 2014 12:42:39 +0200 Subject: [PATCH] hw: fix bug in Kernel::update_*_region fix #1125 --- base-hw/src/core/kernel/kernel.cc | 2 +- base-hw/src/core/kernel/thread.cc | 27 +++++++++++++++++++++++++ base-hw/src/core/processor_driver/arm.h | 4 ++-- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/base-hw/src/core/kernel/kernel.cc b/base-hw/src/core/kernel/kernel.cc index bbb52eb4bf..d6926d865f 100644 --- a/base-hw/src/core/kernel/kernel.cc +++ b/base-hw/src/core/kernel/kernel.cc @@ -213,7 +213,7 @@ extern "C" void init_kernel_multiprocessor() /* synchronize data view of all processors */ Processor::invalidate_data_caches(); - Processor::invalidate_instruction_caches(); + Processor::invalidate_instr_caches(); Processor::invalidate_control_flow_predictions(); Processor::data_synchronization_barrier(); diff --git a/base-hw/src/core/kernel/thread.cc b/base-hw/src/core/kernel/thread.cc index e3935382d8..6bd89fa750 100644 --- a/base-hw/src/core/kernel/thread.cc +++ b/base-hw/src/core/kernel/thread.cc @@ -543,6 +543,19 @@ void Thread::_call_update_pd() void Thread::_call_update_data_region() { + /* + * FIXME: If the caller is not a core thread, the kernel operates in a + * different address space than the caller. Combined with the fact + * that at least ARMv7 doesn't provide cache operations by physical + * address, this prevents us from selectively maintaining caches. + * The future solution will be a kernel that is mapped to every + * address space so we can use virtual addresses of the caller. Up + * until then we apply operations to caches as a whole instead. + */ + if (!_core()) { + Processor::flush_data_caches(); + return; + } auto base = (addr_t)user_arg_1(); auto const size = (size_t)user_arg_2(); Processor::flush_data_caches_by_virt_region(base, size); @@ -551,6 +564,20 @@ void Thread::_call_update_data_region() void Thread::_call_update_instr_region() { + /* + * FIXME: If the caller is not a core thread, the kernel operates in a + * different address space than the caller. Combined with the fact + * that at least ARMv7 doesn't provide cache operations by physical + * address, this prevents us from selectively maintaining caches. + * The future solution will be a kernel that is mapped to every + * address space so we can use virtual addresses of the caller. Up + * until then we apply operations to caches as a whole instead. + */ + if (!_core()) { + Processor::flush_data_caches(); + Processor::invalidate_instr_caches(); + return; + } auto base = (addr_t)user_arg_1(); auto const size = (size_t)user_arg_2(); Processor::flush_data_caches_by_virt_region(base, size); diff --git a/base-hw/src/core/processor_driver/arm.h b/base-hw/src/core/processor_driver/arm.h index e27664222e..0d8bf092d5 100644 --- a/base-hw/src/core/processor_driver/arm.h +++ b/base-hw/src/core/processor_driver/arm.h @@ -625,7 +625,7 @@ namespace Arm * Invalidate all entries of all instruction caches */ __attribute__((always_inline)) - static void invalidate_instruction_caches() + static void invalidate_instr_caches() { asm volatile ("mcr p15, 0, %[rd], c7, c5, 0" :: [rd]"r"(0) : ); } @@ -646,7 +646,7 @@ namespace Arm static void flush_caches() { flush_data_caches(); - invalidate_instruction_caches(); + invalidate_instr_caches(); } /**