qemu学习之添加一个新machine

  • 1 xlnx-versal-virt machine所在的代码
    • 1.1 声明一个新的machine
      • 1.1.1 xlnx-versal-virt machine声明
      • 1.1.2 struct TypeInfo 结构体的声明
      • 1.1.3 versal_virt_machine_init_typeinfo
    • 1.2 versal_virt_machine_class_init
      • 1.2.1 versal_virt_machine_class_init
      • 1.2.2 struct MachineClass
    • 1.3 versal_virt_init
      • 1.3.1 versal_virt_init
      • 1.3.2 XLNX_VERSAL_VIRT_MACHINE
      • 1.3.3 fdt_create
  • 2 xilinx qemu编译安装
    • 2.1 添加xlnx-versal-virt.c的编译
    • 2.2 添加配置开关XLNX_VERSAL和XLNX_VERSAL_ARM
    • 2.3 编译和安装
  • 3 依据`xlnx-versal-virt`添加jimmy-virt测试machine
    • 3.1 添加`hw/arm/jimmy-virt.c`
    • 3.2 添加jimmy-virt.c的编译
    • 3.3 添加CONFIG_JIMMY_VERSAL和CONFIG_JIMMY_VERSAL_ARM
    • 3.3 编译和安装
    • 3.4 查看新添加的测试machine是否成功
      • 3.4.1 sudo qemu-system-aarch64 -M help | grep jimmy
      • 3.4.2 sudo qemu-system-aarch64 -M help

本文以xilinx的qemu为例去介绍,首先通过介绍xlnx-versal-virt machine的添加流程去了解添加一个新的machine需要注意和关注的地方。然后再通过完全从头开始添加一个machine的方式去处理,然后编译看一下实验效果。

xilinx qemu源码的链接:https://github.com/Xilinx/qemu

1 xlnx-versal-virt machine所在的代码

完成的添加xlnx-versal-virt machine的代码如下所示:
https://github.com/Xilinx/qemu/blob/master/hw/arm/xlnx-versal-virt.c

1.1 声明一个新的machine

1.1.1 xlnx-versal-virt machine声明

  • xlnx-versal-virt即为新声明的machine名称
#define TYPE_XLNX_VERSAL_VIRT_MACHINE MACHINE_TYPE_NAME("xlnx-versal-virt")
  • versal_virt_machine_init_typeinfoxlnx-versal-virt machine所需要关注的属性以及machine初始化相关的配置。
  • versal_virt_machine_init_register_types是machine的注册函数,通过type_init函数以模块注册到系统中,type_init宏的定义如下所示
    #define type_init(function) module_init(function, MODULE_INIT_QOM)
static const TypeInfo versal_virt_machine_init_typeinfo = {.name       = TYPE_XLNX_VERSAL_VIRT_MACHINE,.parent     = TYPE_MACHINE,.class_init = versal_virt_machine_class_init,.instance_init = versal_virt_machine_instance_init,.instance_size = sizeof(VersalVirt),
};static void versal_virt_machine_init_register_types(void)
{type_register_static(&versal_virt_machine_init_typeinfo);
}type_init(versal_virt_machine_init_register_types)

1.1.2 struct TypeInfo 结构体的声明

通过struct TypeInfo我们描述了一个新的单板所具有的一些基本的属性和初始化所需要的的接口。

/*** struct TypeInfo:* @name: The name of the type.* @parent: The name of the parent type.* @instance_size: The size of the object (derivative of #Object).  If*   @instance_size is 0, then the size of the object will be the size of the*   parent object.* @instance_align: The required alignment of the object.  If @instance_align*   is 0, then normal malloc alignment is sufficient; if non-zero, then we*   must use qemu_memalign for allocation.* @instance_init: This function is called to initialize an object.  The parent*   class will have already been initialized so the type is only responsible*   for initializing its own members.* @instance_post_init: This function is called to finish initialization of*   an object, after all @instance_init functions were called.* @instance_finalize: This function is called during object destruction.  This*   is called before the parent @instance_finalize function has been called.*   An object should only free the members that are unique to its type in this*   function.* @abstract: If this field is true, then the class is considered abstract and*   cannot be directly instantiated.* @class_size: The size of the class object (derivative of #ObjectClass)*   for this object.  If @class_size is 0, then the size of the class will be*   assumed to be the size of the parent class.  This allows a type to avoid*   implementing an explicit class type if they are not adding additional*   virtual functions.* @class_init: This function is called after all parent class initialization*   has occurred to allow a class to set its default virtual method pointers.*   This is also the function to use to override virtual methods from a parent*   class.* @class_base_init: This function is called for all base classes after all*   parent class initialization has occurred, but before the class itself*   is initialized.  This is the function to use to undo the effects of*   memcpy from the parent class to the descendants.* @class_data: Data to pass to the @class_init,*   @class_base_init. This can be useful when building dynamic*   classes.* @interfaces: The list of interfaces associated with this type.  This*   should point to a static array that's terminated with a zero filled*   element.*/
struct TypeInfo
{const char *name;const char *parent;size_t instance_size;size_t instance_align;void (*instance_init)(Object *obj);void (*instance_post_init)(Object *obj);void (*instance_finalize)(Object *obj);bool abstract;size_t class_size;void (*class_init)(ObjectClass *klass, void *data);void (*class_base_init)(ObjectClass *klass, void *data);void *class_data;InterfaceInfo *interfaces;
};

1.1.3 versal_virt_machine_init_typeinfo

xlnx-versal-virt所声明的属性中添加了下面的配置信息。

  • TYPE_XLNX_VERSAL_VIRT_MACHINE表示是当前machine的名字
  • TYPE_MACHINE表示的是machine的公共属性
  • versal_virt_machine_class_init是当前machine初始化的接口
  • versal_virt_machine_instance_init是当前machine实例初始化的接口
static const TypeInfo versal_virt_machine_init_typeinfo = {.name       = TYPE_XLNX_VERSAL_VIRT_MACHINE,.parent     = TYPE_MACHINE,.class_init = versal_virt_machine_class_init,.instance_init = versal_virt_machine_instance_init,.instance_size = sizeof(VersalVirt),
};

1.2 versal_virt_machine_class_init

1.2.1 versal_virt_machine_class_init

  • XLNX_VERSAL_NR_ACPUS表示当前machine所支持的CPU的数量,在设备启动的过程中需要通过-cpu去指定
  • mc->min_cpusmc->max_cpus表示的是当前的machine支持的cpu的上限和下限,在qemu启动过程-cpu CPU_NR只要是在这个范围内都可以被接受。
  • mc->default_cpus表示如果在qemu启动时不通过-cpu 去指定CPU数量时,默认的CPU数量是多少
  • versal_virt_init是当前machine初始化的接口
  • mc->desc是对当前machine的描述,在执行sudo qemu-system-aarch64 -M help命令时,所支持machine后面所对应点描述信息。
sudo qemu-system-aarch64 -M help
...
xlnx-versal-virt     Xilinx Versal Virtual development board
...
static void versal_virt_machine_class_init(ObjectClass *oc, void *data)
{MachineClass *mc = MACHINE_CLASS(oc);mc->desc = "Xilinx Versal Virtual development board";mc->init = versal_virt_init;mc->min_cpus = XLNX_VERSAL_NR_ACPUS;mc->max_cpus = XLNX_VERSAL_NR_ACPUS;mc->default_cpus = XLNX_VERSAL_NR_ACPUS;mc->no_cdrom = true;mc->default_ram_id = "ddr";
}

1.2.2 struct MachineClass

struct MachineClass结构体描述了当前machine的一些更具体的属性信息。

/*** MachineClass:* @deprecation_reason: If set, the machine is marked as deprecated. The*    string should provide some clear information about what to use instead.* @max_cpus: maximum number of CPUs supported. Default: 1* @min_cpus: minimum number of CPUs supported. Default: 1* @default_cpus: number of CPUs instantiated if none are specified. Default: 1* @is_default:*    If true QEMU will use this machine by default if no '-M' option is given.* @get_hotplug_handler: this function is called during bus-less*    device hotplug. If defined it returns pointer to an instance*    of HotplugHandler object, which handles hotplug operation*    for a given @dev. It may return NULL if @dev doesn't require*    any actions to be performed by hotplug handler.* @cpu_index_to_instance_props:*    used to provide @cpu_index to socket/core/thread number mapping, allowing*    legacy code to perform maping from cpu_index to topology properties*    Returns: tuple of socket/core/thread ids given cpu_index belongs to.*    used to provide @cpu_index to socket number mapping, allowing*    a machine to group CPU threads belonging to the same socket/package*    Returns: socket number given cpu_index belongs to.* @hw_version:*    Value of QEMU_VERSION when the machine was added to QEMU.*    Set only by old machines because they need to keep*    compatibility on code that exposed QEMU_VERSION to guests in*    the past (and now use qemu_hw_version()).* @possible_cpu_arch_ids:*    Returns an array of @CPUArchId architecture-dependent CPU IDs*    which includes CPU IDs for present and possible to hotplug CPUs.*    Caller is responsible for freeing returned list.* @get_default_cpu_node_id:*    returns default board specific node_id value for CPU slot specified by*    index @idx in @ms->possible_cpus[]* @has_hotpluggable_cpus:*    If true, board supports CPUs creation with -device/device_add.* @default_cpu_type:*    specifies default CPU_TYPE, which will be used for parsing target*    specific features and for creating CPUs if CPU name wasn't provided*    explicitly at CLI* @minimum_page_bits:*    If non-zero, the board promises never to create a CPU with a page size*    smaller than this, so QEMU can use a more efficient larger page*    size than the target architecture's minimum. (Attempting to create*    such a CPU will fail.) Note that changing this is a migration*    compatibility break for the machine.* @ignore_memory_transaction_failures:*    If this is flag is true then the CPU will ignore memory transaction*    failures which should cause the CPU to take an exception due to an*    access to an unassigned physical address; the transaction will instead*    return zero (for a read) or be ignored (for a write). This should be*    set only by legacy board models which rely on the old RAZ/WI behaviour*    for handling devices that QEMU does not yet model. New board models*    should instead use "unimplemented-device" for all memory ranges where*    the guest will attempt to probe for a device that QEMU doesn't*    implement and a stub device is required.* @kvm_type:*    Return the type of KVM corresponding to the kvm-type string option or*    computed based on other criteria such as the host kernel capabilities.*    kvm-type may be NULL if it is not needed.* @numa_mem_supported:*    true if '--numa node.mem' option is supported and false otherwise* @smp_parse:*    The function pointer to hook different machine specific functions for*    parsing "smp-opts" from QemuOpts to MachineState::CpuTopology and more*    machine specific topology fields, such as smp_dies for PCMachine.* @hotplug_allowed:*    If the hook is provided, then it'll be called for each device*    hotplug to check whether the device hotplug is allowed.  Return*    true to grant allowance or false to reject the hotplug.  When*    false is returned, an error must be set to show the reason of*    the rejection.  If the hook is not provided, all hotplug will be*    allowed.* @default_ram_id:*    Specifies inital RAM MemoryRegion name to be used for default backend*    creation if user explicitly hasn't specified backend with "memory-backend"*    property.*    It also will be used as a way to optin into "-m" option support.*    If it's not set by board, '-m' will be ignored and generic code will*    not create default RAM MemoryRegion.* @fixup_ram_size:*    Amends user provided ram size (with -m option) using machine*    specific algorithm. To be used by old machine types for compat*    purposes only.*    Applies only to default memory backend, i.e., explicit memory backend*    wasn't used.*/
struct MachineClass {/*< private >*/ObjectClass parent_class;/*< public >*/const char *family; /* NULL iff @name identifies a standalone machtype */char *name;const char *alias;const char *desc;const char *deprecation_reason;void (*init)(MachineState *state);void (*reset)(MachineState *state);void (*wakeup)(MachineState *state);int (*kvm_type)(MachineState *machine, const char *arg);void (*smp_parse)(MachineState *ms, SMPConfiguration *config, Error **errp);BlockInterfaceType block_default_type;int units_per_default_bus;int max_cpus;int min_cpus;int default_cpus;unsigned int no_serial:1,no_parallel:1,no_floppy:1,no_cdrom:1,no_sdcard:1,pci_allow_0_address:1,legacy_fw_cfg_order:1;bool is_default;const char *default_machine_opts;const char *default_boot_order;const char *default_display;GPtrArray *compat_props;const char *hw_version;ram_addr_t default_ram_size;const char *default_cpu_type;bool default_kernel_irqchip_split;bool option_rom_has_mr;bool rom_file_has_mr;int minimum_page_bits;bool has_hotpluggable_cpus;bool ignore_memory_transaction_failures;int numa_mem_align_shift;const char **valid_cpu_types;strList *allowed_dynamic_sysbus_devices;bool auto_enable_numa_with_memhp;bool auto_enable_numa_with_memdev;bool ignore_boot_device_suffixes;bool smbus_no_migration_support;bool nvdimm_supported;bool numa_mem_supported;bool auto_enable_numa;const char *default_ram_id;HotplugHandler *(*get_hotplug_handler)(MachineState *machine,DeviceState *dev);bool (*hotplug_allowed)(MachineState *state, DeviceState *dev,Error **errp);CpuInstanceProperties (*cpu_index_to_instance_props)(MachineState *machine,unsigned cpu_index);const CPUArchIdList *(*possible_cpu_arch_ids)(MachineState *machine);int64_t (*get_default_cpu_node_id)(const MachineState *ms, int idx);ram_addr_t (*fixup_ram_size)(ram_addr_t size);
};

1.3 versal_virt_init

1.3.1 versal_virt_init

对于xlnx-versal-virtmachine来说,versal_virt_init函数接口的处理主要是去解析设备所对应的设备树文件去获取对应的machine的device属性和配置。

static void versal_virt_init(MachineState *machine)
{VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(machine);int psci_conduit = QEMU_PSCI_CONDUIT_DISABLED;int i;/** If the user provides an Operating System to be loaded, we expect them* to use the -kernel command line option.** Users can load firmware or boot-loaders with the -device loader options.** When loading an OS, we generate a dtb and let arm_load_kernel() select* where it gets loaded. This dtb will be passed to the kernel in x0.** If there's no -kernel option, we generate a DTB and place it at 0x1000* for the bootloaders or firmware to pick up.** If users want to provide their own DTB, they can use the -dtb option.* These dtb's will have their memory nodes modified to match QEMU's* selected ram_size option before they get passed to the kernel or fw.** When loading an OS, we turn on QEMU's PSCI implementation with SMC* as the PSCI conduit. When there's no -kernel, we assume the user* provides EL3 firmware to handle PSCI.*/if (machine->kernel_filename) {psci_conduit = QEMU_PSCI_CONDUIT_SMC;}object_initialize_child(OBJECT(machine), "xlnx-versal", &s->soc,TYPE_XLNX_VERSAL);object_property_set_link(OBJECT(&s->soc), "ddr", OBJECT(machine->ram),&error_abort);object_property_set_int(OBJECT(&s->soc), "psci-conduit", psci_conduit,&error_abort);sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);fdt_create(s);create_virtio_regions(s);fdt_add_gem_nodes(s);fdt_add_uart_nodes(s);fdt_add_gic_nodes(s);fdt_add_timer_nodes(s);fdt_add_zdma_nodes(s);fdt_add_usb_xhci_nodes(s);fdt_add_sd_nodes(s);fdt_add_rtc_node(s);fdt_add_cpu_nodes(s, psci_conduit);fdt_add_clk_node(s, "/clk125", 125000000, s->phandle.clk_125Mhz);fdt_add_clk_node(s, "/clk25", 25000000, s->phandle.clk_25Mhz);/* Make the APU cpu address space visible to virtio and other* modules unaware of muliple address-spaces.  */memory_region_add_subregion_overlap(get_system_memory(),0, &s->soc.fpd.apu.mr, 0);/* Plugin SD cards.  */for (i = 0; i < ARRAY_SIZE(s->soc.pmc.iou.sd); i++) {sd_plugin_card(&s->soc.pmc.iou.sd[i], drive_get_next(IF_SD));}s->binfo.ram_size = machine->ram_size;s->binfo.loader_start = 0x0;s->binfo.get_dtb = versal_virt_get_dtb;s->binfo.modify_dtb = versal_virt_modify_dtb;if (machine->kernel_filename) {arm_load_kernel(&s->soc.fpd.apu.cpu[0], machine, &s->binfo);} else {AddressSpace *as = arm_boot_address_space(&s->soc.fpd.apu.cpu[0],&s->binfo);/* Some boot-loaders (e.g u-boot) don't like blobs at address 0 (NULL).* Offset things by 4K.  */s->binfo.loader_start = 0x1000;s->binfo.dtb_limit = 0x1000000;if (arm_load_dtb(s->binfo.loader_start,&s->binfo, s->binfo.dtb_limit, as, machine) < 0) {exit(EXIT_FAILURE);}}
}

1.3.2 XLNX_VERSAL_VIRT_MACHINE

XLNX_VERSAL_VIRT_MACHINE的定义是在hw/arm/xlnx-versal-virt.c文件中;通过OBJECT_DECLARE_SIMPLE_TYPE声明了XLNX_VERSAL_VIRT_MACHINE一个内联函数,其实现如下所示:

OBJECT_DECLARE_SIMPLE_TYPE(VersalVirt, XLNX_VERSAL_VIRT_MACHINE)

OBJECT_DECLARE_SIMPLE_TYPE的定义代码路径为:include/qom/object.h

 164 /**165  * DECLARE_INSTANCE_CHECKER:166  * @InstanceType: instance struct name167  * @OBJ_NAME: the object name in uppercase with underscore separators168  * @TYPENAME: type name169  *170  * Direct usage of this macro should be avoided, and the complete171  * OBJECT_DECLARE_TYPE macro is recommended instead.172  *173  * This macro will provide the instance type cast functions for a174  * QOM type.175  */176 #define DECLARE_INSTANCE_CHECKER(InstanceType, OBJ_NAME, TYPENAME) \177     static inline G_GNUC_UNUSED InstanceType * \178     OBJ_NAME(const void *obj) \179     { return OBJECT_CHECK(InstanceType, obj, TYPENAME); }243 /**244  * OBJECT_DECLARE_SIMPLE_TYPE:245  * @InstanceType: instance struct name246  * @MODULE_OBJ_NAME: the object name in uppercase with underscore separators247  *248  * This does the same as OBJECT_DECLARE_TYPE(), but with no class struct249  * declared.250  *251  * This macro should be used unless the class struct needs to have252  * virtual methods declared.253  */254 #define OBJECT_DECLARE_SIMPLE_TYPE(InstanceType, MODULE_OBJ_NAME) \255     typedef struct InstanceType InstanceType; \256     \257     G_DEFINE_AUTOPTR_CLEANUP_FUNC(InstanceType, object_unref) \258     \259     DECLARE_INSTANCE_CHECKER(InstanceType, MODULE_OBJ_NAME, TYPE_##MODULE_OBJ_NAME)

TYPE_##MODULE_OBJ_NAME所对应的是TYPE_XLNX_VERSAL_VIRT_MACHINE,在其中的##是一个连接符,用于讲TYPE_MODULE_OBJ_NAME组成一个符号。

1.3.3 fdt_create

versal_virt_init函数中的众多调用接口中以fdt_create为例来做简单介绍:

  • qemu_fdt_alloc_phandle用于依次去获取对应的device的配置信息,其起始地址为machine->phandle_start
  • qemu_fdt_setprop_cell用于解析对应的device node的属性信息
  • qemu_fdt_setprop_string用于解析设备树的信息,作为对当前machine的描述
static void fdt_create(VersalVirt *s)
{MachineClass *mc = MACHINE_GET_CLASS(s);int i;s->fdt = create_device_tree(&s->fdt_size);if (!s->fdt) {error_report("create_device_tree() failed");exit(1);}/* Allocate all phandles.  */s->phandle.gic = qemu_fdt_alloc_phandle(s->fdt);for (i = 0; i < ARRAY_SIZE(s->phandle.ethernet_phy); i++) {s->phandle.ethernet_phy[i] = qemu_fdt_alloc_phandle(s->fdt);}s->phandle.clk_25Mhz = qemu_fdt_alloc_phandle(s->fdt);s->phandle.clk_125Mhz = qemu_fdt_alloc_phandle(s->fdt);s->phandle.usb = qemu_fdt_alloc_phandle(s->fdt);s->phandle.dwc = qemu_fdt_alloc_phandle(s->fdt);/* Create /chosen node for load_dtb.  */qemu_fdt_add_subnode(s->fdt, "/chosen");/* Header */qemu_fdt_setprop_cell(s->fdt, "/", "interrupt-parent", s->phandle.gic);qemu_fdt_setprop_cell(s->fdt, "/", "#size-cells", 0x2);qemu_fdt_setprop_cell(s->fdt, "/", "#address-cells", 0x2);qemu_fdt_setprop_string(s->fdt, "/", "model", mc->desc);qemu_fdt_setprop_string(s->fdt, "/", "compatible", "xlnx-versal-virt");
}

2 xilinx qemu编译安装

2.1 添加xlnx-versal-virt.c的编译

代码路径:hw/arm/meson.build

arm_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal.c', 'xlnx-versal-virt.c'))

添加CONFIG_XLNX_VERSAL的配置宏。

2.2 添加配置开关XLNX_VERSAL和XLNX_VERSAL_ARM

代码路径:hw/arm/Kconfig

config XLNX_VERSALboolselect PL011select CADENCEselect VIRTIO_MMIOselect UNIMPselect XLNX_ZDMAselect XLNX_ZYNQMPselect OR_IRQconfig XLNX_VERSAL_ARMboolselect ARM_GICselect USB_DWC3select USB_XHCI_SYSBUS

2.3 编译和安装

cd qemu
mkdir build && cd build
../configure                (在该处会检查依赖软件)
make -j8                    (在该处编译的时间比较长)
sudo make install

安装完成之后通过sudo qemu-system-aarch64 --version查看qemu的版本是否正确

3 依据xlnx-versal-virt添加jimmy-virt测试machine

3.1 添加hw/arm/jimmy-virt.c

添加hw/arm/jimmy-virt.c时,直接借助xlnx-versal-virt的一些配置去处理,这样比较简单。现在只保留一个xlnx-versal-virt的简单框架,将xlnx-versal-virt的配置信息修改为jimmy-virt,然后添加jimmy-virt.c到编译中。

/** Xilinx Versal Virtual board.** Copyright (c) 2018 Xilinx Inc.* Written by Edgar E. Iglesias** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License version 2 or* (at your option) any later version.*/#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
#include "sysemu/device_tree.h"
#include "hw/boards.h"
#include "hw/sysbus.h"
#include "hw/arm/sysbus-fdt.h"
#include "hw/arm/fdt.h"
#include "cpu.h"
#include "hw/qdev-properties.h"
#include "hw/arm/xlnx-versal.h"
#include "qom/object.h"#define TYPE_JIMMY_VIRT_MACHINE MACHINE_TYPE_NAME("jimmy-virt")
OBJECT_DECLARE_SIMPLE_TYPE(JimmyVersalVirt, JIMMY_VIRT_MACHINE)#define JIMMY_NR_ACPUS   8
#define JIMMY_NR_UARTS   2
#define JIMMY_NR_GEMS    2
#define JIMMY_NR_ADMAS   8
#define JIMMY_NR_SDS     2
#define JIMMY_NR_XRAM    4
#define JIMMY_NR_IRQS    192struct JimmyVersalVirt {MachineState parent_obj;Versal soc;void *fdt;int fdt_size;struct {uint32_t gic;uint32_t ethernet_phy[2];uint32_t clk_125Mhz;uint32_t clk_25Mhz;uint32_t usb;uint32_t dwc;} phandle;struct arm_boot_info binfo;struct {bool secure;} cfg;
};static void jimmy_virt_init(MachineState *machine)
{}static void jimmy_machine_instance_init(Object *obj)
{}static void jimmy_machine_class_init(ObjectClass *oc, void *data)
{MachineClass *mc = MACHINE_CLASS(oc);mc->desc = "Jimmy Versal Virtual development board";mc->init = jimmy_virt_init;mc->min_cpus = JIMMY_NR_ACPUS;mc->max_cpus = JIMMY_NR_ACPUS;mc->default_cpus = JIMMY_NR_ACPUS;mc->no_cdrom = true;mc->default_ram_id = "ddr";
}static const TypeInfo jimmy_machine_init_typeinfo = {.name       = TYPE_JIMMY_VIRT_MACHINE,.parent     = TYPE_MACHINE,.class_init = jimmy_machine_class_init,.instance_init = jimmy_machine_instance_init,.instance_size = sizeof(JimmyVersalVirt),
};static void jimmy_machine_init_register_types(void)
{type_register_static(&jimmy_machine_init_typeinfo);
}type_init(jimmy_machine_init_register_types)

3.2 添加jimmy-virt.c的编译

代码路径:hw/arm/meson.build

arm_ss.add(when: 'CONFIG_JIMMY_VERSAL', if_true: files('jimmy-virt.c'))

3.3 添加CONFIG_JIMMY_VERSAL和CONFIG_JIMMY_VERSAL_ARM

代码路径:hw/arm/Kconfig

rlk@rlk:qemu-xilinx$ git diff hw/arm/Kconfig
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 4644930efb..e93cea5d86 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -375,6 +375,22 @@ config XLNX_ZYNQMP_ARMselect USB_XHCI_SYSBUSselect XLNX_ZDMA+config JIMMY_VERSAL
+    bool
+    select PL011
+    select CADENCE
+    select VIRTIO_MMIO
+    select UNIMP
+    select XLNX_ZDMA
+    select XLNX_ZYNQMP
+    select OR_IRQ
+
+config JIMMY_VERSAL_ARM
+    bool
+    select ARM_GIC
+    select USB_DWC3
+    select USB_XHCI_SYSBUS
+config XLNX_VERSALboolselect PL011
rlk@rlk:qemu-xilinx$

3.3 编译和安装

cd qemu
mkdir build && cd build
../configure                (在该处会检查依赖软件)
make -j8                    (在该处编译的时间比较长)
sudo make install

3.4 查看新添加的测试machine是否成功

3.4.1 sudo qemu-system-aarch64 -M help | grep jimmy

当执行sudo qemu-system-aarch64 -M help | grep jimmy可以看到新添加的测试machine已经被添加到qemu中。

rlk@rlk:build$ sudo qemu-system-aarch64 -M help | grep jimmy
jimmy-virt           Jimmy Versal Virtual development board
rlk@rlk:build$

3.4.2 sudo qemu-system-aarch64 -M help

rlk@rlk:build$ sudo qemu-system-aarch64 -M help
Supported machines are:
akita                Sharp SL-C1000 (Akita) PDA (PXA270)
arm-generic-fdt-7series ARM device tree driven machine model for the Zynq-7000
arm-generic-fdt      ARM device tree driven machine model
arm-generic-fdt-plnx Deprecated ARM device tree driven machine for the Zynq-7000
ast2500-evb          Aspeed AST2500 EVB (ARM1176)
ast2600-evb          Aspeed AST2600 EVB (Cortex-A7)
borzoi               Sharp SL-C3100 (Borzoi) PDA (PXA270)
canon-a1100          Canon PowerShot A1100 IS (ARM946)
cheetah              Palm Tungsten|E aka. Cheetah PDA (OMAP310)
collie               Sharp SL-5500 (Collie) PDA (SA-1110)
connex               Gumstix Connex (PXA255)
cubieboard           cubietech cubieboard (Cortex-A8)
emcraft-sf2          SmartFusion2 SOM kit from Emcraft (M2S010)
g220a-bmc            Bytedance G220A BMC (ARM1176)
highbank             Calxeda Highbank (ECX-1000)
imx25-pdk            ARM i.MX25 PDK board (ARM926)
integratorcp         ARM Integrator/CP (ARM926EJ-S)
jimmy-virt           Jimmy Versal Virtual development board
kzm                  ARM KZM Emulation Baseboard (ARM1136)
lm3s6965evb          Stellaris LM3S6965EVB (Cortex-M3)
lm3s811evb           Stellaris LM3S811EVB (Cortex-M3)
mainstone            Mainstone II (PXA27x)
mcimx6ul-evk         Freescale i.MX6UL Evaluation Kit (Cortex-A7)
mcimx7d-sabre        Freescale i.MX7 DUAL SABRE (Cortex-A7)
microbit             BBC micro:bit (Cortex-M0)
midway               Calxeda Midway (ECX-2000)
mps2-an385           ARM MPS2 with AN385 FPGA image for Cortex-M3
mps2-an386           ARM MPS2 with AN386 FPGA image for Cortex-M4
mps2-an500           ARM MPS2 with AN500 FPGA image for Cortex-M7
mps2-an505           ARM MPS2 with AN505 FPGA image for Cortex-M33
mps2-an511           ARM MPS2 with AN511 DesignStart FPGA image for Cortex-M3
mps2-an521           ARM MPS2 with AN521 FPGA image for dual Cortex-M33
mps3-an524           ARM MPS3 with AN524 FPGA image for dual Cortex-M33
mps3-an547           ARM MPS3 with AN547 FPGA image for Cortex-M55
musca-a              ARM Musca-A board (dual Cortex-M33)
musca-b1             ARM Musca-B1 board (dual Cortex-M33)
musicpal             Marvell 88w8618 / MusicPal (ARM926EJ-S)
n800                 Nokia N800 tablet aka. RX-34 (OMAP2420)
n810                 Nokia N810 tablet aka. RX-44 (OMAP2420)
netduino2            Netduino 2 Machine (Cortex-M3)
netduinoplus2        Netduino Plus 2 Machine (Cortex-M4)
none                 empty machine
npcm750-evb          Nuvoton NPCM750 Evaluation Board (Cortex-A9)
nuri                 Samsung NURI board (Exynos4210)
orangepi-pc          Orange Pi PC (Cortex-A7)
palmetto-bmc         OpenPOWER Palmetto BMC (ARM926EJ-S)
quanta-gbs-bmc       Quanta GBS (Cortex-A9)
quanta-gsj           Quanta GSJ (Cortex-A9)
quanta-q71l-bmc      Quanta-Q71l BMC (ARM926EJ-S)
rainier-bmc          IBM Rainier BMC (Cortex-A7)
raspi0               Raspberry Pi Zero (revision 1.2)
raspi1ap             Raspberry Pi A+ (revision 1.1)
raspi2               Raspberry Pi 2B (revision 1.1) (alias of raspi2b)
raspi2b              Raspberry Pi 2B (revision 1.1)
raspi3ap             Raspberry Pi 3A+ (revision 1.0)
raspi3               Raspberry Pi 3B (revision 1.2) (alias of raspi3b)
raspi3b              Raspberry Pi 3B (revision 1.2)
realview-eb          ARM RealView Emulation Baseboard (ARM926EJ-S)
realview-eb-mpcore   ARM RealView Emulation Baseboard (ARM11MPCore)
realview-pb-a8       ARM RealView Platform Baseboard for Cortex-A8
realview-pbx-a9      ARM RealView Platform Baseboard Explore for Cortex-A9
romulus-bmc          OpenPOWER Romulus BMC (ARM1176)
sabrelite            Freescale i.MX6 Quad SABRE Lite Board (Cortex-A9)
sbsa-ref             QEMU 'SBSA Reference' ARM Virtual Machine
smdkc210             Samsung SMDKC210 board (Exynos4210)
sonorapass-bmc       OCP SonoraPass BMC (ARM1176)
spitz                Sharp SL-C3000 (Spitz) PDA (PXA270)
stm32vldiscovery     ST STM32VLDISCOVERY (Cortex-M3)
supermicrox11-bmc    Supermicro X11 BMC (ARM926EJ-S)
swift-bmc            OpenPOWER Swift BMC (ARM1176) (deprecated)
sx1                  Siemens SX1 (OMAP310) V2
sx1-v1               Siemens SX1 (OMAP310) V1
tacoma-bmc           OpenPOWER Tacoma BMC (Cortex-A7)
terrier              Sharp SL-C3200 (Terrier) PDA (PXA270)
tosa                 Sharp SL-6000 (Tosa) PDA (PXA255)
verdex               Gumstix Verdex (PXA270)
versatileab          ARM Versatile/AB (ARM926EJ-S)
versatilepb          ARM Versatile/PB (ARM926EJ-S)
vexpress-a15         ARM Versatile Express for Cortex-A15
vexpress-a9          ARM Versatile Express for Cortex-A9
virt-2.10            QEMU 2.10 ARM Virtual Machine
virt-2.11            QEMU 2.11 ARM Virtual Machine
virt-2.12            QEMU 2.12 ARM Virtual Machine
virt-2.6             QEMU 2.6 ARM Virtual Machine
virt-2.7             QEMU 2.7 ARM Virtual Machine
virt-2.8             QEMU 2.8 ARM Virtual Machine
virt-2.9             QEMU 2.9 ARM Virtual Machine
virt-3.0             QEMU 3.0 ARM Virtual Machine
virt-3.1             QEMU 3.1 ARM Virtual Machine
virt-4.0             QEMU 4.0 ARM Virtual Machine
virt-4.1             QEMU 4.1 ARM Virtual Machine
virt-4.2             QEMU 4.2 ARM Virtual Machine
virt-5.0             QEMU 5.0 ARM Virtual Machine
virt-5.1             QEMU 5.1 ARM Virtual Machine
virt-5.2             QEMU 5.2 ARM Virtual Machine
virt-6.0             QEMU 6.0 ARM Virtual Machine
virt                 QEMU 6.1 ARM Virtual Machine (alias of virt-6.1)
virt-6.1             QEMU 6.1 ARM Virtual Machine
witherspoon-bmc      OpenPOWER Witherspoon BMC (ARM1176)
xilinx-zynq-a9       Xilinx Zynq Platform Baseboard for Cortex-A9
xlnx-versal-virt     Xilinx Versal Virtual development board
xlnx-zcu102          Xilinx ZynqMP ZCU102 board with 4xA53s and 2xR5Fs based on the value of smp
z2                   Zipit Z2 (PXA27x)
rlk@rlk:build$ sudo qemu-system-aarch64 -M help | grep jimmy
jimmy-virt           Jimmy Versal Virtual development board
rlk@rlk:build$

qemu学习之添加一个新machine相关推荐

  1. golang mysql 插入_Mysql学习(一)添加一个新的用户并用golang操作Mysql

    Mysql添加一个新的用户并赋予权限 添加一个自己的用户到mysql 首先我们需要先用root用户登录mysql,但是刚安装完没有密码,我们先跳过密码 ailumiyana@ailumiyana:~/ ...

  2. 如何给MindSpore添加一个新的硬件后端?快速构建测试环境!

    摘要:介绍如何给MindSpore添加一个新的硬件后端. 本文分享自华为云社区<如何给MindSpore添加一个新的硬件后端?快速构建测试环境!>,原文作者:HWCloudAI. Mind ...

  3. 向Hadoop集群添加一个新的节点

    如何向向Hadoop集群添加一个新的节点? 1.在新节点安装好hadoop或者从其他节点复制一份 2.把namenode的有关配置文件复制到该节点 3.修改masters和slaves文件,增加该节点 ...

  4. 012.Adding a New Field --【添加一个新字段】

    索引: 目录索引 Adding a New Field 添加一个新字段 2016-10-14 3 分钟阅读时长 作者 By Rick Anderson In this section you'll u ...

  5. [vue] 动态给vue的data添加一个新的属性时会发生什么?怎样解决?

    [vue] 动态给vue的data添加一个新的属性时会发生什么?怎样解决? 如果在实例创建之后添加新的属性到实例上,它不会触发视图更新.如果想要使添加的值做到响应式,应当使用$set()来添加对象. ...

  6. 【IntelliJ IDEA】添加一个新的tomcat,tomcat启动无法访问欢迎页面,空白页,404

    ===================================第一部分,添加一个tomcat================================================== ...

  7. liunx centos 如何添加一个新的网卡

    1.虚拟机中按照下面两个图片添加一个新的网络适配器 二. 查看网卡是否识别! vi /etc/udev/rules.d/70-persistent-net.rules #可以看到有两块网卡! 复制et ...

  8. linux下 添加一个新账户tom,linux 账户管理命令 useradd、groupadd使用方法

    内容提要: 1. 掌握用户的 增/删/改 命令 2. 掌握组的 增/删/改 命令 组管理 1)groupadd groupadd 用于添加组账号.格式如下:groupadd [-g gid] grou ...

  9. 使用layui 做后台管理界面,在Tab中的链接点击后添加一个新TAB的解决方法

    使用layui 做后台管理界面,在Tab中的链接点击后添加一个新TAB的解决方法 参考文章: (1)使用layui 做后台管理界面,在Tab中的链接点击后添加一个新TAB的解决方法 (2)https: ...

最新文章

  1. 激光雷达Lidar Architecture and Lidar Design(下)
  2. 线程的调度、优先级和亲缘性——Windows核心编程学习手札系列之七
  3. 常用算法 之三 详解 SHA1 实现(基于算法的官方原文档)及源码详细注释
  4. 文明重启服务器维护怎么卡进去,文明重启更新之后进不去,具体玩法介绍
  5. Create new SAP DDL view and click finish in wizard
  6. 5 video关掉字幕选项_Photoshop 2020中英文字幕批量生成的制作方法
  7. 【白皮书分享】人工智能“新基建”发展白皮书.pdf(附下载链接)
  8. 2021-04-06梦笔记
  9. (黑马教程)-webpack学习笔记
  10. 集成电路总设计(Ⅴ)
  11. 计算机硬件相关专业学校,计算机硬件相关专业有哪些
  12. Android Dialog宽度设置固定大小
  13. Android实现手机静音,Android实现手机静音
  14. 应用软件安全编程代码实现安全
  15. 随手笔记之逆序输出数字
  16. MS coco数据集下载链接
  17. jQuery生成动态表格
  18. 如何恢复sd卡数据呢?
  19. 【二叉树前/先序DLR中序LDR后序LRD遍历及镜像翻转,so esay~】
  20. 全排列Permutation

热门文章

  1. MFC exe文件生成的图标更改方法
  2. 苹果(maccms V10) Python 采集豆瓣评分直接入库。
  3. 从位图图像中读取2D纹理(C ++,OpenGL)
  4. 浅谈React和VDom关系
  5. 驱动层SSDT 隐藏进程
  6. 美军如何在不可信设备上安全访问国防部网络?
  7. 个人通讯录系统——数据库课程设计
  8. python运行界面如何缩小_如何使用Python调整图像大小
  9. typescript 中 any 和 unknow 区别
  10. JAVA编写的纯色背景图片去除底色变成透明背景图片的工具