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

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

    # machine type definition structure
    type_machine_macro = Type["TYPE_MACHINE"]
    type_machine_suf_macro = Type["TYPE_MACHINE_SUFFIX"]

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

    # machine type registration function
    mach.type_reg_func = Function("machine_init_%s" % mach.qtn.for_id_name,
                                  body="""\
    type_register(&{type_info});
""".format(type_info=mach.type_info.name),
                                  static=True,
                                  used_types=[Type["type_register"]],
                                  used_globals=[mach.type_info])
    mach.source.add_type(mach.type_reg_func)

    # Main machine registration macro
    def_type = get_vp("machine initialization function register type name")
    machine_init_def_args = Initializer(code={"function": mach.type_reg_func})
    mach.source.add_type(
        Type[def_type].gen_usage(initializer=machine_init_def_args))
Beispiel #2
0
    def setUp(self):
        super(TestOpaqueCode, self).setUp()

        name = type(self).__name__

        hdr = Header(name.lower() + ".h", protection=False)

        test_var = Type["int"]("test_var")
        test_func = Function(name="test_func")

        opaque_top = OpaqueCode("""\
/* Generic comment above macros */
""",
                                weight=0)

        opaque_bottom = OpaqueCode("""
/* A comment at bottom of file */
""",
                                   weight=10)

        opaque_middle = OpaqueCode("""
/* How to use test_var and test_func. */

""",
                                   used_variables=[test_var],
                                   used_types=[test_func]
                                   # Default weight (5)
                                   )

        hdr.add_types([
            # Yields #define statement with weight 1
            Macro("TEST_MACRO"),
            # Yields function declaration with weight 6
            Function(name="another_test_func"),
            opaque_middle,
            opaque_bottom,
            opaque_top
        ])

        hdr_content = """\
/* {path} */

/* Generic comment above macros */

#define TEST_MACRO

extern int test_var;
void test_func(void);

/* How to use test_var and test_func. */

void another_test_func(void);

/* A comment at bottom of file */
""".format(path=hdr.path)

        self.files = [(hdr, hdr_content)]
Beispiel #3
0
    def setUp(self):
        super(TestSeparateCases, self).setUp()

        src = Source(type(self).__name__.lower() + ".c")

        i = Type["int"]("i")
        src.add_type(
            Function(name="func_a",
                     body=BodyTree()(Declare(OpDeclareAssign(i, 0)),
                                     BranchSwitch(i, separate_cases=True)(
                                         SwitchCase(1), SwitchCase(2)))))

        src_content = """\
/* {} */

void func_a(void)
{{
    int i = 0;
    switch (i) {{
    case 1:
        break;

    case 2:
        break;

    default:
        break;
    }}
}}

""".format(src.path)

        self.files = [(src, src_content)]
Beispiel #4
0
    def setUp(self):
        super(TestRedirectionToDeclaration, self).setUp()
        name = type(self).__name__

        private_h = Header("private.h")
        private_h.add_type(Structure("Private"))

        public_h = Header("public.h")
        public_h.add_types([
            Type["Private"].gen_forward_declaration(),
            Function("public_func")
        ])

        private_c = Source("private.c")
        public_func_impl = Type["public_func"].gen_definition()
        private_c.add_type(public_func_impl)

        src = Source(name.lower() + ".c").add_global_variable(
            # It must internally re-direct pointer from type "Private"
            # to "Private.declaration", its forward declaration.
            Pointer(Type["Private"])("handler"))
        src.add_type(Pointer(public_func_impl, name="cb_ptr"))

        src_content = """\
/* %s */

#include "public.h"

typedef void (*cb_ptr)(void);
Private *handler __attribute__((unused));

""" % (name.lower() + ".c")

        self.files = [(src, src_content)]
Beispiel #5
0
    def setUp(self):
        super(TestLabelAndGotoGeneration, self).setUp()
        name = type(self).__name__

        src = Source(name.lower() + ".c")

        lbl = Label("begin")
        i = Type["int"]("i")

        src.add_type(
            Function(name="main",
                     body=BodyTree()(Declare(i), lbl, OpAssign(i, OpAdd(i, 1)),
                                     Goto(lbl))))

        src_content = """\
/* {} */

void main(void)
{{
    int i;
begin:
    i = i + 1;
    goto begin;
}}

""".format(src.path)

        self.files = [(src, src_content)]
Beispiel #6
0
    def setUp(self):
        super(TestHeaderInclusion, self).setUp()
        name = type(self).__name__

        f = Function(name="test_f")
        f_def = f.gen_definition()

        hdr = Header(name.lower() + ".h").add_type(f)
        hdr_content = """\
/* {path} */
#ifndef INCLUDE_{fname_upper}_H
#define INCLUDE_{fname_upper}_H

void test_f(void);
#endif /* INCLUDE_{fname_upper}_H */
""".format(path=hdr.path, fname_upper=name.upper())

        src1 = Source(name.lower() + ".c").add_type(f_def)
        src1_content = """\
/* {} */

void test_f(void) {{}}

""".format(src1.path)

        src2 = Source(name.lower() + "2.c").add_type(
            Function(
                name="func_a",
                body=BodyTree()(
                    Call(f_def)  # use function definition to Call
                )))
        src2_content = """\
/* {} */

#include "{}"

void func_a(void)
{{
    test_f();
}}

""".format(src2.path, hdr.path)

        self.files = [(hdr, hdr_content), (src1, src1_content),
                      (src2, src2_content)]
Beispiel #7
0
def define_qemu_2_6_5_types():
    add_base_types()
    define_only_qemu_2_6_0_types()

    if get_vp("char backend hotswap handler"):
        Header["chardev/char-fe.h"].add_type(
            Function("BackendChangeHandler",
                     ret_type=Type["int"],
                     args=[Type["void"].gen_var("opaque", pointer=True)]))
Beispiel #8
0
    def gen_register_types_fn(self, *infos):
        fn = Function(name=self.gen_register_types_name(),
                      body=BodyTree()(*[
                          Call(Type["type_register_static"], OpAddr(info))
                          for info in infos
                      ]),
                      static=True)

        return fn
Beispiel #9
0
    def timer_gen_cb(self, index, source, state_struct, type_cast_macro):
        timer_cb = Function(name=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=[Pointer(Type["void"])("opaque")],
                            static=True,
                            used_types=set([state_struct, type_cast_macro]))
        source.add_type(timer_cb)
        return timer_cb
Beispiel #10
0
def define_msi_init_2_6_0():
    Header["hw/pci/msi.h"].add_type(
        Function("msi_init",
                 ret_type=Type["int"],
                 args=[
                     Type["PCIDevice"].gen_var("dev", pointer=True),
                     Type["uint8_t"].gen_var("offset"),
                     Type["unsigned int"].gen_var("nr_vectors"),
                     Type["bool"].gen_var("msi64bit"),
                     Type["bool"].gen_var("msi_per_vector_mask")
                 ]))
Beispiel #11
0
def define_msi_init_2_6_0():
    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")
                 ]))
Beispiel #12
0
    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
Beispiel #13
0
def define_msi_init_2_6_5():
    Header["hw/pci/msi.h"].add_type(
        Function(name="msi_init",
                 ret_type=Type["int"],
                 args=[
                     Pointer(Type["PCIDevice"])("dev"),
                     Type["uint8_t"]("offset"),
                     Type["unsigned int"]("nr_vectors"),
                     Type["bool"]("msi64bit"),
                     Type["bool"]("msi_per_vector_mask"),
                     Pointer(Pointer(Type["Error"]))("errp")
                 ]))
Beispiel #14
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))
Beispiel #15
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
Beispiel #16
0
    def _parse(self):
        funclines = {}
        source = None

        with open(self.filename) as f:
            for line in f:
                line = line.strip()

                if line == 'end_of_record':
                    if source is not None:
                        directory, filename = os.path.split(source.filename)
                        self.sources[directory][filename] = source
                        source = None
                else:
                    key, argstr = tuple(line.split(':'))
                    args = argstr.split(',')

                    if key == 'SF':
                        fname = args[0]
                        if fname.startswith(self.basepath):
                            source = Source(args[0])
                        else:
                            source = None

                    elif source is not None:

                        if key == 'FN':
                            name = args[1]
                            funclines[name] = int(args[0])

                        elif key == 'FNDA':
                            hits = int(args[0])
                            name = args[1]
                            func = Function(funclines[name], name, hits)
                            source.add_function(func)

                        elif key == 'BRDA':
                            line = int(args[0])
                            path = int(args[2])
                            hits = 0 if args[3] == '-' else int(args[3])
                            source.add_branch(Branch(line, path, hits))

                        elif key == 'DA':
                            line = int(args[0])
                            hits = int(args[1])
                            source.add_line(Line(line, hits))
Beispiel #17
0
    def setUp(self):
        super(TestEnumerations, self).setUp()
        name = type(self).__name__

        try:
            h = Header["enums.h"]
        except:
            h = Header("enums.h")
        h.add_type(Enumeration("A", [("one", 1), ("two", 2)]))

        a = Type["int"]("a")
        b = Type["int"]("b")
        c = Type["int"]("c")

        src = Source(name.lower() + ".c").add_types([
            Enumeration("B", [("three", 3), ("four", 4)], "B"),
            Function(name="main",
                     body=BodyTree()(Declare(a, b, c),
                                     OpAssign(a, Type["A"].one),
                                     OpAssign(b, Type["B"].three),
                                     OpAssign(c, Type["four"])))
        ])

        src_content = """\
/* {} */

#include "enums.h"

enum B {{
    three = 3,
    four = 4
}};

void main(void)
{{
    int a, b, c;
    a = one;
    b = three;
    c = four;
}}

""".format(src.path)

        self.files = [(src, src_content)]
Beispiel #18
0
    def fill_source(self):
        """ Adds a hook callback in MMIO read handler.
        """

        super(CustomSBDType, self).fill_source()

        # Now, code of device's module is generated. It's time to patch it!

        # Assuming, your code uses functions and types from your header.
        custom_h = Header("custom-api.h", is_global=True)

        # If your header is inside Qemu source tree and under Git, then you
        # likely should write above statement as follows:
        #
        # custom_h = Header["custom/custom-api.h"]
        #
        # Because the header is already registered.

        # To use custom functions (and other things) you must declare them.
        # Note that, macros are added automatically if header is inside Qemu
        # source tree.
        # Only name is sufficient because no code will be generated for them.
        custom_h.add_types([Function("custom_callback")])

        read_func = self.find_mmio_read_helper(0)

        # We are going to pass second and following argument values of the
        # read helper to the custom callback.
        # Of course, you can made different choice in your code.
        args2callback = read_func.args[1:]

        # Insert function call statement before 3-nd statement.
        # Note, first statements are likely variable declarations.
        # This is for prettiness only.
        read_func.body.children.insert(2,
                                       Call("custom_callback", *args2callback))
Beispiel #19
0
    def gen_realize(self, dev_type_name,
        code = "",
        s_is_used = False,
        used_types = [],
        used_globals = []
    ):
        total_used_types = set([self.state_struct, self.type_cast_macro])
        total_used_types.update(used_types)

        total_used_globals = list(used_globals)

        if self.char_num > 0:
            if get_vp()["v2.8 chardev"]:
                helper_name = "qemu_chr_fe_set_handlers"
                char_name_fmt = "&s->%s"
                extra_args = ",@sNULL,@strue"
            else:
                helper_name = "qemu_chr_add_handlers"
                char_name_fmt = "s->%s"
                extra_args = ""

            total_used_types.add(Type[helper_name])
            code += "\n"
            s_is_used = True

            for chrN in range(self.char_num):
                chr_name = self.char_name(chrN)
                har_handlers = self.char_gen_handlers(chrN, self.source,
                    self.state_struct, self.type_cast_macro
                )
                code += """\
    if@b({chr_name})@b{{
        {helper_name}(@a{chr_name},@s{helpers},@ss{extra_args});
    }}
""".format(
    helper_name = helper_name,
    chr_name = char_name_fmt % chr_name,
    helpers = ",@s".join([h.name for h in har_handlers]),
    extra_args = extra_args
                )
                total_used_types.update(har_handlers)

        if self.block_num > 0:
            code += "\n"
            s_is_used = True
            # actually not, but user probably needed functions from same header
            total_used_types.add(Type["BlockDevOps"])

            for blkN in range(self.block_num):
                blk_name = self.block_name(blkN)
                code += """\
    if@b(s->%s)@b{
        /*@sTODO:@sImplement@sinteraction@swith@sblock@sdriver.@c@s*/
    }
""" % (blk_name
                )

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

            def_mac = Type["qemu_macaddr_default_if_unset"]
            fmt_info = Type["qemu_format_nic_info_str"]
            obj_tn = Type["object_get_typename"]
            obj_cast = Type["OBJECT"]
            def_cast = Type["DEVICE"]
            new_nic = Type["qemu_new_nic"]
            get_queue = Type["qemu_get_queue"]

            total_used_types.update([def_mac, fmt_info, obj_tn, obj_cast,
                def_cast, new_nic, get_queue
            ])

            for nicN in range(self.nic_num):
                conf_name = self.nic_conf_name(nicN)
                nic_name = self.nic_name(nicN)
                info = self.gen_net_client_info(nicN)

                self.source.add_global_variable(info)
                total_used_globals.append(info)

                code += """\
    {def_mac}(&s->{conf_name}.macaddr);
    s->{nic_name}@b=@s{new_nic}(@a&{info},@s&s->{conf_name},@s{obj_tn}\
({obj_cast}(s)),@s{def_cast}(s)->id,@ss);
    {fmt_info}(@a{get_queue}(s->{nic_name}),@ss->{conf_name}.macaddr.a);
""".format(
    def_mac = def_mac.name,
    conf_name = conf_name,
    nic_name = nic_name,
    new_nic = new_nic.name,
    info = info.name,
    obj_tn = obj_tn.name,
    obj_cast = obj_cast.name,
    def_cast = def_cast.name,
    fmt_info = fmt_info.name,
    get_queue = get_queue.name
                )

        fn = Function(
            name = "%s_realize" % self.qtn.for_id_name,
            body = """\
    {unused}{Struct}@b*s@b=@s{UPPER}(dev);
{extra_code}\
""".format(
    unused = "" if s_is_used else "__attribute__((unused))@b",
    Struct = self.state_struct.name,
    UPPER = self.type_cast_macro.name,
    extra_code = code
            ),
            args = [
                Pointer(Type[dev_type_name])("dev"),
                Pointer(Pointer(Type["Error"]))("errp")
            ],
            static = True,
            used_types = total_used_types,
            used_globals = total_used_globals
        )

        return fn
Beispiel #20
0
def machine_register_2_5(mach):
    # machine class definition function
    class_init = Function(
        name = "machine_%s_class_init" % mach.qtn.for_id_name,
        static = True,
        ret_type = Type["void"],
        args = [
            Pointer(Type["ObjectClass"])("oc"),
            Pointer(Type["void"])("opaque")
        ]
    )
    mc = Pointer(Type["MachineClass"])("mc")
    class_init.body = BodyTree()(
        Declare(
            OpDeclareAssign(
                mc,
                MCall(
                   "MACHINE_CLASS",
                    class_init.args[0]
                )
            )
        ),
        NewLine(),
        OpAssign(
            OpSDeref(mc, "name"),
            mach.qtn.for_id_name
        ),
        OpAssign(
            OpSDeref(mc, "desc"),
            mach.desc
        ),
        OpAssign(
            OpSDeref(mc, "init"),
            mach.instance_init
        )
    )
    mach.class_init = class_init
    mach.source.add_type(class_init)

    # machine type definition structure
    type_machine_macro = Type["TYPE_MACHINE"]
    type_machine_suf_macro = Type["TYPE_MACHINE_SUFFIX"]

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

    # machine type registration function
    mach.type_reg_func = Function(
        name = "machine_init_%s" % mach.qtn.for_id_name,
        body = BodyTree()(
            Call(
                "type_register",
                OpAddr(mach.type_info)
            )
        ),
        static = True
    )
    mach.source.add_type(mach.type_reg_func)

    # Main machine registration macro
    def_type = get_vp("machine initialization function register type name")
    machine_init_def_args = Initializer(
        code = { "function": mach.type_reg_func }
    )
    mach.source.add_type(
        Type[def_type].gen_type(initializer = machine_init_def_args)
    )
Beispiel #21
0
def machine_register_2_6(mach):
    # machine class definition function
    class_init = Function(
        name = "machine_%s_class_init" % mach.qtn.for_id_name,
        static = True,
        ret_type = Type["void"],
        args = [
            Pointer(Type["ObjectClass"])("oc"),
            Pointer(Type["void"])("opaque")
        ]
    )
    mc = Pointer(Type["MachineClass"])("mc")
    class_init.body = BodyTree()(
        Declare(
            OpDeclareAssign(
                mc,
                MCall(
                   "MACHINE_CLASS",
                    class_init.args[0]
                )
            )
        ),
        NewLine(),
        OpAssign(
            OpSDeref(mc, "desc"),
            mach.desc
        ),
        OpAssign(
            OpSDeref(mc, "init"),
            mach.instance_init
        )
    )
    mach.class_init = class_init
    mach.source.add_type(class_init)

    # machine type definition structure
    type_machine_macro = Type["TYPE_MACHINE"]
    type_machine_type_name_macro = Type["MACHINE_TYPE_NAME"]

    mach.type_info = Type["TypeInfo"](
        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_args = Initializer({ "function": mach.type_reg_func })
    mach.source.add_type(
        Type["type_init"].gen_type(initializer = machine_init_def_args)
    )
Beispiel #22
0
def define_only_qemu_2_6_0_types():
    # According to Qemu inclusion policy, each source file must include
    # qemu/osdep.h. This could be met using different ways. For now add a
    # reference to a fake type inside osdep.h.
    # TODO: the tweak must be handled using version API.
    osdep_fake_type = Type("FAKE_TYPE_IN_QEMU_OSDEP")

    if not get_vp("tcg_enabled is macro"):
        Header.lookup("qemu-common.h").add_types(
            [Function("tcg_enabled", ret_type=Type.lookup("bool"))])

    Header.lookup("tcg.h").add_types([
        Type("TCGv_i32"),
        Type("TCGv_i64"),
        Type("TCGv_ptr"),
        Type("TCGv_env"),
        Type("TCGv"),
        Function("tcg_global_mem_new_i32"),
        Function("tcg_global_mem_new_i64"),
        Function("tcg_op_buf_full")
    ])

    Header.lookup("tcg-op.h").add_types([
        Function("tcg_gen_insn_start"),
        Function("tcg_gen_goto_tb"),
        Function("tcg_gen_exit_tb")
    ])

    Header.lookup("tcg-op.h").add_types([
        # HLTTemp is a fake type intended to mark
        # variables which are to be replaced by this tool
        # preprocessor (still in progress)
        # HLTTemp is then converted to some existing QEMU types
        Type("HLTTemp")
    ])

    Header.lookup("qemu/osdep.h").add_types([osdep_fake_type])

    Header.lookup("exec/hwaddr.h").add_types([Type("hwaddr", False)
                                              ]).add_reference(osdep_fake_type)

    Header.lookup("exec/cpu-defs.h").add_types([
        Type("target_ulong", False),
    ])

    Header.lookup("exec/cpu_ldst.h").add_types([
        Function("cpu_ldub_code", ret_type=Type.lookup("uint8_t")),
        Function("cpu_lduw_code", ret_type=Type.lookup("uint16_t")),
        Function("cpu_ldl_code", ret_type=Type.lookup("uint32_t")),
        Function("cpu_ldq_code", ret_type=Type.lookup("uint64_t")),
    ])

    Header.lookup("qom/object.h").add_types([
        Type("ObjectClass", False),
        Type("Object", False),
        Structure(
            "TypeInfo",
            fields=[
                # These are required fields only
                Pointer(Type.lookup("const char")).gen_var("name"),
                Pointer(Type.lookup("const char")).gen_var("parent"),
                Pointer(Type.lookup("void")).gen_var("class_init")
            ]),
        Type("Type", False),
        Type("TypeImpl", False),
        Function(name="type_register_static",
                 ret_type=Type.lookup("TypeImpl"),
                 args=[Type.lookup("TypeInfo").gen_var("info", pointer=True)]),
        Function(name="type_register",
                 ret_type=Type.lookup("TypeImpl"),
                 args=[Type.lookup("TypeInfo").gen_var("info", pointer=True)]),
        Function("object_get_typename"),
        Function("object_property_set_str"),
        Function("object_property_set_link"),
        Function("object_property_set_bool"),
        Function("object_property_set_int"),
        Function("object_class_by_name"),
        Function("object_class_dynamic_cast"),
        Function("object_class_is_abstract")
    ]).add_reference(osdep_fake_type)

    Header.lookup("qom/cpu.h").add_types([
        Type("CPUState", False),
        Type("CPUClass", False),
        Type("vaddr", False),
        Type("MMUAccessType", False),
        Type("CPUBreakpoint", False),
        Function("qemu_init_vcpu",
                 args=[Type.lookup("CPUState").gen_var("cpu", pointer=True)]),
        Function("cpu_exec_realizefn"),
        Function("cpu_reset"),
        Function("cpu_generic_init")
    ]).add_reference(osdep_fake_type)

    Header.lookup("qapi/error.h").add_types([Type("Error")
                                             ]).add_reference(osdep_fake_type)

    Header.lookup("disas/bfd.h").add_types([Type("disassemble_info", False)
                                            ]).add_reference(osdep_fake_type)

    Header.lookup("qemu/fprintf-fn.h").add_types(
        [Type("fprintf_function", False)]).add_reference(osdep_fake_type)

    Header.lookup("exec/exec-all.h").add_types([
        Type("TranslationBlock", False),
        Function("tlb_fill",
                 args=[
                     Type.lookup("CPUState").gen_var("cs", pointer=True),
                     Type.lookup("target_ulong").gen_var("addr"),
                     Type.lookup("MMUAccessType").gen_var("access_type"),
                     Type.lookup("int").gen_var("mmu_idx"),
                     Type.lookup("uintptr_t").gen_var("retaddr")
                 ],
                 used_types=[]),
        Function("cpu_exec_init",
                 args=[
                     Type.lookup("CPUState").gen_var("cs", pointer=True),
                     Pointer(Pointer(Type.lookup("Error"))).gen_var("errp")
                 ]),
        Function("gen_intermediate_code"),
        Function("cpu_restore_state"),
        Function("cpu_loop_exit"),
        Function("cpu_loop_exit_restore"),
        Function("tlb_set_page")
    ]).add_reference(osdep_fake_type)

    Header.lookup("exec/gen-icount.h").add_types(
        [Function("gen_tb_start"),
         Function("gen_tb_end")])

    Header.lookup("exec/address-spaces.h").add_types(
        [Function("get_system_memory")]).add_reference(osdep_fake_type)

    Header.lookup("exec/memory.h").add_types([
        Type("MemoryRegion", False),
        Function(name="MemoryRegionOps_read",
                 ret_type=Type.lookup("uint64_t"),
                 args=[
                     Type.lookup("void").gen_var("opaque", pointer=True),
                     Type.lookup("hwaddr").gen_var("offset"),
                     Type.lookup("unsigned").gen_var("size")
                 ]),
        Function(name="MemoryRegionOps_write",
                 ret_type=Type.lookup("void"),
                 args=[
                     Type.lookup("void").gen_var("opaque", pointer=True),
                     Type.lookup("hwaddr").gen_var("offset"),
                     Type.lookup("uint64_t").gen_var("value"),
                     Type.lookup("unsigned").gen_var("size")
                 ]),
        Structure("MemoryRegionOps", [
            Type.lookup("MemoryRegionOps_read").gen_var("read"),
            Type.lookup("MemoryRegionOps_write").gen_var("write"),
        ]),
        Function(
            name="memory_region_init_io",
            args=[
                Type.lookup("MemoryRegion").gen_var("mr", pointer=True),
                # struct
                Type.lookup("Object").gen_var("owner", pointer=True),
                # const
                Type.lookup("MemoryRegionOps").gen_var("ops", pointer=True),
                Type.lookup("void").gen_var("opaque", pointer=True),
                Type.lookup("const char").gen_var("name", pointer=True),
                Type.lookup("uint64_t").gen_var("size")
            ]),
        Function("memory_region_init"),
        Function("memory_region_init_alias"),
        Function("memory_region_init_ram"),
        Function("memory_region_add_subregion_overlap"),
        Function("memory_region_add_subregion")
    ]).add_reference(osdep_fake_type)

    Header.lookup("exec/gdbstub.h").add_types([
        Function(name="gdb_get_reg8"),
        Function(name="gdb_get_reg16"),
        Function(name="gdb_get_reg32"),
        Function(name="gdb_get_reg64")
    ]).add_reference(osdep_fake_type)

    Header.lookup("exec/ioport.h").add_types(
        [Type("pio_addr_t", incomplete=False)]).add_reference(osdep_fake_type)

    Header.lookup("hw/boards.h").add_types(
        [Structure("MachineClass"),
         Structure("MachineState")]).add_reference(osdep_fake_type)

    Header.lookup("hw/sysbus.h").add_types([
        Type("SysBusDevice", False),
        Type("qemu_irq", False),
        Function(name="sysbus_init_mmio",
                 ret_type=Type.lookup("void"),
                 args=[
                     Type.lookup("SysBusDevice").gen_var("dev", pointer=True),
                     Type.lookup("MemoryRegion").gen_var("memory",
                                                         pointer=True)
                 ]),
        Function(name="sysbus_init_irq",
                 ret_type=Type.lookup("void"),
                 args=[
                     Type.lookup("SysBusDevice").gen_var("dev", pointer=True),
                     Type.lookup("qemu_irq").gen_var("p", pointer=True)
                 ]),
        Function(name="sysbus_add_io",
                 ret_type=Type.lookup("void"),
                 args=[
                     Type.lookup("SysBusDevice").gen_var("dev", pointer=True),
                     Type.lookup("hwaddr").gen_var("addr"),
                     Type.lookup("MemoryRegion").gen_var("mem", pointer=True)
                 ]),
        Function(name="sysbus_init_ioports",
                 ret_type=Type.lookup("void"),
                 args=[
                     Type.lookup("SysBusDevice").gen_var("dev", pointer=True),
                     Type.lookup("pio_addr_t").gen_var("dev"),
                     Type.lookup("pio_addr_t").gen_var("dev")
                 ]),
        Function("sysbus_mmio_map"),
        Function("sysbus_connect_irq")
    ]).add_reference(osdep_fake_type)

    Header.lookup("hw/irq.h").add_types([
        Function(name="qemu_irq_handler",
                 ret_type=Type.lookup("void"),
                 args=[
                     Type.lookup("void").gen_var("opaque", pointer=True),
                     Type.lookup("int").gen_var("n"),
                     Type.lookup("int").gen_var("level")
                 ]),
        Function("qemu_irq_split")
    ]).add_reference(osdep_fake_type)

    Header.lookup("hw/qdev-core.h").add_types([
        Type("DeviceClass", False),
        Type("DeviceState", False),
        Type("Property", False),
        Function(name="qdev_init_gpio_in",
                 ret_type=Type.lookup("void"),
                 args=[
                     Type.lookup("DeviceState").gen_var("dev", pointer=True),
                     Type.lookup("qemu_irq_handler").gen_var("handler"),
                     Type.lookup("int").gen_var("n")
                 ]),
        Pointer(
            Function(name="device_realize pointee",
                     args=[
                         Type.lookup("DeviceState").gen_var("dev",
                                                            pointer=True),
                         Pointer(Type.lookup("Error")).gen_var("errp",
                                                               pointer=True)
                     ]),
            name="DeviceRealize",
        ),
        Function(name="qdev_create"),
        Function(name="qdev_init_nofail"),
        Function(name="qdev_get_child_bus"),
        Structure(name="BusState"),
        Function(name="qdev_get_gpio_in"),
        Function(name="qdev_get_gpio_in_named"),
        Function(name="qdev_connect_gpio_out"),
        Function(name="qdev_connect_gpio_out_named")
    ]).add_reference(osdep_fake_type)

    Header.lookup("migration/vmstate.h").add_types([
        Type("VMStateDescription", False),
        Type("VMStateField", False),
        Function("vmstate_register_ram_global")
    ]).add_reference(osdep_fake_type)

    Header.lookup("qemu/module.h").add_reference(osdep_fake_type)

    Header.lookup("hw/pci/pci.h").add_types([
        Type("PCIDevice", False),
        Type("PCIDeviceClass", False),
        Function("pci_create_multifunction"),
        Type("PCIIOMMUFunc"),
    ]).add_reference(osdep_fake_type)

    Header.lookup("hw/pci/msi.h").add_types([
        Function(name="msi_uninit",
                 ret_type=Type.lookup("void"),
                 args=[Type.lookup("PCIDevice").gen_var("dev", pointer=True)])
    ]).add_reference(osdep_fake_type)

    Header.lookup("hw/pci/pci_bus.h").add_types([
        Type("PCIBus", incomplete=True)
    ]).add_references([Type.lookup("PCIIOMMUFunc"), osdep_fake_type])
    Header.lookup("hw/pci/pci_host.h").add_reference(osdep_fake_type)

    Header.lookup("qemu/typedefs.h").add_types([
        # BlockBackend is defined in internal block_int.h. Its fields may not
        # be accessed outside internal code. Methods from block-backend.h must
        # be used instead.
        Structure("BlockBackend"),
        Structure("I2CBus")  # the structure is defined in .c file
    ]).add_reference(osdep_fake_type)

    Header.lookup("qemu/bswap.h").add_types(
        [Function("bswap64"),
         Function("bswap32"),
         Function("bswap16")]).add_reference(osdep_fake_type)

    Header.lookup("hw/ide/internal.h").add_types(
        [Structure("IDEDMA")]).add_reference(osdep_fake_type)

    Header.lookup("hw/ide/ahci.h").add_references(
        [Type.lookup("IDEDMA"), osdep_fake_type])

    Header.lookup("hw/block/flash.h").add_references(
        [Type.lookup("VMStateDescription"), osdep_fake_type])

    Header.lookup("qemu/timer.h").add_types([
        Structure("QEMUTimer"),
        Function("timer_new_ns"),
        Function("timer_del"),
        Function("timer_free"),
        Type("QEMU_CLOCK_VIRTUAL")  # It is enumeration entry...
    ]).add_references([osdep_fake_type])

    Header.lookup("qemu/main-loop.h").add_types([
        Function("IOCanReadHandler",
                 ret_type=Type.lookup("int"),
                 args=[Pointer(Type.lookup("void")).gen_var("opaque")]),
        Function("IOReadHandler",
                 args=[
                     Pointer(Type.lookup("void")).gen_var("opaque"),
                     Pointer(Type.lookup("uint8_t"),
                             const=True).gen_var("buf"),
                     Type.lookup("int").gen_var("size")
                 ])
    ]).add_references([osdep_fake_type])

    if get_vp()["v2.8 chardev"]:
        chardev_types = [
            Function("qemu_chr_fe_set_handlers"),
            Structure("CharBackend")
        ]
    else:
        chardev_types = [
            Function("qemu_chr_add_handlers"),
            Structure("CharDriverState")
        ]

    Header.lookup(get_vp("header with IOEventHandler")).add_types([
        Function("IOEventHandler",
                 args=[
                     Pointer(Type.lookup("void")).gen_var("opaque"),
                     Type.lookup("int").gen_var("event")
                 ])
    ] + chardev_types).add_references([osdep_fake_type])

    Header.lookup("sysemu/block-backend.h").add_types([
        Structure("BlockDevOps"),
    ]).add_references([osdep_fake_type])

    Header.lookup("hw/isa/isa.h").add_types([Type("IsaDmaTransferHandler")])

    if get_vp()["include/hw/isa/i8257.h have IsaDmaTransferHandler reference"]:
        Header.lookup(get_vp()["i8257.h path"]).add_references([
            Type.lookup("IsaDmaTransferHandler"),
            Type.lookup("MemoryRegion")
        ])

    Header.lookup("net/net.h").add_types([
        Type("qemu_macaddr_default_if_unset"),
        Type("qemu_format_nic_info_str"),
        Type("qemu_new_nic"),
        Type("qemu_del_nic"),
        Type("qemu_get_queue"),
        Structure("NICConf"),
        Type("NICState"),
        Type("NetClientState"),
        Function("NetCanReceive",
                 ret_type=Type.lookup("int"),
                 args=[Pointer(Type.lookup("NetClientState")).gen_var("nc")]),
        Function("NetReceive",
                 ret_type=Type.lookup("ssize_t"),
                 args=[
                     Pointer(Type.lookup("NetClientState")).gen_var("nc"),
                     Pointer(Type.lookup("const uint8_t")).gen_var("buf"),
                     Type.lookup("size_t").gen_var("size")
                 ]),
        Function("LinkStatusChanged",
                 args=[Pointer(Type.lookup("NetClientState")).gen_var("nc")]),
        Function("NetCleanup",
                 args=[Pointer(Type.lookup("NetClientState")).gen_var("nc")]),
        Structure(
            "NetClientInfo",
            fields=[
                # "type" field type is enum NetClientDriver, but enum is not
                # supported by model
                Type.lookup("int").gen_var("type"),
                Type.lookup("size_t").gen_var("size"),
                Type.lookup("NetReceive").gen_var("receive"),
                Type.lookup("NetCanReceive").gen_var("can_receive"),
                Type.lookup("NetCleanup").gen_var("cleanup"),
                Type.lookup("LinkStatusChanged").gen_var("link_status_changed")
                # There are other fields but they are not needed.
            ]),
        Macro("NET_CLIENT_DRIVER_NIC")  # This is an enum item actually. It
        # is defined in auto generated "qapi-types.h" which is not presented in
        # registry but is included by "net.h" indirectly.
    ]).add_references([osdep_fake_type])

    Header.lookup("exec/helper-proto.h").add_type(Macro("HELPER_PROTO_H"))

    Header.lookup("disas/bfd.h").add_types([
        Type("bfd_vma", False),
        Type("bfd_byte", False),
        Type("const bfd_tyte", False),
        Function("bfd_getl64",
                 ret_type=Type.lookup("bfd_vma"),
                 args=[
                     Pointer(Type.lookup("const bfd_tyte")).gen_var(
                         "addr", pointer=True)
                 ]),
        Function("bfd_getl32",
                 ret_type=Type.lookup("bfd_vma"),
                 args=[
                     Pointer(Type.lookup("const bfd_tyte")).gen_var(
                         "addr", pointer=True)
                 ]),
        Function("bfd_getb32",
                 ret_type=Type.lookup("bfd_vma"),
                 args=[
                     Pointer(Type.lookup("const bfd_tyte")).gen_var(
                         "addr", pointer=True)
                 ]),
        Function("bfd_getl16",
                 ret_type=Type.lookup("bfd_vma"),
                 args=[
                     Pointer(Type.lookup("const bfd_tyte")).gen_var(
                         "addr", pointer=True)
                 ]),
        Function("bfd_getb16",
                 ret_type=Type.lookup("bfd_vma"),
                 args=[
                     Pointer(Type.lookup("const bfd_tyte")).gen_var(
                         "addr", pointer=True)
                 ])
    ])

    Header.lookup("disas/disas.h").add_types([Function("lookup_symbol")])
    Header.lookup("qemu/log.h").add_types([
        Function("qemu_loglevel_mask"),
        Function("qemu_log_in_addr_range"),
        Function("qemu_log_lock"),
        Function("qemu_log_unlock"),
        Function("qemu_log")
    ])
    Header.lookup("exec/log.h").add_types([Function("log_target_disas")])
Beispiel #23
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()
Beispiel #24
0
    def fill_source(self):
        glob_mem = get_vp("explicit global memory registration")

        all_nodes = sort_topologically(self.cpus + self.devices + self.buses +
                                       self.irqs + self.mems + self.irq_hubs)

        decl_code = ""
        def_code = ""
        self.reset_generator()

        skip_nl = False

        for idx, node in enumerate(all_nodes):
            if not skip_nl:
                if idx > 0:
                    def_code += "\n"
            else:
                skip_nl = False

            if isinstance(node, DeviceNode):
                self.use_type_name("qdev_init_nofail")
                self.use_type_name("BUS")
                if Type.exists(node.qom_type):
                    self.use_type_name(node.qom_type)

                dev_name = self.node_map[node]

                props_code = ""
                for p in node.properties:
                    self.use_type_name("OBJECT")
                    self.use_type_name(p.prop_type.set_f)
                    if Type.exists(p.prop_name):
                        self.use_type_name(p.prop_name)
                    if isinstance(p.prop_val, str) and Type.exists(p.prop_val):
                        self.use_type_name(p.prop_val)

                    props_code += """
    {set_func}(@aOBJECT({dev_name}),@s{value},@s{prop_name},@sNULL);\
""".format(set_func=p.prop_type.set_f,
                    dev_name=dev_name,
                    prop_name=p.prop_name if Type.exists(p.prop_name) else "\"%s\"" %
                    p.prop_name,
                    value=self.gen_prop_val(p))

                if isinstance(node, PCIExpressDeviceNode):
                    self.use_type_name("PCIDevice")
                    self.use_type_name("pci_create_multifunction")
                    self.use_type_name("bool")
                    self.use_type_name("DEVICE")

                    decl_code += "    PCIDevice *%s;\n" % dev_name
                    def_code += """\
    {dev_name} = pci_create_multifunction(@a{bus_name},@sPCI_DEVFN({slot},@s{func}),@s{multifunction},@s{qom_type});{props_code}
    qdev_init_nofail(DEVICE({dev_name}));
""".format(dev_name=dev_name,
                    bus_name=self.node_map[node.parent_bus],
                    qom_type=node.qom_type if Type.exists(node.qom_type) else "\"%s\"" %
                    node.qom_type,
                    props_code=props_code,
                    multifunction="true" if node.multifunction else "false",
                    slot=node.slot,
                    func=node.function)
                else:
                    self.use_type_name("DeviceState")
                    self.use_type_name("qdev_create")

                    decl_code += "    DeviceState *%s;\n" % dev_name

                    if ((node.parent_bus is None)
                            or isinstance(node.parent_bus, SystemBusNode)):
                        bus_name = "NULL"
                    else:
                        bus_name = "BUS(%s)" % self.node_map[node.parent_bus]

                    if Type.exists(node.qom_type):
                        qom_type = node.qom_type
                    else:
                        qom_type = "\"%s\"" % node.qom_type

                    def_code += """\
    {dev_name} = qdev_create(@a{bus_name},@s{qom_type});{props_code}
    qdev_init_nofail({dev_name});
""".format(dev_name=dev_name,
                    bus_name=bus_name,
                    qom_type=qom_type,
                    props_code=props_code)

                if isinstance(node, SystemBusDeviceNode):
                    for idx, mmio in node.mmio_mappings.items():
                        if mmio is not None:
                            self.use_type_name("sysbus_mmio_map")
                            self.use_type_name("SYS_BUS_DEVICE")

                            if isinstance(mmio, str) and Type.exists(mmio):
                                self.use_type_name(mmio)
                                mmio_val = str(mmio)
                            else:
                                mmio_val = "0x%x" % mmio

                            def_code += """\
    sysbus_mmio_map(@aSYS_BUS_DEVICE({dev_name}),@s{idx},@s{mmio_val});
""".format(dev_name=dev_name, idx=idx, mmio_val=mmio_val)

                for bus in node.buses:
                    if len(bus.devices) == 0:
                        continue

                    bus_name = self.node_map[bus]
                    try:
                        if isinstance(bus, PCIExpressBusNode):
                            if isinstance(node, SystemBusDeviceNode):
                                bridge_cast = "PCI_HOST_BRIDGE"
                                bus_field = "bus"
                            elif isinstance(node, PCIExpressDeviceNode):
                                bridge_cast = "PCI_BRIDGE"
                                bus_field = "sec_bus"
                            else:
                                raise UnknownBusBridgeType(
                                    node.parent_bus, bus)

                            self.use_type_name(bridge_cast)

                            def_code += """\
    {bus_name} = {bridge_cast}({bridge_name})->{bus_field};
""".format(bus_name=bus_name,
                            bridge_name=dev_name,
                            bridge_cast=bridge_cast,
                            bus_field=bus_field)
                        else:
                            raise UnknownBusBridgeType(node.parent_bus, bus)
                    except UnknownBusBridgeType:
                        self.use_type_name("qdev_get_child_bus")
                        self.use_type_name("DEVICE")
                        if bus.cast is not None:
                            self.use_type_name(bus.cast)

                        def_code += """\
    {bus_name} = {bus_cast};
""".format(
                            bus_name=bus_name,
                            bus_cast=("(%s *) %%s" %
                                      bus.c_type) if bus.cast is None else
                            ("%s(%%s)" % bus.cast),
                        ) % """\
qdev_get_child_bus(@aDEVICE({bridge_name}),@s"{bus_child_name}")\
""".format(
                            bridge_name=dev_name,
                            bus_child_name=bus.gen_child_name_for_bus(),
                        )

            elif isinstance(node, BusNode):
                # No definition code will be generated
                skip_nl = True

                if isinstance(node, SystemBusNode):
                    continue
                if len(node.devices) == 0:
                    continue

                self.use_type_name(node.c_type)

                bus_name = self.node_map[node]

                decl_code += "    %s *%s;\n" % (node.c_type, bus_name)
            elif isinstance(node, IRQLine):
                if node.hub_ended():
                    # Do not generate a code for IRQ lines that refers an IRQ
                    # hub. The code will be generated during the hub processing.
                    skip_nl = True
                    continue

                self.use_type_name("qemu_irq")

                irq_name = self.node_map[node]

                decl_code += "    qemu_irq %s;\n" % irq_name

                def_code += (self.gen_irq_get(node.dst, irq_name) +
                             self.gen_irq_connect(node.src, irq_name))
            elif isinstance(node, MemoryNode):
                self.use_type_name("MemoryRegion")
                if isinstance(node.size, str) and Type.exists(node.size):
                    self.use_type_name(node.size)
                if Type.exists(node.name):
                    self.use_type_name(node.name)

                mem_name = self.node_map[node]

                decl_code += "    MemoryRegion *%s;\n" % mem_name

                if isinstance(node, MemorySASNode):
                    self.use_type_name("get_system_memory")

                    def_code += "    %s = get_system_memory();\n" % mem_name
                else:
                    def_code += "    %s = g_new(MemoryRegion, 1);\n" % mem_name

                if isinstance(node, MemoryAliasNode):
                    self.use_type_name("memory_region_init_alias")
                    if Type.exists(node.alias_offset):
                        self.use_type_name(node.alias_offset)

                    def_code += """\
    memory_region_init_alias(@a{mem_name},@sNULL,@s{dbg_name},@s{orig},@s{offset},@s{size});
""".format(mem_name=mem_name,
                    dbg_name=node.name if Type.exists(node.name) else "\"%s\"" %
                    node.name,
                    size=node.size,
                    orig=self.node_map[node.alias_to],
                    offset=node.alias_offset)
                elif (isinstance(node, MemoryRAMNode)
                      or isinstance(node, MemoryROMNode)):
                    self.use_type_name("memory_region_init_ram")
                    if glob_mem:
                        self.use_type_name("vmstate_register_ram_global")

                    def_code += """\
    memory_region_init_ram(@a{mem_name},@sNULL,@s{dbg_name},@s{size},@sNULL);{glob}
""".format(mem_name=mem_name,
                    dbg_name=node.name if Type.exists(node.name) else "\"%s\"" %
                    node.name,
                    size=node.size,
                    glob=(("\n    vmstate_register_ram_global(%s);" %
                    mem_name) if glob_mem else ""))
                elif not isinstance(node, MemorySASNode):
                    self.use_type_name("memory_region_init")

                    def_code += """\
    memory_region_init(@a{mem_name},@sNULL,@s{dbg_name},@s{size});
""".format(mem_name=mem_name,
                    dbg_name=node.name if Type.exists(node.name) else "\"%s\"" %
                    node.name,
                    size=node.size)

                if node.parent is not None:
                    if (isinstance(node.offset, str)
                            and Type.exists(node.offset)):
                        self.use_type_name(node.offset)
                    if node.may_overlap:
                        self.use_type_name(
                            "memory_region_add_subregion_overlap")
                        if (isinstance(node.priority, str)
                                and Type.exists(node.priority)):
                            self.use_type_name(node.priority)

                        def_code += """\
    memory_region_add_subregion_overlap(@a{parent_name},@s{offset},@s{child},@s{priority});
""".format(parent_name=self.node_map[node.parent],
                        offset=node.offset,
                        priority=node.priority,
                        child=mem_name)
                    else:
                        self.use_type_name("memory_region_add_subregion")
                        if (isinstance(node.priority, str)
                                and Type.exists(node.priority)):
                            self.use_type_name(node.priority)

                        def_code += """\
    memory_region_add_subregion(@a{parent_name},@s{offset},@s{child});
""".format(parent_name=self.node_map[node.parent],
                        offset=node.offset,
                        child=mem_name)

            elif isinstance(node, IRQHub):
                if len(node.irqs) < 1:
                    # Nothing to do for detached IRQ hub
                    skip_nl = True
                    continue

                self.use_type_name("qemu_irq")

                hub_in_name = self.node_map[node]

                decl_code += "    qemu_irq %s;\n" % hub_in_name

                hubl = self.provide_hub_layout(node)

                code = hubl.gen_irq_get()
                decl_code += code[0]
                def_code += code[1]

                for in_irq in [irq for irq in node.irqs if irq.dst[0] == node]:
                    src = in_irq.src
                    if isinstance(src[0], IRQHub):
                        # A source hub does connects to this hub by itself
                        continue
                    def_code += self.gen_irq_connect(src, hub_in_name)
            elif isinstance(node, CPUNode):
                self.use_type_name("CPUState")
                self.use_type_name("cpu_create")
                self.use_type_name("qemu_register_reset")
                cpu_reset = self.cpu_reset
                self.use_type_name(cpu_reset.name)

                cpu_name = self.node_map[node]

                decl_code += "    CPUState *%s;\n" % cpu_name

                if Type.exists(node.qom_type):
                    qom_type = node.qom_type
                else:
                    qom_type = "\"%s\"" % node.qom_type

                def_code += """\
    {var_name}@b=@scpu_create(@a{qom_type});
    qemu_register_reset(@a{reset},@s{var_name});
""".format(var_name=cpu_name, qom_type=qom_type, reset=cpu_reset.name)
            else:
                raise UnknownMachineNodeType(str(type(node)))

        # machine initialization function
        self.instance_init = Function(
            name="init_%s" % self.qtn.for_id_name,
            static=True,
            args=[Pointer(Type["MachineState"])("machine")],
            body=decl_code + "\n" + def_code,
            used_types=self.init_used_types)
        self.source.add_type(self.instance_init)

        get_vp("machine type register template generator")(self)
Beispiel #25
0
    def setUp(self):
        super(TestEnumerations, self).setUp()
        name = type(self).__name__

        try:
            h = Header["enums.h"]
        except:
            h = Header("enums.h")
        h.add_type(Enumeration([("EXT", 1)]))

        src = Source(name.lower() + ".c").add_types([
            Enumeration([("ONE", 1)]),
            Enumeration([("TWO", 2)], enum_name="A"),
            Enumeration([("THREE", 3)], typedef_name="B"),
            Enumeration([("FOUR", 4)], enum_name="C", typedef_name="D")
        ])

        a = Type["int"]("a")
        b = Type["int"]("b")
        c = Type["A"]("c")
        d = Type["B"]("d")
        e = Type["D"]("e")

        src.add_types([
            Function(name="main",
                     body=BodyTree()(Declare(a, b), OpAssign(a, Type["EXT"]),
                                     OpAssign(b, Type["ONE"]), Declare(c),
                                     OpAssign(c, Type["TWO"]), Declare(d),
                                     OpAssign(d, Type["THREE"]), Declare(e),
                                     OpAssign(e, Type["FOUR"])))
        ])

        src_content = """\
/* {} */

#include "enums.h"

enum A {{
    TWO = 2
}};

typedef enum {{
    THREE = 3
}} B;

typedef enum C {{
    FOUR = 4
}} D;

enum {{
    ONE = 1
}};

void main(void)
{{
    int a, b;
    a = EXT;
    b = ONE;
    enum A c;
    c = TWO;
    B d;
    d = THREE;
    D e;
    e = FOUR;
}}

""".format(src.path)

        self.files = [(src, src_content)]
Beispiel #26
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()