def collect_memsection_elements(el, ignore_name, namespace, image, machine, pools, env, pd): for ms_el in el.find_children('memsection'): if not ignore_name.match(ms_el.name): ms = collect_memsection_element(ms_el, ignore_name, namespace, image, machine, pools) pd.attach_memsection(ms) image.add_group(0, [ms.get_ms()]) env.add_entry(key = ms.get_name(), cap_name = ms.get_name() + '/master', attach = ms.get_attrs().attach)
def collect_zone_element(zone_el, ignore_name, namespace, pools, image, bootinfo, machine): """Collect the contents of a zone.""" non_zone_ms = [] # New namespace for objects living in the memsection. zone_namespace = namespace.add_namespace(zone_el.name) physpool = getattr(zone_el, 'physpool', None) attrs = image.new_attrs(zone_namespace.add_namespace(zone_el.name)) zone = Zone(attrs, pools, image, machine) bootinfo.add_zone(zone) # Push the overriding attributes for the zone. image.push_attrs(virtual = zone_el.name, physical = physpool) master = Cap("master", ["master"]) zone.add_cap(master) zone_namespace.add(master.get_name(), master) for ms_el in zone_el.find_children('memsection'): if not ignore_name.match(ms_el.name): ms = collect_memsection_element(ms_el, ignore_name, zone_namespace, image, machine, pools) # Memsections that aren't allocated in the zone belong to the PD. if ms.get_attrs().virtpool == zone_el.name: zone.add_memsection(ms) image.add_group(None, [ms.get_ms()]) else: non_zone_ms.append(ms) # All of the segments have already been processed by the program/pd, but # record the ones probably should belong to the zone. These will be added # to the zone by PD.add_zone() segment_els = zone_el.find_children("segment") zone.claimed_segments = [segment_el.name for segment_el in segment_els] image.pop_attrs() return (zone, non_zone_ms)
def collect_xml(self, iguana_el, ignore_name, namespace, machine, pools, kernel, image): """Handle an Iguana Server Compound Object""" cell = \ kernel.register_cell(iguana_el.name, iguana_el.kernel_heap, max_caps = getattr(iguana_el, "caps", None)) # New namespace for objects living in the root program's PD. ig_namespace = namespace.add_namespace(iguana_el.name) self.namespace = ig_namespace self.s_namespace = self.namespace self.name = iguana_el.name self.space = \ cell.register_space(self.namespace, "MAIN", is_privileged = True, max_clists = getattr(iguana_el, "clists", None), max_spaces = getattr(iguana_el, "spaces", None), max_mutexes = getattr(iguana_el, "mutexes", None), max_threads = getattr(iguana_el, "threads", None), plat_control = \ getattr(iguana_el, "platform_control", False)) self.setup_bootinfo_pools(namespace, pools) self.setup_device_namespace(namespace, machine) self.env = CellEnvironment(iguana_el.name, self.namespace, machine, image, kernel, self.space.mappings) cell.env = self.env pd = weaver.cells.iguana.bootinfo.RootServerPD(iguana_el.name, ig_namespace) # Declare the default memory pools. def_virtpool = getattr(iguana_el, "virtpool", pools.get_default_virtual_pool()) def_physpool = getattr(iguana_el, "physpool", pools.get_default_physical_pool()) def_pager = getattr(iguana_el, "pager", None) def_direct = getattr(iguana_el, "direct", None) # Record any IRQs that are assigned to Iguana for irq_el in iguana_el.find_children("irq"): self.space.register_irq(irq_el.value) self.bootinfo.set_system_default_attrs(def_virtpool, def_physpool, image, def_pager, def_direct) # Iguana is not aware of segment ids. # The old mapping API uses segment 0 for all mapping ops. # Segment 0 needs to cover all of physical memory. # Subsequent segments will be created but never used, # but must still be mapped! # XXX: VVVVV THIS IS PURE EVIL VVVVV physpool_attrs = \ image.new_attrs(self.s_namespace.add_namespace("physpool_hack")) physpool_attrs.phys_addr = 0 #first_phys_base physpool_attrs.size = 0xfffff000 #first_phys_end physpool_attrs.attach = PF_R | PF_W | PF_X physpool_attrs.cache_policy = 0xff # XXX: Define me properly physpool_attrs.mem_type = physpool_attrs.unmapped self.space.register_mapping(physpool_attrs) # XXX: ^^^^^ THIS IS PURE EVIL ^^^^^ filename = os.path.join(iguana_el._path, iguana_el.file) elf = UnpreparedElfFile(filename=filename) pd.set_default_pools(image, self.bootinfo) # Collect the object environment pd.add_env_ms(image, ig_namespace, machine, pools) env, extra_ms = \ collect_environment_element(iguana_el.find_child('environment'), ig_namespace, machine, pools, image, self.bootinfo) segment_els = iguana_el.find_children("segment") segs = collect_elf_segments(elf, image.ROOT_PROGRAM, segment_els, filename, [], ig_namespace, image, machine, pools) self.elf_prog_segments = segs for seg in segs: self.space.register_mapping(seg.attrs) if elf.elf_type != ET_EXEC: raise MergeError, "All the merged ELF files must be of EXEC type." # Find out which version of libokl4 that iguana was built # against sym = elf.find_symbol("okl4_api_version") if sym == None: raise MergeError("Unable to locate the symbol 'okl4_api_version' " "in file \"%s\". Cells must link with libokl4." % filename) self.api_version = elf.get_value(sym.value, sym.size, elf.endianess) if self.api_version == None: raise MergeError("Unable to read the symbol 'okl4_api_version' in " "file \"%s\". Cells must link with libokl4." % filename) # Record any patches being made to the program. patch_els = iguana_el.find_children("patch") for patch in getattr(Iguana_el, "extra_patches", []): addr = get_symbol(elf, patch[0], True) if addr == None: continue addr = int(addr[0])+ int(patch[1]) new_patch = Patch_el(address=hex(addr), bytes=patch[2], value=patch[3]) patch_els.append(new_patch) collect_patches(elf, patch_els, filename, image) for extension_el in iguana_el.find_children("extension"): if not ignore_name.match(extension_el.name): collect_extension_element(extension_el, pd, ig_namespace, elf, image, machine, self.bootinfo, pools) # Collect the main thread. The root program can only have one # thread, so this call chiefly is used to collect information # about the stack. # # The stack is not set up as a memsection, so it is not put in the # object environment. if not hasattr(iguana_el, 'priority'): iguana_el.priority = 255 thread = collect_thread(elf, iguana_el, ignore_name, ig_namespace, image, machine, pools, self.space, entry = elf.entry_point, name = 'iguana', namespace_thread_name = "main", cell_create_thread = True) pd.add_thread(thread) # Collect the heap. Is there no element, create a fake one for # the collection code to use. # # The heap is not set up as a memsection, so it is not put in the # object environment. heap_el = iguana_el.find_child('heap') if heap_el is None: heap_el = ParsedElement('heap') heap_ms = collect_memsection_element(heap_el, ignore_name, ig_namespace, image, machine, pools) pd.attach_heap(heap_ms) self.space.register_mapping(heap_ms.ms.attrs) self.space.register_mapping(thread.get_stack().get_ms().attrs) self.elf_segments.extend([pd.env_ms.get_ms(), thread.get_stack().get_ms(), heap_ms.get_ms()] + [ms.get_ms() for ms in extra_ms]) pd.add_environment(env) pd.utcb_size = image.utcb_size self.bootinfo.add_rootserver_pd(pd) # And now parse the programs and pd's collect_program_pd_elements(iguana_el, ignore_name, ig_namespace, image, machine, self.bootinfo, pools, kernel, cell)
def collect_program_element(program_el, ignore_name, namespace, image, machine, bootinfo, pools, kernel, cell): """Collect the attributes of a program element.""" pd, env, prog_namespace, extra_ms = \ _init_program_pd(program_el, image, bootinfo, machine, pools, namespace) space = cell.register_space(prog_namespace, program_el.name, create = False) elf, segs = _init_elf_file(program_el, image, prog_namespace, machine, pools, bootinfo, pd, kernel) # Collect remaining threads. threads = collect_thread_elements(program_el, ignore_name, elf, prog_namespace, image, machine, pools, env, pd, space) bootinfo.add_elf_info(name = os.path.join(program_el._path, program_el.file), elf_type = image.PROGRAM, entry_point = elf.entry_point) # Collect the main thread. thread = collect_thread(elf, program_el, ignore_name, prog_namespace, image, machine, pools, space, entry = elf.entry_point, name = program_el.name, namespace_thread_name = "main") # Record the main thread and its stack in the environment. env.add_entry(key = "MAIN", cap_name = 'main/master') env.add_entry(key = "MAIN/STACK", cap_name = 'main/stack/master', attach = thread.get_stack().get_attrs().attach) pd.add_thread(thread) pd.server_thread = thread # Add the virtual device elements # Virtual devices always get added to the global namespace because they # should be globally unique server_spawn_nvdevs = 0 dev_ns = namespace.root.get_namespace("dev") if dev_ns is None: raise MergeError, "Device namespace does not exist!" for v_el in program_el.find_children('virt_device'): virt_dev = pd.add_virt_dev(v_el.name, program_el.name, pd, thread, server_spawn_nvdevs) create_alias_cap(virt_dev, dev_ns) server_spawn_nvdevs += 1 # If marked, sure that the program is exported to every # environment so that it can be found by other programs. # if hasattr(program_el, 'server'): bootinfo.add_server( key = program_el.server, cap_name = prog_namespace.abs_path('main') + '/stack/master') # Collect any other memsections in the program. collect_memsection_elements(program_el, ignore_name, prog_namespace, image, machine, pools, env, pd) # Collect any zones in the program. collect_zone_elements(program_el, ignore_name, prog_namespace, image, machine, pools, bootinfo, env, pd) # Collect the heap. Is there no element, create a fake one for # the collection code to use. heap_el = program_el.find_child('heap') if heap_el is None: heap_el = ParsedElement('heap') heap_ms = collect_memsection_element(heap_el, ignore_name, prog_namespace, image, machine, pools) pd.attach_heap(heap_ms) threads.append(thread) image.add_group(None, [segs[0], pd.env_ms.get_ms(), pd.callback.get_ms(), heap_ms.get_ms()] + [thread.get_stack().get_ms() for thread in threads] + [ms.get_ms() for ms in extra_ms]) # Fill env with default values. env.add_entry(key = "HEAP", cap_name = 'heap/master', attach = heap_ms.get_attrs().attach) env.add_entry(key = "HEAP_BASE", base = heap_ms) env.add_entry(key = "HEAP_SIZE", value = heap_ms.get_attrs().size) pd.add_environment(env) bootinfo.add_pd(pd) image.pop_attrs()
def collect_thread(elf, el, ignore_name, namespace, image, machine, pools, space, entry, name = None, namespace_thread_name = None, cell_create_thread = False): """Collect the attributes of a thread element.""" if entry is None: raise MergeError, "No entry point specified for thread %s" % name # el can be a program element or a thread element. if name is None: name = el.name user_main = getattr(el, 'start', None) # HACK: There is no easy way for a PD to specify the main thread, # so is the user entry point is '_start' (the traditional entry # point symbol), then start there rather then the thread entry # point. if user_main == "_start": user_main = None entry = start_to_value(entry, elf) user_main = start_to_value(user_main, elf) # XXX: Iguana only runs on Micro, so default prio is 100! priority = getattr(el, 'priority', 100) physpool = getattr(el, 'physpool', None) virtpool = getattr(el, 'virtpool', None) # New namespace for objects living in the thread. if namespace_thread_name is None: namespace_thread_name = name new_namespace = namespace.add_namespace(namespace_thread_name) # Push the overriding pools for the thread. image.push_attrs(virtual = virtpool, physical = physpool) # Create the thread desription object. thread = Thread(name, entry, user_main, priority) utcb = image.new_attrs(new_namespace.add_namespace("utcb")) # Create the cell thread and assign the entry point cell_thread = space.register_thread(entry, user_main, utcb, priority, create = cell_create_thread) cell_thread.ip = entry # Add the standard caps for the thread. create_standard_caps(thread, new_namespace) # Collect the stack. Is there no element, create a fake one for # the collection code to use. stack_el = el.find_child('stack') if stack_el is None: stack_el = ParsedElement('stack') stack_ms = collect_memsection_element(stack_el, ignore_name, new_namespace, image, machine, pools) thread.attach_stack(stack_ms) # Setup the stack for the new cell thread cell_thread.stack = stack_ms.get_ms().attrs # Collect any command line arguments. commandline_el = el.find_child('commandline') if commandline_el is not None: for arg_el in commandline_el.find_children("arg"): thread.add_argv(arg_el.value) image.pop_attrs() return thread