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)])
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 )
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
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)
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))
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
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
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))
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
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
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
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)
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
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
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
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], )
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)
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
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)
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)
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) ]))
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
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
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] )
def find_macro(self): return Type.lookup("PCI_DEVICE_ID_%s_%s" % (self.vendor.name, self.name))
def find_macro(self): return Type.lookup("PCI_VENDOR_ID_%s" % self.name)
def find_macro(self): return Type.lookup("PCI_CLASS_%s" % self.name)
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()
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()
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))