mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-11 13:22:33 +00:00
nova: map write_combined ds as dma able
This commit is contained in:
parent
1c2f76cd2a
commit
ff062f24ff
@ -66,6 +66,8 @@ namespace Genode {
|
||||
Nova::Rights(true, _rw, true));
|
||||
}
|
||||
|
||||
bool write_combined() { return _write_combined; };
|
||||
|
||||
addr_t dst_addr() { return _dst_addr; }
|
||||
};
|
||||
|
||||
|
@ -463,6 +463,11 @@ namespace Nova {
|
||||
*/
|
||||
unsigned msg_words() { return items & 0xffffU; }
|
||||
|
||||
/**
|
||||
* Return current number of message items on UTCB
|
||||
*/
|
||||
unsigned msg_items() { return items >> 16; }
|
||||
|
||||
/**
|
||||
* Append message-transfer item to message buffer
|
||||
*
|
||||
@ -478,7 +483,7 @@ namespace Nova {
|
||||
/* transfer items start at the end of the UTCB */
|
||||
items += 1 << 16;
|
||||
Item *item = reinterpret_cast<Item *>(this);
|
||||
item += (PAGE_SIZE_BYTE / sizeof(struct Item)) - (items >> 16);
|
||||
item += (PAGE_SIZE_BYTE / sizeof(struct Item)) - msg_items();
|
||||
|
||||
/* check that there is enough space left on UTCB */
|
||||
if (msg + msg_words() >= reinterpret_cast<mword_t *>(item)) {
|
||||
|
@ -57,7 +57,8 @@ void Ipc_pager::set_reply_mapping(Mapping m)
|
||||
{
|
||||
Nova::Utcb *utcb = (Nova::Utcb *)Thread_base::myself()->utcb();
|
||||
utcb->set_msg_word(0);
|
||||
bool res = utcb->append_item(m.mem_crd(), m.dst_addr());
|
||||
bool res = utcb->append_item(m.mem_crd(), m.dst_addr(), false, false,
|
||||
false, m.write_combined());
|
||||
/* one item ever fits on the UTCB */
|
||||
(void)res;
|
||||
}
|
||||
|
@ -45,11 +45,13 @@ static void echo_reply()
|
||||
Nova::Crd snd_rcv(echo()->utcb()->msg[0]);
|
||||
Nova::mword_t offset = echo()->utcb()->msg[1];
|
||||
bool kern_pd = echo()->utcb()->msg[2];
|
||||
bool dma_mem = echo()->utcb()->msg[3];
|
||||
|
||||
/* reset message transfer descriptor */
|
||||
echo()->utcb()->set_msg_word(0);
|
||||
/* append capability-range as message-transfer item */
|
||||
bool res = echo()->utcb()->append_item(snd_rcv, offset, kern_pd);
|
||||
bool res = echo()->utcb()->append_item(snd_rcv, offset, kern_pd, false,
|
||||
false, dma_mem);
|
||||
|
||||
/* set return code, 0 means failure */
|
||||
echo()->utcb()->msg[0] = res;
|
||||
|
@ -29,21 +29,23 @@ enum { verbose_local_map = false };
|
||||
|
||||
|
||||
/**
|
||||
* Establish a one-to-one mapping
|
||||
* Establish a mapping
|
||||
*
|
||||
* \param utcb UTCB of the calling EC
|
||||
* \param src_crd capability range descriptor of source
|
||||
* resource to map locally
|
||||
* \param dst_crd capability range descriptor of mapping
|
||||
* target
|
||||
* \param kern_pd Whether to map the items from the kernel or from core
|
||||
* \param dma_mem Whether the memory is usable for DMA or not
|
||||
*
|
||||
* This functions sends a mapping from the calling EC to the echo EC.
|
||||
* In order to successfully transfer the mapping, we have to open a
|
||||
* corresponding receive window at the echo EC. We do this by poking
|
||||
* a receive-capability-range descriptor directly onto the echo UTCB.
|
||||
* This functions sends a message from the calling EC to the echo EC.
|
||||
* The calling EC opens a receive window and the echo EC creates a transfer
|
||||
* item of the message and replies. The kernel will map during the reply
|
||||
* from the echo EC to the calling EC.
|
||||
*/
|
||||
static int map_local(Nova::Utcb *utcb, Nova::Crd src_crd, Nova::Crd dst_crd,
|
||||
bool kern_pd = false)
|
||||
bool kern_pd = false, bool dma_mem = false)
|
||||
{
|
||||
/* open receive window at current EC */
|
||||
utcb->crd_rcv = dst_crd;
|
||||
@ -52,16 +54,18 @@ static int map_local(Nova::Utcb *utcb, Nova::Crd src_crd, Nova::Crd dst_crd,
|
||||
utcb->msg[0] = src_crd.value();
|
||||
utcb->msg[1] = 0;
|
||||
utcb->msg[2] = kern_pd;
|
||||
utcb->set_msg_word(3);
|
||||
utcb->msg[3] = dma_mem;
|
||||
utcb->set_msg_word(4);
|
||||
|
||||
/* establish the mapping via a portal traversal during reply phase */
|
||||
Nova::uint8_t res = Nova::call(echo()->pt_sel());
|
||||
if (res != Nova::NOVA_OK || utcb->msg_words() != 1 || !utcb->msg[0]) {
|
||||
if (res != Nova::NOVA_OK || utcb->msg_words() != 1 || !utcb->msg[0] ||
|
||||
utcb->msg_items() != 1) {
|
||||
PERR("Failure - map_local 0x%lx:%lu:%u->0x%lx:%lu:%u - call result=%x"
|
||||
" utcb=%x:%lx !!! %p %u",
|
||||
" utcb=%x:%x:%lx !!! utcb=%p kern=%u",
|
||||
src_crd.addr(), src_crd.order(), src_crd.type(),
|
||||
dst_crd.addr(), dst_crd.order(), dst_crd.type(),
|
||||
res, utcb->msg_words(), utcb->msg[0], utcb, kern_pd);
|
||||
dst_crd.addr(), dst_crd.order(), dst_crd.type(), res,
|
||||
utcb->msg_items(), utcb->msg_words(), utcb->msg[0], utcb, kern_pd);
|
||||
return res > 0 ? res : -1;
|
||||
}
|
||||
/* clear receive window */
|
||||
@ -74,12 +78,11 @@ static int map_local(Nova::Utcb *utcb, Nova::Crd src_crd, Nova::Crd dst_crd,
|
||||
static inline int unmap_local(Nova::Crd crd, bool self = true) {
|
||||
return Nova::revoke(crd, self); }
|
||||
|
||||
inline int
|
||||
map_local_phys_to_virt(Nova::Utcb *utcb, Nova::Crd src, Nova::Crd dst) {
|
||||
inline int map_local_phys_to_virt(Nova::Utcb *utcb, Nova::Crd src,
|
||||
Nova::Crd dst) {
|
||||
return map_local(utcb, src, dst, true); }
|
||||
|
||||
inline int
|
||||
map_local_one_to_one(Nova::Utcb *utcb, Nova::Crd crd) {
|
||||
inline int map_local_one_to_one(Nova::Utcb *utcb, Nova::Crd crd) {
|
||||
return map_local(utcb, crd, crd, true); }
|
||||
|
||||
|
||||
@ -95,7 +98,7 @@ inline int map_local(Nova::Utcb *utcb,
|
||||
Genode::addr_t from_start, Genode::addr_t to_start,
|
||||
Genode::size_t num_pages,
|
||||
Nova::Rights const &permission,
|
||||
bool kern_pd = false)
|
||||
bool kern_pd = false, bool dma_mem = false)
|
||||
{
|
||||
if (verbose_local_map)
|
||||
Genode::printf("::map_local: from %lx to %lx, %zd pages from kernel %u\n",
|
||||
@ -146,7 +149,7 @@ inline int map_local(Nova::Utcb *utcb,
|
||||
int const res = map_local(utcb,
|
||||
Mem_crd((from_curr >> 12), order - get_page_size_log2(), permission),
|
||||
Mem_crd((to_curr >> 12), order - get_page_size_log2(), permission),
|
||||
kern_pd);
|
||||
kern_pd, dma_mem);
|
||||
if (res) return res;
|
||||
|
||||
/* advance offset by current flexpage size */
|
||||
|
@ -51,10 +51,10 @@ addr_t Io_mem_session_component::_map_local(addr_t base, size_t size)
|
||||
}
|
||||
|
||||
/* map the dataspace's physical pages to local addresses */
|
||||
const Nova::Rights rights(true, true, true);
|
||||
map_local((Nova::Utcb *)Thread_base::myself()->utcb(),
|
||||
base, (addr_t)virt_addr,
|
||||
page_rounded_size >> get_page_size_log2(), rights, true);
|
||||
const Nova::Rights rights(true, true, false);
|
||||
int res = map_local((Nova::Utcb *)Thread_base::myself()->utcb(),
|
||||
base, (addr_t)virt_addr,
|
||||
page_rounded_size >> get_page_size_log2(), rights, true);
|
||||
|
||||
return (addr_t)virt_addr;
|
||||
return res ? 0 : (addr_t)virt_addr;
|
||||
}
|
||||
|
@ -86,10 +86,17 @@ void Ram_session_component::_clear_ds(Dataspace_component *ds)
|
||||
page_rounded_size, ds->phys_addr(), virt_addr, Thread_base::myself()->utcb());
|
||||
|
||||
/* map the dataspace's physical pages to local addresses */
|
||||
const Nova::Rights rights(true, true, true);
|
||||
map_local((Nova::Utcb *)Thread_base::myself()->utcb(),
|
||||
ds->phys_addr(), (addr_t)virt_addr,
|
||||
page_rounded_size >> get_page_size_log2(), rights, true);
|
||||
const Nova::Rights rights(true, ds->writable(), true);
|
||||
int res = map_local((Nova::Utcb *)Thread_base::myself()->utcb(),
|
||||
ds->phys_addr(), (addr_t)virt_addr,
|
||||
page_rounded_size >> get_page_size_log2(), rights,
|
||||
true);
|
||||
|
||||
if (res) {
|
||||
PERR("map failed - ram ds size=0x%8zx phys 0x%8lx, core-local 0x%8p\n",
|
||||
page_rounded_size, ds->phys_addr(), virt_addr);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(virt_addr, 0, page_rounded_size);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user