def register_fill_frame(addr_space, symbol, fill, size, obj_space, label): ''' Take a symbol and create a collection of 4K frames that can comfortably store a region in the bootinfo. Return a static_assert checking that the symbol is of the correct size ''' assert addr_space number_frames = size // 4096 frames = [] for i in range(number_frames): fill_str = [ '%d %d %s %d' % (0, 4096 if (size - (i * 4096)) >= 4096 else (size - (i * 4096)), fill, i * 4096) ] name = '%s_%s_%d_obj' % (symbol, label, i) frames.append( obj_space.alloc(ObjectType.seL4_FrameObject, name=name, label=label, fill=fill_str, size=4096)) caps = [ Cap(frame, read=True, write=False, grant=False) for frame in frames ] sizes = [4096] * number_frames addr_space.add_symbol_with_caps(symbol, sizes, caps) return 'static_assert(sizeof(%(sym)s) == %(size)s,\n' \ ' "%(sym)s not page sized. Templage bug in its declaration?");' \ % {'sym': symbol, 'size': size}
def register_shared_variable(addr_space, obj_space, global_name, symbol, size, frame_size=None, paddr=None, perm='RWX', cached=None, label=None): ''' Create a reservation for a shared memory region between multiple components. global_name: a global key that is used to link up the reservations across multiple components. symbol: the name of the local symbol to be backed by the mapping frames. size: the size of the region. Needs to be a multiple of the smallest page size. frame_size: the size of frames to use to back the region. `size` must be a multiple of `frame_size`. If `frame_size` is not specified, the largest frame size that divides evenly into `size` will be used. paddr: the starting physical address of the frames. Only one caller needs to specify this. If multiple callers specify different values, the result is undefined. perm, cached: page mapping options. These are only applied to the caller's mapping label: integrity label of the frame objects. In the default `Context`, this defaults to the current entity name. ''' assert addr_space size = int(size) frame_size = calc_frame_size(size, frame_size, obj_space.spec.arch.capdl_name()) num_frames = size//frame_size # If these frames have been allocated already then the allocator will return them. # Therefore calls to register_shared_variable with the same global_name have to have the same size. frames = [obj_space.alloc(ObjectType.seL4_FrameObject, name='%s_%d_obj' % (global_name, i), size=frame_size, label=label) for i in range(num_frames)] if paddr is not None: for f in frames: f.paddr = paddr paddr += frame_size read = 'R' in perm write = 'W' in perm grant = 'X' in perm caps = [Cap(frame, read=read, write=write, grant=grant, cached=cached) for frame in frames] sizes = [frame_size] * num_frames addr_space.add_symbol_with_caps(symbol, sizes, caps) # Return code to: # 1. page-align the shared variable; # 2. make it visible in the final ELF; and # 3. Check that it is page-sized. return 'extern typeof(%(sym)s) %(sym)s ALIGN(%(size)d) VISIBLE;\n' \ 'static_assert(sizeof(%(sym)s) <= %(size)d,\n' \ ' "typeof(%(sym)s) size greater than dataport size.");\n' \ 'static_assert(sizeof(%(sym)s) %% %(frame_size)d == 0,\n' \ ' "%(sym)s not page-sized. Template bug in its declaration? ' \ 'Suggested formulation: `char %(sym)s[ROUND_UP_UNSAFE(sizeof(...), ' \ 'PAGE_SIZE_4K)];`");' % {'sym':symbol, 'size': size, 'frame_size': frame_size}
def register_ipc_symbol(addr_space, symbol, frame): ''' Register an IPC buffer symbol with a cap to the frame that is passed in. The frame needs to be passed in instead of allocated internally because caps to the frame are needed by other objects such as the TCB for the thread. It is left to the caller to manage references to the Frame passed in. ''' assert addr_space # We create 3*4K mappings with None on each side of the IPC buffer for guard pages caps = [None, Cap(frame, read=True, write=True, grant=False), None] sizes = [4096] * 3 addr_space.add_symbol_with_caps(symbol, sizes, caps)
def register_fill_frame(addr_space, symbol, fill, obj_space, label): ''' Take a 4K sized symbol and create a 4k Frame with fill data to be added by the loader. Return a static_assert checking that the symbol is of the correct size ''' assert addr_space frame = obj_space.alloc(ObjectType.seL4_FrameObject, name='%s_%s_obj' % (symbol, label), label=label, fill=fill, size=4096) addr_space.add_symbol_with_caps(symbol, [4096], [Cap(frame, read=True, write=False, grant=False)]) return 'static_assert(sizeof(%(sym)s) == PAGE_SIZE_4K,\n' \ ' "%(sym)s not page sized. Templage bug in its declaration?");' \ % {'sym':symbol}
def register_stack_symbol(addr_space, symbol, size, obj_space, label): ''' Create a stack of `size` with a guard page on each side. This allocates the frames internally from the obj_space that is passed in as the frame objects shouldn't be needed anywhere else. Stack frames are read, write mappings. ''' assert addr_space number_frames = size//4096 frames = [obj_space.alloc(ObjectType.seL4_FrameObject, name='stack_%s_%d_%s_obj' % (symbol, i, label), label=label, size=4096) for i in range(number_frames)] # We create 2 additional mappings with None caps that are for the guard pages. sizes = [4096] * (number_frames + 2) caps = [None] + [Cap(frame, read=True, write=True, grant=False) for frame in frames] + [None] addr_space.add_symbol_with_caps(symbol, sizes, caps)
def register_shared_variable(addr_space, obj_space, global_name, symbol, size, cap_space, frame_size=None, paddr=None, perm='RWX', cached=True, label=None, with_mapping_caps=None): ''' Create a reservation for a shared memory region between multiple components. global_name: a global key that is used to link up the reservations across multiple components. symbol: the name of the local symbol to be backed by the mapping frames. size: the size of the region. Needs to be a multiple of the smallest page size. cap_space: the component's cspace. This is potentially used if the mapping caps need to be moved to the component. In this case, with_mapping_caps needs to be set when register_shared_variable is called. frame_size: the size of frames to use to back the region. `size` must be a multiple of `frame_size`. If `frame_size` is not specified, the largest frame size that divides evenly into `size` will be used. paddr: the starting physical address of the frames. Only one caller needs to specify this. If multiple callers specify different values, the result is undefined. perm, cached: page mapping options. These are only applied to the caller's mapping label: integrity label of the frame objects. In the default `Context`, this defaults to the current entity name. with_mapping_caps: An array to return mapping caps if the component needs the caps for the mapping to be moved into their own cspace. ''' assert addr_space size = int(size) frame_size = calc_frame_size(size, frame_size, obj_space.spec.arch) num_frames = size//frame_size digits = str(int(log10(num_frames + 1)) + 1) namefmt = '%s_%0' + digits + 'd_obj' # If these frames have been allocated already then the allocator will return them. # Therefore calls to register_shared_variable with the same global_name have to have the same size. frames = [obj_space.alloc(ObjectType.seL4_FrameObject, name=namefmt % (global_name, i), size=frame_size, label=label) for i in range(num_frames)] if paddr is not None: for f in frames: f.paddr = paddr paddr += frame_size read = 'R' in perm write = 'W' in perm grant = 'X' in perm if with_mapping_caps is not None: # If we need the caps in our cspace, then we need to allocate them and call set_mapping_deferred on the cap # set_mapping_deferred will result in the correct mapping info being set when the spec is being generated. slots = [cap_space.alloc(frame, read=read, write=write, grant=grant, cached=cached) for frame in frames] caps = [cap_space.cnode[slot] for slot in slots] [cap.set_mapping_deferred() for cap in caps] with_mapping_caps.extend(slots) else: caps = [Cap(frame, read=read, write=write, grant=grant, cached=cached) for frame in frames] sizes = [frame_size] * num_frames addr_space.add_symbol_with_caps(symbol, sizes, caps) # Return code to: # 1. page-align the shared variable; # 2. make it visible in the final ELF; and # 3. Check that it is page-sized. return 'extern typeof(%(sym)s) %(sym)s ALIGN(%(frame_size)d) VISIBLE;\n' \ 'static_assert(sizeof(%(sym)s) <= %(size)d,\n' \ ' "typeof(%(sym)s) size greater than dataport size.");\n' \ 'static_assert(sizeof(%(sym)s) %% %(frame_size)d == 0,\n' \ ' "%(sym)s not page-sized. Template bug in its declaration? ' \ 'Suggested formulation: `char %(sym)s[ROUND_UP_UNSAFE(sizeof(...), ' \ 'PAGE_SIZE_4K)];`");' % {'sym': symbol, 'size': size, 'frame_size': frame_size}