{"id":10158,"date":"2022-08-17T09:26:05","date_gmt":"2022-08-17T09:26:05","guid":{"rendered":"https:\/\/digitalgateamg.com\/?p=10158"},"modified":"2023-08-08T14:46:20","modified_gmt":"2023-08-08T14:46:20","slug":"qemu-development-during-the-chip-shortage","status":"publish","type":"post","link":"https:\/\/digitalgateamg.com\/de\/blog\/2022\/08\/17\/qemu-development-during-the-chip-shortage\/","title":{"rendered":"QEMU-Entwicklung"},"content":{"rendered":"<p data-renderer-start-pos=\"37\">Considering the current developments in the global market, especially having the issue of a Global Chip Shortage, there are some issues to be addressed when having to deploy software on an Embedded platform, but the platform itself is missing.<\/p>\n<p data-renderer-start-pos=\"37\">The issue posed is no small undertaking, especially for companies deploying software for different platforms and not having the possibility of holding in stock the multitude of SoCs available on the market. There is also the situation when a new chip is under development and, for efficiency reasons, the software for it has to be developed in parallel.<\/p>\n<p data-renderer-start-pos=\"636\">All of this considered, it has to be handy to emulate hardware on our standard x64 machines. But what do we do when there are different memory maps or even ISAs (Instruction Set Architectures) involved? For this task, QEMU\u2019s capabilities come to the rescue.<\/p>\n<p data-renderer-start-pos=\"891\">This article documents the steps required to add a custom machine to QEMUs existing machines and make use of established constructs in QEMU, and even use of the project\u2019s open-source nature.<\/p>\n<h2>A short QEMU description<\/h2>\n<p data-renderer-start-pos=\"1138\">QEMU as an open-source machine emulator and virtualizer. Meaning that it can both act as your VM of choice, or even act as a machine virtualizer, mocking memory maps of actual hardware and producing effects (visible to the software running as a guest on it) highly similar to its corresponding hardware counterpart.<\/p>\n<p data-renderer-start-pos=\"1466\">It currently supports a high variety of ARM guests, offering support for around fifty different machines. There is support offered for both \u201cA-profile\u201d CPUs, and \u201cM-profile\u201d CPUs as well, although in a more numerically limited fashion, machine-wise, for the latter.<\/p>\n<p data-renderer-start-pos=\"1733\">Even though there is support offered for a variety of specific machines and SoCs, there is also a <em data-renderer-mark=\"true\">virt <\/em>machine being offered. This machine, called <em data-renderer-mark=\"true\">virt<\/em>, is a generic ARM system emulation variant. <em data-renderer-mark=\"true\">Virt<\/em> is offering a variety of supported \u201ccpus\u201d (e.g. cortex-a15, cortex-a53, etc.), and different peripherals. The use of this machine is recommended only when the particularities of specific hardware and its limitation are ignored in the software development process.<\/p>\n<h2>System Requirements<\/h2>\n<p data-renderer-start-pos=\"2219\">QEMU is able to run on the following host platforms:<\/p>\n<ul>\n<li data-renderer-start-pos=\"2219\">Linux<\/li>\n<li data-renderer-start-pos=\"2219\">Microsoft Windows<\/li>\n<li data-renderer-start-pos=\"2219\">macOS<\/li>\n<li data-renderer-start-pos=\"2219\">some other UNIX platforms<\/li>\n<\/ul>\n<h2>Initialization<\/h2>\n<p data-renderer-start-pos=\"2361\">For the running of QEMU, there is a recommendation of using a Linux-based system as a host, at least for the specific case of this article. In this case, QEMU is running on an Ubuntu version 18.04.<\/p>\n<p data-renderer-start-pos=\"2555\">The QEMU version used for this example is marked with the tag v.7.0.0 on GitHub.<\/p>\n<p data-renderer-start-pos=\"2360\"><strong data-renderer-mark=\"true\">DISCLAIMER:<\/strong> this is not a fully-fledged tutorial, if you expect to have a specific machine implemented at the end of it, with exact addresses and other parameters of a specific machine, I would recommend the tutorial mentioned in the References from S. Sopha (with the mention that the FreeRTOS tutorial required to check the machine implementation is not a complete one). The current work documents another perspective on how to implement a machine in QEMU, and it aims to be more explanatory than practical starting with the \u201c<em data-renderer-mark=\"true\">Cloning already existing source and header files\u201d <\/em>part. Before this, you can follow the tutorial step by step and fulfills practical requirements.<\/p>\n<h2>Cloning of the Git Repository<\/h2>\n<p data-renderer-start-pos=\"2360\">For cloning the most recent version of QEMU, you should run the following command:<\/p>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>git clone https:\/\/github.com\/qemu\/qemu<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<h2>Pre-build preparations<\/h2>\n<p data-renderer-start-pos=\"2360\">There are a number of dependencies required for successfully running QEMU, but the following script should suffice at least for the version 7.0.0 of QEMU:<\/p>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp># Set up locales\napt-get update && apt-get install -y \n    apt-utils locales sudo && \n    dpkg-reconfigure locales && \n    locale-gen en_US.UTF-8 && \n    update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 && \n    apt-get clean && \n    rm -rf \/var\/lib\/apt\/lists\/*\napt-get update && apt-get install -y \n    git \n    build-essential \n    zlib1g-dev \n    pkg-config \n    libglib2.0-dev \n    binutils-dev \n    libboost-all-dev \n    autoconf \n    libtool \n    libssl-dev \n    libpixman-1-dev \n    libpython-dev \n    python-pip \n    python-capstone \n    virtualenv && \n    apt-get clean && \n    rm -rf \/var\/lib\/apt\/lists\/*\napt update -y\napt upgrade -y\napt install ninja-build<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<h2>Configuring and building<\/h2>\n<p data-renderer-start-pos=\"4245\">For configuring and building there is a need to be sure that a build directory exists inside of the QEMU repository. The selected configuration is marked in line 4 and is for a number of 32-bit and 64-bit ARM-supported machines. This configuration includes the <em data-renderer-mark=\"true\">virt<\/em> generic machine, as well.<\/p>\n<p data-renderer-start-pos=\"4539\"><strong data-renderer-mark=\"true\">! Warning: <\/strong>In case of performing modifications on source or header files already included by configure, there is no need to run <em data-renderer-mark=\"true\">configure <\/em>again when compiling. You should only run <em>make<\/em>,&nbsp;because of the time required&nbsp;to compile these numerous machine header and source files from ground zero.<\/p>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>cd qemu \nmkdir build \ncd build \n..\/configure --target-list=aarch64-softmmu # preparing the build for ARM machines running on 64 and 32 bits\nmake<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<h2>Checking the machine list<\/h2>\n<p data-renderer-start-pos=\"4370\">To check the machine list use the following commands:<\/p>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>cd qemu\ncd build\ncd aarch64-softmmu\n.\/qemu-system-aarch64 -M help<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<p data-renderer-start-pos=\"4370\">This command is useful to check if the compilation process was performed correctly, and is going to be useful when trying to add the custom machine to QEMU.<\/p>\n<h2>Running a machine<\/h2>\n<p data-renderer-start-pos=\"4370\">Running of a machine might require a kernel image and a device tree file (<em data-renderer-mark=\"true\">.dtb &#8211; device tree blob file<\/em>). The kernel image can be a buildroot compiled Linux kernel image, or even Yocto could be used for this task. The compilation of a Linux kernel image is outside of the scope of this tutorial. The .dtb file describes the memory mappings of the representing hardware.<\/p>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp># Follow the steps from the pervious code snippet to get to the qemu-system-aarch64 file, or use make install instead of just make\n.\/qemu-system-aarch64 -M <machine_selected_from_list> \n                      -kernel <path_to_kernel_image_file> \n                      -dtb <path_to_dtb_file><\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<h2>Adding a new machine to QEMU<\/h2>\n<p data-renderer-start-pos=\"6154\">Let\u2019s name the new machine <em data-renderer-mark=\"true\">arm-example <\/em>or <em data-renderer-mark=\"true\">ARM_EXAMPLE<\/em>, in order to be generic enough. Thus, we will use this naming convention over the course of this section.<\/p>\n<p data-renderer-start-pos=\"6305\">To have the machine appear when calling&nbsp;<em>.\/qemu-system-aarch64 -M help<\/em>, you have to add it to&nbsp;<em data-rich-text-format-boundary=\"true\">Kconfig, meson.build&nbsp;<\/em>files.<\/p>\n<p data-renderer-start-pos=\"6427\">After adding the mentioned parts, the source and header files are copied from a similar enough machine to be further implemented.<\/p>\n<p data-renderer-start-pos=\"6558\">Modifications have to be performed to variables representing the addresses of the machine. Also, there could be a need to modify constants representing machine name, type, clocks, and interrupt routines.<\/p>\n<h2>Adding machine to configuration<\/h2>\n<p data-renderer-start-pos=\"6792\">Considering it is an ARM 64-bit machine, first, there is a need to locate <em data-renderer-mark=\"true\">hw\/arm<\/em> directory inside of the <em data-renderer-mark=\"true\">qemu<\/em> directory. There, the <em data-renderer-mark=\"true\">meson.build<\/em> and <em data-renderer-mark=\"true\">Kconfig<\/em> files are modified like in the snippets below:<\/p>\n<ul>\n<li data-renderer-start-pos=\"6992\"><em data-renderer-mark=\"true\">Kconfig:<\/em><\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>config RASPI\n    bool\n    select FRAMEBUFFER\n    select PL011 # UART\n    select SDHCI\n    select USB_DWC2\n# beginning of added arm-example\/ARM_EXAMPLE \nconfig ARM_EXAMPLE\n    bool\n    select PL011 # UART for a latter implementation, it can even be commented\n# end of added arm-example\/ARM_EXAMPLE\nconfig STM32F100_SOC\n    bool\n    select ARM_V7M\n    select STM32F2XX_USART\n    select STM32F2XX_SPI<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li data-renderer-start-pos=\"6792\"><em data-renderer-mark=\"true\">meson.build:<\/em><\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>arm_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_peripherals.c', 'bcm2836.c', 'raspi.c'))\n# beginning of added arm-example\/ARM_EXAMPLE file(s)\narm_ss.add(when: 'CONFIG_ARM_EXAMPLE', if_true: files('arm-example.c'))\n# end of added arm-example\/ARM_EXAMPLE file(s)\narm_ss.add(when: 'CONFIG_STM32F100_SOC', if_true: files('stm32f100_soc.c'))<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<p data-renderer-start-pos=\"7766\">In the&nbsp;<em>configs\/devices\/&nbsp;<\/em>directory, you have to modify the&nbsp;<em>arm-softmmu.mak<\/em>&nbsp;file, as following.<\/p>\n<p data-renderer-start-pos=\"7861\"><em data-renderer-mark=\"true\">arm-softmmu.mak<\/em>:<\/p>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>CONFIG_TOSA=y\n# beginning of added arm-example\/ARM_EXAMPLE\nCONFIG_ARM_EXAMPLE=y\n# end of added arm-example\/ARM_EXAMPLE\nCONFIG_Z2=y<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<h2>Cloning already existing source and header files<\/h2>\n<p data-renderer-start-pos=\"8063\">The main <em data-renderer-mark=\"true\">raspi.c <\/em>source file and its corresponding header and dependency files are either cloned or kept in their original form for this example to work.<\/p>\n<p data-renderer-start-pos=\"8212\">Copy the <em data-renderer-mark=\"true\">raspi.c <\/em>file, and rename it to <em data-renderer-mark=\"true\">arm-example.c<\/em>.<\/p>\n<p data-renderer-start-pos=\"8268\">In the <em data-renderer-mark=\"true\">arm-example.c<\/em> the following structure is going to be used:<\/p>\n<ul>\n<li>header files;<\/li>\n<li data-renderer-start-pos=\"8337\">constants &#8211; representing the name, firmware address, machine name macro initialization, etc.;<\/li>\n<li data-renderer-start-pos=\"8337\">function <em data-renderer-mark=\"true\">board_ram_size<\/em> &#8211; for retrieving board specific RAM memory size available;<\/li>\n<li data-renderer-start-pos=\"8337\">function <em data-renderer-mark=\"true\">setup_boot<\/em> &#8211; verifies if firmware exists and loads the kernel;<\/li>\n<li data-renderer-start-pos=\"8337\">function <em data-renderer-mark=\"true\">arm_example_machine_init<\/em> &#8211; initialization of different devices used by this machine (e.g. SoC);<\/li>\n<li data-renderer-start-pos=\"8337\">function <em data-renderer-mark=\"true\">arm_example_machine_class_common_init<\/em> &#8211; declares the names and some variables present in the <em data-renderer-mark=\"true\">MachineClass <\/em>data structure;<\/li>\n<li data-renderer-start-pos=\"8337\">function <em data-renderer-mark=\"true\">arm_example_machine_class_init <\/em>&#8211; declares general names and variables in the <em data-renderer-mark=\"true\">MachineClass<\/em> data structure;<\/li>\n<li data-renderer-start-pos=\"8337\">constant <em data-renderer-mark=\"true\">arm_example_machine_types<\/em> &#8211; declares fields used for registering the machine in the QEMU\u2019s list of machines, links the initialization functions from above with the machine type;<\/li>\n<li data-renderer-start-pos=\"8337\">call of the function defined by <strong data-renderer-mark=\"true\">DEFINE_TYPES <\/strong>macro &#8211; used for appending the machine to the list of machines by calling the TypeInfo constant described exactly above.<\/li>\n<\/ul>\n<p data-renderer-start-pos=\"9331\">Following, the snippets for these parts of code are introduced. The order is going to be from below to above.<\/p>\n<ul>\n<li>DEFINE_TYPES MACRO<\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>DEFINE_TYPES(arm_example_machine_types)<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li>CONSTANT arm_example_machine_types<\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>static const TypeInfo arm_example_machine_types[] = {\n    {\n        .name           = MACHINE_TYPE_NAME(\"arm-example\"),\n        .parent         = TYPE_ARM_EXAMPLE_MACHINE,\n        .class_init     = arm_example_machine_class_init,\n    },\n    {\n        .name           = TYPE_ARM_EXAMPLE_MACHINE,\n        .parent         = TYPE_MACHINE,\n        .instance_size  = sizeof(ARMExampleMachineState),\n        .class_size     = sizeof(ARMExampleMachineClass),\n        .abstract       = true, \n    }\n};<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li>FUNCTION arm_example_machine_class_init<\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>static void arm_example_machine_class_init(ObjectClass *oc, void *data)\n{\n    MachineClass *mc = MACHINE_CLASS(oc);\n    ARMExampleMachineClass *smc = ARM_EXAMPLE_MACHINE_CLASS(oc);\n    smc->board_rev = 0x920092;\n    arm_example_machine_class_common_init(mc, smc->board_rev);\n};<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li style=\"font-size: 25px; font-weight: 300; font-family: Montserrat, Montseraat; line-height: 1em; letter-spacing: normal; text-transform: none; outline-style: initial; outline-width: 0px; color: var( --e-global-color-nvprimaryaccent );\" data-elementor-setting-key=\"title\" data-pen-placeholder=\"Type Here...\">FUNCTION arm_example_machine_class_common_init<\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>static void arm_example_machine_class_common_init (MachineClass *mc, uint32_t board_rev) {\n    mc->desc = \"ARM EXAMPLE MACHINE (64-bit)\";\n    mc->init = arm_example_machine_init;\n    mc->default_ram_size = board_ram_size(board_rev);\n    mc->default_ram_id = \"ram\";\n};<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li style=\"font-size: 25px; font-weight: 300; font-family: Montserrat, Montseraat; line-height: 1em; letter-spacing: normal; text-transform: none; outline-style: initial; outline-width: 0px; color: var( --e-global-color-nvprimaryaccent );\" data-elementor-setting-key=\"title\" data-pen-placeholder=\"Type Here...\">FUNCTION arm_example_machine_init<\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>static void arm_example_machine_init(MachineState *machine) {\n    ARMExampleMachineClass *mc = ARM_EXAMPLE_MACHINE_GET_CLASS(machine);\n    ARMExampleMachineState *s = ARM_EXAMPLE_MACHINE(machine);\n    uint32_t board_rev = mc->board_rev;\n    uint32_t vcram_size;\n    uint64_t ram_size = board_ram_size(board_rev);\n    if (machine->ram_size != ram_size) {\n            char *size_str = size_to_str(ram_size);\n            error_report(\"Invalid RAM size, should be %s\", size_str);\n            g_free(size_str);\n            exit(1);\n        }\n    memory_region_add_subregion_overlap(get_system_memory(), 0,\n                                             machine->ram, 0);\n    \/* Setup the SoC *\/\n    object_initialize_child(OBJECT(machine), \"soc\", &s->soc, \"arm-example-soc\");\n    object_property_add_const_link(OBJECT(&s->soc), \"ram\", OBJECT(machine->ram));\n    object_property_set_int(OBJECT(&s->soc), \"board-rev\", board_rev, &error_abort);\n    qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);\n    vcram_size = object_property_get_uint(OBJECT(&s->soc), \"vcram-size\",\n                                          &error_abort);\n    setup_boot(machine, 0,\n               machine->ram_size - vcram_size);\n}<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li style=\"font-size: 25px; font-weight: 300; font-family: Montserrat, Montseraat; line-height: 1em; letter-spacing: normal; text-transform: none; outline-style: initial; outline-width: 0px; color: var( --e-global-color-nvprimaryaccent );\" data-elementor-setting-key=\"title\" data-pen-placeholder=\"Type Here...\">FUNCTION setup_boot<\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>static void setup_boot(MachineState *machine, int processor_id, \n                        size_t ram_size) \n{\n    ARMExampleMachineState *s = ARM_EXAMPLE_MACHINE(machine);\n    s->bdinfo.board_id = 0; \/\/ TODO: Change this, if required\n    s->bdinfo.ram_size = ram_size;\n    if (machine->firmware) {    \n        int r = load_image_targphys(machine->firmware, FIRMWARE_ADDR, ram_size - FIRMWARE_ADDR);\n        if (r < 0) {\n            error_report(\"Failed to load firmware from %s\", machine->firmware);\n            exit(1);\n        }\n        s->bdinfo.entry = FIRMWARE_ADDR;\n        s->bdinfo.firmware_loaded = true;\n    }\n    arm_load_kernel(&s->soc.cpu[0].core, machine, &s->bdinfo);\n}<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li style=\"font-size: 25px; font-weight: 300; font-family: Montserrat, Montseraat; line-height: 1em; letter-spacing: normal; text-transform: none; outline-style: initial; outline-width: 0px; color: var( --e-global-color-nvprimaryaccent );\" data-elementor-setting-key=\"title\" data-pen-placeholder=\"Type Here...\">FUNCTION board_ram_size&nbsp; &nbsp;<\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>static uint64_t board_ram_size(uint32_t board_rev)\n{\n    assert(FIELD_EX32(board_rev, REV_CODE, STYLE)); \/* Only new style *\/\n    return 256 * MiB << FIELD_EX32(board_rev, REV_CODE, MEMORY_SIZE);\n}<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li>\n<h6>CONSTANTS<\/h6>\n<\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>#define BOARDSETUP_ADDR (ARM_EXAMPLE_RAM_START_ADDR + 0x20)\n#define FIRMWARE_ADDR 0x8000 \/\/ TODO: Change this if needed\n#define NAME_SIZE 20\nFIELD(REV_CODE, REVISION,           0, 4);\nFIELD(REV_CODE, TYPE,               4, 8);\nFIELD(REV_CODE, PROCESSOR,         12, 4);\nFIELD(REV_CODE, MANUFACTURER,      16, 4);\nFIELD(REV_CODE, MEMORY_SIZE,       20, 3);\nFIELD(REV_CODE, STYLE,             23, 1);\nstruct ARMExampleMachineState {\n    \/*< private >*\/\n    MachineState parent_obj;\n    \/*< public >*\/\n    ARMExample_SoCState soc;\n    struct arm_boot_info bdinfo;\n    \/\/ MemoryRegion ram;\n};\ntypedef struct ARMExampleMachineState ARMExampleMachineState;\nstruct ARMExampleMachineClass {\n    \/*< private >*\/\n    MachineClass parent_obj;\n    \/*< public >*\/\n    uint32_t board_rev;\n    \/\/ MemoryRegion ram;\n};\ntypedef struct ARMExampleMachineClass ARMExampleMachineClass;\n#define TYPE_ARM_EXAMPLE_MACHINE       MACHINE_TYPE_NAME(\"arm-example-common\")\nDECLARE_OBJ_CHECKERS(ARMExampleMachineState, ARMExampleMachineClass,\n                     ARM_EXAMPLE_MACHINE, TYPE_ARM_EXAMPLE_MACHINE)<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li>\n<h6>HEADER FILES<\/h6>\n<\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>#include \"qemu\/osdep.h\"\n#include \"qapi\/error.h\"\n#include \"hw\/arm\/arm-example.h\"\n#include \"qemu\/cutils.h\"\n#include \"qemu\/units.h\"\n#include \"hw\/registerfields.h\"\n#include \"qemu\/error-report.h\"\n#include \"hw\/arm\/boot.h\"\n#include \"hw\/boards.h\"\n#include \"qemu\/module.h\"\n#include \"qom\/object.h\"\n#include \"hw\/loader.h\"<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<p data-renderer-start-pos=\"8063\">Other corresponding files are the following:<\/p>\n<ul>\n<li>\n<p data-renderer-start-pos=\"14325\"><em data-renderer-mark=\"true\">arm_example.h<\/em><\/p>\n<\/li>\n<li>\n<p data-renderer-start-pos=\"14325\"><em data-renderer-mark=\"true\">arm_example_soc.h<\/em><\/p>\n<\/li>\n<li>\n<p data-renderer-start-pos=\"14325\"><em data-renderer-mark=\"true\">arm_example_soc.c<\/em><\/p>\n<\/li>\n<li>\n<p data-renderer-start-pos=\"14384\"><em data-renderer-mark=\"true\">arm_example_peripherals.h<\/em><\/p>\n<\/li>\n<li>\n<p data-renderer-start-pos=\"14413\"><em data-renderer-mark=\"true\">arm_example_peripherals.c<\/em><\/p>\n<\/li>\n<\/ul>\n<ul>\n<li>MODIFY arm_example.h<\/li>\n<\/ul>\n<p data-renderer-start-pos=\"14464\">There is a requirement of implementing an <strong data-renderer-mark=\"true\">enum <\/strong>containing the number of cpus, devices, timers, and other machine-specific devices. We can name it&nbsp;<em data-renderer-mark=\"true\">ARMExampleConfiguration<\/em>.<\/p>\n<p data-renderer-start-pos=\"14638\">There is also a need for an <strong data-renderer-mark=\"true\">enum<\/strong> containing the entire memory map of the device wished to be implemented. The recommendation is to implement the entire memory map mentioned in the reference manual of the machine or development board to be implemented. We can name it&nbsp;<em data-renderer-mark=\"true\">ARMExampleMemoryMap<\/em>.<\/p>\n<p data-renderer-start-pos=\"14930\">The last <strong data-renderer-mark=\"true\">enum<\/strong> to be implemented can represent the IRQs. As mentioned previously, the IRQs can be found in the Reference manual of the specific machine\/device. We can name it ARMExampleIRQs.<\/p>\n<ul>\n<li>MODIFY arm_example_soc.h<\/li>\n<\/ul>\n<p data-renderer-start-pos=\"15148\">This header file contains includes the header files of peripherals as well as the control parts. The constants for the name of the machine are declared, and a struct represents SoC\u2019s state.<\/p>\n<p data-renderer-start-pos=\"15329\">You can seet the aforementioned struct in the code snippet below:<\/p>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>struct ARMExample_SoCState {\n    \/*< private >*\/\n    DeviceState parent_obj;\n    \/*< public >*\/\n    uint32_t enabled_cpus;\n    struct {\n        ARMCPU core;\n    } cpu[ARM_EXAMPLE_SOC_NCPUS];\n    BCM2835PeripheralState peripherals; \/\/ TODO: Change this implementation later\n    BCM2836ControlState control;        \/\/ TODO: Change this implementation later\n};<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li>MODIFY arm_example_soc.c<\/li>\n<\/ul>\n<p data-renderer-start-pos=\"15781\">This Source file focuses on adding the SoC device to the QEMU device tree.<\/p>\n<p data-renderer-start-pos=\"15857\">If follows a path similar to&nbsp;<em data-renderer-mark=\"true\">arm_example.c<\/em>, defining types, a types structure, initialization, and implementation functions, and declaration of constants. Like in the other source file example, the walkthrough is going to be from below to above.<\/p>\n<p data-renderer-start-pos=\"16103\"><em data-renderer-mark=\"true\">DEFINE_TYPES macro:<\/em><\/p>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>DEFINE_TYPES(arm_example_types)<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li data-renderer-start-pos=\"15781\">\n<h6><em data-renderer-mark=\"true\">Constant arm_example_types:<\/em><\/h6>\n<\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>static const TypeInfo arm_example_types[] = {\n     {\n        .name           = TYPE_ARM_EXAMPLE_SOC,\n        .parent         = TYPE_DEVICE,\n        .instance_size  = sizeof(ARMExample_SoCState),\n        .instance_init  = s32g_init,\n        .class_size     = sizeof(ARMExample_SOCClass),\n        .class_init     = s32g_class_init,\n        .abstract       = false,\n    }\n};<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li data-renderer-start-pos=\"15781\">\n<h6><em data-renderer-mark=\"true\">Function arm_example_class_init:<\/em><\/h6>\n<\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>static void arm_example_class_init(ObjectClass *oc, void *data)\n{\n    DeviceClass *dc = DEVICE_CLASS(oc);\n    ARMExample_SOCClass *sc = ARM_EXAMPLE_SOC_CLASS(oc);\n    \/\/ dc->user_creatable = false; \/\/ TODO: Eliminate this one, if needed\n    sc->cpu_type = ARM_CPU_TYPE_NAME(\"cortex-a53\");\n    sc->core_count = ARM_EXAMPLE_NCPUS;\n    sc->peri_base = ARM_EXAMPLE_PERIPH_GR_0_ADDR; \/\/ peripheral base address\n    sc->clusterid = 0xf; \/\/ No idea from where is this one.\n    dc->realize = arm_example_soc_realize;\n}<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li data-renderer-start-pos=\"15781\">\n<h6><em data-renderer-mark=\"true\">Function arm_example_soc_realize:<\/em><\/h6>\n<\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>static void s32g_soc_realize(DeviceState *dev, Error **errp)\n{\n    ARMExample_SoCState *s = ARM_EXAMPLE_SOC(dev);\n    if (!arm_example_soc_common_realize(dev, errp)) {\n        return;\n    }\n    if (!qdev_realize(DEVICE(&s->cpu[0].core), NULL, errp)) {\n        return;\n    }\n    \/* Connect irq\/fiq outputs from the interrupt controller. *\/\n    sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 0,\n            qdev_get_gpio_in(DEVICE(&s->cpu[0].core), ARM_CPU_IRQ));\n    sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 1,\n            qdev_get_gpio_in(DEVICE(&s->cpu[0].core), ARM_CPU_FIQ));\n}<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li data-renderer-start-pos=\"15781\">\n<h6><em data-renderer-mark=\"true\">Function arm_example_soc_common_realize:<\/em><\/h6>\n<\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>static bool arm_example_soc_common_realize(DeviceState *dev, Error **errp)\n{\n    ARMExample_SoCState *s = ARM_EXAMPLE_SOC(dev);\n    \/\/ ARMExample_SOCClass *sc = ARM_EXAMPLE_SOC_GET_CLASS(dev);\n    Object *obj;\n    obj = object_property_get_link(OBJECT(dev), \"ram\", &error_abort);\n    \/* START: UNCOMMENT WHEN PERIPHERALS IMPLEMENTED *\/\n    object_property_add_const_link(OBJECT(&s->peripherals), \"ram\", obj);\n    if (!sysbus_realize(SYS_BUS_DEVICE(&s->peripherals), errp)) {\n        return false;\n    }\n    \/\/ sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->peripherals), 0,\n                            \/\/ sc->peri_base, 1);\n    \/* END: UNCOMMENT WHEN PERIPHERALS IMPLEMENTED *\/                            \n    return true;                      \n}  <\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li data-renderer-start-pos=\"15781\">\n<h6><em data-renderer-mark=\"true\">Function arm_example_init:<\/em><\/h6>\n<\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>static void arm_example_init(Object *obj)\n{\n    ARMExample_SoCState *s = ARM_EXAMPLE_SOC(obj);\n    ARMExample_SOCClass *sc = ARM_EXAMPLE_SOC_GET_CLASS(obj);\n    int n;\n    for (n = 0; n < sc->core_count; n++)\n    {\n        object_initialize_child(obj, \"cpu[*]\", &s->cpu[n].core, sc->cpu_type);\n    }\n    if (sc->core_count > 1) {\n        qdev_property_add_static(DEVICE(obj), &arm_example_soc_enabled_cores_property);\n        qdev_prop_set_uint32(DEVICE(obj), \"enabled-cpus\", sc->core_count);\n    }\n    if (sc->ctrl_base) {\n        object_initialize_child(obj, \"control\", &s->control,\n                                TYPE_BCM2836_CONTROL); \/\/ TODO: Change this, if required\n    }\n    object_initialize_child(obj, \"peripherals\", &s->peripherals,\n                            TYPE_BCM2835_PERIPHERALS); \/\/ TODO: Change this, if required\n    object_property_add_alias(obj, \"board-rev\", OBJECT(&s->peripherals),\n                              \"board-rev\");\n    object_property_add_alias(obj, \"vcram-size\", OBJECT(&s->peripherals),\n                              \"vcram-size\");\n} <\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li data-renderer-start-pos=\"15781\">\n<h6><em data-renderer-mark=\"true\">Constants:<\/em><\/h6>\n<\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>typedef struct ARMExample_SOCClass {\n    \/*< private >*\/\n    DeviceClass parent_class;\n    \/*< public >*\/\n    const char *name;\n    const char *cpu_type;\n    unsigned core_count;\n    hwaddr peri_base;\n    hwaddr ctrl_base;\n    int clusterid;\n} ARMExample_SOCClass;\n#define ARM_EXAMPLE_SOC_CLASS(klass) \n    OBJECT_CLASS_CHECK(ARMExample_SOCClass, (klass), TYPE_ARM_EXAMPLE_SOC)\n#define ARM_EXAMPLE_SOC_GET_CLASS(obj) \n    OBJECT_GET_CLASS(ARMExample_SOCClass, (obj), TYPE_ARM_EXAMPLE_SOC)\nstatic Property arm_example_soc_enabled_cores_property =\n    DEFINE_PROP_UINT32(\"enabled-cpus\", ARMExample_SoCState, enabled_cpus, 0);<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li data-renderer-start-pos=\"15781\">\n<h6><em data-renderer-mark=\"true\">Header files:<\/em><\/h6>\n<\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>#include \"qemu\/osdep.h\"\n#include \"qapi\/error.h\"\n#include \"qemu\/module.h\"\n#include \"hw\/arm\/arm_example_soc.h\"\n#include \"hw\/arm\/arm_example.h\" \/\/ Maybe this one could and should be replaced\n#include \"hw\/sysbus.h\"\n#include \"hw\/qdev-properties.h\"<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li style=\"font-size: 25px; font-weight: 300; font-family: Montserrat, Montseraat; line-height: 1em; letter-spacing: normal; text-transform: none; outline-style: initial; outline-width: 0px; color: var( --e-global-color-nvprimaryaccent ); -webkit-text-stroke-color: #000000; stroke: #000000;\" data-elementor-setting-key=\"title\" data-pen-placeholder=\"Type Here...\">MODIFY arm_example_peripherals.h<\/li>\n<\/ul>\n<p data-renderer-start-pos=\"20580\">In the following file, we chose a simplified implementation of the&nbsp;<em style=\"color: var( --e-global-color-secondary ); font-family: var( --e-global-typography-secondary-font-family ), Montseraat; font-weight: var( --e-global-typography-secondary-font-weight ); background-color: var(--nv-site-bg); font-size: var(--bodyfontsize); letter-spacing: var(--bodyletterspacing); text-transform: var(--bodytexttransform);\">include\/hw\/arm\/bcm2835_peripherals.h<\/em>, especially when talking about the headers included&nbsp;especially when talking about the headers included. There is the choice of either implementing own arm_example_ic.h, arm_example_systmr.h, arm_example_fb.h, and arm_example_mbox.h, or using the original headers from the original implementation mentioned at the beginning of the paragraph.<\/p>\n<ul>\n<li>MODIFY arm_example.h<\/li>\n<\/ul>\n<p data-renderer-start-pos=\"20580\"><em data-renderer-mark=\"true\" style=\"color: var( --e-global-color-secondary ); font-family: var( --e-global-typography-secondary-font-family ), Montseraat; font-weight: var( --e-global-typography-secondary-font-weight ); background-color: var(--nv-site-bg); font-size: var(--bodyfontsize); letter-spacing: var(--bodyletterspacing); text-transform: var(--bodytexttransform);\">ARMExamplePeripheralState struct:<\/em><\/p>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp> struct ARMExamplePeripheralState {\n    \/* < private > *\/\n    SysBusDevice parent_obj;\n    \/* < public > *\/\n    MemoryRegion peri_mr, peri_mr_alias, gpu_bus_mr, mbow_mr;\n    MemoryRegion ram_alias[4];\n    qemu_irq irq, fiq;\n    ARMExampleICState ic;\n    ARMExampleSystemTimerState systmr;\n    ARMExampleMboxState mboxes;\n    ARMExampleFBState fb;\n};<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li data-renderer-start-pos=\"20580\">\n<h6><em data-renderer-mark=\"true\">Constants:<\/em><\/h6>\n<\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>#define TYPE_ARM_EXAMPLE_PERIPHERALS \"arm-example-peripherals\"\nOBJECT_DECLARE_SIMPLE_TYPE(ARMExamplePeripheralState, ARM_EXAMPLE_PERIPHERALS)<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li data-renderer-start-pos=\"20580\">\n<h6><em data-renderer-mark=\"true\">Headers:<\/em><\/h6>\n<\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>#include \"hw\/sysbus.h\"\n#include \"exec\/memory.h\"\n#include \"qom\/object.h\"\n#include \"hw\/intc\/arm_example_ic.h\"\n#include \"hw\/timer\/arm_example_systmr.h\"\n#include \"hw\/misc\/unimp.h\"\n#include \"hw\/display\/arm_example_fb.h\"\n#include \"hw\/misc\/arm_example_mbox.h\"<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li style=\"font-size: 25px; font-weight: 300; font-family: Montserrat, Montseraat; line-height: 1em; letter-spacing: normal; text-transform: none; outline-style: initial; outline-width: 0px; color: var( --e-global-color-nvprimaryaccent );\" data-elementor-setting-key=\"title\" data-pen-placeholder=\"Type Here...\">MODIFY arm_example_peripherals.c<\/li>\n<\/ul>\n<ul>\n<li data-renderer-start-pos=\"20580\"><em data-renderer-mark=\"true\">type_init macro:<\/em><\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>type_init(arm_example_peripherals_register_types)<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li data-renderer-start-pos=\"20580\"><em data-renderer-mark=\"true\">Function arm_example_peripherals_register_types:<\/em><\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>static void arm_example_peripherals_register_types(void) \n{\n    type_register_static(&arm_example_peripherals_type_info);\n}<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li data-renderer-start-pos=\"20580\"><em data-renderer-mark=\"true\">Constant arm_example_peripherals_type_info:<\/em><\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>static const TypeInfo arm_example_peripherals_type_info = {\n    .name = TYPE_ARM_EXAMPLE_PERIPHERALS,\n    .parent = TYPE_SYS_BUS_DEVICE,\n    .instance_size = sizeof(ARMExamplePeripheralState),\n    .instance_init = arm_example_peripherals_init,\n    .class_init = arm_example_peripherals_class_init,\n};<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li data-renderer-start-pos=\"20580\"><em data-renderer-mark=\"true\">Function arm_example_peripherals_class_init:<\/em><\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>static void arm_example_peripherals_class_init (ObjectClass *oc, void *data)\n{\n    DeviceClass *dc = DEVICE_CLASS(oc);\n    dc->realize = arm_example_peripherals_realize;\n} <\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li data-renderer-start-pos=\"20580\"><em data-renderer-mark=\"true\">Function arm_example_peripherals_class_init:<\/em><\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>static void arm_example_peripherals_realize (DeviceState *dev, Error **errp)\n{\n    ARMExamplePeripheralState *s = ARM_EXAMPLE_PERIPHERALS(dev);\n    Object *obj;\n    MemoryRegion *ram;\n    Error *err = NULL;\n    uint64_t ram_size, vcram_size;\n    int n;\n    obj = object_property_get_link(OBJECT(dev), \"ram\", &error_abort);\n    ram = MEMORY_REGION(obj);\n    ram_size = memory_region_size(ram);\n    \/* Interrupt Controller *\/\n    if (!sysbus_realize(SYS_BUS_DEVICE(&s->ic), errp)) {\n        return;\n    }\n    \/* Sys Timer *\/\n    if (!sysbus_realize(SYS_BUS_DEVICE(&s->systmr), errp)) {\n        return;\n    }\n    \/* Framebuffer *\/\n    vcram_size = object_property_get_uint(OBJECT(s), \"vcram-size\", &err);\n    if (err) {\n        error_propagate(errp, err);\n        return;\n    }\n    if (!object_property_set_uint(OBJECT(&s->fb), \"vcram-base\",\n                                  ram_size - vcram_size, errp)) {\n        return;\n    }\n    if (!sysbus_realize(SYS_BUS_DEVICE(&s->fb), errp)) {\n        return;\n    }\n    memory_region_add_subregion(&s->mbox_mr, MBOX_CHAN_FB << MBOX_AS_CHAN_SHIFT,\n                sysbus_mmio_get_region(SYS_BUS_DEVICE(&#038;s->fb), 0));\n    sysbus_connect_irq(SYS_BUS_DEVICE(&s->fb), 0,\n                       qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_FB));\n} <\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li data-renderer-start-pos=\"20580\"><em data-renderer-mark=\"true\">Function arm_example_peripherals_init:<\/em><\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>static void arm_example_peripherals_init (Object *obj)\n{\n    ARMExamplePeripheralState *s = ARM_EXAMPLE_PERIPHERALS(dev);\n    \/* Memory region for peripheral devices, which we export to our parent *\/\n    memory_region_init(&s->peri_mr, obj,\"arm-example-peripherals\", 0x1000000);  \n    \/\/ TODO: Change this line above, if needed\n    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->peri_mr);\n    \/* Interrupt Controller *\/\n    object_initialize_child(obj, \"ic\", &s->ic, TYPE_ARM_EXAMPLE_IC);\n    \/* SYS Timer *\/\n    object_initialize_child(obj, \"systimer\", &s->systmr,\n                            TYPE_ARM_EXAMPLE_SYSTIMER);\n} <\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>#include \"qemu\/osdep.h\"\n#include \"qapi\/error.h\"\n#include \"qemu\/module.h\"\n#include \"hw\/arm\/arm_example_peripherals.h\"\n#include \"hw\/arm\/arm_example.h\"\n#include \"sysemu\/sysemu.h\"<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<ul>\n<li data-renderer-start-pos=\"20580\">\n<h6><em data-renderer-mark=\"true\">Header files:<\/em><\/h6>\n<\/li>\n<\/ul>\n<pre data-line=\"\">\t\t\t\t<code readonly=\"true\">\n\t\t\t\t\t<xmp>#include \"qemu\/osdep.h\"\n#include \"qapi\/error.h\"\n#include \"qemu\/module.h\"\n#include \"hw\/arm\/arm_example_peripherals.h\"\n#include \"hw\/arm\/arm_example.h\"\n#include \"sysemu\/sysemu.h\"<\/xmp>\n\t\t\t\t<\/code>\n<\/pre>\n<h2>Issues encountered<\/h2>\n<p data-renderer-start-pos=\"20580\">If you are an experienced programmer, probably you have encountered some line endings incompatibilities from time to time. The issue happens when you want to modify code on a Windows host in Visual Studio code, and want to run the QEMU code in a Linux container. There will be some errors about \u2018\/r\u2019 incompatibilities.<\/p>\n<h2>Testing &amp; Results<\/h2>\n<ul>\n<li id=\"Testing\" data-renderer-start-pos=\"25180\">\n<h5>Testing<\/h5>\n<\/li>\n<\/ul>\n<p data-renderer-start-pos=\"25189\">We can perform the testing either using GDB or using a kernel and running QEMU normally with the specific machine enabled. What is important when using a kernel image, is to use the properly compiled one, which respects the memory map and the IRQs of the implemented devices.<\/p>\n<ul>\n<li id=\"Results\" data-renderer-start-pos=\"25484\">\n<h5>Results<\/h5>\n<\/li>\n<\/ul>\n<p data-renderer-start-pos=\"25493\">Following the steps presented previously and making use of the Related materials should be enough for an experienced programmer to be able to implement a fully functional ARM-based machine in QEMU.<\/p>\n<h2>Conclusion<\/h2>\n<p data-renderer-start-pos=\"25705\">Although not ideal, there is an alternative to real hardware, especially in these times of hard try when having to deal with supply chain issues for chips, or even when having to address the issue of not having the physical device in production.<\/p>\n<p data-renderer-start-pos=\"25952\">In conclusion, the task at hand might seem intimidating: to implement the virtualization of an actual machine and emulate its real effects in a virtual environment, but this abstractization should pave the road for even more recognition of QEMU as a valuable tool.<\/p>\n<p data-renderer-start-pos=\"26217\">As a final idea, if the idea of hardware emulation is popularized enough, there might be useful to create a generic tool that creates the possibility of implementing at least the common parts of ARM machines in a simpler fashion than through coding or having to deal with a code-as-documentation situation like in the case of QEMU source code. There is a possibility that even a GUI solution might accelerate the innovation in the embedded domain even further.<\/p>\n<h2>References<\/h2>\n<ul data-indent-level=\"1\">\n<li>\n<p data-renderer-start-pos=\"26895\">S. Sopha, <em data-renderer-mark=\"true\">Adding a custom ARM platform to QEMU 5.2.0<\/em>, 2021. Available: <a tabindex=\"0\" role=\"button\" href=\"https:\/\/web.archive.org\/web\/20220709202327\/https:\/\/souktha.github.io\/software\/qemu-port\/\" data-testid=\"inline-card-resolved-view\">Adding a custom ARM platform to QEMU 5.2.0<\/a><\/p>\n<\/li>\n<\/ul>\n<h2>See other articles:<\/h2>\n","protected":false},"excerpt":{"rendered":"<p>Considering the current developments in the global market, especially having the issue of a Global Chip Shortage, there are some issues to be addressed when having to deploy software on an Embedded platform, but the platform itself is missing. The issue posed is no small undertaking, especially for companies deploying software for different platforms and&hellip;&nbsp;<a href=\"https:\/\/digitalgateamg.com\/de\/blog\/2022\/08\/17\/qemu-development-during-the-chip-shortage\/\" class=\"\" rel=\"bookmark\">Weiterlesen &raquo;<span class=\"screen-reader-text\">QEMU-Entwicklung<\/span><\/a><\/p>","protected":false},"author":12,"featured_media":10186,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"neve_meta_sidebar":"","neve_meta_container":"","neve_meta_enable_content_width":"","neve_meta_content_width":0,"neve_meta_title_alignment":"","neve_meta_author_avatar":"","neve_post_elements_order":"","neve_meta_disable_header":"","neve_meta_disable_footer":"","neve_meta_disable_title":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[1],"tags":[],"coauthors":[],"class_list":["post-10158","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v21.1 (Yoast SEO v28.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>QEMU Development - DigitalGate Custom Electronics<\/title>\n<meta name=\"description\" content=\"Read the article to find out how Global Chip Shortage affects QEMU development, what you can do about it and how to do it.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/digitalgateamg.com\/de\/blog\/2022\/08\/17\/qemu-development-during-the-chip-shortage\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"QEMU Development\" \/>\n<meta property=\"og:description\" content=\"Read the article to find out how Global Chip Shortage affects QEMU development, what you can do about it and how to do it.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/digitalgateamg.com\/de\/blog\/2022\/08\/17\/qemu-development-during-the-chip-shortage\/\" \/>\n<meta property=\"og:site_name\" content=\"DigitalGate Custom Electronics\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/DigitalGateamg\/\" \/>\n<meta property=\"article:published_time\" content=\"2022-08-17T09:26:05+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-08-08T14:46:20+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/digitalgateamg.com\/wp-content\/uploads\/2022\/08\/blog-2-1-1024x1024.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1024\" \/>\n\t<meta property=\"og:image:height\" content=\"1024\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Digital Gate\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Digital Gate\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"17\u00a0Minuten\" \/>\n\t<meta name=\"twitter:label3\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data3\" content=\"Digital Gate\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/digitalgateamg.com\\\/blog\\\/2022\\\/08\\\/17\\\/qemu-development-during-the-chip-shortage\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/digitalgateamg.com\\\/blog\\\/2022\\\/08\\\/17\\\/qemu-development-during-the-chip-shortage\\\/\"},\"author\":{\"name\":\"Digital Gate\",\"@id\":\"https:\\\/\\\/digitalgateamg.com\\\/#\\\/schema\\\/person\\\/27511cb01dbba51abd9b489e6adc2fce\"},\"headline\":\"QEMU Development\",\"datePublished\":\"2022-08-17T09:26:05+00:00\",\"dateModified\":\"2023-08-08T14:46:20+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/digitalgateamg.com\\\/blog\\\/2022\\\/08\\\/17\\\/qemu-development-during-the-chip-shortage\\\/\"},\"wordCount\":1945,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/digitalgateamg.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/digitalgateamg.com\\\/blog\\\/2022\\\/08\\\/17\\\/qemu-development-during-the-chip-shortage\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/digitalgateamg.com\\\/wp-content\\\/uploads\\\/2022\\\/08\\\/blog-2-1.png\",\"articleSection\":[\"Uncategorized\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/digitalgateamg.com\\\/blog\\\/2022\\\/08\\\/17\\\/qemu-development-during-the-chip-shortage\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/digitalgateamg.com\\\/blog\\\/2022\\\/08\\\/17\\\/qemu-development-during-the-chip-shortage\\\/\",\"url\":\"https:\\\/\\\/digitalgateamg.com\\\/blog\\\/2022\\\/08\\\/17\\\/qemu-development-during-the-chip-shortage\\\/\",\"name\":\"QEMU Development - DigitalGate Custom Electronics\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/digitalgateamg.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/digitalgateamg.com\\\/blog\\\/2022\\\/08\\\/17\\\/qemu-development-during-the-chip-shortage\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/digitalgateamg.com\\\/blog\\\/2022\\\/08\\\/17\\\/qemu-development-during-the-chip-shortage\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/digitalgateamg.com\\\/wp-content\\\/uploads\\\/2022\\\/08\\\/blog-2-1.png\",\"datePublished\":\"2022-08-17T09:26:05+00:00\",\"dateModified\":\"2023-08-08T14:46:20+00:00\",\"description\":\"Read the article to find out how Global Chip Shortage affects QEMU development, what you can do about it and how to do it.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/digitalgateamg.com\\\/blog\\\/2022\\\/08\\\/17\\\/qemu-development-during-the-chip-shortage\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/digitalgateamg.com\\\/blog\\\/2022\\\/08\\\/17\\\/qemu-development-during-the-chip-shortage\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/digitalgateamg.com\\\/blog\\\/2022\\\/08\\\/17\\\/qemu-development-during-the-chip-shortage\\\/#primaryimage\",\"url\":\"https:\\\/\\\/digitalgateamg.com\\\/wp-content\\\/uploads\\\/2022\\\/08\\\/blog-2-1.png\",\"contentUrl\":\"https:\\\/\\\/digitalgateamg.com\\\/wp-content\\\/uploads\\\/2022\\\/08\\\/blog-2-1.png\",\"width\":3676,\"height\":2451,\"caption\":\"QEMU development during Global Chip Shortage\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/digitalgateamg.com\\\/blog\\\/2022\\\/08\\\/17\\\/qemu-development-during-the-chip-shortage\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/digitalgateamg.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"QEMU Development\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/digitalgateamg.com\\\/#website\",\"url\":\"https:\\\/\\\/digitalgateamg.com\\\/\",\"name\":\"DigitalGate Custom Electronics\",\"description\":\"Embedded Software and Hardware Solutions\",\"publisher\":{\"@id\":\"https:\\\/\\\/digitalgateamg.com\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/digitalgateamg.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/digitalgateamg.com\\\/#organization\",\"name\":\"DigitalGate Amg S.A.\",\"url\":\"https:\\\/\\\/digitalgateamg.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/digitalgateamg.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/digitalgateamg.com\\\/wp-content\\\/uploads\\\/2021\\\/10\\\/logo-firma.png\",\"contentUrl\":\"https:\\\/\\\/digitalgateamg.com\\\/wp-content\\\/uploads\\\/2021\\\/10\\\/logo-firma.png\",\"width\":370,\"height\":370,\"caption\":\"DigitalGate Amg S.A.\"},\"image\":{\"@id\":\"https:\\\/\\\/digitalgateamg.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/DigitalGateamg\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/sc-digitalgate-amg-srl\\\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/digitalgateamg.com\\\/#\\\/schema\\\/person\\\/27511cb01dbba51abd9b489e6adc2fce\",\"name\":\"Digital Gate\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/digitalgateamg.com\\\/wp-content\\\/litespeed\\\/avatar\\\/46f85298923a63b5939c9a06d38c2790.jpg?ver=1788949926c4177d0df5f612588c988bb8cfef7b68\",\"url\":\"https:\\\/\\\/digitalgateamg.com\\\/wp-content\\\/litespeed\\\/avatar\\\/46f85298923a63b5939c9a06d38c2790.jpg?ver=1788949926\",\"contentUrl\":\"https:\\\/\\\/digitalgateamg.com\\\/wp-content\\\/litespeed\\\/avatar\\\/46f85298923a63b5939c9a06d38c2790.jpg?ver=1788949926\",\"caption\":\"Digital Gate\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"QEMU Development - DigitalGate Custom Electronics","description":"Read the article to find out how Global Chip Shortage affects QEMU development, what you can do about it and how to do it.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/digitalgateamg.com\/de\/blog\/2022\/08\/17\/qemu-development-during-the-chip-shortage\/","og_locale":"de_DE","og_type":"article","og_title":"QEMU Development","og_description":"Read the article to find out how Global Chip Shortage affects QEMU development, what you can do about it and how to do it.","og_url":"https:\/\/digitalgateamg.com\/de\/blog\/2022\/08\/17\/qemu-development-during-the-chip-shortage\/","og_site_name":"DigitalGate Custom Electronics","article_publisher":"https:\/\/www.facebook.com\/DigitalGateamg\/","article_published_time":"2022-08-17T09:26:05+00:00","article_modified_time":"2023-08-08T14:46:20+00:00","og_image":[{"width":1024,"height":1024,"url":"https:\/\/digitalgateamg.com\/wp-content\/uploads\/2022\/08\/blog-2-1-1024x1024.png","type":"image\/png"}],"author":"Digital Gate","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Digital Gate","Gesch\u00e4tzte Lesezeit":"17\u00a0Minuten","Written by":"Digital Gate"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/digitalgateamg.com\/blog\/2022\/08\/17\/qemu-development-during-the-chip-shortage\/#article","isPartOf":{"@id":"https:\/\/digitalgateamg.com\/blog\/2022\/08\/17\/qemu-development-during-the-chip-shortage\/"},"author":{"name":"Digital Gate","@id":"https:\/\/digitalgateamg.com\/#\/schema\/person\/27511cb01dbba51abd9b489e6adc2fce"},"headline":"QEMU Development","datePublished":"2022-08-17T09:26:05+00:00","dateModified":"2023-08-08T14:46:20+00:00","mainEntityOfPage":{"@id":"https:\/\/digitalgateamg.com\/blog\/2022\/08\/17\/qemu-development-during-the-chip-shortage\/"},"wordCount":1945,"commentCount":0,"publisher":{"@id":"https:\/\/digitalgateamg.com\/#organization"},"image":{"@id":"https:\/\/digitalgateamg.com\/blog\/2022\/08\/17\/qemu-development-during-the-chip-shortage\/#primaryimage"},"thumbnailUrl":"https:\/\/digitalgateamg.com\/wp-content\/uploads\/2022\/08\/blog-2-1.png","articleSection":["Uncategorized"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/digitalgateamg.com\/blog\/2022\/08\/17\/qemu-development-during-the-chip-shortage\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/digitalgateamg.com\/blog\/2022\/08\/17\/qemu-development-during-the-chip-shortage\/","url":"https:\/\/digitalgateamg.com\/blog\/2022\/08\/17\/qemu-development-during-the-chip-shortage\/","name":"QEMU Development - DigitalGate Custom Electronics","isPartOf":{"@id":"https:\/\/digitalgateamg.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/digitalgateamg.com\/blog\/2022\/08\/17\/qemu-development-during-the-chip-shortage\/#primaryimage"},"image":{"@id":"https:\/\/digitalgateamg.com\/blog\/2022\/08\/17\/qemu-development-during-the-chip-shortage\/#primaryimage"},"thumbnailUrl":"https:\/\/digitalgateamg.com\/wp-content\/uploads\/2022\/08\/blog-2-1.png","datePublished":"2022-08-17T09:26:05+00:00","dateModified":"2023-08-08T14:46:20+00:00","description":"Read the article to find out how Global Chip Shortage affects QEMU development, what you can do about it and how to do it.","breadcrumb":{"@id":"https:\/\/digitalgateamg.com\/blog\/2022\/08\/17\/qemu-development-during-the-chip-shortage\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/digitalgateamg.com\/blog\/2022\/08\/17\/qemu-development-during-the-chip-shortage\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/digitalgateamg.com\/blog\/2022\/08\/17\/qemu-development-during-the-chip-shortage\/#primaryimage","url":"https:\/\/digitalgateamg.com\/wp-content\/uploads\/2022\/08\/blog-2-1.png","contentUrl":"https:\/\/digitalgateamg.com\/wp-content\/uploads\/2022\/08\/blog-2-1.png","width":3676,"height":2451,"caption":"QEMU development during Global Chip Shortage"},{"@type":"BreadcrumbList","@id":"https:\/\/digitalgateamg.com\/blog\/2022\/08\/17\/qemu-development-during-the-chip-shortage\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/digitalgateamg.com\/"},{"@type":"ListItem","position":2,"name":"QEMU Development"}]},{"@type":"WebSite","@id":"https:\/\/digitalgateamg.com\/#website","url":"https:\/\/digitalgateamg.com\/","name":"DigitalGate Custom Electronics","description":"Embedded Software and Hardware Solutions","publisher":{"@id":"https:\/\/digitalgateamg.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/digitalgateamg.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/digitalgateamg.com\/#organization","name":"DigitalGate Amg S.A.","url":"https:\/\/digitalgateamg.com\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/digitalgateamg.com\/#\/schema\/logo\/image\/","url":"https:\/\/digitalgateamg.com\/wp-content\/uploads\/2021\/10\/logo-firma.png","contentUrl":"https:\/\/digitalgateamg.com\/wp-content\/uploads\/2021\/10\/logo-firma.png","width":370,"height":370,"caption":"DigitalGate Amg S.A."},"image":{"@id":"https:\/\/digitalgateamg.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/DigitalGateamg\/","https:\/\/www.linkedin.com\/company\/sc-digitalgate-amg-srl\/"]},{"@type":"Person","@id":"https:\/\/digitalgateamg.com\/#\/schema\/person\/27511cb01dbba51abd9b489e6adc2fce","name":"Digital Gate","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/digitalgateamg.com\/wp-content\/litespeed\/avatar\/46f85298923a63b5939c9a06d38c2790.jpg?ver=1788949926c4177d0df5f612588c988bb8cfef7b68","url":"https:\/\/digitalgateamg.com\/wp-content\/litespeed\/avatar\/46f85298923a63b5939c9a06d38c2790.jpg?ver=1788949926","contentUrl":"https:\/\/digitalgateamg.com\/wp-content\/litespeed\/avatar\/46f85298923a63b5939c9a06d38c2790.jpg?ver=1788949926","caption":"Digital Gate"}}]}},"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/digitalgateamg.com\/wp-content\/uploads\/2022\/08\/blog-2-1.png","_links":{"self":[{"href":"https:\/\/digitalgateamg.com\/de\/wp-json\/wp\/v2\/posts\/10158","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/digitalgateamg.com\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/digitalgateamg.com\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/digitalgateamg.com\/de\/wp-json\/wp\/v2\/users\/12"}],"replies":[{"embeddable":true,"href":"https:\/\/digitalgateamg.com\/de\/wp-json\/wp\/v2\/comments?post=10158"}],"version-history":[{"count":67,"href":"https:\/\/digitalgateamg.com\/de\/wp-json\/wp\/v2\/posts\/10158\/revisions"}],"predecessor-version":[{"id":13391,"href":"https:\/\/digitalgateamg.com\/de\/wp-json\/wp\/v2\/posts\/10158\/revisions\/13391"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/digitalgateamg.com\/de\/wp-json\/wp\/v2\/media\/10186"}],"wp:attachment":[{"href":"https:\/\/digitalgateamg.com\/de\/wp-json\/wp\/v2\/media?parent=10158"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/digitalgateamg.com\/de\/wp-json\/wp\/v2\/categories?post=10158"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/digitalgateamg.com\/de\/wp-json\/wp\/v2\/tags?post=10158"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/digitalgateamg.com\/de\/wp-json\/wp\/v2\/coauthors?post=10158"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}