Skip to content
This repository has been archived by the owner on Jan 4, 2024. It is now read-only.

Commit

Permalink
Add copyregion support for mapping a frame into the VSpace.
Browse files Browse the repository at this point in the history
Add a "copyregion" object that supports a named page-aligned memory
region where page frames can be mapped. A copyregion has a name used to
construct the C symbol name and an optional size that specifies how
large a window to create (default is one "small page").  Any specified
size must be a multiple of the base page size (4096 on RISCV). Multiple
regions can be created per component by using different names. Note
there is no synchronization copyregion accesses (e.g. if used by multiple
threads).  A copy region is setup before any pre_init method is called;
any attempt to use it before then is undefined.

A copy region is implemented "under the covers" by creating a C array
named who's pages are unmapped at startup to create a hole in the VSpace.

Change-Id: I78c99441869860c55a80f8c1d93e3a31107af8d1
GitOrigin-RevId: 0dbaa9886d988ff622e8d96188023c0ec8440589
  • Loading branch information
sleffler committed Aug 12, 2022
1 parent 7e59d64 commit 32f2a71
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 7 deletions.
2 changes: 1 addition & 1 deletion camkes/ast/__init__.py
Expand Up @@ -21,7 +21,7 @@
from .location import SourceLocation
from .objects import Assembly, Attribute, AttributeReference, Component, \
Composition, Configuration, Connection, ConnectionEnd, Connector, \
Consumes, Dataport, DictLookup, Emits, Export, Group, Include, Instance, Interface, \
Consumes, CopyRegion, Dataport, DictLookup, Emits, Export, Group, Include, Instance, Interface, \
Method, Mutex, Parameter, Procedure, Provides, Reference, Semaphore, \
BinarySemaphore, Setting, Uses, Struct, QueryObject
from .traversal import SimpleTraversalContext, TraversalAction, \
Expand Down
21 changes: 17 additions & 4 deletions camkes/ast/objects.py
Expand Up @@ -609,17 +609,19 @@ def freeze(self):
all(isinstance_fallback(x, "Semaphore") for x in s))
@ast_property("binary_semaphores", lambda b: isinstance(b, (list, tuple)) and
all(isinstance_fallback(x, "BinarySemaphore") for x in b))
@ast_property("copyregions", lambda c: isinstance(c, (list, tuple)) and
all(isinstance_fallback(x, "CopyRegion") for x in c))
@ast_property("composition", Composition)
@ast_property("configuration", Configuration)
class Component(MapLike):
child_fields = ('attributes', 'includes', 'provides', 'uses', 'emits',
'consumes', 'dataports', 'mutexes', 'semaphores', 'binary_semaphores', 'composition',
'configuration')
'consumes', 'dataports', 'mutexes', 'semaphores', 'binary_semaphores', 'copyregions',
'composition', 'configuration')

def __init__(self, name=None, includes=None, control=False, hardware=False,
provides=None, uses=None, emits=None, consumes=None, dataports=None,
attributes=None, mutexes=None, semaphores=None, binary_semaphores=None, composition=None,
configuration=None, location=None):
attributes=None, mutexes=None, semaphores=None, binary_semaphores=None, copyregions=None,
composition=None, configuration=None, location=None):
super(Component, self).__init__(location)
self.name = name
self.includes = list(includes or [])
Expand All @@ -634,6 +636,7 @@ def __init__(self, name=None, includes=None, control=False, hardware=False,
self.mutexes = list(mutexes or [])
self.semaphores = list(semaphores or [])
self.binary_semaphores = list(binary_semaphores or [])
self.copyregions = list(copyregions or [])
if composition is not None:
self.composition = composition
else:
Expand All @@ -655,6 +658,7 @@ def claim_children(self):
[self.adopt(m) for m in self.mutexes]
[self.adopt(s) for s in self.semaphores]
[self.adopt(b) for b in self.binary_semaphores]
[self.adopt(b) for b in self.copyregions]
if self.composition is not None:
self.adopt(self.composition)
if self.configuration is not None:
Expand Down Expand Up @@ -777,6 +781,15 @@ def __init__(self, name, location=None):
self.name = name


@ast_property("name", six.string_types)
@ast_property("size", lambda x: isinstance(x, six.integer_types) and x >= 0)
class CopyRegion(ASTObject):
def __init__(self, name, size, location=None):
super(CopyRegion, self).__init__(location)
self.name = name
self.size = size


@ast_property("name", lambda x: x is None or isinstance(x, six.string_types))
@ast_property("from_type", lambda x: isinstance(x, six.string_types) and
x in ('Dataport', 'Event', 'Procedure'))
Expand Down
5 changes: 4 additions & 1 deletion camkes/parser/camkes.g
Expand Up @@ -66,6 +66,7 @@ ID: '[a-zA-Z_]\w*'
REFIN: 'refin';
SEMAPHORE: 'semaphore';
BINARY_SEMAPHORE: 'binary_semaphore';
COPYREGION: 'copyregion';
SIGNED: 'signed';
STRUCT: 'struct';
STRING: 'string';
Expand Down Expand Up @@ -98,7 +99,7 @@ attribute_decl: attribute_parameter ('=' item)? ;
component_decl: COMPONENT id? component_defn;
component_defn: '\{' (attribute | consumes | control | dataport | emits |
hardware | include | mutex | provides | semaphore | binary_semaphore |
uses)*
copyregion | uses)*
((composition_sing configuration_sing?) | configuration_sing composition_sing)? '\}';
component_ref: reference | component_defn;

Expand All @@ -116,6 +117,8 @@ mutex: HAS MUTEX id ';';
provides: PROVIDES reference id ';';
semaphore: HAS SEMAPHORE id ';';
binary_semaphore: HAS BINARY_SEMAPHORE id ';';
copyregion_size: '\(' numeric_expr '\)';
copyregion: HAS COPYREGION id copyregion_size? ';';
uses: maybe? USES reference id ';';
maybe: MAYBE;

Expand Down
19 changes: 18 additions & 1 deletion camkes/parser/stage3.py
Expand Up @@ -27,7 +27,7 @@

from camkes.ast import Assembly, Attribute, AttributeReference, Component, \
Composition, Configuration, Connection, ConnectionEnd, Connector, \
Consumes, Dataport, DictLookup, Emits, Export, Group, Include, Instance, Interface, \
Consumes, CopyRegion, Dataport, DictLookup, Emits, Export, Group, Include, Instance, Interface, \
LiftedAST, Method, Mutex, normalise_type, Parameter, Procedure, Provides, \
Reference, Semaphore, BinarySemaphore, QueryObject, Setting, SourceLocation, Uses, Struct
from .base import Parser
Expand Down Expand Up @@ -240,6 +240,7 @@ def _lift_component_decl(location, *args):
attributes=component_defn.attributes, mutexes=component_defn.mutexes,
semaphores=component_defn.semaphores,
binary_semaphores=component_defn.binary_semaphores,
copyregions=component_defn.copyregions,
composition=component_defn.composition,
configuration=component_defn.configuration, location=location)

Expand All @@ -263,6 +264,7 @@ def _lift_component_defn(location, *args):
mutexes=[x for x in args if isinstance(x, Mutex)],
semaphores=[x for x in args if isinstance(x, Semaphore)],
binary_semaphores=[x for x in args if isinstance(x, BinarySemaphore)],
copyregions=[x for x in args if isinstance(x, CopyRegion)],
composition=composition, configuration=configuration,
location=location)

Expand Down Expand Up @@ -688,6 +690,19 @@ def _lift_binary_semaphore(location, id):
return BinarySemaphore(id, location)


def _lift_copyregion(location, *args):
if len(args) == 2:
name, size = args
return CopyRegion(name, size, location)
else:
# XXX use pagesize?
return CopyRegion(args[0], 4096, location)


def _lift_copyregion_size(location, arg):
return arg


def _lift_setting(location, id, id2, item):
item = strip_quotes(item)
return Setting(id, id2, item, location)
Expand Down Expand Up @@ -838,6 +853,8 @@ def _collapse(location, content):
'reference': _lift_reference,
'semaphore': _lift_semaphore,
'binary_semaphore': _lift_binary_semaphore,
'copyregion': _lift_copyregion,
'copyregion_size': _lift_copyregion_size,
'setting': _lift_setting,
'signed_char': _lift_signed_char,
'signed_int': _lift_signed_int,
Expand Down
33 changes: 33 additions & 0 deletions camkes/templates/component.common.c
Expand Up @@ -80,6 +80,26 @@ const char *get_instance_name(void) {
return name;
}

/*- set copy_region_caps = [] -*/
/*- for c in me.type.copyregions -*/
/*# Setup any per-component copy regions. The pre_init (or similar) routine
* is expected to unmap the pages using copy_region_caps. This leaves each
* COPY_REGION as a "hole" in the component's VSpace where it can map page
* frames. Users are required to implement any necessary synchronization. #*/
/*- set copy_region_size = c.size -*/
/*- set page_size = macros.get_page_size(copy_region_size, options.architecture) -*/
/*- if page_size == 0 -*/
/*? raise(TemplateError('Invalid %s copy_region size %d: must be a multiple of %d' % (c.name, copy_region_size, 4096))) ?*/
/*- endif -*/
/*- set page_size_bits = int(math.log(page_size, 2)) -*/
/*# set copy_region_symbol = '%s_COPY_REGION' % c.name #*/
/*- set copy_region_symbol = c.name -*/
char /*? copy_region_symbol ?*/[ROUND_UP_UNSAFE(/*? copy_region_size ?*/, /*? page_size ?*/)]
ALIGN(/*? page_size ?*/)
SECTION("align_/*? page_size_bits ?*/bit");
/*? register_shared_variable('%s_copy_region_%s' % (me.name, c.name), copy_region_symbol, copy_region_size, frame_size=page_size, perm='RW', with_mapping_caps=copy_region_caps) ?*/
/*- endfor -*/

/*- set cnode_size = configuration[me.address_space].get('cnode_size_bits') -*/
/*- if cnode_size -*/
/*- if isinstance(cnode_size, six.string_types) -*/
Expand Down Expand Up @@ -791,6 +811,19 @@ static int post_main(int thread_id) {
ZF_LOGF_IF(tls_regions[i] == NULL, "Failed to create tls");
}
}
/*- for cap in copy_region_caps -*/
/*# Would otherwise put this in pre_init... #*/
ret = seL4_ARCH_Page_Unmap(/*? cap ?*/);
ERR_IF(ret != 0, camkes_error, ((camkes_error_t){
.type = CE_SYSCALL_FAILED,
.instance = "/*? me.name ?*/",
.description = "failed to unmap copy_region frame /*? cap ?*/",
.syscall = 0, /* XXX no ARCHPageUnmap */
.error = ret,
}), ({
return -1;
}));
/*- endfor -*/
ret = component_control_main();
sync_sem_bare_wait(/*? interface_init_ep ?*/, &interface_init_lock);
return ret;
Expand Down

0 comments on commit 32f2a71

Please sign in to comment.