Example #1
0
File: qom.py Project: laerreal/qdt
 def gen_nic_helper(self, helper, cbtn, index):
     cbt = Type.lookup(cbtn)
     return cbt.use_as_prototype(
         self.nic_helper_name(helper, index),
         body="    return 0;\n" if cbt.ret_type.name != "void" else "",
         static=True,
         used_types=[Type.lookup(self.struct_name)])
Example #2
0
    def gen_net_client_info(self, index):
        helpers = []
        code = {}
        for helper_name, cbtn in [
            ("link_status_changed", "LinkStatusChanged"),
            ("can_receive", "NetCanReceive"),
            ("receive", "NetReceive"),
            ("cleanup", "NetCleanup")
        ]:
            helper = self.gen_nic_helper(helper_name, cbtn, index)
            self.source.add_type(helper)
            helpers.append(helper)
            code[helper_name] = helper

        # Define relative order of helpers: link, can recv, recv, cleanup
        line_origins(helpers)

        code["type"] = Type.lookup("NET_CLIENT_DRIVER_NIC")
        types = set([Type.lookup("NICState")] + list(code.values()))
        code["size"] = "sizeof(NICState)"

        init = Initializer(code, used_types = types)

        return Type.lookup("NetClientInfo").gen_var(
            self.net_client_info_name(index),
            initializer = init,
            static = True
        )
Example #3
0
    def gen_vmstate_initializer(self, state_struct):
        type_macro = Type.lookup(self.qtn.type_macro)
        code = ("""{
    .name@b=@s%s,
    .version_id@b=@s1,
    .fields@b=@s(VMStateField[])@b{
""" % type_macro.name
        )

        used_macros = set()
        global type2vmstate

        for f in self.state_fields:
            if not f.save:
                continue

            if f.num is not None:
                raise Exception(
                    "VMState field generation for arrays is not supported"
                )

            try:
                vms_macro_name = type2vmstate[f.type.name]
            except KeyError:
                raise Exception(
                    "VMState generation for type %s is not implemented" % \
                        f.type.name
                )

            vms_macro = Type.lookup(vms_macro_name)
            used_macros.add(vms_macro)

            init = Initializer(
                # code of macro initializer is dict
                {
                    "_f": f.name,
                    "_s": state_struct.name,
                    # Macros may use different argument names
                    "_field": f.name,
                    "_state": state_struct.name
                }
            )
            code += " " * 8 + vms_macro.gen_usage_string(init) + ",\n"

        # Generate VM state list terminator macro.
        code += " " * 8 + Type.lookup("VMSTATE_END_OF_LIST").gen_usage_string()

        code += "\n    }\n}"

        init = Initializer(
            code = code,
            used_types = used_macros.union([
                type_macro,
                Type.lookup("VMStateField"),
                state_struct
            ])
        )
        return init
Example #4
0
File: qom.py Project: laerreal/qdt
def gen_prop_declaration(field,
                         decl_macro_name,
                         state_struct,
                         default_default=None):
    decl_macro = Type.lookup(decl_macro_name)
    used_types = set([decl_macro])
    bool_true = Type.lookup("true")
    bool_false = Type.lookup("false")

    init_code = {
        "_f": field.name,
        "_s": state_struct,
    }

    if field.prop_macro_name is not None:
        init_code["_n"] = Type.lookup(field.prop_macro_name)
        init_code["_name"] = init_code["_n"]

    init_code["_state"] = init_code["_s"]
    init_code["_field"] = init_code["_f"]

    # _conf is name of argument of macro DEFINE_NIC_PROPERTIES that
    # corresponds to structure filed name
    init_code["_conf"] = init_code["_f"]

    if default_default is not None:
        if field.default is None:
            val = default_default
        else:
            val = field.default

        if isinstance(val, str):
            try:
                val_macro = Type.lookup(val)
            except TypeNotRegistered:
                val = '"%s"' % val
            else:
                val = val_macro
        elif isinstance(val, bool):
            if val:
                val = bool_true
            else:
                val = bool_false
        elif isinstance(val, integer_types):
            if field.type.name[0] == "u":
                val = "0x%X" % val
            else:
                val = str(val)
        else:
            val = str(val)

        init_code["_d"] = val
        init_code["_defval"] = val

    initializer = Initializer(code=init_code)
    usage_str = decl_macro.gen_usage_string(initializer)
    return (usage_str, used_types)
Example #5
0
File: qom.py Project: laerreal/qdt
    def char_declare_fields(self):
        field_type = (Type.lookup("CharBackend") if get_vp()["v2.8 chardev"]
                      else Pointer(Type.lookup("CharDriverState")))

        for index in range(self.char_num):
            self.add_state_field(
                QOMStateField(field_type,
                              self.char_name(index),
                              save=False,
                              prop=True))
Example #6
0
File: qom.py Project: laerreal/qdt
 def nic_declare_field(self, index):
     self.add_state_field(
         QOMStateField(Pointer(Type.lookup("NICState")),
                       self.nic_name(index),
                       save=False))
     f = QOMStateField(Type.lookup("NICConf"),
                       self.nic_conf_name(index),
                       save=False,
                       prop=True)
     self.add_state_field(f)
     # NIC properties have standard names
     f.prop_macro_name = None
Example #7
0
    def gen_instance_init_fn(self, state_struct,
        code = "",
        s_is_used = False,
        used_types = [],
        used_globals = []
    ):
        type_cast_macro = Type.lookup(self.qtn.for_macros)

        total_used_types = set([state_struct, type_cast_macro])
        total_used_types.update(used_types)

        if self.timer_num > 0:
            total_used_types.update([
                Type.lookup("QEMU_CLOCK_VIRTUAL"),
                Type.lookup("timer_new_ns")
            ])
            s_is_used = True
            code += "\n"

            for timerN in range(self.timer_num):
                cb = self.timer_gen_cb(timerN, self.source, state_struct,
                    self.type_cast_macro
                )

                total_used_types.add(cb)

                code += """\
    s->%s@b=@stimer_new_ns(@aQEMU_CLOCK_VIRTUAL,@s%s,@ss);
""" % (self.timer_name(timerN), cb.name,
                )

        fn = Function(
            name = self.gen_instance_init_name(),
            body = """\
    {used}{Struct}@b*s@b=@s{UPPER}(obj);
{extra_code}\
""".format(
    Struct = state_struct.name,
    UPPER = type_cast_macro.name,
    extra_code = code,
    used = "" if s_is_used else "__attribute__((unused))@b"
            ),
            static = True,
            args = [
                Type.lookup("Object").gen_var("obj", pointer = True)
            ],
            used_types = total_used_types,
            used_globals = used_globals
        )

        return fn
Example #8
0
def machine_register_2_6(mach):
    # machine class definition function
    mach.class_init = Function(
        name="machine_%s_class_init" % mach.qtn.for_id_name,
        static=True,
        ret_type=Type.lookup("void"),
        args=[
            Type.lookup("ObjectClass").gen_var("oc", pointer=True),
            Type.lookup("void").gen_var("opaque", pointer=True)
        ],
        body="""\
    MachineClass *mc = MACHINE_CLASS(oc);

    mc->desc = \"{desc}\";
    mc->init = {instance_init};
""".format(desc=mach.desc, instance_init=mach.instance_init.name),
        used_types=[
            Type.lookup("MachineClass"),
            Type.lookup("MACHINE_CLASS"), mach.instance_init
        ])
    mach.source.add_type(mach.class_init)

    # machine type definition structure
    type_machine_macro = Type.lookup("TYPE_MACHINE")
    type_machine_type_name_macro = Type.lookup("MACHINE_TYPE_NAME")

    mach.type_info = Type.lookup("TypeInfo").gen_var(
        name="machine_type_%s" % mach.qtn.for_id_name,
        static=True,
        initializer=Initializer(
            {
                "name":
                type_machine_type_name_macro.gen_usage_string(
                    Initializer({"machinename": '"%s"' % mach.qtn.for_id_name
                                 })),
                "parent":
                type_machine_macro,
                "class_init":
                mach.class_init
            },
            used_types=[type_machine_type_name_macro]))
    mach.source.add_global_variable(mach.type_info)

    # machine type registration function
    mach.type_reg_func = mach.gen_register_types_fn(mach.type_info)
    mach.source.add_type(mach.type_reg_func)

    # Main machine registration macro
    machine_init_def = Type.lookup("type_init").gen_var()
    machine_init_def_args = Initializer({"function": mach.type_reg_func})
    mach.source.add_usage(machine_init_def.gen_usage(machine_init_def_args))
Example #9
0
File: qom.py Project: laerreal/qdt
    def char_gen_cb(self, proto_name, handler_name, index, source,
                    state_struct, type_cast_macro):
        proto = Type.lookup(proto_name)
        cb = proto.use_as_prototype(handler_name,
            body = """\
    __attribute__((unused))@b%s@b*s@b=@s%s(opaque);%s
""" % (
        state_struct.name,
        self.type_cast_macro.name,
        "\n\n    return 0;" \
    if proto.ret_type not in [ None, Type.lookup("void") ] else "",
            ),
            static = True,
            used_types = set([state_struct, type_cast_macro])
        )
        source.add_type(cb)
        return cb
Example #10
0
File: qom.py Project: laerreal/qdt
 def gen_properties_global(self, state_struct):
     init = self.gen_properties_initializer(state_struct)
     prop_type = Type.lookup("Property")
     var = prop_type.gen_var(name=self.qtn.for_id_name + "_properties",
                             initializer=init,
                             static=True,
                             array_size=0)
     return var
Example #11
0
    def gen_mmio_write(name, struct_name, type_cast_macro, regs = None):
        func = Type["MemoryRegionOps"].write.type.type.use_as_prototype(name,
            body = BodyTree(),
            static = True
        )
        root = func.body

        s = Type.lookup(struct_name).gen_var("s", pointer = True)

        root.add_child(
            Declare(
                OpAssign(
                    s,
                    MCall(
                        type_cast_macro,
                        func.args[0]
                    )
                )
            )
        )
        root.add_child(NewLine())

        if regs:
            cases = gen_reg_cases(
                regs, "w", func.args[1], func.args[2], None, s
            )
        else:
            cases = []
        switch = BranchSwitch(func.args[1],
            cases = cases,
            separate_cases = True
        )
        case_default = SwitchCase("default")
        case_default.add_child(
            Call(
                "printf",
                StrConcat(
                    "%s: unimplemented write to 0x%",
                    MCall("HWADDR_PRIx"),
                    StrConcat(
                        ", size %d, ",
                        "value 0x%",
                        delim = "@s"
                    ),
                    MCall("PRIx64"),
                    "\\n",
                    delim = "@s"
                ),
                MCall("__FUNCTION__"),
                func.args[1],
                func.args[3],
                func.args[2]
            )
        )
        switch.add_child(case_default)
        root.add_child(switch)

        return func
Example #12
0
File: qom.py Project: laerreal/qdt
 def block_declare_fields(self):
     for index in range(self.block_num):
         f = QOMStateField(Pointer(Type.lookup("BlockBackend")),
                           self.block_name(index),
                           save=False,
                           prop=True)
         self.add_state_field(f)
         # override macro name assigned by `add_state_field`
         f.prop_macro_name = self.block_prop_name(index)
Example #13
0
File: qom.py Project: laerreal/qdt
    def gen_vmstate_var(self, state_struct):
        init = self.gen_vmstate_initializer(state_struct)

        vmstate = Type.lookup("VMStateDescription").gen_var(
            name="vmstate_%s" % self.qtn.for_id_name,
            static=True,
            initializer=init)

        return vmstate
Example #14
0
File: qom.py Project: laerreal/qdt
    def timer_gen_cb(self, index, source, state_struct, type_cast_macro):
        timer_cb = Function(
            self.timer_cb_name(index),
            body="""\
    __attribute__((unused))@b%s@b*s@b=@s%s(opaque);
""" % (state_struct.name, self.type_cast_macro.name),
            args=[Type.lookup("void").gen_var("opaque", pointer=True)],
            static=True,
            used_types=set([state_struct, type_cast_macro]))
        source.add_type(timer_cb)
        return timer_cb
Example #15
0
File: qom.py Project: laerreal/qdt
    def gen_register_types_fn(self, *infos):
        body = ""
        for info in infos:
            body += "    type_register_static(&%s);\n" % info.name

        fn = Function(name=self.gen_register_types_name(),
                      body=body,
                      static=True,
                      used_types=[Type.lookup("type_register_static")],
                      used_globals=list(infos))

        return fn
Example #16
0
    def gen_irq_get(self, irq, var_name):
        dst = irq[0]
        if isinstance(dst, IRQHub):
            raise RuntimeError("Cannot get an IRQ from a hub (%u)."
                " A hub _is_ an IRQ itself." % dst.id
            )

        self.use_type_name("DEVICE")

        if irq[2] is None:
            self.use_type_name("qdev_get_gpio_in")

            return """\
    {irq_name} = qdev_get_gpio_in(@aDEVICE({dst_name}),@s{dst_index});
""".format(
    irq_name = var_name,
    dst_name = self.node_map[dst],
    dst_index = irq[1],
            )
        else:
            gpio_name = irq[2]
            try:
                gpio_name_type = Type.lookup(gpio_name)
            except TypeNotRegistered:
                gpio_name = '"%s"' % gpio_name
            else:
                self.use_type(gpio_name_type)

            irq_get = Type.lookup("qdev_get_gpio_in_named")
            self.use_type(irq_get)
            return """\
    {irq_name} = {irq_get}(@aDEVICE({dst_name}),@s{gpio_name},@s{dst_index});
""".format(
    irq_name = var_name,
    irq_get = irq_get.name,
    dst_name = self.node_map[dst],
    gpio_name = gpio_name,
    dst_index = irq[1],
            )
Example #17
0
File: qom.py Project: laerreal/qdt
    def gen_mmio_write(name, struct_name, type_cast_macro, regs=None):
        write = Type.lookup("MemoryRegionOps_write")

        used_types = set([
            write.args[1].type, write.args[2].type,
            Type.lookup("uint64_t"),
            Type.lookup("printf"),
            Type.lookup("HWADDR_PRIx"),
            Type.lookup("PRIx64")
        ])

        context = {"s_is_used": False}

        regs = "" if regs is None else (
            "\n" + gen_reg_cases(regs, "w", used_types, write.args[1].name,
                                 write.args[2].name, context))

        body = """\
    {unused}{Struct}@b*s@b=@s{UPPER}(opaque);

    switch@b({offset})@b{{{regs}
    default:
        printf(@a"%s:@bunimplemented@bwrite@bto@b0x%"HWADDR_PRIx",@bsize@b%d,@b"
               @a"value@b0x%"PRIx64"\\n",@s__FUNCTION__,@s{offset},@ssize,\
@s{value});
        break;
    }}
""".format(regs=regs,
           unused="" if context["s_is_used"] else "__attribute__((unused))@b",
           offset=write.args[1].name,
           value=write.args[2].name,
           Struct=struct_name,
           UPPER=type_cast_macro)

        return write.use_as_prototype(name=name,
                                      static=True,
                                      body=body,
                                      used_types=used_types)
Example #18
0
File: qom.py Project: laerreal/qdt
    def gen_type_info_var(self,
                          state_struct,
                          instance_init_fn,
                          class_init_fn,
                          parent_tn="TYPE_OBJECT"):
        used_types = [state_struct, instance_init_fn, class_init_fn]

        try:
            parent_macro = Type.lookup(parent_tn)
        except TypeNotRegistered:
            parent_macro = None
        else:
            used_types.append(parent_macro)

        # Type info initializer
        tii = Initializer(
            code = """{{
    .name@b@b@b@b@b@b@b@b@b@b=@sTYPE_{UPPER},
    .parent@b@b@b@b@b@b@b@b=@s{parent_tn},
    .instance_size@b=@ssizeof({Struct}),
    .instance_init@b=@s{instance_init},
    .class_init@b@b@b@b=@s{class_init}
}}""".format(
        UPPER = self.qtn.for_macros,
        parent_tn = ('"%s"' % parent_tn) if parent_macro is None \
                else parent_macro.name,
        Struct = state_struct.name,
        instance_init = instance_init_fn.name,
        class_init = class_init_fn.name
            ),
            used_types = used_types
        )
        # TypeInfo variable
        tiv = Type.lookup("TypeInfo").gen_var(name=self.gen_type_info_name(),
                                              static=True,
                                              initializer=tii)

        return tiv
Example #19
0
 def add_state_field_h(self, type_name, field_name,
         num = None,
         save = True,
         prop = False,
         default = None
     ):
     t = Type.lookup(type_name)
     f = QOMStateField(t, field_name,
         num = num,
         save = save,
         prop = prop,
         default = default
     )
     self.add_state_field(f)
Example #20
0
File: qom.py Project: laerreal/qdt
    def gen_mmio_read(name, struct_name, type_cast_macro, regs=None):
        read = Type.lookup("MemoryRegionOps_read")

        used_types = set([
            read.args[1].type,
            Type.lookup("uint64_t"),
            Type.lookup("printf"),
            Type.lookup("HWADDR_PRIx")
        ])

        context = {"s_is_used": False}

        regs = "" if regs is None else ("\n" + gen_reg_cases(
            regs, "r", used_types, read.args[1].name, None, context))

        body = """\
    {unused}{Struct}@b*s@b=@s{UPPER}(opaque);
    uint64_t@bret@b=@s0;

    switch@b({offset})@b{{{regs}
    default:
        printf(@a"%s:@bunimplemented@bread@bfrom@b0x%"HWADDR_PRIx",@bsize@b%d\
\\n",@s__FUNCTION__,@s{offset},@ssize);
        break;
    }}

    return@sret;
""".format(regs=regs,
           unused="" if context["s_is_used"] else "__attribute__((unused))@b",
           offset=read.args[1].name,
           Struct=struct_name,
           UPPER=type_cast_macro)

        return read.use_as_prototype(name=name,
                                     static=True,
                                     body=body,
                                     used_types=used_types)
Example #21
0
def define_msi_init_2_6_5():
    Header.lookup("hw/pci/msi.h").add_type(
        Function(name="msi_init",
                 ret_type=Type.lookup("int"),
                 args=[
                     Type.lookup("PCIDevice").gen_var("dev", pointer=True),
                     Type.lookup("uint8_t").gen_var("offset"),
                     Type.lookup("unsigned int").gen_var("nr_vectors"),
                     Type.lookup("bool").gen_var("msi64bit"),
                     Type.lookup("bool").gen_var("msi_per_vector_mask"),
                     Pointer(Type.lookup("Error")).gen_var("errp",
                                                           pointer=True)
                 ]))
Example #22
0
    def char_gen_cb(self, proto_name, handler_name, index, source,
        state_struct, type_cast_macro, ret
    ):
        proto = Type.lookup(proto_name)
        cb = proto.use_as_prototype(handler_name,
            body = """\
    __attribute__((unused))@b%s@b*s@b=@s%s(opaque);%s
""" % (
    state_struct.name,
    self.type_cast_macro.name,
    ("\n\n    return %s;" % ret) if ret is not None else "",
            ),
            static = True,
            used_types = set([state_struct, type_cast_macro])
        )
        source.add_type(cb)
        return cb
Example #23
0
    def gen_properties_initializer(self, state_struct):
        used_types = set()
        global type2prop

        code = "{"

        first = True
        for f in self.state_fields:
            if not f.prop:
                continue

            try:
                helper = type2prop[f.type.name]
            except KeyError:
                raise Exception(
                    "Property generation for type %s is not implemented" % \
                        f.type.name
                )

            decl_code, decl_types = helper(f, state_struct)

            used_types |= decl_types

            if first:
                first = False
                code += "\n"
            else:
                code += ",\n"
            code += "    " + decl_code

        # generate property list terminator
        terminator_macro = Type.lookup("DEFINE_PROP_END_OF_LIST")
        if first:
            code += "\n"
        else:
            code += ",\n"
        code += "    " + terminator_macro.gen_usage_string() + "\n}"

        init = Initializer(
            code = code,
            used_types = used_types.union([
                terminator_macro,
                state_struct
            ])
        )
        return init
Example #24
0
    def gen_irq_connect(self, irq, var_name):
        src = irq[0]
        if isinstance(src, IRQHub):
            raise RuntimeError("Cannot connect an IRQ to a hub (%u)."
                " A hub does use each its IRQ by itself." % src.id
            )

        if irq[2] is None:
            self.use_type_name("DEVICE")
            self.use_type_name("qdev_connect_gpio_out")

            return """\
    qdev_connect_gpio_out(@aDEVICE({src_name}),@s{src_index},@s{irq_name});
""".format(
    irq_name = var_name,
    src_name = self.node_map[src],
    src_index = irq[1]
            )
        else:
            sysbus_name = Type.lookup("SYSBUS_DEVICE_GPIO_IRQ").text
            if sysbus_name == "\"%s\"" % irq[2] or "SYSBUS_DEVICE_GPIO_IRQ" == irq[2]:
                self.use_type_name("sysbus_connect_irq")
                self.use_type_name("SYS_BUS_DEVICE")

                return """\
    sysbus_connect_irq(@aSYS_BUS_DEVICE({src_name}),@s{src_index},@s{irq_name});
""".format(
    irq_name = var_name,
    src_name = self.node_map[src],
    src_index = irq[1]
                )
            else:
                self.use_type_name("DEVICE")
                self.use_type_name("qdev_connect_gpio_out_named")
                if Type.exists(irq[2]):
                    self.use_type_name(irq[2])

                return """\
    qdev_connect_gpio_out_named(@aDEVICE({src_name}),@s{gpio_name},@s{src_index},@s{irq_name});
""".format(
    irq_name = var_name,
    src_name = self.node_map[src],
    src_index = irq[1],
    gpio_name = irq[2] if Type.exists(irq[2]) else "\"%s\"" % irq[2]
                )
Example #25
0
 def find_macro(self):
     return Type.lookup("PCI_DEVICE_ID_%s_%s" %
                        (self.vendor.name, self.name))
Example #26
0
 def find_macro(self):
     return Type.lookup("PCI_VENDOR_ID_%s" % self.name)
Example #27
0
 def find_macro(self):
     return Type.lookup("PCI_CLASS_%s" % self.name)
Example #28
0
    def generate_source(self):
        self.device_reset = Function(
            "%s_reset" % self.qtn.for_id_name,
            body="""\
    __attribute__((unused))@b{Struct}@b*s@b=@s{UPPER}(dev);
""".format(
                Struct=self.state_struct.name,
                UPPER=self.type_cast_macro.name,
            ),
            args=[Type.lookup("DeviceState").gen_var("dev", True)],
            static=True,
            used_types=[self.state_struct])
        self.source.add_type(self.device_reset)

        realize_code = ''
        realize_used_types = set()
        realize_used_globals = []
        s_is_used = False

        if self.mem_bar_num > 0:
            s_is_used = True
            realize_used_types.update([
                Type.lookup("sysbus_init_mmio"),
                Type.lookup("memory_region_init_io"),
                Type.lookup("Object")
            ])

        for barN in range(0, self.mem_bar_num):
            size_macro = self.mem_bar_size_macros[barN]
            realize_used_types.add(size_macro)

            component = self.get_Ith_mem_bar_id_component(barN)

            read_func = QOMType.gen_mmio_read(
                name=self.qtn.for_id_name + "_" + component + "_read",
                struct_name=self.state_struct.name,
                type_cast_macro=self.type_cast_macro.name,
                regs=self.bars.get(barN, None))

            write_func = QOMType.gen_mmio_write(
                name=self.qtn.for_id_name + "_" + component + "_write",
                struct_name=self.state_struct.name,
                type_cast_macro=self.type_cast_macro.name,
                regs=self.bars.get(barN, None))

            write_func.extra_references = {read_func}

            self.source.add_types([read_func, write_func])

            ops_init = Initializer(used_types=[read_func, write_func],
                                   code="""{{
    .read = {read},
    .write = {write}
}}""".format(read=read_func.name, write=write_func.name))

            ops = Type.lookup("MemoryRegionOps").gen_var(
                name=self.gen_Ith_mem_bar_ops_name(barN),
                pointer=False,
                initializer=ops_init,
                static=True)

            self.source.add_global_variable(ops)
            realize_used_globals.append(ops)

            realize_code += """
    memory_region_init_io(@a&s->{bar},@sOBJECT(dev),@s&{ops},@ss,@s{TYPE_MACRO},@s{size});
    pci_register_bar(@a&s->parent_obj,@s{barN},@sPCI_BASE_ADDRESS_SPACE_MEMORY,@s&s->{bar});
""".format(barN=barN,
            bar=self.get_Ith_mem_bar_name(barN),
            ops=self.gen_Ith_mem_bar_ops_name(barN),
            TYPE_MACRO=self.qtn.type_macro,
            size=size_macro.name)

        if self.msi_messages_num > 0:
            msi_init_type = Type.lookup("msi_init")
            s_is_used = True

            realize_code += """
    msi_init(dev,@s%s,@s%s,@s%s,@s%s%s);
""" % (self.msi_cap_offset.gen_usage_string(),
            self.msi_vectors.gen_usage_string(),
            self.msi_64bit.gen_usage_string(),
            self.msi_masking.gen_usage_string(),
            ",@serrp" if msi_init_type.args[-1].type \
                   == Pointer(Pointer(Type.lookup("Error"))) else ""
            )

            realize_used_types.update(self.msi_types)
            realize_used_types.add(msi_init_type)

        self.device_realize = self.gen_realize(
            "PCIDevice",
            code=realize_code,
            s_is_used=s_is_used,
            used_types=realize_used_types,
            used_globals=realize_used_globals)
        self.source.add_type(self.device_realize)

        code = ""
        used_types = set([self.state_struct])
        used_s = False

        if self.msi_messages_num > 0:
            code += """
    msi_uninit(dev);
"""
            used_types.add(Type.lookup("msi_uninit"))

        if self.nic_num > 0:
            code += "\n"
            used_s = True

            del_nic = Type.lookup("qemu_del_nic")
            used_types.add(del_nic)

            for nicN in xrange(self.nic_num):
                nic_name = self.nic_name(nicN)
                code += "    %s(s->%s);\n" % (del_nic.name, nic_name)

        if self.timer_num > 0:
            used_s = True
            code += "\n"
            used_types.update(
                [Type.lookup("timer_del"),
                 Type.lookup("timer_free")])

            for timerN in range(self.timer_num):
                code += """    timer_del(s->{timerN});
    timer_free(s->{timerN});
""".format(timerN=self.timer_name(timerN))

        self.device_exit = Function(
            name="%s_exit" % self.qtn.for_id_name,
            args=[Type.lookup("PCIDevice").gen_var("dev", pointer=True)],
            static=True,
            used_types=used_types,
            body="""\
    {unused}{Struct}@b*s@b=@s{UPPER}(dev);
{extra_code}\
""".format(unused="" if used_s else "__attribute__((unused))@b",
           Struct=self.state_struct.name,
           UPPER=self.type_cast_macro.name,
           extra_code=code))
        self.source.add_type(self.device_exit)

        self.vmstate = self.gen_vmstate_var(self.state_struct)

        self.source.add_global_variable(self.vmstate)

        self.properties = self.gen_properties_global(self.state_struct)

        self.source.add_global_variable(self.properties)

        self.vmstate.extra_references = {self.properties}

        self.class_init = Function(
            name="%s_class_init" % self.qtn.for_id_name,
            body="""\
    DeviceClass@b*dc@b=@sDEVICE_CLASS(oc);
    PCIDeviceClass@b*pc@b=@sPCI_DEVICE_CLASS(oc);

    pc->realize@b@b@b{pad}=@s{dev}_realize;
    dc->reset@b@b@b@b@b{pad}=@s{dev}_reset;
    pc->exit@b@b@b@b@b@b{pad}=@s{dev}_exit;
    pc->vendor_id@b{pad}=@s{vendor_macro};
    pc->device_id@b{pad}=@s{device_macro};
    pc->class_id@b@b{pad}=@s{pci_class_macro};{subsys_id}{subsys_vid}
    pc->revision@b@b{pad}=@s{revision};
    dc->vmsd@b@b@b@b@b@b{pad}=@s&vmstate_{dev};
    dc->props@b@b@b@b@b{pad}=@s{dev}_properties;
""".format(dev=self.qtn.for_id_name,
           revision=self.revision,
           vendor_macro=self.vendor_macro.name,
           device_macro=self.device_macro.name,
           pci_class_macro=self.pci_class_macro.name,
           subsys_id='' if self.subsystem_macro is None else ("""
    pc->subsystem_id@b@b@b@b@b@b@b@b=@s%s;""" % self.subsystem_macro.name),
           subsys_vid='' if self.subsystem_vendor_macro is None else ("""
    pc->subsystem_vendor_id@b=@s%s;""" % self.subsystem_vendor_macro.name),
           pad='@b@b@b@b@b@b@b@b@b@b' if self.subsystem_vendor_macro else ''),
            args=[
                Type.lookup("ObjectClass").gen_var("oc", True),
                Type.lookup("void").gen_var("opaque", True),
            ],
            static=True,
            used_types=[
                Type.lookup("DeviceClass"),
                Type.lookup("PCIDeviceClass"), self.device_realize,
                self.device_reset, self.device_exit, self.vendor_macro,
                self.device_macro, self.pci_class_macro
            ],
            used_globals=[self.vmstate, self.properties])
        self.source.add_type(self.class_init)

        instance_init_used_types = set()
        instance_init_code = ""
        s_is_used = False

        self.instance_init = self.gen_instance_init_fn(
            self.state_struct,
            code=instance_init_code,
            s_is_used=s_is_used,
            used_types=instance_init_used_types)
        self.source.add_type(self.instance_init)

        self.type_info = self.gen_type_info_var(self.state_struct,
                                                self.instance_init,
                                                self.class_init,
                                                parent_tn="TYPE_PCI_DEVICE")

        self.source.add_global_variable(self.type_info)

        self.register_types = self.gen_register_types_fn(self.type_info)

        self.source.add_type(self.register_types)

        type_init_usage_init = Initializer(
            code={"function": self.register_types})
        self.source.add_type(
            Type.lookup("type_init").gen_usage(type_init_usage_init))

        # order life cycle functions
        self.device_reset.extra_references = {self.device_realize}
        self.device_exit.extra_references = {self.device_reset}

        return self.source.generate()
Example #29
0
    def generate_source(self):
        s_is_used = False

        all_regs = []
        for idx, regs in self.mmio.items():
            if idx >= self.mmio_num:
                continue
            all_regs.extend(regs)
        for idx, regs in self.pio.items():
            if idx >= self.pio_num:
                continue
            all_regs.extend(regs)

        reg_resets = []

        used_types = set([self.state_struct])

        for reg in all_regs:
            name = reg.name
            if name is None or name == "gap":
                continue
            qtn = QemuTypeName(name)

            s_is_used = True

            reg_resets.append("s->%s@b=@s%s;" %
                              (qtn.for_id_name, reg.reset.gen_c_code()))

            warb = reg.warbits
            if warb.v:
                # forbid writing to WAR bits just after reset
                wm = reg.wmask
                if wm.v == (1 << (8 * reg.size)) - 1:
                    if reg.size < 4:
                        # Avoid gcc "overflow" warning: large integer
                        # implicitly truncated to unsigned type
                        cast_type = "uint%u_t" % (8 * reg.size)
                        used_types.add(Type[cast_type])
                        cast = "(%s)" % cast_type
                    else:
                        cast = ""

                    reg_resets.append(
                        "s->%s_war@b=@s%s~%s;" %
                        (qtn.for_id_name, cast, warb.gen_c_code()))
                elif wm.v:
                    reg_resets.append(
                        "s->%s_war@b=@s%s@s&@b~%s;" %
                        (qtn.for_id_name, wm.gen_c_code(), warb.gen_c_code()))

        self.device_reset = Function(
            "%s_reset" % self.qtn.for_id_name,
            body="""\
    {unused}{Struct}@b*s@b=@s{UPPER}(dev);{reset}
""".format(unused="" if s_is_used else "__attribute__((unused))@b",
           Struct=self.state_struct.name,
           UPPER=self.type_cast_macro.name,
           reset="\n\n    " + "\n    ".join(reg_resets) if reg_resets else ""),
            args=[Type.lookup("DeviceState").gen_var("dev", True)],
            static=True,
            used_types=used_types)

        self.source.add_type(self.device_reset)

        self.device_realize = self.gen_realize("DeviceState")
        self.source.add_type(self.device_realize)

        s_is_used = False
        instance_init_code = ''
        instance_init_used_types = set()
        instance_init_used_globals = []

        if self.mmio_num > 0:
            instance_init_used_types.update([
                Type.lookup("sysbus_init_mmio"),
                Type.lookup("memory_region_init_io"),
                Type.lookup("Object")
            ])

        for mmioN in range(0, self.mmio_num):
            size_macro = self.mmio_size_macros[mmioN]
            instance_init_used_types.add(size_macro)

            component = self.get_Ith_mmio_id_component(mmioN)

            regs = self.mmio.get(mmioN, None)

            read_func = QOMType.gen_mmio_read(
                name=self.qtn.for_id_name + "_" + component + "_read",
                struct_name=self.state_struct.name,
                type_cast_macro=self.type_cast_macro.name,
                regs=regs)

            write_func = QOMType.gen_mmio_write(
                name=self.qtn.for_id_name + "_" + component + "_write",
                struct_name=self.state_struct.name,
                type_cast_macro=self.type_cast_macro.name,
                regs=regs)

            impl = ""

            if regs:
                reg_sizes = set(reg.size for reg in regs)

                size = regs[0].size  # note that all sizes are equal

                if len(reg_sizes) == 1 and size < 8:  # 8 is max size by impl.
                    impl = """,
    .impl = {{
        .max_access_size = {size}
    }}""".format(size=size)

            write_func.extra_references = {read_func}

            self.source.add_types([read_func, write_func])

            ops_init = Initializer(used_types=[read_func, write_func],
                                   code="""{{
    .read@b=@s{read},
    .write@b=@s{write}{impl}
}}""".format(read=read_func.name, write=write_func.name, impl=impl))

            ops = Type.lookup("MemoryRegionOps").gen_var(
                name=self.gen_Ith_mmio_ops_name(mmioN),
                pointer=False,
                initializer=ops_init,
                static=True)

            self.source.add_global_variable(ops)
            instance_init_used_globals.append(ops)

            instance_init_code += """
    memory_region_init_io(@a&s->{mmio},@sobj,@s&{ops},@ss,@s{TYPE_MACRO},\
@s{size});
    sysbus_init_mmio(@aSYS_BUS_DEVICE(obj),@s&s->{mmio});
""".format(mmio=self.get_Ith_mmio_name(mmioN),
            ops=self.gen_Ith_mmio_ops_name(mmioN),
            TYPE_MACRO=self.qtn.type_macro,
            size=size_macro.name)
            s_is_used = True

        if self.pio_num > 0:
            instance_init_used_types.update([
                Type.lookup("sysbus_add_io"),
                Type.lookup("memory_region_init_io"),
                Type.lookup("Object"),
                Type.lookup("sysbus_init_ioports")
            ])

        for pioN in range(0, self.pio_num):
            size_macro = self.pio_size_macros[pioN]
            address_macro = self.pio_address_macros[pioN]
            instance_init_used_types.update([size_macro, address_macro])

            component = self.get_Ith_pio_id_component(pioN)

            read_func = QOMType.gen_mmio_read(
                name=self.qtn.for_id_name + "_" + component + "_read",
                struct_name=self.state_struct.name,
                type_cast_macro=self.type_cast_macro.name,
                regs=self.pio.get(pioN, None))

            write_func = QOMType.gen_mmio_write(
                name=self.qtn.for_id_name + "_" + component + "_write",
                struct_name=self.state_struct.name,
                type_cast_macro=self.type_cast_macro.name,
                regs=self.pio.get(pioN, None))

            write_func.extra_references = {read_func}

            self.source.add_types([read_func, write_func])

            ops_init = Initializer(used_types=[read_func, write_func],
                                   code="""{{
    .read@b=@s{read},
    .write@b=@s{write}
}}""".format(read=read_func.name, write=write_func.name))

            ops = Type.lookup("MemoryRegionOps").gen_var(
                name=self.gen_Ith_pio_ops_name(pioN),
                pointer=False,
                initializer=ops_init,
                static=True)

            self.source.add_global_variable(ops)
            instance_init_used_globals.append(ops)

            instance_init_code += """
    memory_region_init_io(@a&s->{pio},@sobj,@s&{ops},@ss,@s{TYPE_MACRO},\
@s{size});
    sysbus_add_io(@aSYS_BUS_DEVICE(obj),@s{addr},@s&s->{pio});
    sysbus_init_ioports(@aSYS_BUS_DEVICE(obj),@s{addr},@s{size});
""".format(pio=self.get_Ith_io_name(pioN),
            ops=self.gen_Ith_pio_ops_name(pioN),
            TYPE_MACRO=self.qtn.type_macro,
            size=size_macro.name,
            addr=address_macro.name)
            s_is_used = True

        if self.out_irq_num > 0:
            instance_init_used_types.update(
                [Type.lookup("qemu_irq"),
                 Type.lookup("sysbus_init_irq")])

            instance_init_code += "\n"

            for irqN in range(0, self.out_irq_num):
                instance_init_code += """\
    sysbus_init_irq(@aSYS_BUS_DEVICE(obj),@s&s->%s);
""" % self.get_Ith_irq_name(irqN)

        if self.in_irq_num > 0:
            self.irq_handler = Type["qemu_irq_handler"].use_as_prototype(
                name=self.qtn.for_id_name + "_irq_handler",
                static=True,
                used_types=[self.state_struct, self.type_cast_macro],
                body="""\
    __attribute__((unused))@b{Struct}@b*s@b=@s{UPPER}(opaque);
""".format(
                    Struct=self.state_struct.name,
                    UPPER=self.type_cast_macro.name,
                ))

            self.source.add_type(self.irq_handler)

            instance_init_code += """
    qdev_init_gpio_in(@aDEVICE(obj),@s{handler},@s{irqs});
""".format(handler=self.irq_handler.name, irqs=self.in_irq_macro.name)

            instance_init_used_types.update([
                self.irq_handler, self.in_irq_macro,
                Type.lookup("qdev_init_gpio_in"),
                Type.lookup("DEVICE")
            ])

        self.instance_init = self.gen_instance_init_fn(
            self.state_struct,
            code=instance_init_code,
            s_is_used=s_is_used,
            used_types=instance_init_used_types,
            used_globals=instance_init_used_globals)

        self.source.add_type(self.instance_init)

        # `unrealized` method code generation
        code = ""
        used_s = False
        used_types = set([self.state_struct, self.type_cast_macro])

        if self.timer_num > 0:
            used_s = True
            code += "\n"
            used_types.update(
                [Type.lookup("timer_del"),
                 Type.lookup("timer_free")])

            for timerN in range(self.timer_num):
                code += """    timer_del(s->{timerN});
    timer_free(s->{timerN});
""".format(timerN=self.timer_name(timerN))

        self.device_unrealize = Function(
            self.qtn.for_id_name + "_unrealize",
            args=[
                Pointer(Type.lookup("DeviceState")).gen_var("dev"),
                Pointer(Pointer(Type.lookup("Error"))).gen_var("errp")
            ],
            static=True,
            used_types=used_types,
            body="""    {unused}{Struct}@b*s@b=@s{CAST}(dev);
{extra_code}""".format(unused="" if used_s else "__attribute__((unused))@b",
                       Struct=self.state_struct.name,
                       CAST=self.type_cast_macro.name,
                       extra_code=code))
        self.source.add_type(self.device_unrealize)

        self.vmstate = self.gen_vmstate_var(self.state_struct)

        self.source.add_global_variable(self.vmstate)

        self.properties = self.gen_properties_global(self.state_struct)

        self.source.add_global_variable(self.properties)

        self.vmstate.extra_references = {self.properties}

        self.class_init = Function(
            name="%s_class_init" % self.qtn.for_id_name,
            body="""\
    DeviceClass@b*dc@b=@sDEVICE_CLASS(oc);

    dc->realize@b@b@b=@s{dev}_realize;
    dc->reset@b@b@b@b@b=@s{dev}_reset;
    dc->unrealize@b=@s{dev}_unrealize;
    dc->vmsd@b@b@b@b@b@b=@s&vmstate_{dev};
    dc->props@b@b@b@b@b=@s{dev}_properties;
""".format(dev=self.qtn.for_id_name),
            args=[
                Type.lookup("ObjectClass").gen_var("oc", True),
                Type.lookup("void").gen_var("opaque", True),
            ],
            static=True,
            used_types=[
                Type.lookup("DeviceClass"), self.device_realize,
                self.device_reset, self.device_unrealize
            ],
            used_globals=[self.vmstate, self.properties])

        self.source.add_type(self.class_init)

        self.type_info = self.gen_type_info_var(
            self.state_struct,
            self.instance_init,
            self.class_init,
            parent_tn="TYPE_SYS_BUS_DEVICE")

        self.source.add_global_variable(self.type_info)

        self.register_types = self.gen_register_types_fn(self.type_info)

        self.source.add_type(self.register_types)

        type_init_usage_init = Initializer(
            code={"function": self.register_types})
        self.source.add_type(
            Type.lookup("type_init").gen_usage(type_init_usage_init))

        # order life cycle functions
        self.device_realize.extra_references = {self.instance_init}
        self.device_reset.extra_references = {self.device_realize}
        self.device_unrealize.extra_references = {self.device_reset}

        return self.source.generate()
Example #30
0
File: qom.py Project: laerreal/qdt
 def timer_declare_fields(self):
     for index in range(self.timer_num):
         self.add_state_field(
             QOMStateField(Pointer(Type.lookup("QEMUTimer")),
                           self.timer_name(index),
                           save=True))