Esempio n. 1
0
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)
Esempio n. 2
0
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)
Esempio n. 3
0
    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)
Esempio n. 4
0
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()
Esempio n. 5
0
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