base-hw: flush cached zeroes in 'clear_ds(...)'

Ref #706
This commit is contained in:
Martin Stein
2013-04-29 18:58:11 +02:00
committed by Norman Feske
parent a0d182e25a
commit 2e7802b799
10 changed files with 82 additions and 5 deletions

View File

@ -18,6 +18,10 @@
#include <util/register.h>
#include <cpu/cpu_state.h>
/* local includes */
#include <board.h>
#include <util.h>
namespace Arm
{
using namespace Genode;
@ -637,6 +641,22 @@ namespace Arm
asm volatile ("mcr p15, 0, %[rd], c8, c7, 0" :: [rd]"r"(0) : );
flush_caches();
}
/*
* Clean every data-cache entry within a region via MVA
*/
static void flush_data_cache_by_virt_region(addr_t base, size_t const size)
{
enum {
CACHE_LINE_SIZE = 1 << Board::CACHE_LINE_SIZE_LOG2,
CACHE_LINE_ALIGNM_MASK = ~(CACHE_LINE_SIZE - 1),
};
addr_t const top = base + size;
base = base & CACHE_LINE_ALIGNM_MASK;
for (; base < top; base += CACHE_LINE_SIZE)
asm volatile ("mcr p15, 0, %[base], c7, c10, 1\n" /* DCCMVAC */
:: [base] "r" (base) : );
}
};
}

View File

@ -1092,6 +1092,19 @@ namespace Kernel
}
/**
* Do specific syscall for 'user', for details see 'syscall.h'
*/
void do_update_region(Thread * const user)
{
assert(user->pd_id() == core_id());
/* FIXME we don't handle instruction caches by now */
Cpu::flush_data_cache_by_virt_region((addr_t)user->user_arg_1(),
(size_t)user->user_arg_2());
}
/**
* Do specific syscall for 'user', for details see 'syscall.h'
*/
@ -1372,6 +1385,7 @@ namespace Kernel
/* 29 */ do_ack_signal,
/* 30 */ do_kill_signal_context,
/* 31 */ do_pause_vm,
/* 32 */ do_update_region,
};
enum { MAX_SYSCALL = sizeof(handle_sysc)/sizeof(handle_sysc[0]) - 1 };

View File

@ -13,6 +13,7 @@
/* Genode includes */
#include <base/printf.h>
#include <kernel/syscalls.h>
/* core includes */
#include <ram_session_component.h>
@ -27,5 +28,10 @@ void Ram_session_component::_revoke_ram_ds(Dataspace_component *ds) { }
void Ram_session_component::_clear_ds (Dataspace_component * ds)
{ memset((void *)ds->phys_addr(), 0, ds->size()); }
{
memset((void *)ds->phys_addr(), 0, ds->size());
/* make the new DS-content visible to other PDs */
Kernel::update_region(ds->phys_addr(), ds->size());
}