blob: 1e5ec8b08c0e9af1960dda9fed9c774700dd505c [file] [log] [blame]
/*#
*#Copyright 2017, Data61, CSIRO (ABN 41 687 119 230)
*#
*#SPDX-License-Identifier: BSD-2-Clause
#*/
#include <camkes/dataport.h>
#include <stdint.h>
#include <stdlib.h>
#include <utils/util.h>
#include <sel4/sel4.h>
#include <camkes/dataport_caps.h>
/*? macros.show_includes(me.instance.type.includes) ?*/
/*- if me in me.parent.from_ends -*/
/*- set index = me.parent.from_ends.index(me) -*/
/*- set end = 'from' -*/
/*- elif me in me.parent.to_ends -*/
/*- set index = me.parent.to_ends.index(me) -*/
/*- set end = 'to' -*/
/*- endif -*/
/*- set dataport_symbol_name = "%s_%d_%s_data" % (end, index, me.interface.name) -*/
/*- set type_size = macros.dataport_size(me.interface.type) -*/
/*# Get the dataport size from the .size property on the dataport connection. For backwards compatiblity reasons
# also check the ${interface_name}_size property on the `to` end of the connector.
#*/
/*- if 'size' in configuration[me.parent.name] -*/
/*- set dataport_size = configuration[me.parent.name].get('size') -*/
/*- else -*/
/*- set dataport_size = none -*/
/*- endif -*/
/*- if len(me.parent.to_ends) == 1 -*/
/*- if '%s_size' % me.parent.to_interface.name in configuration[me.parent.to_instance.name] -*/
/*- if dataport_size != none -*/
/*? raise(TemplateError('Duplicate setting for %s dataport size: Cannot set both %s.%s and %s.%s' % (me.parent.name, me.parent.name, 'size', me.parent.to_instance.name, '%s_size' % me.parent.to_interface.name))) ?*/
/*- endif -*/
/*- set dataport_size = configuration[me.parent.to_instance.name].get('%s_size' % me.parent.to_interface.name) -*/
/*- endif -*/
/*- endif -*/
/*- if dataport_size == none -*/
/*- set dataport_size = 4096 -*/
/*- endif -*/
/*- set page_size = macros.get_page_size(dataport_size, options.architecture) -*/
/*- if page_size == 0 -*/
/*? raise(TemplateError('Setting %s.%s_size does not meet minimum size requirements. %d must be at least %d and %d aligned' % (me.instance.name, me.interface.name, size, 4096, 4096))) ?*/
/*- endif -*/
/*- set shmem_symbol_size = "MAX_UNSAFE(%s, %s)" % (type_size, dataport_size) -*/
/*? macros.shared_buffer_symbol(sym=dataport_symbol_name, shmem_size=shmem_symbol_size, page_size=page_size) ?*/
/*- set arch_name = obj_space.spec.arch.capdl_name() -*/
/*- if arch_name in ['ia32', 'x86_64'] -*/
/*- set cached_default = true -*/
/*- else -*/
/*- set cached_default = false -*/
/*- endif -*/
/*- set cached = configuration[me.instance.name].get('%s_hardware_cached' % me.instance.name, cached_default) -*/
/*- if 'paddr' in configuration[me.parent.name] and me in me.parent.to_ends -*/
/*- set paddr = configuration[me.parent.name].get('paddr') -*/
/*- else -*/
/*- set paddr = None -*/
/*- endif -*/
/*- set perm = macros.get_perm(configuration, me.instance.name, me.interface.name) -*/
/*? register_shared_variable('%s_data' % me.parent.name, dataport_symbol_name, dataport_size, frame_size=page_size, perm=perm, cached=cached, paddr=paddr) ?*/
volatile /*? macros.dataport_type(me.interface.type) ?*/ * /*? me.interface.name ?*/ =
(volatile /*? macros.dataport_type(me.interface.type) ?*/ *) &/*? dataport_symbol_name ?*/;
/*- set id = composition.connections.index(me.parent) -*/
int /*? me.interface.name ?*/_wrap_ptr(dataport_ptr_t *p, void *ptr) {
if ((uintptr_t)ptr < (uintptr_t)/*? me.interface.name ?*/ ||
(uintptr_t)ptr >= (uintptr_t)/*? me.interface.name ?*/ + /*? macros.dataport_size(me.interface.type) ?*/) {
return -1;
}
p->id = /*? id ?*/;
p->offset = (off_t)((uintptr_t)ptr - (uintptr_t)/*? me.interface.name ?*/);
return 0;
}
void * /*? me.interface.name ?*/_unwrap_ptr(dataport_ptr_t *p) {
if (p->id == /*? id ?*/) {
return (void*)((uintptr_t)/*? me.interface.name ?*/ + (uintptr_t)p->offset);
} else {
return NULL;
}
}
/*- set read_perm = False -*/
/*- set write_perm = False -*/
/*- if 'R' in perm -*/
/*- set read_perm = True -*/
/*- endif -*/
/*- if 'W' in perm -*/
/*- set write_perm = True -*/
/*- endif -*/
/*- set frame_objs = get_shared_variable_backing_frames('%s_data' % me.parent.name, dataport_size) -*/
/*- set frame_caps = [] -*/
static seL4_CPtr frame_caps[] = {
/*- for (i, frame) in enumerate(frame_objs) -*/
/*- set frame_cap = alloc_cap('%s_%d' % ('%s_data' % me.parent.name, i), frame, read=read_perm, write=write_perm) -*/
/*- do frame_caps.append(frame_cap) -*/
/*? frame_cap ?*/,
/*- endfor -*/
};
/*- set num_frame_caps = len(frame_caps) -*/
static seL4_CPtr /*? me.interface.name ?*/_get_nth_frame_cap(unsigned int n) {
return frame_caps[n];
}
static seL4_CPtr* /*? me.interface.name ?*/_get_frame_caps(void) {
return frame_caps;
}
static unsigned int /*? me.interface.name ?*/_get_num_frame_caps(void) {
return /*? num_frame_caps ?*/;
}
static unsigned int /*? me.interface.name ?*/_get_id(void) {
return /*? configuration[me.instance.name].get('%s_id' % me.interface.name, 0) ?*/;
}
static size_t /*? me.interface.name ?*/_get_size(void) {
return /*? dataport_size ?*/;
}
static seL4_CapRights_t /*? me.interface.name ?*/_get_rights(void) {
/*- if perm is none -*/
return seL4_AllRights;
/*- else -*/
/*- set read = int(read_perm) -*/
/*- set write = int(write_perm) -*/
/*# The 0 grant/grantreply argument below is because the grant operations are meaningless on dataports.
*# The lack of execute permission is because cap rights don't capture the right to execute
*# the contents of a mapped-in page. #*/
return seL4_CapRights_new(0, 0, /*? read ?*/, /*? write ?*/);
/*- endif -*/
}
dataport_caps_handle_t /*? me.interface.name ?*/_handle = {
.get_nth_frame_cap = /*? me.interface.name ?*/_get_nth_frame_cap,
.get_id = /*? me.interface.name ?*/_get_id,
.get_num_frame_caps = /*? me.interface.name ?*/_get_num_frame_caps,
.get_frame_caps = /*? me.interface.name ?*/_get_frame_caps,
.get_size = /*? me.interface.name ?*/_get_size,
.get_rights = /*? me.interface.name ?*/_get_rights,
};