From 22d5523d3fbb95264055e11eb47738a7442a4ecb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 29 Jul 2013 17:01:37 +0200 Subject: [PATCH 01/54] mips_mipssim: Silence BIOS loading warning for qtest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Aurelien Jarno Signed-off-by: Andreas Färber --- hw/mips/mips_mipssim.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/mips/mips_mipssim.c b/hw/mips/mips_mipssim.c index 242bab9779..239aa6ac8c 100644 --- a/hw/mips/mips_mipssim.c +++ b/hw/mips/mips_mipssim.c @@ -38,6 +38,7 @@ #include "hw/sysbus.h" #include "exec/address-spaces.h" #include "qemu/error-report.h" +#include "sysemu/qtest.h" static struct _loaderparams { int ram_size; @@ -190,7 +191,8 @@ mips_mipssim_init(QEMUMachineInitArgs *args) } else { bios_size = -1; } - if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) { + if ((bios_size < 0 || bios_size > BIOS_SIZE) && + !kernel_filename && !qtest_enabled()) { /* Bail out if we have neither a kernel image nor boot vector code. */ error_report("Could not load MIPS bios '%s', and no " "-kernel argument was specified", filename); From f741a26c126448adebee7b85fc87b72176c3dfa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 29 Jul 2013 18:43:57 +0200 Subject: [PATCH 02/54] puv3: Turn puv3_load_kernel() into a no-op for qtest without -kernel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replacing the assert() with more user-friendly error handling is left for a follow-up. Signed-off-by: Andreas Färber --- hw/unicore32/puv3.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/unicore32/puv3.c b/hw/unicore32/puv3.c index a9000617b4..e05cbc131e 100644 --- a/hw/unicore32/puv3.c +++ b/hw/unicore32/puv3.c @@ -17,6 +17,7 @@ #include "hw/boards.h" #include "hw/loader.h" #include "hw/i386/pc.h" +#include "sysemu/qtest.h" #undef DEBUG_PUV3 #include "hw/unicore32/puv3.h" @@ -84,6 +85,9 @@ static void puv3_load_kernel(const char *kernel_filename) { int size; + if (kernel_filename == NULL && qtest_enabled()) { + return; + } assert(kernel_filename != NULL); /* only zImage format supported */ From d2f7c496c32476bb5eff616f6fda293393d70740 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 29 Jul 2013 17:12:41 +0200 Subject: [PATCH 03/54] mainstone: Don't enforce use of -pflash for qtest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simply skip flash setup for now. Also drop useless debug output. Signed-off-by: Andreas Färber --- hw/arm/mainstone.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c index b244f7e112..9402c841e9 100644 --- a/hw/arm/mainstone.c +++ b/hw/arm/mainstone.c @@ -21,6 +21,7 @@ #include "sysemu/blockdev.h" #include "hw/sysbus.h" #include "exec/address-spaces.h" +#include "sysemu/qtest.h" /* Device addresses */ #define MST_FPGA_PHYS 0x08000000 @@ -127,6 +128,9 @@ static void mainstone_common_init(MemoryRegion *address_space_mem, for (i = 0; i < 2; i ++) { dinfo = drive_get(IF_PFLASH, 0, i); if (!dinfo) { + if (qtest_enabled()) { + break; + } fprintf(stderr, "Two flash images must be given with the " "'pflash' parameter\n"); exit(1); @@ -147,7 +151,6 @@ static void mainstone_common_init(MemoryRegion *address_space_mem, qdev_get_gpio_in(mpu->gpio, 0)); /* setup keypad */ - printf("map addr %p\n", &map); pxa27x_register_keypad(mpu->kp, map, 0xe0); /* MMC/SD host */ From bdf921d65f83c1958e00c347816c0f754f9bc6dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 29 Jul 2013 17:15:01 +0200 Subject: [PATCH 04/54] gumstix: Don't enforce use of -pflash for qtest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber --- hw/arm/gumstix.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c index e97fbbd231..aeea17295b 100644 --- a/hw/arm/gumstix.c +++ b/hw/arm/gumstix.c @@ -42,6 +42,7 @@ #include "hw/boards.h" #include "sysemu/blockdev.h" #include "exec/address-spaces.h" +#include "sysemu/qtest.h" static const int sector_len = 128 * 1024; @@ -58,7 +59,7 @@ static void connex_init(QEMUMachineInitArgs *args) cpu = pxa255_init(address_space_mem, connex_ram); dinfo = drive_get(IF_PFLASH, 0, 0); - if (!dinfo) { + if (!dinfo && !qtest_enabled()) { fprintf(stderr, "A flash image must be given with the " "'pflash' parameter\n"); exit(1); @@ -70,7 +71,8 @@ static void connex_init(QEMUMachineInitArgs *args) be = 0; #endif if (!pflash_cfi01_register(0x00000000, NULL, "connext.rom", connex_rom, - dinfo->bdrv, sector_len, connex_rom / sector_len, + dinfo ? dinfo->bdrv : NULL, + sector_len, connex_rom / sector_len, 2, 0, 0, 0, 0, be)) { fprintf(stderr, "qemu: Error registering flash memory.\n"); exit(1); @@ -95,7 +97,7 @@ static void verdex_init(QEMUMachineInitArgs *args) cpu = pxa270_init(address_space_mem, verdex_ram, cpu_model ?: "pxa270-c0"); dinfo = drive_get(IF_PFLASH, 0, 0); - if (!dinfo) { + if (!dinfo && !qtest_enabled()) { fprintf(stderr, "A flash image must be given with the " "'pflash' parameter\n"); exit(1); @@ -107,7 +109,8 @@ static void verdex_init(QEMUMachineInitArgs *args) be = 0; #endif if (!pflash_cfi01_register(0x00000000, NULL, "verdex.rom", verdex_rom, - dinfo->bdrv, sector_len, verdex_rom / sector_len, + dinfo ? dinfo->bdrv : NULL, + sector_len, verdex_rom / sector_len, 2, 0, 0, 0, 0, be)) { fprintf(stderr, "qemu: Error registering flash memory.\n"); exit(1); From e25ac5f66275b3f9615a6c24d7ef5625f1b49ef4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 29 Jul 2013 17:15:55 +0200 Subject: [PATCH 05/54] z2: Don't enforce use of -pflash for qtest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber --- hw/arm/z2.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/arm/z2.c b/hw/arm/z2.c index a00fcc042d..d52c5019b3 100644 --- a/hw/arm/z2.c +++ b/hw/arm/z2.c @@ -24,6 +24,7 @@ #include "ui/console.h" #include "audio/audio.h" #include "exec/address-spaces.h" +#include "sysemu/qtest.h" #ifdef DEBUG_Z2 #define DPRINTF(fmt, ...) \ @@ -323,7 +324,7 @@ static void z2_init(QEMUMachineInitArgs *args) be = 0; #endif dinfo = drive_get(IF_PFLASH, 0, 0); - if (!dinfo) { + if (!dinfo && !qtest_enabled()) { fprintf(stderr, "Flash image must be given with the " "'pflash' parameter\n"); exit(1); @@ -331,7 +332,7 @@ static void z2_init(QEMUMachineInitArgs *args) if (!pflash_cfi01_register(Z2_FLASH_BASE, NULL, "z2.flash0", Z2_FLASH_SIZE, - dinfo->bdrv, sector_len, + dinfo ? dinfo->bdrv : NULL, sector_len, Z2_FLASH_SIZE / sector_len, 4, 0, 0, 0, 0, be)) { fprintf(stderr, "qemu: Error registering flash memory.\n"); From 1ca8334e42d84cf246db88502cebf11042df2c51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 29 Jul 2013 18:24:47 +0200 Subject: [PATCH 06/54] palm: Don't enforce loading ROM or kernel for qtest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber --- hw/arm/palm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/arm/palm.c b/hw/arm/palm.c index 0b72bbe5fb..fac4f69807 100644 --- a/hw/arm/palm.c +++ b/hw/arm/palm.c @@ -19,6 +19,7 @@ #include "hw/hw.h" #include "audio/audio.h" #include "sysemu/sysemu.h" +#include "sysemu/qtest.h" #include "ui/console.h" #include "hw/arm/omap.h" #include "hw/boards.h" @@ -255,7 +256,7 @@ static void palmte_init(QEMUMachineInitArgs *args) } } - if (!rom_loaded && !kernel_filename) { + if (!rom_loaded && !kernel_filename && !qtest_enabled()) { fprintf(stderr, "Kernel or ROM image must be specified\n"); exit(1); } From db3fd06902c96644cb4d4a76f54924c754faf13c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 29 Jul 2013 18:27:58 +0200 Subject: [PATCH 07/54] omap_sx1: Don't enforce use of kernel or flash for qtest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber --- hw/arm/omap_sx1.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c index 03b381688b..3ba263ab4d 100644 --- a/hw/arm/omap_sx1.c +++ b/hw/arm/omap_sx1.c @@ -32,6 +32,7 @@ #include "hw/arm/arm.h" #include "hw/block/flash.h" #include "sysemu/blockdev.h" +#include "sysemu/qtest.h" #include "exec/address-spaces.h" /*****************************************************************************/ @@ -188,7 +189,7 @@ static void sx1_init(QEMUMachineInitArgs *args, const int version) OMAP_CS1_BASE, &cs[1]); } - if (!args->kernel_filename && !fl_idx) { + if (!args->kernel_filename && !fl_idx && !qtest_enabled()) { fprintf(stderr, "Kernel or Flash image must be specified\n"); exit(1); } From 4bd2f93ff9dcf5fbbdb55affc55b7f1a568e43cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 29 Jul 2013 18:29:54 +0200 Subject: [PATCH 08/54] exynos4_boards: Silence lack of -smp 2 warning for qtest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber --- hw/arm/exynos4_boards.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c index 2929f9f8ab..26cedecee3 100644 --- a/hw/arm/exynos4_boards.c +++ b/hw/arm/exynos4_boards.c @@ -22,6 +22,7 @@ */ #include "sysemu/sysemu.h" +#include "sysemu/qtest.h" #include "hw/sysbus.h" #include "net/net.h" #include "hw/arm/arm.h" @@ -96,7 +97,7 @@ static void lan9215_init(uint32_t base, qemu_irq irq) static Exynos4210State *exynos4_boards_init_common(QEMUMachineInitArgs *args, Exynos4BoardType board_type) { - if (smp_cpus != EXYNOS4210_NCPUS) { + if (smp_cpus != EXYNOS4210_NCPUS && !qtest_enabled()) { fprintf(stderr, "%s board supports only %d CPU cores. Ignoring smp_cpus" " value.\n", exynos4_machines[board_type].name, From 5633b90ad44f08a57c44bb602cb0ae6668420ac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 29 Jul 2013 18:36:59 +0200 Subject: [PATCH 09/54] armv7m: Don't enforce use of kernel for qtest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adopt error_report(). Signed-off-by: Andreas Färber --- hw/arm/armv7m.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c index 89a9015de7..397e8dfb37 100644 --- a/hw/arm/armv7m.c +++ b/hw/arm/armv7m.c @@ -11,6 +11,8 @@ #include "hw/arm/arm.h" #include "hw/loader.h" #include "elf.h" +#include "sysemu/qtest.h" +#include "qemu/error-report.h" /* Bitbanded IO. Each word corresponds to a single bit. */ @@ -232,21 +234,22 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem, big_endian = 0; #endif - if (!kernel_filename) { + if (!kernel_filename && !qtest_enabled()) { fprintf(stderr, "Guest image must be specified (using -kernel)\n"); exit(1); } - image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr, - NULL, big_endian, ELF_MACHINE, 1); - if (image_size < 0) { - image_size = load_image_targphys(kernel_filename, 0, flash_size); - lowaddr = 0; - } - if (image_size < 0) { - fprintf(stderr, "qemu: could not load kernel '%s'\n", - kernel_filename); - exit(1); + if (kernel_filename) { + image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr, + NULL, big_endian, ELF_MACHINE, 1); + if (image_size < 0) { + image_size = load_image_targphys(kernel_filename, 0, flash_size); + lowaddr = 0; + } + if (image_size < 0) { + error_report("Could not load kernel '%s'", kernel_filename); + exit(1); + } } /* Hack to map an additional page of ram at the top of the address From 5efe843a9a0e049d3d2a13411b7df7d3a430540c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 29 Jul 2013 18:40:20 +0200 Subject: [PATCH 10/54] axis_dev88: Don't enforce use of kernel for qtest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Edgar E. Iglesias Signed-off-by: Andreas Färber --- hw/cris/axis_dev88.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/hw/cris/axis_dev88.c b/hw/cris/axis_dev88.c index 03058d3bc5..55240886f5 100644 --- a/hw/cris/axis_dev88.c +++ b/hw/cris/axis_dev88.c @@ -32,6 +32,7 @@ #include "boot.h" #include "sysemu/blockdev.h" #include "exec/address-spaces.h" +#include "sysemu/qtest.h" #define D(x) #define DNAND(x) @@ -340,14 +341,14 @@ void axisdev88_init(QEMUMachineInitArgs *args) irq[0x14 + i]); } - if (!kernel_filename) { + if (kernel_filename) { + li.image_filename = kernel_filename; + li.cmdline = kernel_cmdline; + cris_load_image(cpu, &li); + } else if (!qtest_enabled()) { fprintf(stderr, "Kernel image must be specified\n"); exit(1); } - - li.image_filename = kernel_filename; - li.cmdline = kernel_cmdline; - cris_load_image(cpu, &li); } static QEMUMachine axisdev88_machine = { From 5c12762c2d9cfc7ff9744e4af14ef35190c5369b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 29 Jul 2013 18:47:21 +0200 Subject: [PATCH 11/54] mcf5208: Don't enforce use of kernel for qtest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber --- hw/m68k/mcf5208.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c index fb96fe8548..6e30c0b393 100644 --- a/hw/m68k/mcf5208.c +++ b/hw/m68k/mcf5208.c @@ -10,6 +10,7 @@ #include "qemu/timer.h" #include "hw/ptimer.h" #include "sysemu/sysemu.h" +#include "sysemu/qtest.h" #include "net/net.h" #include "hw/boards.h" #include "hw/loader.h" @@ -267,6 +268,9 @@ static void mcf5208evb_init(QEMUMachineInitArgs *args) /* Load kernel. */ if (!kernel_filename) { + if (qtest_enabled()) { + return; + } fprintf(stderr, "Kernel image must be specified\n"); exit(1); } From 19c82aac7540acdd4645b033bb99ceff960f9570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 29 Jul 2013 18:48:58 +0200 Subject: [PATCH 12/54] an5206: Don't enforce use of kernel for qtest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber --- hw/m68k/an5206.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/m68k/an5206.c b/hw/m68k/an5206.c index a8eee44e62..24f2068559 100644 --- a/hw/m68k/an5206.c +++ b/hw/m68k/an5206.c @@ -12,6 +12,7 @@ #include "hw/loader.h" #include "elf.h" #include "exec/address-spaces.h" +#include "sysemu/qtest.h" #define KERNEL_LOAD_ADDR 0x10000 #define AN5206_MBAR_ADDR 0x10000000 @@ -62,6 +63,9 @@ static void an5206_init(QEMUMachineInitArgs *args) /* Load kernel. */ if (!kernel_filename) { + if (qtest_enabled()) { + return; + } fprintf(stderr, "Kernel image must be specified\n"); exit(1); } From c00eb5cee145ec7ff030a6bfcb98afd7285868c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 4 Aug 2013 16:49:28 +0200 Subject: [PATCH 13/54] milkymist: Suppress -kernel/-bios/-drive error for qtest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Acked-by: Michael Walle Signed-off-by: Andreas Färber --- hw/lm32/milkymist.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c index f1744ec07e..15053c4c37 100644 --- a/hw/lm32/milkymist.c +++ b/hw/lm32/milkymist.c @@ -21,6 +21,7 @@ #include "hw/hw.h" #include "hw/block/flash.h" #include "sysemu/sysemu.h" +#include "sysemu/qtest.h" #include "hw/devices.h" #include "hw/boards.h" #include "hw/loader.h" @@ -143,7 +144,7 @@ milkymist_init(QEMUMachineInitArgs *args) reset_info->bootstrap_pc = BIOS_OFFSET; /* if no kernel is given no valid bios rom is a fatal error */ - if (!kernel_filename && !dinfo && !bios_filename) { + if (!kernel_filename && !dinfo && !bios_filename && !qtest_enabled()) { fprintf(stderr, "qemu: could not load Milkymist One bios '%s'\n", bios_name); exit(1); From b6e770ee505771a6f3c3ffbf05719c149e069e3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 4 Aug 2013 17:53:24 +0200 Subject: [PATCH 14/54] shix: Drop debug output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Aurelien Jarno Signed-off-by: Andreas Färber --- hw/sh4/shix.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/hw/sh4/shix.c b/hw/sh4/shix.c index 1ff37f54a0..f008b9891b 100644 --- a/hw/sh4/shix.c +++ b/hw/sh4/shix.c @@ -50,7 +50,6 @@ static void shix_init(QEMUMachineInitArgs *args) if (!cpu_model) cpu_model = "any"; - printf("Initializing CPU\n"); cpu = cpu_sh4_init(cpu_model); if (cpu == NULL) { fprintf(stderr, "Unable to find CPU definition\n"); @@ -58,16 +57,13 @@ static void shix_init(QEMUMachineInitArgs *args) } /* Allocate memory space */ - printf("Allocating ROM\n"); memory_region_init_ram(rom, NULL, "shix.rom", 0x4000); vmstate_register_ram_global(rom); memory_region_set_readonly(rom, true); memory_region_add_subregion(sysmem, 0x00000000, rom); - printf("Allocating SDRAM 1\n"); memory_region_init_ram(&sdram[0], NULL, "shix.sdram1", 0x01000000); vmstate_register_ram_global(&sdram[0]); memory_region_add_subregion(sysmem, 0x08000000, &sdram[0]); - printf("Allocating SDRAM 2\n"); memory_region_init_ram(&sdram[1], NULL, "shix.sdram2", 0x01000000); vmstate_register_ram_global(&sdram[1]); memory_region_add_subregion(sysmem, 0x0c000000, &sdram[1]); @@ -75,10 +71,8 @@ static void shix_init(QEMUMachineInitArgs *args) /* Load BIOS in 0 (and access it through P2, 0xA0000000) */ if (bios_name == NULL) bios_name = BIOS_FILENAME; - printf("%s: load BIOS '%s'\n", __func__, bios_name); ret = load_image_targphys(bios_name, 0, 0x4000); if (ret < 0) { /* Check bios size */ - fprintf(stderr, "ret=%d\n", ret); fprintf(stderr, "qemu: could not load SHIX bios '%s'\n", bios_name); exit(1); @@ -88,7 +82,6 @@ static void shix_init(QEMUMachineInitArgs *args) s = sh7750_init(cpu, sysmem); /* XXXXX Check success */ tc58128_init(s, "shix_linux_nand.bin", NULL); - fprintf(stderr, "initialization terminated\n"); } static QEMUMachine shix_machine = { From d32f7d2506f1dab996e977e478f19baff5d47b51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 4 Aug 2013 17:51:15 +0200 Subject: [PATCH 15/54] shix: Don't require firmware presence for qtest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adopt error_report() while at it. Reviewed-by: Stefan Hajnoczi Reviewed-by: Aurelien Jarno Signed-off-by: Andreas Färber --- hw/block/tc58128.c | 10 ++++++---- hw/sh4/shix.c | 9 +++++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/hw/block/tc58128.c b/hw/block/tc58128.c index a3929d444f..728f1c3b68 100644 --- a/hw/block/tc58128.c +++ b/hw/block/tc58128.c @@ -1,6 +1,8 @@ #include "hw/hw.h" #include "hw/sh4/sh.h" #include "hw/loader.h" +#include "sysemu/qtest.h" +#include "qemu/error-report.h" #define CE1 0x0100 #define CE2 0x0200 @@ -36,10 +38,10 @@ static void init_dev(tc58128_dev * dev, const char *filename) /* Load flash image skipping the first block */ ret = load_image(filename, dev->flash_contents + 528 * 32); if (ret < 0) { - fprintf(stderr, "ret=%d\n", ret); - fprintf(stderr, "qemu: could not load flash image %s\n", - filename); - exit(1); + if (!qtest_enabled()) { + error_report("Could not load flash image %s", filename); + exit(1); + } } else { /* Build first block with number of blocks */ blocks = (ret + 528 * 32 - 1) / (528 * 32); diff --git a/hw/sh4/shix.c b/hw/sh4/shix.c index f008b9891b..904a966700 100644 --- a/hw/sh4/shix.c +++ b/hw/sh4/shix.c @@ -30,9 +30,11 @@ #include "hw/hw.h" #include "hw/sh4/sh.h" #include "sysemu/sysemu.h" +#include "sysemu/qtest.h" #include "hw/boards.h" #include "hw/loader.h" #include "exec/address-spaces.h" +#include "qemu/error-report.h" #define BIOS_FILENAME "shix_bios.bin" #define BIOS_ADDRESS 0xA0000000 @@ -72,10 +74,9 @@ static void shix_init(QEMUMachineInitArgs *args) if (bios_name == NULL) bios_name = BIOS_FILENAME; ret = load_image_targphys(bios_name, 0, 0x4000); - if (ret < 0) { /* Check bios size */ - fprintf(stderr, "qemu: could not load SHIX bios '%s'\n", - bios_name); - exit(1); + if (ret < 0 && !qtest_enabled()) { + error_report("Could not load SHIX bios '%s'", bios_name); + exit(1); } /* Register peripherals */ From 7761254120905cb2c5c435246f97e51968ddddec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 4 Aug 2013 17:58:58 +0200 Subject: [PATCH 16/54] leon3: Don't enforce use of -bios with qtest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber --- hw/sparc/leon3.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c index 390f3e4bda..c583c3d0c5 100644 --- a/hw/sparc/leon3.c +++ b/hw/sparc/leon3.c @@ -26,6 +26,7 @@ #include "hw/ptimer.h" #include "sysemu/char.h" #include "sysemu/sysemu.h" +#include "sysemu/qtest.h" #include "hw/boards.h" #include "hw/loader.h" #include "elf.h" @@ -178,7 +179,7 @@ static void leon3_generic_hw_init(QEMUMachineInitArgs *args) fprintf(stderr, "qemu: could not load prom '%s'\n", filename); exit(1); } - } else if (kernel_filename == NULL) { + } else if (kernel_filename == NULL && !qtest_enabled()) { fprintf(stderr, "Can't read bios image %s\n", filename); exit(1); } From 7c41f2177e280dec1f1d4c5cd72333c5c55943af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 29 Jul 2013 05:44:47 +0200 Subject: [PATCH 17/54] qtest: Prepare QOM machine tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instantiate all [*] machines per target, so that they get a bit of test coverage at all. This has proven helpful during QOM refactorings. [*] ppcemb target contains some non-working non-embedded machines, and ppc405 CPUs are not available there either. i386 and x86_64 do not cover pc*-x.y or xenfv. Signed-off-by: Andreas Färber --- tests/Makefile | 26 +++++ tests/qom-test.c | 253 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 279 insertions(+) create mode 100644 tests/qom-test.c diff --git a/tests/Makefile b/tests/Makefile index fa4c9f0cbb..f414f2c80a 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -67,25 +67,50 @@ check-qtest-i386-y += tests/boot-order-test$(EXESUF) check-qtest-i386-y += tests/rtc-test$(EXESUF) check-qtest-i386-y += tests/i440fx-test$(EXESUF) check-qtest-i386-y += tests/fw_cfg-test$(EXESUF) +check-qtest-i386-y += tests/qom-test$(EXESUF) check-qtest-x86_64-y = $(check-qtest-i386-y) gcov-files-i386-y += i386-softmmu/hw/mc146818rtc.c gcov-files-x86_64-y = $(subst i386-softmmu/,x86_64-softmmu/,$(gcov-files-i386-y)) check-qtest-mips-y = tests/endianness-test$(EXESUF) check-qtest-mips64-y = tests/endianness-test$(EXESUF) check-qtest-mips64el-y = tests/endianness-test$(EXESUF) +check-qtest-mips-y += tests/qom-test$(EXESUF) +check-qtest-mipsel-y += tests/qom-test$(EXESUF) +check-qtest-mips64-y += tests/qom-test$(EXESUF) +check-qtest-mips64el-y += tests/qom-test$(EXESUF) check-qtest-ppc-y = tests/endianness-test$(EXESUF) check-qtest-ppc64-y = tests/endianness-test$(EXESUF) check-qtest-sh4-y = tests/endianness-test$(EXESUF) check-qtest-sh4eb-y = tests/endianness-test$(EXESUF) +check-qtest-sh4-y += tests/qom-test$(EXESUF) +check-qtest-sh4eb-y += tests/qom-test$(EXESUF) check-qtest-sparc64-y = tests/endianness-test$(EXESUF) #check-qtest-sparc-y = tests/m48t59-test$(EXESUF) #check-qtest-sparc64-y += tests/m48t59-test$(EXESUF) gcov-files-sparc-y += hw/m48t59.c gcov-files-sparc64-y += hw/m48t59.c +check-qtest-sparc-y += tests/qom-test$(EXESUF) +check-qtest-sparc64-y += tests/qom-test$(EXESUF) check-qtest-arm-y = tests/tmp105-test$(EXESUF) gcov-files-arm-y += hw/tmp105.c +check-qtest-arm-y += tests/qom-test$(EXESUF) check-qtest-ppc-y += tests/boot-order-test$(EXESUF) check-qtest-ppc64-y += tests/boot-order-test$(EXESUF) +check-qtest-ppc-y += tests/qom-test$(EXESUF) +check-qtest-ppc64-y += tests/qom-test$(EXESUF) +check-qtest-ppcemb-y += tests/qom-test$(EXESUF) +check-qtest-alpha-y += tests/qom-test$(EXESUF) +check-qtest-cris-y += tests/qom-test$(EXESUF) +check-qtest-lm32-y += tests/qom-test$(EXESUF) +check-qtest-m68k-y += tests/qom-test$(EXESUF) +check-qtest-microblaze-y += tests/qom-test$(EXESUF) +check-qtest-microblazeel-y = $(check-qtest-microblaze-y) +check-qtest-moxie-y += tests/qom-test$(EXESUF) +check-qtest-or32-y += tests/qom-test$(EXESUF) +check-qtest-s390x-y += tests/qom-test$(EXESUF) +check-qtest-unicore32-y += tests/qom-test$(EXESUF) +check-qtest-xtensa-y += tests/qom-test$(EXESUF) +check-qtest-xtensaeb-y = $(check-qtest-xtensa-y) check-qapi-schema-y := $(addprefix tests/qapi-schema/, \ comments.json empty.json funny-char.json indented-expr.json \ @@ -174,6 +199,7 @@ tests/boot-order-test$(EXESUF): tests/boot-order-test.o $(libqos-obj-y) tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y) tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y) tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y) +tests/qom-test$(EXESUF): tests/qom-test.o tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o # QTest rules diff --git a/tests/qom-test.c b/tests/qom-test.c new file mode 100644 index 0000000000..6ed23c5e54 --- /dev/null +++ b/tests/qom-test.c @@ -0,0 +1,253 @@ +/* + * QTest testcase for QOM + * + * Copyright (c) 2013 SUSE LINUX Products GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#include "libqtest.h" + +#include +#include +#include "qemu/osdep.h" + +static void test_nop(gconstpointer data) +{ + QTestState *s; + const char *machine = data; + char *args; + + args = g_strdup_printf("-display none -machine %s", machine); + s = qtest_start(args); + if (s) { + qtest_quit(s); + } + g_free(args); +} + +static const char *x86_machines[] = { + "pc", + "isapc", + "q35", +}; + +static const char *alpha_machines[] = { + "clipper", +}; + +static const char *arm_machines[] = { + "integratorcp", + "versatilepb", + "versatileab", + "lm3s811evb", + "lm3s6965evb", + "collie", + "akita", + "spitz", + "borzoi", + "terrier", + "tosa", + "cheetah", + "sx1-v1", + "sx1", + "realview-eb", + "realview-eb-mpcore", + "realview-pb-a8", + "realview-pbx-a9", + "musicpal", + "mainstone", + "connex", + "verdex", + "z2", + "n800", + "n810", + "kzm", + "vexpress-a9", + "vexpress-a15", + "smdkc210", + "nuri", + "xilinx-zynq-a9", + "highbank", + "midway", +}; + +static const char *cris_machines[] = { + "axis-dev88", +}; + +static const char *lm32_machines[] = { + "lm32-evr", + "lm32-uclinux", + "milkymist", +}; + +static const char *m68k_machines[] = { + "mcf5208evb", + "an5206", + "dummy", +}; + +static const char *microblaze_machines[] = { + "petalogix-ml605", + "petalogix-s3adsp1800", +}; + +static const char *mips_machines[] = { + "malta", + "magnum", + "mips", + "mipssim", + "pica61", +}; + +static const char *moxie_machines[] = { + "moxiesim", +}; + +static const char *openrisc_machines[] = { + "or32-sim", +}; + +static const char *ppc_machines[] = { + "g3beige", + "mac99", + "prep", + "mpc8544ds", + "ppce500", +}; + +static const char *ppc64_machines[] = { + "pseries", +}; + +static const char *ppc405_machines[] = { + "ref405ep", + "taihu", +}; + +static const char *ppc440_machines[] = { + "bamboo", + "virtex-ml507", +}; + +static const char *s390_machines[] = { + "s390-virtio", + "s390-ccw-virtio", +}; + +static const char *superh_machines[] = { + "r2d", + "shix", +}; + +static const char *sparc_machines[] = { + "SS-4", + "SS-5", + "SS-10", + "SS-20", + "SS-600MP", + "LX", + "SPARCClassic", + "SPARCbook", + "leon3_generic", +}; + +static const char *sparc64_machines[] = { + "sun4u", + "sun4v", + "Niagara", +}; + +static const char *unicore32_machines[] = { + "puv3", +}; + +static const char *xtensa_machines[] = { + "sim", + "lx60", + "lx200", +}; + +static void add_test_cases(const char *arch, const char *machine) +{ + char *path; + path = g_strdup_printf("/%s/qom/%s", arch, machine); + g_test_add_data_func(path, machine, test_nop); +} + +#define ADD_MACHINE_TESTS(arch, array) do { \ + int i; \ + for (i = 0; i < ARRAY_SIZE(array); i++) { \ + add_test_cases((arch), (array)[i]); \ + } \ +} while (false) + +int main(int argc, char **argv) +{ + const char *arch = qtest_get_arch(); + + g_test_init(&argc, &argv, NULL); + + add_test_cases(arch, "none"); + + if (strcmp(arch, "i386") == 0 || + strcmp(arch, "x86_64") == 0) { + ADD_MACHINE_TESTS(arch, x86_machines); + } else if (strcmp(arch, "alpha") == 0) { + ADD_MACHINE_TESTS(arch, alpha_machines); + } else if (strcmp(arch, "arm") == 0) { + ADD_MACHINE_TESTS(arch, arm_machines); + } else if (strcmp(arch, "cris") == 0) { + ADD_MACHINE_TESTS(arch, cris_machines); + } else if (strcmp(arch, "lm32") == 0) { + ADD_MACHINE_TESTS(arch, lm32_machines); + } else if (strcmp(arch, "m68k") == 0) { + ADD_MACHINE_TESTS(arch, m68k_machines); + } else if (strcmp(arch, "microblaze") == 0 || + strcmp(arch, "microblazeel") == 0) { + ADD_MACHINE_TESTS(arch, microblaze_machines); + } else if (strcmp(arch, "mips") == 0 || + strcmp(arch, "mipsel") == 0 || + strcmp(arch, "mips64") == 0) { + ADD_MACHINE_TESTS(arch, mips_machines); + } else if (strcmp(arch, "mips64el") == 0) { + ADD_MACHINE_TESTS(arch, mips_machines); + add_test_cases(arch, "fulong2e"); + } else if (strcmp(arch, "moxie") == 0) { + ADD_MACHINE_TESTS(arch, moxie_machines); + } else if (strcmp(arch, "or32") == 0) { + ADD_MACHINE_TESTS(arch, openrisc_machines); + } else if (strcmp(arch, "ppcemb") == 0) { +#if 0 + /* XXX Available in ppcemb but don't work */ + ADD_MACHINE_TESTS(arch, ppc405_machines); +#endif + ADD_MACHINE_TESTS(arch, ppc440_machines); + } else if (strcmp(arch, "ppc") == 0) { + ADD_MACHINE_TESTS(arch, ppc405_machines); + ADD_MACHINE_TESTS(arch, ppc440_machines); + ADD_MACHINE_TESTS(arch, ppc_machines); + } else if (strcmp(arch, "ppc64") == 0) { + ADD_MACHINE_TESTS(arch, ppc405_machines); + ADD_MACHINE_TESTS(arch, ppc440_machines); + ADD_MACHINE_TESTS(arch, ppc_machines); + ADD_MACHINE_TESTS(arch, ppc64_machines); + } else if (strcmp(arch, "s390x") == 0) { + ADD_MACHINE_TESTS(arch, s390_machines); + } else if (strcmp(arch, "sh4") == 0 || + strcmp(arch, "sh4eb") == 0) { + ADD_MACHINE_TESTS(arch, superh_machines); + } else if (strcmp(arch, "sparc") == 0) { + ADD_MACHINE_TESTS(arch, sparc_machines); + } else if (strcmp(arch, "sparc64") == 0) { + ADD_MACHINE_TESTS(arch, sparc64_machines); + } else if (strcmp(arch, "unicore32") == 0) { + ADD_MACHINE_TESTS(arch, unicore32_machines); + } else if (strcmp(arch, "xtensa") == 0 || + strcmp(arch, "xtensaeb") == 0) { + ADD_MACHINE_TESTS(arch, xtensa_machines); + } + + return g_test_run(); +} From c77dd5f6140acd62ba73fbb8b8144c42c003b995 Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Sat, 31 Aug 2013 21:22:40 +0400 Subject: [PATCH 18/54] milkymist-uart: Use Device::realize instead of SysBusDevice::init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use of SysBusDevice::init is deprecated. Use Device::realize instead. Also introduce TypeInfo::instance_init milkymist_uart_init(). Reported-by: Peter Crosthwaite Signed-off-by: Antony Pavlov Signed-off-by: Andreas Färber --- hw/char/milkymist-uart.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/hw/char/milkymist-uart.c b/hw/char/milkymist-uart.c index 2e4b5c58b0..2c52a0fa8e 100644 --- a/hw/char/milkymist-uart.c +++ b/hw/char/milkymist-uart.c @@ -195,22 +195,26 @@ static void milkymist_uart_reset(DeviceState *d) s->regs[R_STAT] = STAT_THRE; } -static int milkymist_uart_init(SysBusDevice *dev) +static void milkymist_uart_realize(DeviceState *dev, Error **errp) { MilkymistUartState *s = MILKYMIST_UART(dev); - sysbus_init_irq(dev, &s->irq); - - memory_region_init_io(&s->regs_region, OBJECT(s), &uart_mmio_ops, s, - "milkymist-uart", R_MAX * 4); - sysbus_init_mmio(dev, &s->regs_region); - s->chr = qemu_char_get_next_serial(); if (s->chr) { qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s); } +} - return 0; +static void milkymist_uart_init(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + MilkymistUartState *s = MILKYMIST_UART(obj); + + sysbus_init_irq(sbd, &s->irq); + + memory_region_init_io(&s->regs_region, OBJECT(s), &uart_mmio_ops, s, + "milkymist-uart", R_MAX * 4); + sysbus_init_mmio(sbd, &s->regs_region); } static const VMStateDescription vmstate_milkymist_uart = { @@ -227,9 +231,8 @@ static const VMStateDescription vmstate_milkymist_uart = { static void milkymist_uart_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = milkymist_uart_init; + dc->realize = milkymist_uart_realize; dc->reset = milkymist_uart_reset; dc->vmsd = &vmstate_milkymist_uart; } @@ -238,6 +241,7 @@ static const TypeInfo milkymist_uart_info = { .name = TYPE_MILKYMIST_UART, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(MilkymistUartState), + .instance_init = milkymist_uart_init, .class_init = milkymist_uart_class_init, }; From 753bc6e981101b2a1d8bd4cb68f54dcdf82e9b63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 30 Jun 2013 19:52:31 +0200 Subject: [PATCH 19/54] a9mpcore: Split off instance_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prepares for QOM realize. Reviewed-by: Peter Maydell Signed-off-by: Andreas Färber --- hw/cpu/a9mpcore.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c index 3e675e3941..acbdab50dc 100644 --- a/hw/cpu/a9mpcore.c +++ b/hw/cpu/a9mpcore.c @@ -34,6 +34,14 @@ static void a9mp_priv_set_irq(void *opaque, int irq, int level) qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level); } +static void a9mp_priv_initfn(Object *obj) +{ + A9MPPrivState *s = A9MPCORE_PRIV(obj); + + memory_region_init(&s->container, obj, "a9mp-priv-container", 0x2000); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->container); +} + static int a9mp_priv_init(SysBusDevice *dev) { A9MPPrivState *s = A9MPCORE_PRIV(dev); @@ -78,7 +86,6 @@ static int a9mp_priv_init(SysBusDevice *dev) * * We should implement the global timer but don't currently do so. */ - memory_region_init(&s->container, OBJECT(s), "a9mp-priv-container", 0x2000); memory_region_add_subregion(&s->container, 0, sysbus_mmio_get_region(scubusdev, 0)); /* GIC CPU interface */ @@ -94,8 +101,6 @@ static int a9mp_priv_init(SysBusDevice *dev) memory_region_add_subregion(&s->container, 0x1000, sysbus_mmio_get_region(gicbusdev, 0)); - sysbus_init_mmio(dev, &s->container); - /* Wire up the interrupt from each watchdog and timer. * For each core the timer is PPI 29 and the watchdog PPI 30. */ @@ -134,6 +139,7 @@ static const TypeInfo a9mp_priv_info = { .name = TYPE_A9MPCORE_PRIV, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(A9MPPrivState), + .instance_init = a9mp_priv_initfn, .class_init = a9mp_priv_class_init, }; From 83728796ad3f2ce7d6162c1cb894528b12915646 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Tue, 23 Jul 2013 03:37:49 +0200 Subject: [PATCH 20/54] arm_gic: Extract headers hw/intc/arm_gic{,_common}.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename NCPU to GIC_NCPU and move GICState away from gic_internal.h. Reviewed-by: Peter Maydell Signed-off-by: Andreas Färber --- hw/intc/arm_gic_common.c | 18 +++---- hw/intc/gic_internal.h | 80 +-------------------------- include/hw/intc/arm_gic.h | 42 +++++++++++++++ include/hw/intc/arm_gic_common.h | 92 ++++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+), 87 deletions(-) create mode 100644 include/hw/intc/arm_gic.h create mode 100644 include/hw/intc/arm_gic_common.h diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c index 709b5c2984..c7658508dd 100644 --- a/hw/intc/arm_gic_common.c +++ b/hw/intc/arm_gic_common.c @@ -64,17 +64,17 @@ static const VMStateDescription vmstate_gic = { .post_load = gic_post_load, .fields = (VMStateField[]) { VMSTATE_BOOL(enabled, GICState), - VMSTATE_BOOL_ARRAY(cpu_enabled, GICState, NCPU), + VMSTATE_BOOL_ARRAY(cpu_enabled, GICState, GIC_NCPU), VMSTATE_STRUCT_ARRAY(irq_state, GICState, GIC_MAXIRQ, 1, vmstate_gic_irq_state, gic_irq_state), VMSTATE_UINT8_ARRAY(irq_target, GICState, GIC_MAXIRQ), - VMSTATE_UINT8_2DARRAY(priority1, GICState, GIC_INTERNAL, NCPU), + VMSTATE_UINT8_2DARRAY(priority1, GICState, GIC_INTERNAL, GIC_NCPU), VMSTATE_UINT8_ARRAY(priority2, GICState, GIC_MAXIRQ - GIC_INTERNAL), - VMSTATE_UINT16_2DARRAY(last_active, GICState, GIC_MAXIRQ, NCPU), - VMSTATE_UINT16_ARRAY(priority_mask, GICState, NCPU), - VMSTATE_UINT16_ARRAY(running_irq, GICState, NCPU), - VMSTATE_UINT16_ARRAY(running_priority, GICState, NCPU), - VMSTATE_UINT16_ARRAY(current_pending, GICState, NCPU), + VMSTATE_UINT16_2DARRAY(last_active, GICState, GIC_MAXIRQ, GIC_NCPU), + VMSTATE_UINT16_ARRAY(priority_mask, GICState, GIC_NCPU), + VMSTATE_UINT16_ARRAY(running_irq, GICState, GIC_NCPU), + VMSTATE_UINT16_ARRAY(running_priority, GICState, GIC_NCPU), + VMSTATE_UINT16_ARRAY(current_pending, GICState, GIC_NCPU), VMSTATE_END_OF_LIST() } }; @@ -84,9 +84,9 @@ static void arm_gic_common_realize(DeviceState *dev, Error **errp) GICState *s = ARM_GIC_COMMON(dev); int num_irq = s->num_irq; - if (s->num_cpu > NCPU) { + if (s->num_cpu > GIC_NCPU) { error_setg(errp, "requested %u CPUs exceeds GIC maximum %d", - s->num_cpu, NCPU); + s->num_cpu, GIC_NCPU); return; } s->num_irq += GIC_BASE_IRQ; diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h index 14264373fe..3989fd1bd5 100644 --- a/hw/intc/gic_internal.h +++ b/hw/intc/gic_internal.h @@ -21,16 +21,9 @@ #ifndef QEMU_ARM_GIC_INTERNAL_H #define QEMU_ARM_GIC_INTERNAL_H -#include "hw/sysbus.h" +#include "hw/intc/arm_gic.h" -/* Maximum number of possible interrupts, determined by the GIC architecture */ -#define GIC_MAXIRQ 1020 -/* First 32 are private to each CPU (SGIs and PPIs). */ -#define GIC_INTERNAL 32 -/* Maximum number of possible CPU interfaces, determined by GIC architecture */ -#define NCPU 8 - -#define ALL_CPU_MASK ((unsigned)(((1 << NCPU) - 1))) +#define ALL_CPU_MASK ((unsigned)(((1 << GIC_NCPU) - 1))) /* The NVIC has 16 internal vectors. However these are not exposed through the normal GIC interface. */ @@ -59,48 +52,6 @@ s->priority2[(irq) - GIC_INTERNAL]) #define GIC_TARGET(irq) s->irq_target[irq] -typedef struct gic_irq_state { - /* The enable bits are only banked for per-cpu interrupts. */ - uint8_t enabled; - uint8_t pending; - uint8_t active; - uint8_t level; - bool model; /* 0 = N:N, 1 = 1:N */ - bool trigger; /* nonzero = edge triggered. */ -} gic_irq_state; - -typedef struct GICState { - /*< private >*/ - SysBusDevice parent_obj; - /*< public >*/ - - qemu_irq parent_irq[NCPU]; - bool enabled; - bool cpu_enabled[NCPU]; - - gic_irq_state irq_state[GIC_MAXIRQ]; - uint8_t irq_target[GIC_MAXIRQ]; - uint8_t priority1[GIC_INTERNAL][NCPU]; - uint8_t priority2[GIC_MAXIRQ - GIC_INTERNAL]; - uint16_t last_active[GIC_MAXIRQ][NCPU]; - - uint16_t priority_mask[NCPU]; - uint16_t running_irq[NCPU]; - uint16_t running_priority[NCPU]; - uint16_t current_pending[NCPU]; - - uint32_t num_cpu; - - MemoryRegion iomem; /* Distributor */ - /* This is just so we can have an opaque pointer which identifies - * both this GIC and which CPU interface we should be accessing. - */ - struct GICState *backref[NCPU]; - MemoryRegion cpuiomem[NCPU+1]; /* CPU interfaces */ - uint32_t num_irq; - uint32_t revision; -} GICState; - /* The special cases for the revision property: */ #define REV_11MPCORE 0 #define REV_NVIC 0xffffffff @@ -111,31 +62,4 @@ void gic_complete_irq(GICState *s, int cpu, int irq); void gic_update(GICState *s); void gic_init_irqs_and_distributor(GICState *s, int num_irq); -#define TYPE_ARM_GIC_COMMON "arm_gic_common" -#define ARM_GIC_COMMON(obj) \ - OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC_COMMON) -#define ARM_GIC_COMMON_CLASS(klass) \ - OBJECT_CLASS_CHECK(ARMGICCommonClass, (klass), TYPE_ARM_GIC_COMMON) -#define ARM_GIC_COMMON_GET_CLASS(obj) \ - OBJECT_GET_CLASS(ARMGICCommonClass, (obj), TYPE_ARM_GIC_COMMON) - -typedef struct ARMGICCommonClass { - SysBusDeviceClass parent_class; - void (*pre_save)(GICState *s); - void (*post_load)(GICState *s); -} ARMGICCommonClass; - -#define TYPE_ARM_GIC "arm_gic" -#define ARM_GIC(obj) \ - OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC) -#define ARM_GIC_CLASS(klass) \ - OBJECT_CLASS_CHECK(ARMGICClass, (klass), TYPE_ARM_GIC) -#define ARM_GIC_GET_CLASS(obj) \ - OBJECT_GET_CLASS(ARMGICClass, (obj), TYPE_ARM_GIC) - -typedef struct ARMGICClass { - ARMGICCommonClass parent_class; - DeviceRealize parent_realize; -} ARMGICClass; - #endif /* !QEMU_ARM_GIC_INTERNAL_H */ diff --git a/include/hw/intc/arm_gic.h b/include/hw/intc/arm_gic.h new file mode 100644 index 0000000000..0971e37710 --- /dev/null +++ b/include/hw/intc/arm_gic.h @@ -0,0 +1,42 @@ +/* + * ARM GIC support + * + * Copyright (c) 2012 Linaro Limited + * Written by Peter Maydell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#ifndef HW_ARM_GIC_H +#define HW_ARM_GIC_H + +#include "arm_gic_common.h" + +#define TYPE_ARM_GIC "arm_gic" +#define ARM_GIC(obj) \ + OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC) +#define ARM_GIC_CLASS(klass) \ + OBJECT_CLASS_CHECK(ARMGICClass, (klass), TYPE_ARM_GIC) +#define ARM_GIC_GET_CLASS(obj) \ + OBJECT_GET_CLASS(ARMGICClass, (obj), TYPE_ARM_GIC) + +typedef struct ARMGICClass { + /*< private >*/ + ARMGICCommonClass parent_class; + /*< public >*/ + + DeviceRealize parent_realize; +} ARMGICClass; + +#endif diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h new file mode 100644 index 0000000000..4f381bdce7 --- /dev/null +++ b/include/hw/intc/arm_gic_common.h @@ -0,0 +1,92 @@ +/* + * ARM GIC support + * + * Copyright (c) 2012 Linaro Limited + * Written by Peter Maydell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#ifndef HW_ARM_GIC_COMMON_H +#define HW_ARM_GIC_COMMON_H + +#include "hw/sysbus.h" + +/* Maximum number of possible interrupts, determined by the GIC architecture */ +#define GIC_MAXIRQ 1020 +/* First 32 are private to each CPU (SGIs and PPIs). */ +#define GIC_INTERNAL 32 +/* Maximum number of possible CPU interfaces, determined by GIC architecture */ +#define GIC_NCPU 8 + +typedef struct gic_irq_state { + /* The enable bits are only banked for per-cpu interrupts. */ + uint8_t enabled; + uint8_t pending; + uint8_t active; + uint8_t level; + bool model; /* 0 = N:N, 1 = 1:N */ + bool trigger; /* nonzero = edge triggered. */ +} gic_irq_state; + +typedef struct GICState { + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + + qemu_irq parent_irq[GIC_NCPU]; + bool enabled; + bool cpu_enabled[GIC_NCPU]; + + gic_irq_state irq_state[GIC_MAXIRQ]; + uint8_t irq_target[GIC_MAXIRQ]; + uint8_t priority1[GIC_INTERNAL][GIC_NCPU]; + uint8_t priority2[GIC_MAXIRQ - GIC_INTERNAL]; + uint16_t last_active[GIC_MAXIRQ][GIC_NCPU]; + + uint16_t priority_mask[GIC_NCPU]; + uint16_t running_irq[GIC_NCPU]; + uint16_t running_priority[GIC_NCPU]; + uint16_t current_pending[GIC_NCPU]; + + uint32_t num_cpu; + + MemoryRegion iomem; /* Distributor */ + /* This is just so we can have an opaque pointer which identifies + * both this GIC and which CPU interface we should be accessing. + */ + struct GICState *backref[GIC_NCPU]; + MemoryRegion cpuiomem[GIC_NCPU + 1]; /* CPU interfaces */ + uint32_t num_irq; + uint32_t revision; +} GICState; + +#define TYPE_ARM_GIC_COMMON "arm_gic_common" +#define ARM_GIC_COMMON(obj) \ + OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC_COMMON) +#define ARM_GIC_COMMON_CLASS(klass) \ + OBJECT_CLASS_CHECK(ARMGICCommonClass, (klass), TYPE_ARM_GIC_COMMON) +#define ARM_GIC_COMMON_GET_CLASS(obj) \ + OBJECT_GET_CLASS(ARMGICCommonClass, (obj), TYPE_ARM_GIC_COMMON) + +typedef struct ARMGICCommonClass { + /*< private >*/ + SysBusDeviceClass parent_class; + /*< public >*/ + + void (*pre_save)(GICState *s); + void (*post_load)(GICState *s); +} ARMGICCommonClass; + +#endif From 9b5f952bb8015b079783a9197f3331085075fbc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 30 Jun 2013 19:01:18 +0200 Subject: [PATCH 21/54] a9mpcore: Embed GICState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prepares for conversion to QOM realize. Reviewed-by: Peter Maydell Signed-off-by: Andreas Färber --- hw/cpu/a9mpcore.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c index acbdab50dc..c57b149536 100644 --- a/hw/cpu/a9mpcore.c +++ b/hw/cpu/a9mpcore.c @@ -9,6 +9,7 @@ */ #include "hw/sysbus.h" +#include "hw/intc/arm_gic.h" #define TYPE_A9MPCORE_PRIV "a9mpcore_priv" #define A9MPCORE_PRIV(obj) \ @@ -23,15 +24,17 @@ typedef struct A9MPPrivState { MemoryRegion container; DeviceState *mptimer; DeviceState *wdt; - DeviceState *gic; DeviceState *scu; uint32_t num_irq; + + GICState gic; } A9MPPrivState; static void a9mp_priv_set_irq(void *opaque, int irq, int level) { A9MPPrivState *s = (A9MPPrivState *)opaque; - qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level); + + qemu_set_irq(qdev_get_gpio_in(DEVICE(&s->gic), irq), level); } static void a9mp_priv_initfn(Object *obj) @@ -40,19 +43,23 @@ static void a9mp_priv_initfn(Object *obj) memory_region_init(&s->container, obj, "a9mp-priv-container", 0x2000); sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->container); + + object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC); + qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default()); } static int a9mp_priv_init(SysBusDevice *dev) { A9MPPrivState *s = A9MPCORE_PRIV(dev); + DeviceState *gicdev; SysBusDevice *timerbusdev, *wdtbusdev, *gicbusdev, *scubusdev; int i; - s->gic = qdev_create(NULL, "arm_gic"); - qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu); - qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq); - qdev_init_nofail(s->gic); - gicbusdev = SYS_BUS_DEVICE(s->gic); + gicdev = DEVICE(&s->gic); + qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu); + qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq); + qdev_init_nofail(gicdev); + gicbusdev = SYS_BUS_DEVICE(&s->gic); /* Pass through outbound IRQ lines from the GIC */ sysbus_pass_irq(dev, gicbusdev); @@ -107,9 +114,9 @@ static int a9mp_priv_init(SysBusDevice *dev) for (i = 0; i < s->num_cpu; i++) { int ppibase = (s->num_irq - 32) + i * 32; sysbus_connect_irq(timerbusdev, i, - qdev_get_gpio_in(s->gic, ppibase + 29)); + qdev_get_gpio_in(gicdev, ppibase + 29)); sysbus_connect_irq(wdtbusdev, i, - qdev_get_gpio_in(s->gic, ppibase + 30)); + qdev_get_gpio_in(gicdev, ppibase + 30)); } return 0; } From 9eb39db520cea30620b24098b6d731f78cc819a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 30 Jun 2013 19:22:12 +0200 Subject: [PATCH 22/54] a9scu: QOM cleanups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename A9SCUState::busdev field to parent_obj and turn realizefn into an instance_init function to allow early MMIO mapping. Reviewed-by: Peter Crosthwaite Reviewed-by: Peter Maydell Signed-off-by: Andreas Färber --- hw/misc/a9scu.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c index 601b5733f2..2661014a63 100644 --- a/hw/misc/a9scu.c +++ b/hw/misc/a9scu.c @@ -13,7 +13,10 @@ /* A9MP private memory region. */ typedef struct A9SCUState { - SysBusDevice busdev; + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + MemoryRegion iomem; uint32_t control; uint32_t status; @@ -114,12 +117,12 @@ static void a9_scu_reset(DeviceState *dev) s->control = 0; } -static void a9_scu_realize(DeviceState *dev, Error ** errp) +static void a9_scu_init(Object *obj) { - A9SCUState *s = A9_SCU(dev); - SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + A9SCUState *s = A9_SCU(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - memory_region_init_io(&s->iomem, OBJECT(dev), &a9_scu_ops, s, + memory_region_init_io(&s->iomem, obj, &a9_scu_ops, s, "a9-scu", 0x100); sysbus_init_mmio(sbd, &s->iomem); } @@ -144,7 +147,6 @@ static void a9_scu_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - dc->realize = a9_scu_realize; dc->props = a9_scu_properties; dc->vmsd = &vmstate_a9_scu; dc->reset = a9_scu_reset; @@ -154,6 +156,7 @@ static const TypeInfo a9_scu_info = { .name = TYPE_A9_SCU, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(A9SCUState), + .instance_init = a9_scu_init, .class_init = a9_scu_class_init, }; From fc719d77412513a07b718e1f083b64dbcac62524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 30 Jun 2013 19:29:36 +0200 Subject: [PATCH 23/54] a9mpcore: Embed A9SCUState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prepares for QOM realize. Reviewed-by: Peter Maydell Signed-off-by: Andreas Färber --- hw/cpu/a9mpcore.c | 16 ++++++++++------ hw/misc/a9scu.c | 18 +----------------- include/hw/misc/a9scu.h | 31 +++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 23 deletions(-) create mode 100644 include/hw/misc/a9scu.h diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c index c57b149536..df92e3fff7 100644 --- a/hw/cpu/a9mpcore.c +++ b/hw/cpu/a9mpcore.c @@ -10,6 +10,7 @@ #include "hw/sysbus.h" #include "hw/intc/arm_gic.h" +#include "hw/misc/a9scu.h" #define TYPE_A9MPCORE_PRIV "a9mpcore_priv" #define A9MPCORE_PRIV(obj) \ @@ -24,10 +25,10 @@ typedef struct A9MPPrivState { MemoryRegion container; DeviceState *mptimer; DeviceState *wdt; - DeviceState *scu; uint32_t num_irq; GICState gic; + A9SCUState scu; } A9MPPrivState; static void a9mp_priv_set_irq(void *opaque, int irq, int level) @@ -46,12 +47,15 @@ static void a9mp_priv_initfn(Object *obj) object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC); qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default()); + + object_initialize(&s->scu, sizeof(s->scu), TYPE_A9_SCU); + qdev_set_parent_bus(DEVICE(&s->scu), sysbus_get_default()); } static int a9mp_priv_init(SysBusDevice *dev) { A9MPPrivState *s = A9MPCORE_PRIV(dev); - DeviceState *gicdev; + DeviceState *gicdev, *scudev; SysBusDevice *timerbusdev, *wdtbusdev, *gicbusdev, *scubusdev; int i; @@ -67,10 +71,10 @@ static int a9mp_priv_init(SysBusDevice *dev) /* Pass through inbound GPIO lines to the GIC */ qdev_init_gpio_in(DEVICE(dev), a9mp_priv_set_irq, s->num_irq - 32); - s->scu = qdev_create(NULL, "a9-scu"); - qdev_prop_set_uint32(s->scu, "num-cpu", s->num_cpu); - qdev_init_nofail(s->scu); - scubusdev = SYS_BUS_DEVICE(s->scu); + scudev = DEVICE(&s->scu); + qdev_prop_set_uint32(scudev, "num-cpu", s->num_cpu); + qdev_init_nofail(scudev); + scubusdev = SYS_BUS_DEVICE(&s->scu); s->mptimer = qdev_create(NULL, "arm_mptimer"); qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu); diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c index 2661014a63..4434945908 100644 --- a/hw/misc/a9scu.c +++ b/hw/misc/a9scu.c @@ -8,23 +8,7 @@ * This code is licensed under the GPL. */ -#include "hw/sysbus.h" - -/* A9MP private memory region. */ - -typedef struct A9SCUState { - /*< private >*/ - SysBusDevice parent_obj; - /*< public >*/ - - MemoryRegion iomem; - uint32_t control; - uint32_t status; - uint32_t num_cpu; -} A9SCUState; - -#define TYPE_A9_SCU "a9-scu" -#define A9_SCU(obj) OBJECT_CHECK(A9SCUState, (obj), TYPE_A9_SCU) +#include "hw/misc/a9scu.h" static uint64_t a9_scu_read(void *opaque, hwaddr offset, unsigned size) diff --git a/include/hw/misc/a9scu.h b/include/hw/misc/a9scu.h new file mode 100644 index 0000000000..efb0c305c2 --- /dev/null +++ b/include/hw/misc/a9scu.h @@ -0,0 +1,31 @@ +/* + * Cortex-A9MPCore Snoop Control Unit (SCU) emulation. + * + * Copyright (c) 2009 CodeSourcery. + * Copyright (c) 2011 Linaro Limited. + * Written by Paul Brook, Peter Maydell. + * + * This code is licensed under the GPL. + */ +#ifndef HW_MISC_A9SCU_H +#define HW_MISC_A9SCU_H + +#include "hw/sysbus.h" + +/* A9MP private memory region. */ + +typedef struct A9SCUState { + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + + MemoryRegion iomem; + uint32_t control; + uint32_t status; + uint32_t num_cpu; +} A9SCUState; + +#define TYPE_A9_SCU "a9-scu" +#define A9_SCU(obj) OBJECT_CHECK(A9SCUState, (obj), TYPE_A9_SCU) + +#endif From 0aadb4909c330bbde8542fcafc465817530cb835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 30 Jun 2013 19:42:55 +0200 Subject: [PATCH 24/54] arm_mptimer: Convert to QOM realize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split the SysBusDevice initfn into instance_init and realizefn. Reviewed-by: Peter Maydell Signed-off-by: Andreas Färber --- hw/timer/arm_mptimer.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c index 8020c9f4b5..2853db47f2 100644 --- a/hw/timer/arm_mptimer.c +++ b/hw/timer/arm_mptimer.c @@ -225,8 +225,18 @@ static void arm_mptimer_reset(DeviceState *dev) } } -static int arm_mptimer_init(SysBusDevice *dev) +static void arm_mptimer_init(Object *obj) { + ARMMPTimerState *s = ARM_MPTIMER(obj); + + memory_region_init_io(&s->iomem, obj, &arm_thistimer_ops, s, + "arm_mptimer_timer", 0x20); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem); +} + +static void arm_mptimer_realize(DeviceState *dev, Error **errp) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); ARMMPTimerState *s = ARM_MPTIMER(dev); int i; @@ -243,19 +253,14 @@ static int arm_mptimer_init(SysBusDevice *dev) * * timer for core 1 * and so on. */ - memory_region_init_io(&s->iomem, OBJECT(s), &arm_thistimer_ops, s, - "arm_mptimer_timer", 0x20); - sysbus_init_mmio(dev, &s->iomem); for (i = 0; i < s->num_cpu; i++) { TimerBlock *tb = &s->timerblock[i]; tb->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, timerblock_tick, tb); - sysbus_init_irq(dev, &tb->irq); + sysbus_init_irq(sbd, &tb->irq); memory_region_init_io(&tb->iomem, OBJECT(s), &timerblock_ops, tb, "arm_mptimer_timerblock", 0x20); - sysbus_init_mmio(dev, &tb->iomem); + sysbus_init_mmio(sbd, &tb->iomem); } - - return 0; } static const VMStateDescription vmstate_timerblock = { @@ -292,9 +297,8 @@ static Property arm_mptimer_properties[] = { static void arm_mptimer_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass); - sbc->init = arm_mptimer_init; + dc->realize = arm_mptimer_realize; dc->vmsd = &vmstate_arm_mptimer; dc->reset = arm_mptimer_reset; dc->no_user = 1; @@ -305,6 +309,7 @@ static const TypeInfo arm_mptimer_info = { .name = TYPE_ARM_MPTIMER, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(ARMMPTimerState), + .instance_init = arm_mptimer_init, .class_init = arm_mptimer_class_init, }; From eb110bd843d3ef70850a7cf44d05056b8a3e81aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 30 Jun 2013 20:30:27 +0200 Subject: [PATCH 25/54] a9mpcore: Embed ARMMPTimerState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prepares for QOM realize. Reviewed-by: Peter Maydell Signed-off-by: Andreas Färber --- hw/cpu/a9mpcore.c | 29 +++++++++++------- hw/timer/arm_mptimer.c | 35 +++------------------- include/hw/timer/arm_mptimer.h | 54 ++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 42 deletions(-) create mode 100644 include/hw/timer/arm_mptimer.h diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c index df92e3fff7..db3907ecfc 100644 --- a/hw/cpu/a9mpcore.c +++ b/hw/cpu/a9mpcore.c @@ -11,6 +11,7 @@ #include "hw/sysbus.h" #include "hw/intc/arm_gic.h" #include "hw/misc/a9scu.h" +#include "hw/timer/arm_mptimer.h" #define TYPE_A9MPCORE_PRIV "a9mpcore_priv" #define A9MPCORE_PRIV(obj) \ @@ -23,12 +24,12 @@ typedef struct A9MPPrivState { uint32_t num_cpu; MemoryRegion container; - DeviceState *mptimer; - DeviceState *wdt; uint32_t num_irq; GICState gic; A9SCUState scu; + ARMMPTimerState mptimer; + ARMMPTimerState wdt; } A9MPPrivState; static void a9mp_priv_set_irq(void *opaque, int irq, int level) @@ -50,12 +51,18 @@ static void a9mp_priv_initfn(Object *obj) object_initialize(&s->scu, sizeof(s->scu), TYPE_A9_SCU); qdev_set_parent_bus(DEVICE(&s->scu), sysbus_get_default()); + + object_initialize(&s->mptimer, sizeof(s->mptimer), TYPE_ARM_MPTIMER); + qdev_set_parent_bus(DEVICE(&s->mptimer), sysbus_get_default()); + + object_initialize(&s->wdt, sizeof(s->wdt), TYPE_ARM_MPTIMER); + qdev_set_parent_bus(DEVICE(&s->wdt), sysbus_get_default()); } static int a9mp_priv_init(SysBusDevice *dev) { A9MPPrivState *s = A9MPCORE_PRIV(dev); - DeviceState *gicdev, *scudev; + DeviceState *gicdev, *scudev, *mptimerdev, *wdtdev; SysBusDevice *timerbusdev, *wdtbusdev, *gicbusdev, *scubusdev; int i; @@ -76,15 +83,15 @@ static int a9mp_priv_init(SysBusDevice *dev) qdev_init_nofail(scudev); scubusdev = SYS_BUS_DEVICE(&s->scu); - s->mptimer = qdev_create(NULL, "arm_mptimer"); - qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu); - qdev_init_nofail(s->mptimer); - timerbusdev = SYS_BUS_DEVICE(s->mptimer); + mptimerdev = DEVICE(&s->mptimer); + qdev_prop_set_uint32(mptimerdev, "num-cpu", s->num_cpu); + qdev_init_nofail(mptimerdev); + timerbusdev = SYS_BUS_DEVICE(&s->mptimer); - s->wdt = qdev_create(NULL, "arm_mptimer"); - qdev_prop_set_uint32(s->wdt, "num-cpu", s->num_cpu); - qdev_init_nofail(s->wdt); - wdtbusdev = SYS_BUS_DEVICE(s->wdt); + wdtdev = DEVICE(&s->wdt); + qdev_prop_set_uint32(wdtdev, "num-cpu", s->num_cpu); + qdev_init_nofail(wdtdev); + wdtbusdev = SYS_BUS_DEVICE(&s->wdt); /* Memory map (addresses are offsets from PERIPHBASE): * 0x0000-0x00ff -- Snoop Control Unit diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c index 2853db47f2..d9f9494f26 100644 --- a/hw/timer/arm_mptimer.c +++ b/hw/timer/arm_mptimer.c @@ -19,7 +19,7 @@ * with this program; if not, see . */ -#include "hw/sysbus.h" +#include "hw/timer/arm_mptimer.h" #include "qemu/timer.h" #include "qom/cpu.h" @@ -27,34 +27,6 @@ * which is used in both the ARM11MPCore and Cortex-A9MP. */ -#define MAX_CPUS 4 - -/* State of a single timer or watchdog block */ -typedef struct { - uint32_t count; - uint32_t load; - uint32_t control; - uint32_t status; - int64_t tick; - QEMUTimer *timer; - qemu_irq irq; - MemoryRegion iomem; -} TimerBlock; - -#define TYPE_ARM_MPTIMER "arm_mptimer" -#define ARM_MPTIMER(obj) \ - OBJECT_CHECK(ARMMPTimerState, (obj), TYPE_ARM_MPTIMER) - -typedef struct { - /*< private >*/ - SysBusDevice parent_obj; - /*< public >*/ - - uint32_t num_cpu; - TimerBlock timerblock[MAX_CPUS]; - MemoryRegion iomem; -} ARMMPTimerState; - static inline int get_current_cpu(ARMMPTimerState *s) { if (current_cpu->cpu_index >= s->num_cpu) { @@ -240,8 +212,9 @@ static void arm_mptimer_realize(DeviceState *dev, Error **errp) ARMMPTimerState *s = ARM_MPTIMER(dev); int i; - if (s->num_cpu < 1 || s->num_cpu > MAX_CPUS) { - hw_error("%s: num-cpu must be between 1 and %d\n", __func__, MAX_CPUS); + if (s->num_cpu < 1 || s->num_cpu > ARM_MPTIMER_MAX_CPUS) { + hw_error("%s: num-cpu must be between 1 and %d\n", + __func__, ARM_MPTIMER_MAX_CPUS); } /* We implement one timer block per CPU, and expose multiple MMIO regions: * * region 0 is "timer for this core" diff --git a/include/hw/timer/arm_mptimer.h b/include/hw/timer/arm_mptimer.h new file mode 100644 index 0000000000..b34cba00ce --- /dev/null +++ b/include/hw/timer/arm_mptimer.h @@ -0,0 +1,54 @@ +/* + * Private peripheral timer/watchdog blocks for ARM 11MPCore and A9MP + * + * Copyright (c) 2006-2007 CodeSourcery. + * Copyright (c) 2011 Linaro Limited + * Written by Paul Brook, Peter Maydell + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ +#ifndef HW_TIMER_ARM_MPTIMER_H +#define HW_TIMER_ARM_MPTIMER_H + +#include "hw/sysbus.h" + +#define ARM_MPTIMER_MAX_CPUS 4 + +/* State of a single timer or watchdog block */ +typedef struct { + uint32_t count; + uint32_t load; + uint32_t control; + uint32_t status; + int64_t tick; + QEMUTimer *timer; + qemu_irq irq; + MemoryRegion iomem; +} TimerBlock; + +#define TYPE_ARM_MPTIMER "arm_mptimer" +#define ARM_MPTIMER(obj) \ + OBJECT_CHECK(ARMMPTimerState, (obj), TYPE_ARM_MPTIMER) + +typedef struct { + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + + uint32_t num_cpu; + TimerBlock timerblock[ARM_MPTIMER_MAX_CPUS]; + MemoryRegion iomem; +} ARMMPTimerState; + +#endif From 837cf1013e6e1aa821ce13d7f63bb3dc0a92a1ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 30 Jun 2013 20:36:15 +0200 Subject: [PATCH 26/54] a9mpcore: Convert to QOM realize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Peter Maydell Signed-off-by: Andreas Färber --- hw/cpu/a9mpcore.c | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c index db3907ecfc..a162ff0f29 100644 --- a/hw/cpu/a9mpcore.c +++ b/hw/cpu/a9mpcore.c @@ -59,38 +59,56 @@ static void a9mp_priv_initfn(Object *obj) qdev_set_parent_bus(DEVICE(&s->wdt), sysbus_get_default()); } -static int a9mp_priv_init(SysBusDevice *dev) +static void a9mp_priv_realize(DeviceState *dev, Error **errp) { + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); A9MPPrivState *s = A9MPCORE_PRIV(dev); DeviceState *gicdev, *scudev, *mptimerdev, *wdtdev; SysBusDevice *timerbusdev, *wdtbusdev, *gicbusdev, *scubusdev; + Error *err = NULL; int i; gicdev = DEVICE(&s->gic); qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu); qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq); - qdev_init_nofail(gicdev); + object_property_set_bool(OBJECT(&s->gic), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } gicbusdev = SYS_BUS_DEVICE(&s->gic); /* Pass through outbound IRQ lines from the GIC */ - sysbus_pass_irq(dev, gicbusdev); + sysbus_pass_irq(sbd, gicbusdev); /* Pass through inbound GPIO lines to the GIC */ - qdev_init_gpio_in(DEVICE(dev), a9mp_priv_set_irq, s->num_irq - 32); + qdev_init_gpio_in(dev, a9mp_priv_set_irq, s->num_irq - 32); scudev = DEVICE(&s->scu); qdev_prop_set_uint32(scudev, "num-cpu", s->num_cpu); - qdev_init_nofail(scudev); + object_property_set_bool(OBJECT(&s->scu), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } scubusdev = SYS_BUS_DEVICE(&s->scu); mptimerdev = DEVICE(&s->mptimer); qdev_prop_set_uint32(mptimerdev, "num-cpu", s->num_cpu); - qdev_init_nofail(mptimerdev); + object_property_set_bool(OBJECT(&s->mptimer), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } timerbusdev = SYS_BUS_DEVICE(&s->mptimer); wdtdev = DEVICE(&s->wdt); qdev_prop_set_uint32(wdtdev, "num-cpu", s->num_cpu); - qdev_init_nofail(wdtdev); + object_property_set_bool(OBJECT(&s->wdt), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } wdtbusdev = SYS_BUS_DEVICE(&s->wdt); /* Memory map (addresses are offsets from PERIPHBASE): @@ -129,7 +147,6 @@ static int a9mp_priv_init(SysBusDevice *dev) sysbus_connect_irq(wdtbusdev, i, qdev_get_gpio_in(gicdev, ppibase + 30)); } - return 0; } static Property a9mp_priv_properties[] = { @@ -147,9 +164,8 @@ static Property a9mp_priv_properties[] = { static void a9mp_priv_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = a9mp_priv_init; + dc->realize = a9mp_priv_realize; dc->props = a9mp_priv_properties; } From de4c2dcf7fedf5fa727113e1dec0d0e5dd0462a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 30 Jun 2013 20:44:23 +0200 Subject: [PATCH 27/54] a9mpcore: Prepare for QOM embedding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Peter Maydell Signed-off-by: Andreas Färber --- hw/cpu/a9mpcore.c | 24 +----------------------- include/hw/cpu/a9mpcore.h | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 23 deletions(-) create mode 100644 include/hw/cpu/a9mpcore.h diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c index a162ff0f29..918a7d1291 100644 --- a/hw/cpu/a9mpcore.c +++ b/hw/cpu/a9mpcore.c @@ -8,29 +8,7 @@ * This code is licensed under the GPL. */ -#include "hw/sysbus.h" -#include "hw/intc/arm_gic.h" -#include "hw/misc/a9scu.h" -#include "hw/timer/arm_mptimer.h" - -#define TYPE_A9MPCORE_PRIV "a9mpcore_priv" -#define A9MPCORE_PRIV(obj) \ - OBJECT_CHECK(A9MPPrivState, (obj), TYPE_A9MPCORE_PRIV) - -typedef struct A9MPPrivState { - /*< private >*/ - SysBusDevice parent_obj; - /*< public >*/ - - uint32_t num_cpu; - MemoryRegion container; - uint32_t num_irq; - - GICState gic; - A9SCUState scu; - ARMMPTimerState mptimer; - ARMMPTimerState wdt; -} A9MPPrivState; +#include "hw/cpu/a9mpcore.h" static void a9mp_priv_set_irq(void *opaque, int irq, int level) { diff --git a/include/hw/cpu/a9mpcore.h b/include/hw/cpu/a9mpcore.h new file mode 100644 index 0000000000..010489b98e --- /dev/null +++ b/include/hw/cpu/a9mpcore.h @@ -0,0 +1,37 @@ +/* + * Cortex-A9MPCore internal peripheral emulation. + * + * Copyright (c) 2009 CodeSourcery. + * Copyright (c) 2011 Linaro Limited. + * Written by Paul Brook, Peter Maydell. + * + * This code is licensed under the GPL. + */ +#ifndef HW_CPU_A9MPCORE_H +#define HW_CPU_A9MPCORE_H + +#include "hw/sysbus.h" +#include "hw/intc/arm_gic.h" +#include "hw/misc/a9scu.h" +#include "hw/timer/arm_mptimer.h" + +#define TYPE_A9MPCORE_PRIV "a9mpcore_priv" +#define A9MPCORE_PRIV(obj) \ + OBJECT_CHECK(A9MPPrivState, (obj), TYPE_A9MPCORE_PRIV) + +typedef struct A9MPPrivState { + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + + uint32_t num_cpu; + MemoryRegion container; + uint32_t num_irq; + + GICState gic; + A9SCUState scu; + ARMMPTimerState mptimer; + ARMMPTimerState wdt; +} A9MPPrivState; + +#endif From b9ed148d243839aba3864b4419114396f6fda2fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 30 Jun 2013 21:07:31 +0200 Subject: [PATCH 28/54] a15mpcore: Split off instance_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prepares for QOM realize. Reviewed-by: Peter Maydell Signed-off-by: Andreas Färber --- hw/cpu/a15mpcore.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c index 9abba67632..af29c35ab8 100644 --- a/hw/cpu/a15mpcore.c +++ b/hw/cpu/a15mpcore.c @@ -44,6 +44,15 @@ static void a15mp_priv_set_irq(void *opaque, int irq, int level) qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level); } +static void a15mp_priv_initfn(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + A15MPPrivState *s = A15MPCORE_PRIV(obj); + + memory_region_init(&s->container, obj, "a15mp-priv-container", 0x8000); + sysbus_init_mmio(sbd, &s->container); +} + static int a15mp_priv_init(SysBusDevice *dev) { A15MPPrivState *s = A15MPCORE_PRIV(dev); @@ -92,14 +101,11 @@ static int a15mp_priv_init(SysBusDevice *dev) * 0x5000-0x5fff -- GIC virtual interface control (not modelled) * 0x6000-0x7fff -- GIC virtual CPU interface (not modelled) */ - memory_region_init(&s->container, OBJECT(s), - "a15mp-priv-container", 0x8000); memory_region_add_subregion(&s->container, 0x1000, sysbus_mmio_get_region(busdev, 0)); memory_region_add_subregion(&s->container, 0x2000, sysbus_mmio_get_region(busdev, 1)); - sysbus_init_mmio(dev, &s->container); return 0; } @@ -128,6 +134,7 @@ static const TypeInfo a15mp_priv_info = { .name = TYPE_A15MPCORE_PRIV, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(A15MPPrivState), + .instance_init = a15mp_priv_initfn, .class_init = a15mp_priv_class_init, }; From 524a2d8e2628b3241f0dcaa6a96d57e8120cc439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 30 Jun 2013 21:20:26 +0200 Subject: [PATCH 29/54] a15mpcore: Embed GICState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This covers both emulated and KVM GIC. Prepares for QOM realize. Reviewed-by: Peter Maydell Signed-off-by: Andreas Färber --- hw/cpu/a15mpcore.c | 49 +++++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c index af29c35ab8..b2614e7208 100644 --- a/hw/cpu/a15mpcore.c +++ b/hw/cpu/a15mpcore.c @@ -20,6 +20,7 @@ #include "hw/sysbus.h" #include "sysemu/kvm.h" +#include "hw/intc/arm_gic.h" /* A15MP private memory region. */ @@ -35,41 +36,49 @@ typedef struct A15MPPrivState { uint32_t num_cpu; uint32_t num_irq; MemoryRegion container; - DeviceState *gic; + + GICState gic; } A15MPPrivState; static void a15mp_priv_set_irq(void *opaque, int irq, int level) { A15MPPrivState *s = (A15MPPrivState *)opaque; - qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level); + + qemu_set_irq(qdev_get_gpio_in(DEVICE(&s->gic), irq), level); } static void a15mp_priv_initfn(Object *obj) { SysBusDevice *sbd = SYS_BUS_DEVICE(obj); A15MPPrivState *s = A15MPCORE_PRIV(obj); - - memory_region_init(&s->container, obj, "a15mp-priv-container", 0x8000); - sysbus_init_mmio(sbd, &s->container); -} - -static int a15mp_priv_init(SysBusDevice *dev) -{ - A15MPPrivState *s = A15MPCORE_PRIV(dev); - SysBusDevice *busdev; + DeviceState *gicdev; const char *gictype = "arm_gic"; - int i; if (kvm_irqchip_in_kernel()) { gictype = "kvm-arm-gic"; } - s->gic = qdev_create(NULL, gictype); - qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu); - qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq); - qdev_prop_set_uint32(s->gic, "revision", 2); - qdev_init_nofail(s->gic); - busdev = SYS_BUS_DEVICE(s->gic); + memory_region_init(&s->container, obj, "a15mp-priv-container", 0x8000); + sysbus_init_mmio(sbd, &s->container); + + object_initialize(&s->gic, sizeof(s->gic), gictype); + gicdev = DEVICE(&s->gic); + qdev_set_parent_bus(gicdev, sysbus_get_default()); + qdev_prop_set_uint32(gicdev, "revision", 2); +} + +static int a15mp_priv_init(SysBusDevice *dev) +{ + A15MPPrivState *s = A15MPCORE_PRIV(dev); + DeviceState *gicdev; + SysBusDevice *busdev; + int i; + + gicdev = DEVICE(&s->gic); + qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu); + qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq); + qdev_init_nofail(gicdev); + busdev = SYS_BUS_DEVICE(&s->gic); /* Pass through outbound IRQ lines from the GIC */ sysbus_pass_irq(dev, busdev); @@ -87,10 +96,10 @@ static int a15mp_priv_init(SysBusDevice *dev) * since a real A15 always has TrustZone but QEMU doesn't. */ qdev_connect_gpio_out(cpudev, 0, - qdev_get_gpio_in(s->gic, ppibase + 30)); + qdev_get_gpio_in(gicdev, ppibase + 30)); /* virtual timer */ qdev_connect_gpio_out(cpudev, 1, - qdev_get_gpio_in(s->gic, ppibase + 27)); + qdev_get_gpio_in(gicdev, ppibase + 27)); } /* Memory map (addresses are offsets from PERIPHBASE): From 7c76a48db48accca337e1e99b9085646b696a895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 30 Jun 2013 21:22:54 +0200 Subject: [PATCH 30/54] a15mpcore: Convert to QOM realize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turn SysBusDevice initfn into a QOM realizefn. Reviewed-by: Peter Maydell Signed-off-by: Andreas Färber --- hw/cpu/a15mpcore.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c index b2614e7208..10dc35af5b 100644 --- a/hw/cpu/a15mpcore.c +++ b/hw/cpu/a15mpcore.c @@ -67,24 +67,30 @@ static void a15mp_priv_initfn(Object *obj) qdev_prop_set_uint32(gicdev, "revision", 2); } -static int a15mp_priv_init(SysBusDevice *dev) +static void a15mp_priv_realize(DeviceState *dev, Error **errp) { + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); A15MPPrivState *s = A15MPCORE_PRIV(dev); DeviceState *gicdev; SysBusDevice *busdev; int i; + Error *err = NULL; gicdev = DEVICE(&s->gic); qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu); qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq); - qdev_init_nofail(gicdev); + object_property_set_bool(OBJECT(&s->gic), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } busdev = SYS_BUS_DEVICE(&s->gic); /* Pass through outbound IRQ lines from the GIC */ - sysbus_pass_irq(dev, busdev); + sysbus_pass_irq(sbd, busdev); /* Pass through inbound GPIO lines to the GIC */ - qdev_init_gpio_in(DEVICE(dev), a15mp_priv_set_irq, s->num_irq - 32); + qdev_init_gpio_in(dev, a15mp_priv_set_irq, s->num_irq - 32); /* Wire the outputs from each CPU's generic timer to the * appropriate GIC PPI inputs @@ -114,8 +120,6 @@ static int a15mp_priv_init(SysBusDevice *dev) sysbus_mmio_get_region(busdev, 0)); memory_region_add_subregion(&s->container, 0x2000, sysbus_mmio_get_region(busdev, 1)); - - return 0; } static Property a15mp_priv_properties[] = { @@ -133,8 +137,8 @@ static Property a15mp_priv_properties[] = { static void a15mp_priv_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = a15mp_priv_init; + + dc->realize = a15mp_priv_realize; dc->props = a15mp_priv_properties; /* We currently have no savable state */ } From 43482f72dbe48448442c3b27f0a26b16d49e8f97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 30 Jun 2013 21:31:01 +0200 Subject: [PATCH 31/54] a15mpcore: Prepare for QOM embedding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Peter Maydell Signed-off-by: Andreas Färber --- hw/cpu/a15mpcore.c | 21 +----------------- include/hw/cpu/a15mpcore.h | 44 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 20 deletions(-) create mode 100644 include/hw/cpu/a15mpcore.h diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c index 10dc35af5b..acc419e11a 100644 --- a/hw/cpu/a15mpcore.c +++ b/hw/cpu/a15mpcore.c @@ -18,27 +18,8 @@ * with this program; if not, see . */ -#include "hw/sysbus.h" +#include "hw/cpu/a15mpcore.h" #include "sysemu/kvm.h" -#include "hw/intc/arm_gic.h" - -/* A15MP private memory region. */ - -#define TYPE_A15MPCORE_PRIV "a15mpcore_priv" -#define A15MPCORE_PRIV(obj) \ - OBJECT_CHECK(A15MPPrivState, (obj), TYPE_A15MPCORE_PRIV) - -typedef struct A15MPPrivState { - /*< private >*/ - SysBusDevice parent_obj; - /*< public >*/ - - uint32_t num_cpu; - uint32_t num_irq; - MemoryRegion container; - - GICState gic; -} A15MPPrivState; static void a15mp_priv_set_irq(void *opaque, int irq, int level) { diff --git a/include/hw/cpu/a15mpcore.h b/include/hw/cpu/a15mpcore.h new file mode 100644 index 0000000000..b423533d20 --- /dev/null +++ b/include/hw/cpu/a15mpcore.h @@ -0,0 +1,44 @@ +/* + * Cortex-A15MPCore internal peripheral emulation. + * + * Copyright (c) 2012 Linaro Limited. + * Written by Peter Maydell. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ +#ifndef HW_CPU_A15MPCORE_H +#define HW_CPU_A15MPCORE_H + +#include "hw/sysbus.h" +#include "hw/intc/arm_gic.h" + +/* A15MP private memory region. */ + +#define TYPE_A15MPCORE_PRIV "a15mpcore_priv" +#define A15MPCORE_PRIV(obj) \ + OBJECT_CHECK(A15MPPrivState, (obj), TYPE_A15MPCORE_PRIV) + +typedef struct A15MPPrivState { + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + + uint32_t num_cpu; + uint32_t num_irq; + MemoryRegion container; + + GICState gic; +} A15MPPrivState; + +#endif From b4a37f17fef343f6400f0ccc1d1e037c6c430807 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 18 Aug 2013 21:00:29 +0200 Subject: [PATCH 32/54] a9scu: Build only once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It does not have a target or ARMCPU dependency. Reviewed-by: Peter Maydell Signed-off-by: Andreas Färber --- hw/misc/Makefile.objs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index cca5c058cc..0a36c97243 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -11,6 +11,7 @@ obj-$(CONFIG_VMPORT) += vmport.o # ARM devices common-obj-$(CONFIG_PL310) += arm_l2x0.o common-obj-$(CONFIG_INTEGRATOR_DEBUG) += arm_integrator_debug.o +common-obj-$(CONFIG_A9SCU) += a9scu.o # PKUnity SoC devices common-obj-$(CONFIG_PUV3) += puv3_pm.o @@ -23,7 +24,6 @@ obj-$(CONFIG_LINUX) += vfio.o endif obj-$(CONFIG_REALVIEW) += arm_sysctl.o -obj-$(CONFIG_A9SCU) += a9scu.o obj-$(CONFIG_NSERIES) += cbus.o obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o From 4c14253c9e889ab1cbd6126eed883682c1cd2718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 18 Aug 2013 20:36:33 +0200 Subject: [PATCH 33/54] arm11mpcore: Fix typo in MemoryRegion name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "mpcode" -> "mpcore" Reviewed-by: Peter Maydell Signed-off-by: Andreas Färber --- hw/cpu/arm11mpcore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/cpu/arm11mpcore.c b/hw/cpu/arm11mpcore.c index a786c628dd..27cd32b51a 100644 --- a/hw/cpu/arm11mpcore.c +++ b/hw/cpu/arm11mpcore.c @@ -93,7 +93,7 @@ static void mpcore_priv_map_setup(ARM11MPCorePriveState *s) SysBusDevice *timerbusdev = SYS_BUS_DEVICE(s->mptimer); SysBusDevice *wdtbusdev = SYS_BUS_DEVICE(s->wdtimer); memory_region_init(&s->container, OBJECT(s), - "mpcode-priv-container", 0x2000); + "mpcore-priv-container", 0x2000); memory_region_init_io(&s->iomem, OBJECT(s), &mpcore_scu_ops, s, "mpcore-scu", 0x100); memory_region_add_subregion(&s->container, 0, &s->iomem); From 21ebaf1d812471e3379c85ffb8b0cc2311d5bff0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 18 Aug 2013 22:08:59 +0200 Subject: [PATCH 34/54] arm11mpcore: Drop unused fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Peter Maydell Signed-off-by: Andreas Färber --- hw/cpu/arm11mpcore.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/cpu/arm11mpcore.c b/hw/cpu/arm11mpcore.c index 27cd32b51a..8719634e2a 100644 --- a/hw/cpu/arm11mpcore.c +++ b/hw/cpu/arm11mpcore.c @@ -20,8 +20,6 @@ typedef struct ARM11MPCorePriveState { SysBusDevice parent_obj; uint32_t scu_control; - int iomemtype; - uint32_t old_timer_status[8]; uint32_t num_cpu; MemoryRegion iomem; MemoryRegion container; From 2c42c3a063c2a8dda74b613bfab021b86ebc7ee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 18 Aug 2013 20:48:33 +0200 Subject: [PATCH 35/54] arm11mpcore: Create container MemoryRegion in instance_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows to map the region directly after object initialization. Reviewed-by: Peter Maydell Signed-off-by: Andreas Färber --- hw/cpu/arm11mpcore.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/hw/cpu/arm11mpcore.c b/hw/cpu/arm11mpcore.c index 8719634e2a..5f80e7bc81 100644 --- a/hw/cpu/arm11mpcore.c +++ b/hw/cpu/arm11mpcore.c @@ -90,8 +90,6 @@ static void mpcore_priv_map_setup(ARM11MPCorePriveState *s) SysBusDevice *gicbusdev = SYS_BUS_DEVICE(s->gic); SysBusDevice *timerbusdev = SYS_BUS_DEVICE(s->mptimer); SysBusDevice *wdtbusdev = SYS_BUS_DEVICE(s->wdtimer); - memory_region_init(&s->container, OBJECT(s), - "mpcore-priv-container", 0x2000); memory_region_init_io(&s->iomem, OBJECT(s), &mpcore_scu_ops, s, "mpcore-scu", 0x100); memory_region_add_subregion(&s->container, 0, &s->iomem); @@ -155,10 +153,19 @@ static int mpcore_priv_init(SysBusDevice *sbd) qdev_init_nofail(s->wdtimer); mpcore_priv_map_setup(s); - sysbus_init_mmio(sbd, &s->container); return 0; } +static void mpcore_priv_initfn(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + ARM11MPCorePriveState *s = ARM11MPCORE_PRIV(obj); + + memory_region_init(&s->container, OBJECT(s), + "mpcore-priv-container", 0x2000); + sysbus_init_mmio(sbd, &s->container); +} + #define TYPE_REALVIEW_MPCORE_RIRQ "realview_mpcore" #define REALVIEW_MPCORE_RIRQ(obj) \ OBJECT_CHECK(mpcore_rirq_state, (obj), TYPE_REALVIEW_MPCORE_RIRQ) @@ -277,6 +284,7 @@ static const TypeInfo mpcore_priv_info = { .name = TYPE_ARM11MPCORE_PRIV, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(ARM11MPCorePriveState), + .instance_init = mpcore_priv_initfn, .class_init = mpcore_priv_class_init, }; From 53cb9a1c2ffa78f5b5f6e4084dc03b98558cea4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 18 Aug 2013 20:07:36 +0200 Subject: [PATCH 36/54] arm11mpcore: Split off SCU device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Inspired by a9scu. Reviewed-by: Peter Maydell Signed-off-by: Andreas Färber --- default-configs/arm-softmmu.mak | 1 + hw/cpu/arm11mpcore.c | 65 +++++---------------- hw/misc/Makefile.objs | 1 + hw/misc/arm11scu.c | 100 ++++++++++++++++++++++++++++++++ include/hw/misc/arm11scu.h | 29 +++++++++ 5 files changed, 145 insertions(+), 51 deletions(-) create mode 100644 hw/misc/arm11scu.c create mode 100644 include/hw/misc/arm11scu.h diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak index 7e6913782e..a555eefed5 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -61,6 +61,7 @@ CONFIG_BITBANG_I2C=y CONFIG_FRAMEBUFFER=y CONFIG_XILINX_SPIPS=y +CONFIG_ARM11SCU=y CONFIG_A9SCU=y CONFIG_MARVELL_88W8618=y CONFIG_OMAP=y diff --git a/hw/cpu/arm11mpcore.c b/hw/cpu/arm11mpcore.c index 5f80e7bc81..5dcc73a142 100644 --- a/hw/cpu/arm11mpcore.c +++ b/hw/cpu/arm11mpcore.c @@ -8,6 +8,7 @@ */ #include "hw/sysbus.h" +#include "hw/misc/arm11scu.h" #include "qemu/timer.h" /* MPCore private memory region. */ @@ -19,64 +20,18 @@ typedef struct ARM11MPCorePriveState { SysBusDevice parent_obj; - uint32_t scu_control; uint32_t num_cpu; - MemoryRegion iomem; MemoryRegion container; DeviceState *mptimer; DeviceState *wdtimer; DeviceState *gic; uint32_t num_irq; + + ARM11SCUState scu; } ARM11MPCorePriveState; /* Per-CPU private memory mapped IO. */ -static uint64_t mpcore_scu_read(void *opaque, hwaddr offset, - unsigned size) -{ - ARM11MPCorePriveState *s = (ARM11MPCorePriveState *)opaque; - int id; - /* SCU */ - switch (offset) { - case 0x00: /* Control. */ - return s->scu_control; - case 0x04: /* Configuration. */ - id = ((1 << s->num_cpu) - 1) << 4; - return id | (s->num_cpu - 1); - case 0x08: /* CPU status. */ - return 0; - case 0x0c: /* Invalidate all. */ - return 0; - default: - qemu_log_mask(LOG_GUEST_ERROR, - "mpcore_priv_read: Bad offset %x\n", (int)offset); - return 0; - } -} - -static void mpcore_scu_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) -{ - ARM11MPCorePriveState *s = (ARM11MPCorePriveState *)opaque; - /* SCU */ - switch (offset) { - case 0: /* Control register. */ - s->scu_control = value & 1; - break; - case 0x0c: /* Invalidate all. */ - /* This is a no-op as cache is not emulated. */ - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, - "mpcore_priv_read: Bad offset %x\n", (int)offset); - } -} - -static const MemoryRegionOps mpcore_scu_ops = { - .read = mpcore_scu_read, - .write = mpcore_scu_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; static void mpcore_priv_set_irq(void *opaque, int irq, int level) { @@ -87,12 +42,13 @@ static void mpcore_priv_set_irq(void *opaque, int irq, int level) static void mpcore_priv_map_setup(ARM11MPCorePriveState *s) { int i; + SysBusDevice *scubusdev = SYS_BUS_DEVICE(&s->scu); SysBusDevice *gicbusdev = SYS_BUS_DEVICE(s->gic); SysBusDevice *timerbusdev = SYS_BUS_DEVICE(s->mptimer); SysBusDevice *wdtbusdev = SYS_BUS_DEVICE(s->wdtimer); - memory_region_init_io(&s->iomem, OBJECT(s), - &mpcore_scu_ops, s, "mpcore-scu", 0x100); - memory_region_add_subregion(&s->container, 0, &s->iomem); + + memory_region_add_subregion(&s->container, 0, + sysbus_mmio_get_region(scubusdev, 0)); /* GIC CPU interfaces: "current CPU" at 0x100, then specific CPUs * at 0x200, 0x300... */ @@ -130,6 +86,10 @@ static int mpcore_priv_init(SysBusDevice *sbd) { DeviceState *dev = DEVICE(sbd); ARM11MPCorePriveState *s = ARM11MPCORE_PRIV(dev); + DeviceState *scudev = DEVICE(&s->scu); + + qdev_prop_set_uint32(scudev, "num-cpu", s->num_cpu); + qdev_init_nofail(scudev); s->gic = qdev_create(NULL, "arm_gic"); qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu); @@ -164,6 +124,9 @@ static void mpcore_priv_initfn(Object *obj) memory_region_init(&s->container, OBJECT(s), "mpcore-priv-container", 0x2000); sysbus_init_mmio(sbd, &s->container); + + object_initialize(&s->scu, sizeof(s->scu), TYPE_ARM11_SCU); + qdev_set_parent_bus(DEVICE(&s->scu), sysbus_get_default()); } #define TYPE_REALVIEW_MPCORE_RIRQ "realview_mpcore" diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index 0a36c97243..9fbcebd15b 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -12,6 +12,7 @@ obj-$(CONFIG_VMPORT) += vmport.o common-obj-$(CONFIG_PL310) += arm_l2x0.o common-obj-$(CONFIG_INTEGRATOR_DEBUG) += arm_integrator_debug.o common-obj-$(CONFIG_A9SCU) += a9scu.o +common-obj-$(CONFIG_ARM11SCU) += arm11scu.o # PKUnity SoC devices common-obj-$(CONFIG_PUV3) += puv3_pm.o diff --git a/hw/misc/arm11scu.c b/hw/misc/arm11scu.c new file mode 100644 index 0000000000..a791675443 --- /dev/null +++ b/hw/misc/arm11scu.c @@ -0,0 +1,100 @@ +/* + * ARM11MPCore Snoop Control Unit (SCU) emulation + * + * Copyright (c) 2006-2007 CodeSourcery. + * Copyright (c) 2013 SUSE LINUX Products GmbH + * Written by Paul Brook and Andreas Färber + * + * This code is licensed under the GPL. + */ + +#include "hw/misc/arm11scu.h" + +static uint64_t mpcore_scu_read(void *opaque, hwaddr offset, + unsigned size) +{ + ARM11SCUState *s = (ARM11SCUState *)opaque; + int id; + /* SCU */ + switch (offset) { + case 0x00: /* Control. */ + return s->control; + case 0x04: /* Configuration. */ + id = ((1 << s->num_cpu) - 1) << 4; + return id | (s->num_cpu - 1); + case 0x08: /* CPU status. */ + return 0; + case 0x0c: /* Invalidate all. */ + return 0; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "mpcore_priv_read: Bad offset %x\n", (int)offset); + return 0; + } +} + +static void mpcore_scu_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + ARM11SCUState *s = (ARM11SCUState *)opaque; + /* SCU */ + switch (offset) { + case 0: /* Control register. */ + s->control = value & 1; + break; + case 0x0c: /* Invalidate all. */ + /* This is a no-op as cache is not emulated. */ + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "mpcore_priv_read: Bad offset %x\n", (int)offset); + } +} + +static const MemoryRegionOps mpcore_scu_ops = { + .read = mpcore_scu_read, + .write = mpcore_scu_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void arm11_scu_realize(DeviceState *dev, Error **errp) +{ +} + +static void arm11_scu_init(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + ARM11SCUState *s = ARM11_SCU(obj); + + memory_region_init_io(&s->iomem, OBJECT(s), + &mpcore_scu_ops, s, "mpcore-scu", 0x100); + sysbus_init_mmio(sbd, &s->iomem); +} + +static Property arm11_scu_properties[] = { + DEFINE_PROP_UINT32("num-cpu", ARM11SCUState, num_cpu, 1), + DEFINE_PROP_END_OF_LIST() +}; + +static void arm11_scu_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = arm11_scu_realize; + dc->props = arm11_scu_properties; +} + +static const TypeInfo arm11_scu_type_info = { + .name = TYPE_ARM11_SCU, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(ARM11SCUState), + .instance_init = arm11_scu_init, + .class_init = arm11_scu_class_init, +}; + +static void arm11_scu_register_types(void) +{ + type_register_static(&arm11_scu_type_info); +} + +type_init(arm11_scu_register_types) diff --git a/include/hw/misc/arm11scu.h b/include/hw/misc/arm11scu.h new file mode 100644 index 0000000000..5ad0f3d339 --- /dev/null +++ b/include/hw/misc/arm11scu.h @@ -0,0 +1,29 @@ +/* + * ARM11MPCore Snoop Control Unit (SCU) emulation + * + * Copyright (c) 2006-2007 CodeSourcery. + * Copyright (c) 2013 SUSE LINUX Products GmbH + * Written by Paul Brook and Andreas Färber + * + * This code is licensed under the GPL. + */ + +#ifndef HW_MISC_ARM11SCU_H +#define HW_MISC_ARM11SCU_H + +#include "hw/sysbus.h" + +#define TYPE_ARM11_SCU "arm11-scu" +#define ARM11_SCU(obj) OBJECT_CHECK(ARM11SCUState, (obj), TYPE_ARM11_SCU) + +typedef struct ARM11SCUState { + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + + uint32_t control; + uint32_t num_cpu; + MemoryRegion iomem; +} ARM11SCUState; + +#endif From 08602ac5bf4f024d7e979de3a4e5df87db01b0ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 18 Aug 2013 22:04:31 +0200 Subject: [PATCH 37/54] arm11mpcore: Convert ARM11MPCorePriveState to QOM realize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Embed child devices and replace SysBus initfn with realizefn. Reviewed-by: Peter Maydell Signed-off-by: Andreas Färber --- hw/cpu/arm11mpcore.c | 84 +++++++++++++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 28 deletions(-) diff --git a/hw/cpu/arm11mpcore.c b/hw/cpu/arm11mpcore.c index 5dcc73a142..f372283de9 100644 --- a/hw/cpu/arm11mpcore.c +++ b/hw/cpu/arm11mpcore.c @@ -9,6 +9,8 @@ #include "hw/sysbus.h" #include "hw/misc/arm11scu.h" +#include "hw/intc/arm_gic.h" +#include "hw/timer/arm_mptimer.h" #include "qemu/timer.h" /* MPCore private memory region. */ @@ -22,12 +24,12 @@ typedef struct ARM11MPCorePriveState { uint32_t num_cpu; MemoryRegion container; - DeviceState *mptimer; - DeviceState *wdtimer; - DeviceState *gic; uint32_t num_irq; ARM11SCUState scu; + GICState gic; + ARMMPTimerState mptimer; + ARMMPTimerState wdtimer; } ARM11MPCorePriveState; /* Per-CPU private memory mapped IO. */ @@ -36,16 +38,18 @@ typedef struct ARM11MPCorePriveState { static void mpcore_priv_set_irq(void *opaque, int irq, int level) { ARM11MPCorePriveState *s = (ARM11MPCorePriveState *)opaque; - qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level); + + qemu_set_irq(qdev_get_gpio_in(DEVICE(&s->gic), irq), level); } static void mpcore_priv_map_setup(ARM11MPCorePriveState *s) { int i; SysBusDevice *scubusdev = SYS_BUS_DEVICE(&s->scu); - SysBusDevice *gicbusdev = SYS_BUS_DEVICE(s->gic); - SysBusDevice *timerbusdev = SYS_BUS_DEVICE(s->mptimer); - SysBusDevice *wdtbusdev = SYS_BUS_DEVICE(s->wdtimer); + DeviceState *gicdev = DEVICE(&s->gic); + SysBusDevice *gicbusdev = SYS_BUS_DEVICE(&s->gic); + SysBusDevice *timerbusdev = SYS_BUS_DEVICE(&s->mptimer); + SysBusDevice *wdtbusdev = SYS_BUS_DEVICE(&s->wdtimer); memory_region_add_subregion(&s->container, 0, sysbus_mmio_get_region(scubusdev, 0)); @@ -76,44 +80,58 @@ static void mpcore_priv_map_setup(ARM11MPCorePriveState *s) for (i = 0; i < s->num_cpu; i++) { int ppibase = (s->num_irq - 32) + i * 32; sysbus_connect_irq(timerbusdev, i, - qdev_get_gpio_in(s->gic, ppibase + 29)); + qdev_get_gpio_in(gicdev, ppibase + 29)); sysbus_connect_irq(wdtbusdev, i, - qdev_get_gpio_in(s->gic, ppibase + 30)); + qdev_get_gpio_in(gicdev, ppibase + 30)); } } -static int mpcore_priv_init(SysBusDevice *sbd) +static void mpcore_priv_realize(DeviceState *dev, Error **errp) { - DeviceState *dev = DEVICE(sbd); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); ARM11MPCorePriveState *s = ARM11MPCORE_PRIV(dev); DeviceState *scudev = DEVICE(&s->scu); + DeviceState *gicdev = DEVICE(&s->gic); + DeviceState *mptimerdev = DEVICE(&s->mptimer); + DeviceState *wdtimerdev = DEVICE(&s->wdtimer); + Error *err = NULL; qdev_prop_set_uint32(scudev, "num-cpu", s->num_cpu); - qdev_init_nofail(scudev); + object_property_set_bool(OBJECT(&s->scu), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } - s->gic = qdev_create(NULL, "arm_gic"); - qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu); - qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq); - /* Request the legacy 11MPCore GIC behaviour: */ - qdev_prop_set_uint32(s->gic, "revision", 0); - qdev_init_nofail(s->gic); + qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu); + qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq); + object_property_set_bool(OBJECT(&s->gic), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } /* Pass through outbound IRQ lines from the GIC */ - sysbus_pass_irq(sbd, SYS_BUS_DEVICE(s->gic)); + sysbus_pass_irq(sbd, SYS_BUS_DEVICE(&s->gic)); /* Pass through inbound GPIO lines to the GIC */ qdev_init_gpio_in(dev, mpcore_priv_set_irq, s->num_irq - 32); - s->mptimer = qdev_create(NULL, "arm_mptimer"); - qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu); - qdev_init_nofail(s->mptimer); + qdev_prop_set_uint32(mptimerdev, "num-cpu", s->num_cpu); + object_property_set_bool(OBJECT(&s->mptimer), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } - s->wdtimer = qdev_create(NULL, "arm_mptimer"); - qdev_prop_set_uint32(s->wdtimer, "num-cpu", s->num_cpu); - qdev_init_nofail(s->wdtimer); + qdev_prop_set_uint32(wdtimerdev, "num-cpu", s->num_cpu); + object_property_set_bool(OBJECT(&s->wdtimer), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } mpcore_priv_map_setup(s); - return 0; } static void mpcore_priv_initfn(Object *obj) @@ -127,6 +145,17 @@ static void mpcore_priv_initfn(Object *obj) object_initialize(&s->scu, sizeof(s->scu), TYPE_ARM11_SCU); qdev_set_parent_bus(DEVICE(&s->scu), sysbus_get_default()); + + object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC); + qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default()); + /* Request the legacy 11MPCore GIC behaviour: */ + qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 0); + + object_initialize(&s->mptimer, sizeof(s->mptimer), TYPE_ARM_MPTIMER); + qdev_set_parent_bus(DEVICE(&s->mptimer), sysbus_get_default()); + + object_initialize(&s->wdtimer, sizeof(s->wdtimer), TYPE_ARM_MPTIMER); + qdev_set_parent_bus(DEVICE(&s->wdtimer), sysbus_get_default()); } #define TYPE_REALVIEW_MPCORE_RIRQ "realview_mpcore" @@ -237,9 +266,8 @@ static Property mpcore_priv_properties[] = { static void mpcore_priv_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = mpcore_priv_init; + dc->realize = mpcore_priv_realize; dc->props = mpcore_priv_properties; } From 612daf06283e2cf6b3aa6178826516512d219de0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 19 Aug 2013 00:37:07 +0200 Subject: [PATCH 38/54] realview_gic: Convert to QOM realize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Embed GICState and replace SysBus initfn with realizefn. Reviewed-by: Peter Maydell Signed-off-by: Andreas Färber --- hw/intc/realview_gic.c | 53 ++++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/hw/intc/realview_gic.c b/hw/intc/realview_gic.c index ce8044780a..4ff48bbab1 100644 --- a/hw/intc/realview_gic.c +++ b/hw/intc/realview_gic.c @@ -8,40 +8,46 @@ */ #include "hw/sysbus.h" +#include "hw/intc/arm_gic.h" #define TYPE_REALVIEW_GIC "realview_gic" #define REALVIEW_GIC(obj) \ OBJECT_CHECK(RealViewGICState, (obj), TYPE_REALVIEW_GIC) -typedef struct { +typedef struct RealViewGICState { SysBusDevice parent_obj; - DeviceState *gic; MemoryRegion container; + + GICState gic; } RealViewGICState; static void realview_gic_set_irq(void *opaque, int irq, int level) { RealViewGICState *s = (RealViewGICState *)opaque; - qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level); + + qemu_set_irq(qdev_get_gpio_in(DEVICE(&s->gic), irq), level); } -static int realview_gic_init(SysBusDevice *sbd) +static void realview_gic_realize(DeviceState *dev, Error **errp) { - DeviceState *dev = DEVICE(sbd); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); RealViewGICState *s = REALVIEW_GIC(dev); SysBusDevice *busdev; + Error *err = NULL; /* The GICs on the RealView boards have a fixed nonconfigurable * number of interrupt lines, so we don't need to expose this as * a qdev property. */ int numirq = 96; - s->gic = qdev_create(NULL, "arm_gic"); - qdev_prop_set_uint32(s->gic, "num-cpu", 1); - qdev_prop_set_uint32(s->gic, "num-irq", numirq); - qdev_init_nofail(s->gic); - busdev = SYS_BUS_DEVICE(s->gic); + qdev_prop_set_uint32(DEVICE(&s->gic), "num-irq", numirq); + object_property_set_bool(OBJECT(&s->gic), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + busdev = SYS_BUS_DEVICE(&s->gic); /* Pass through outbound IRQ lines from the GIC */ sysbus_pass_irq(sbd, busdev); @@ -49,27 +55,40 @@ static int realview_gic_init(SysBusDevice *sbd) /* Pass through inbound GPIO lines to the GIC */ qdev_init_gpio_in(dev, realview_gic_set_irq, numirq - 32); - memory_region_init(&s->container, OBJECT(s), - "realview-gic-container", 0x2000); memory_region_add_subregion(&s->container, 0, sysbus_mmio_get_region(busdev, 1)); memory_region_add_subregion(&s->container, 0x1000, sysbus_mmio_get_region(busdev, 0)); - sysbus_init_mmio(sbd, &s->container); - return 0; } -static void realview_gic_class_init(ObjectClass *klass, void *data) +static void realview_gic_init(Object *obj) { - SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + RealViewGICState *s = REALVIEW_GIC(obj); + DeviceState *gicdev; - sdc->init = realview_gic_init; + memory_region_init(&s->container, OBJECT(s), + "realview-gic-container", 0x2000); + sysbus_init_mmio(sbd, &s->container); + + object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC); + gicdev = DEVICE(&s->gic); + qdev_set_parent_bus(gicdev, sysbus_get_default()); + qdev_prop_set_uint32(gicdev, "num-cpu", 1); +} + +static void realview_gic_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = realview_gic_realize; } static const TypeInfo realview_gic_info = { .name = TYPE_REALVIEW_GIC, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(RealViewGICState), + .instance_init = realview_gic_init, .class_init = realview_gic_class_init, }; From ce31825de64c305cbf0def5657edac21aab7368b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 19 Aug 2013 00:48:55 +0200 Subject: [PATCH 39/54] realview_gic: Prepare for QOM embedding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move state struct, type constant and cast macro to a new header. Reviewed-by: Peter Maydell Signed-off-by: Andreas Färber --- hw/intc/realview_gic.c | 15 +-------------- include/hw/intc/realview_gic.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 14 deletions(-) create mode 100644 include/hw/intc/realview_gic.h diff --git a/hw/intc/realview_gic.c b/hw/intc/realview_gic.c index 4ff48bbab1..6c812961cc 100644 --- a/hw/intc/realview_gic.c +++ b/hw/intc/realview_gic.c @@ -7,20 +7,7 @@ * This code is licensed under the GPL. */ -#include "hw/sysbus.h" -#include "hw/intc/arm_gic.h" - -#define TYPE_REALVIEW_GIC "realview_gic" -#define REALVIEW_GIC(obj) \ - OBJECT_CHECK(RealViewGICState, (obj), TYPE_REALVIEW_GIC) - -typedef struct RealViewGICState { - SysBusDevice parent_obj; - - MemoryRegion container; - - GICState gic; -} RealViewGICState; +#include "hw/intc/realview_gic.h" static void realview_gic_set_irq(void *opaque, int irq, int level) { diff --git a/include/hw/intc/realview_gic.h b/include/hw/intc/realview_gic.h new file mode 100644 index 0000000000..1783ea11b9 --- /dev/null +++ b/include/hw/intc/realview_gic.h @@ -0,0 +1,28 @@ +/* + * ARM RealView Emulation Baseboard Interrupt Controller + * + * Copyright (c) 2006-2007 CodeSourcery. + * Written by Paul Brook + * + * This code is licensed under the GPL. + */ + +#ifndef HW_INTC_REALVIEW_GIC_H +#define HW_INTC_REALVIEW_GIC_H + +#include "hw/sysbus.h" +#include "hw/intc/arm_gic.h" + +#define TYPE_REALVIEW_GIC "realview_gic" +#define REALVIEW_GIC(obj) \ + OBJECT_CHECK(RealViewGICState, (obj), TYPE_REALVIEW_GIC) + +typedef struct RealViewGICState { + SysBusDevice parent_obj; + + MemoryRegion container; + + GICState gic; +} RealViewGICState; + +#endif From 306476eaec483afbbf7f31abeae97874e6d3d29c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 18 Aug 2013 23:38:15 +0200 Subject: [PATCH 40/54] arm11mpcore: Convert mpcore_rirq_state to QOM realize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Embed ARM11MPCorePriveState and RealViewGICState and replace SysBus initfn with realizefn. Reviewed-by: Peter Maydell Signed-off-by: Andreas Färber --- hw/cpu/arm11mpcore.c | 58 +++++++++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/hw/cpu/arm11mpcore.c b/hw/cpu/arm11mpcore.c index f372283de9..578e3d341e 100644 --- a/hw/cpu/arm11mpcore.c +++ b/hw/cpu/arm11mpcore.c @@ -10,6 +10,7 @@ #include "hw/sysbus.h" #include "hw/misc/arm11scu.h" #include "hw/intc/arm_gic.h" +#include "hw/intc/realview_gic.h" #include "hw/timer/arm_mptimer.h" #include "qemu/timer.h" @@ -168,10 +169,12 @@ static void mpcore_priv_initfn(Object *obj) typedef struct { SysBusDevice parent_obj; - SysBusDevice *priv; qemu_irq cpuic[32]; qemu_irq rvic[4][64]; uint32_t num_cpu; + + ARM11MPCorePriveState priv; + RealViewGICState gic[4]; } mpcore_rirq_state; /* Map baseboard IRQs onto CPU IRQ lines. */ @@ -198,34 +201,61 @@ static void mpcore_rirq_set_irq(void *opaque, int irq, int level) } } -static int realview_mpcore_init(SysBusDevice *sbd) +static void realview_mpcore_realize(DeviceState *dev, Error **errp) { - DeviceState *dev = DEVICE(sbd); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); mpcore_rirq_state *s = REALVIEW_MPCORE_RIRQ(dev); + DeviceState *priv = DEVICE(&s->priv); DeviceState *gic; - DeviceState *priv; + SysBusDevice *gicbusdev; + Error *err = NULL; int n; int i; - priv = qdev_create(NULL, TYPE_ARM11MPCORE_PRIV); qdev_prop_set_uint32(priv, "num-cpu", s->num_cpu); - qdev_init_nofail(priv); - s->priv = SYS_BUS_DEVICE(priv); - sysbus_pass_irq(sbd, s->priv); + object_property_set_bool(OBJECT(&s->priv), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + sysbus_pass_irq(sbd, SYS_BUS_DEVICE(&s->priv)); for (i = 0; i < 32; i++) { s->cpuic[i] = qdev_get_gpio_in(priv, i); } /* ??? IRQ routing is hardcoded to "normal" mode. */ for (n = 0; n < 4; n++) { - gic = sysbus_create_simple("realview_gic", 0x10040000 + n * 0x10000, - s->cpuic[10 + n]); + object_property_set_bool(OBJECT(&s->gic[n]), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + gic = DEVICE(&s->gic[n]); + gicbusdev = SYS_BUS_DEVICE(&s->gic[n]); + sysbus_mmio_map(gicbusdev, 0, 0x10040000 + n * 0x10000); + sysbus_connect_irq(gicbusdev, 0, s->cpuic[10 + n]); for (i = 0; i < 64; i++) { s->rvic[n][i] = qdev_get_gpio_in(gic, i); } } qdev_init_gpio_in(dev, mpcore_rirq_set_irq, 64); - sysbus_init_mmio(sbd, sysbus_mmio_get_region(s->priv, 0)); - return 0; +} + +static void mpcore_rirq_init(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + mpcore_rirq_state *s = REALVIEW_MPCORE_RIRQ(obj); + SysBusDevice *privbusdev; + int i; + + object_initialize(&s->priv, sizeof(s->priv), TYPE_ARM11MPCORE_PRIV); + qdev_set_parent_bus(DEVICE(&s->priv), sysbus_get_default()); + privbusdev = SYS_BUS_DEVICE(&s->priv); + sysbus_init_mmio(sbd, sysbus_mmio_get_region(privbusdev, 0)); + + for (i = 0; i < 4; i++) { + object_initialize(&s->gic[i], sizeof(s->gic[i]), TYPE_REALVIEW_GIC); + qdev_set_parent_bus(DEVICE(&s->gic[i]), sysbus_get_default()); + } } static Property mpcore_rirq_properties[] = { @@ -236,9 +266,8 @@ static Property mpcore_rirq_properties[] = { static void mpcore_rirq_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = realview_mpcore_init; + dc->realize = realview_mpcore_realize; dc->props = mpcore_rirq_properties; } @@ -246,6 +275,7 @@ static const TypeInfo mpcore_rirq_info = { .name = TYPE_REALVIEW_MPCORE_RIRQ, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(mpcore_rirq_state), + .instance_init = mpcore_rirq_init, .class_init = mpcore_rirq_class_init, }; From 7b960dc37df088f9ca71bdc2a611864eae38c5c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 19 Aug 2013 01:27:19 +0200 Subject: [PATCH 41/54] arm11mpcore: Prepare for QOM embedding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move state struct, type constant and cast macro to a new header. Reviewed-by: Peter Maydell Signed-off-by: Andreas Färber --- hw/cpu/arm11mpcore.c | 27 +-------------------------- include/hw/cpu/arm11mpcore.h | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 26 deletions(-) create mode 100644 include/hw/cpu/arm11mpcore.h diff --git a/hw/cpu/arm11mpcore.c b/hw/cpu/arm11mpcore.c index 578e3d341e..0ec27c7ecf 100644 --- a/hw/cpu/arm11mpcore.c +++ b/hw/cpu/arm11mpcore.c @@ -7,33 +7,8 @@ * This code is licensed under the GPL. */ -#include "hw/sysbus.h" -#include "hw/misc/arm11scu.h" -#include "hw/intc/arm_gic.h" +#include "hw/cpu/arm11mpcore.h" #include "hw/intc/realview_gic.h" -#include "hw/timer/arm_mptimer.h" -#include "qemu/timer.h" - -/* MPCore private memory region. */ - -#define TYPE_ARM11MPCORE_PRIV "arm11mpcore_priv" -#define ARM11MPCORE_PRIV(obj) \ - OBJECT_CHECK(ARM11MPCorePriveState, (obj), TYPE_ARM11MPCORE_PRIV) - -typedef struct ARM11MPCorePriveState { - SysBusDevice parent_obj; - - uint32_t num_cpu; - MemoryRegion container; - uint32_t num_irq; - - ARM11SCUState scu; - GICState gic; - ARMMPTimerState mptimer; - ARMMPTimerState wdtimer; -} ARM11MPCorePriveState; - -/* Per-CPU private memory mapped IO. */ static void mpcore_priv_set_irq(void *opaque, int irq, int level) diff --git a/include/hw/cpu/arm11mpcore.h b/include/hw/cpu/arm11mpcore.h new file mode 100644 index 0000000000..6196109ca2 --- /dev/null +++ b/include/hw/cpu/arm11mpcore.h @@ -0,0 +1,35 @@ +/* + * ARM11MPCore internal peripheral emulation. + * + * Copyright (c) 2006-2007 CodeSourcery. + * Written by Paul Brook + * + * This code is licensed under the GPL. + */ + +#ifndef HW_CPU_ARM11MPCORE_H +#define HW_CPU_ARM11MPCORE_H + +#include "hw/sysbus.h" +#include "hw/misc/arm11scu.h" +#include "hw/intc/arm_gic.h" +#include "hw/timer/arm_mptimer.h" + +#define TYPE_ARM11MPCORE_PRIV "arm11mpcore_priv" +#define ARM11MPCORE_PRIV(obj) \ + OBJECT_CHECK(ARM11MPCorePriveState, (obj), TYPE_ARM11MPCORE_PRIV) + +typedef struct ARM11MPCorePriveState { + SysBusDevice parent_obj; + + uint32_t num_cpu; + MemoryRegion container; + uint32_t num_irq; + + ARM11SCUState scu; + GICState gic; + ARMMPTimerState mptimer; + ARMMPTimerState wdtimer; +} ARM11MPCorePriveState; + +#endif From 9c219b7be6eeaf31dccaf9b74d738e0ce2ea813b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 19 Aug 2013 01:33:59 +0200 Subject: [PATCH 42/54] arm11mpcore: Split off RealView MPCore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Peter Maydell Signed-off-by: Andreas Färber --- hw/cpu/Makefile.objs | 1 + hw/cpu/arm11mpcore.c | 121 ---------------------------------- hw/cpu/realview_mpcore.c | 139 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+), 121 deletions(-) create mode 100644 hw/cpu/realview_mpcore.c diff --git a/hw/cpu/Makefile.objs b/hw/cpu/Makefile.objs index df287c1d8c..6381238cc5 100644 --- a/hw/cpu/Makefile.objs +++ b/hw/cpu/Makefile.objs @@ -1,4 +1,5 @@ obj-$(CONFIG_ARM11MPCORE) += arm11mpcore.o +obj-$(CONFIG_REALVIEW) += realview_mpcore.o obj-$(CONFIG_A9MPCORE) += a9mpcore.o obj-$(CONFIG_A15MPCORE) += a15mpcore.o obj-$(CONFIG_ICC_BUS) += icc_bus.o diff --git a/hw/cpu/arm11mpcore.c b/hw/cpu/arm11mpcore.c index 0ec27c7ecf..717d3e4f88 100644 --- a/hw/cpu/arm11mpcore.c +++ b/hw/cpu/arm11mpcore.c @@ -134,126 +134,6 @@ static void mpcore_priv_initfn(Object *obj) qdev_set_parent_bus(DEVICE(&s->wdtimer), sysbus_get_default()); } -#define TYPE_REALVIEW_MPCORE_RIRQ "realview_mpcore" -#define REALVIEW_MPCORE_RIRQ(obj) \ - OBJECT_CHECK(mpcore_rirq_state, (obj), TYPE_REALVIEW_MPCORE_RIRQ) - -/* Dummy PIC to route IRQ lines. The baseboard has 4 independent IRQ - controllers. The output of these, plus some of the raw input lines - are fed into a single SMP-aware interrupt controller on the CPU. */ -typedef struct { - SysBusDevice parent_obj; - - qemu_irq cpuic[32]; - qemu_irq rvic[4][64]; - uint32_t num_cpu; - - ARM11MPCorePriveState priv; - RealViewGICState gic[4]; -} mpcore_rirq_state; - -/* Map baseboard IRQs onto CPU IRQ lines. */ -static const int mpcore_irq_map[32] = { - -1, -1, -1, -1, 1, 2, -1, -1, - -1, -1, 6, -1, 4, 5, -1, -1, - -1, 14, 15, 0, 7, 8, -1, -1, - -1, -1, -1, -1, 9, 3, -1, -1, -}; - -static void mpcore_rirq_set_irq(void *opaque, int irq, int level) -{ - mpcore_rirq_state *s = (mpcore_rirq_state *)opaque; - int i; - - for (i = 0; i < 4; i++) { - qemu_set_irq(s->rvic[i][irq], level); - } - if (irq < 32) { - irq = mpcore_irq_map[irq]; - if (irq >= 0) { - qemu_set_irq(s->cpuic[irq], level); - } - } -} - -static void realview_mpcore_realize(DeviceState *dev, Error **errp) -{ - SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - mpcore_rirq_state *s = REALVIEW_MPCORE_RIRQ(dev); - DeviceState *priv = DEVICE(&s->priv); - DeviceState *gic; - SysBusDevice *gicbusdev; - Error *err = NULL; - int n; - int i; - - qdev_prop_set_uint32(priv, "num-cpu", s->num_cpu); - object_property_set_bool(OBJECT(&s->priv), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); - return; - } - sysbus_pass_irq(sbd, SYS_BUS_DEVICE(&s->priv)); - for (i = 0; i < 32; i++) { - s->cpuic[i] = qdev_get_gpio_in(priv, i); - } - /* ??? IRQ routing is hardcoded to "normal" mode. */ - for (n = 0; n < 4; n++) { - object_property_set_bool(OBJECT(&s->gic[n]), true, "realized", &err); - if (err != NULL) { - error_propagate(errp, err); - return; - } - gic = DEVICE(&s->gic[n]); - gicbusdev = SYS_BUS_DEVICE(&s->gic[n]); - sysbus_mmio_map(gicbusdev, 0, 0x10040000 + n * 0x10000); - sysbus_connect_irq(gicbusdev, 0, s->cpuic[10 + n]); - for (i = 0; i < 64; i++) { - s->rvic[n][i] = qdev_get_gpio_in(gic, i); - } - } - qdev_init_gpio_in(dev, mpcore_rirq_set_irq, 64); -} - -static void mpcore_rirq_init(Object *obj) -{ - SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - mpcore_rirq_state *s = REALVIEW_MPCORE_RIRQ(obj); - SysBusDevice *privbusdev; - int i; - - object_initialize(&s->priv, sizeof(s->priv), TYPE_ARM11MPCORE_PRIV); - qdev_set_parent_bus(DEVICE(&s->priv), sysbus_get_default()); - privbusdev = SYS_BUS_DEVICE(&s->priv); - sysbus_init_mmio(sbd, sysbus_mmio_get_region(privbusdev, 0)); - - for (i = 0; i < 4; i++) { - object_initialize(&s->gic[i], sizeof(s->gic[i]), TYPE_REALVIEW_GIC); - qdev_set_parent_bus(DEVICE(&s->gic[i]), sysbus_get_default()); - } -} - -static Property mpcore_rirq_properties[] = { - DEFINE_PROP_UINT32("num-cpu", mpcore_rirq_state, num_cpu, 1), - DEFINE_PROP_END_OF_LIST(), -}; - -static void mpcore_rirq_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = realview_mpcore_realize; - dc->props = mpcore_rirq_properties; -} - -static const TypeInfo mpcore_rirq_info = { - .name = TYPE_REALVIEW_MPCORE_RIRQ, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(mpcore_rirq_state), - .instance_init = mpcore_rirq_init, - .class_init = mpcore_rirq_class_init, -}; - static Property mpcore_priv_properties[] = { DEFINE_PROP_UINT32("num-cpu", ARM11MPCorePriveState, num_cpu, 1), /* The ARM11 MPCORE TRM says the on-chip controller may have @@ -286,7 +166,6 @@ static const TypeInfo mpcore_priv_info = { static void arm11mpcore_register_types(void) { - type_register_static(&mpcore_rirq_info); type_register_static(&mpcore_priv_info); } diff --git a/hw/cpu/realview_mpcore.c b/hw/cpu/realview_mpcore.c new file mode 100644 index 0000000000..c39a2da42d --- /dev/null +++ b/hw/cpu/realview_mpcore.c @@ -0,0 +1,139 @@ +/* + * RealView ARM11MPCore internal peripheral emulation + * + * Copyright (c) 2006-2007 CodeSourcery. + * Copyright (c) 2013 SUSE LINUX Products GmbH + * Written by Paul Brook and Andreas Färber + * + * This code is licensed under the GPL. + */ + +#include "hw/cpu/arm11mpcore.h" +#include "hw/intc/realview_gic.h" + +#define TYPE_REALVIEW_MPCORE_RIRQ "realview_mpcore" +#define REALVIEW_MPCORE_RIRQ(obj) \ + OBJECT_CHECK(mpcore_rirq_state, (obj), TYPE_REALVIEW_MPCORE_RIRQ) + +/* Dummy PIC to route IRQ lines. The baseboard has 4 independent IRQ + controllers. The output of these, plus some of the raw input lines + are fed into a single SMP-aware interrupt controller on the CPU. */ +typedef struct { + SysBusDevice parent_obj; + + qemu_irq cpuic[32]; + qemu_irq rvic[4][64]; + uint32_t num_cpu; + + ARM11MPCorePriveState priv; + RealViewGICState gic[4]; +} mpcore_rirq_state; + +/* Map baseboard IRQs onto CPU IRQ lines. */ +static const int mpcore_irq_map[32] = { + -1, -1, -1, -1, 1, 2, -1, -1, + -1, -1, 6, -1, 4, 5, -1, -1, + -1, 14, 15, 0, 7, 8, -1, -1, + -1, -1, -1, -1, 9, 3, -1, -1, +}; + +static void mpcore_rirq_set_irq(void *opaque, int irq, int level) +{ + mpcore_rirq_state *s = (mpcore_rirq_state *)opaque; + int i; + + for (i = 0; i < 4; i++) { + qemu_set_irq(s->rvic[i][irq], level); + } + if (irq < 32) { + irq = mpcore_irq_map[irq]; + if (irq >= 0) { + qemu_set_irq(s->cpuic[irq], level); + } + } +} + +static void realview_mpcore_realize(DeviceState *dev, Error **errp) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + mpcore_rirq_state *s = REALVIEW_MPCORE_RIRQ(dev); + DeviceState *priv = DEVICE(&s->priv); + DeviceState *gic; + SysBusDevice *gicbusdev; + Error *err = NULL; + int n; + int i; + + qdev_prop_set_uint32(priv, "num-cpu", s->num_cpu); + object_property_set_bool(OBJECT(&s->priv), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + sysbus_pass_irq(sbd, SYS_BUS_DEVICE(&s->priv)); + for (i = 0; i < 32; i++) { + s->cpuic[i] = qdev_get_gpio_in(priv, i); + } + /* ??? IRQ routing is hardcoded to "normal" mode. */ + for (n = 0; n < 4; n++) { + object_property_set_bool(OBJECT(&s->gic[n]), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + gic = DEVICE(&s->gic[n]); + gicbusdev = SYS_BUS_DEVICE(&s->gic[n]); + sysbus_mmio_map(gicbusdev, 0, 0x10040000 + n * 0x10000); + sysbus_connect_irq(gicbusdev, 0, s->cpuic[10 + n]); + for (i = 0; i < 64; i++) { + s->rvic[n][i] = qdev_get_gpio_in(gic, i); + } + } + qdev_init_gpio_in(dev, mpcore_rirq_set_irq, 64); +} + +static void mpcore_rirq_init(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + mpcore_rirq_state *s = REALVIEW_MPCORE_RIRQ(obj); + SysBusDevice *privbusdev; + int i; + + object_initialize(&s->priv, sizeof(s->priv), TYPE_ARM11MPCORE_PRIV); + qdev_set_parent_bus(DEVICE(&s->priv), sysbus_get_default()); + privbusdev = SYS_BUS_DEVICE(&s->priv); + sysbus_init_mmio(sbd, sysbus_mmio_get_region(privbusdev, 0)); + + for (i = 0; i < 4; i++) { + object_initialize(&s->gic[i], sizeof(s->gic[i]), TYPE_REALVIEW_GIC); + qdev_set_parent_bus(DEVICE(&s->gic[i]), sysbus_get_default()); + } +} + +static Property mpcore_rirq_properties[] = { + DEFINE_PROP_UINT32("num-cpu", mpcore_rirq_state, num_cpu, 1), + DEFINE_PROP_END_OF_LIST(), +}; + +static void mpcore_rirq_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = realview_mpcore_realize; + dc->props = mpcore_rirq_properties; +} + +static const TypeInfo mpcore_rirq_info = { + .name = TYPE_REALVIEW_MPCORE_RIRQ, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(mpcore_rirq_state), + .instance_init = mpcore_rirq_init, + .class_init = mpcore_rirq_class_init, +}; + +static void realview_mpcore_register_types(void) +{ + type_register_static(&mpcore_rirq_info); +} + +type_init(realview_mpcore_register_types) From f4d85795605c7dc594c013221a4b6d62967bd8ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sat, 24 Aug 2013 01:21:22 +0200 Subject: [PATCH 43/54] qdev-monitor: Clean up qdev_device_add() variable naming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid confusion between object (obj) and object class (oc). Tidy DeviceClass variable while at it (k -> dc). Signed-off-by: Andreas Färber --- qdev-monitor.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/qdev-monitor.c b/qdev-monitor.c index a02c925cb3..8f9f6cb45f 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -453,8 +453,8 @@ static BusState *qbus_find(const char *path) DeviceState *qdev_device_add(QemuOpts *opts) { - ObjectClass *obj; - DeviceClass *k; + ObjectClass *oc; + DeviceClass *dc; const char *driver, *path, *id; DeviceState *qdev; BusState *bus = NULL; @@ -466,22 +466,22 @@ DeviceState *qdev_device_add(QemuOpts *opts) } /* find driver */ - obj = object_class_by_name(driver); - if (!obj) { + oc = object_class_by_name(driver); + if (!oc) { const char *typename = find_typename_by_alias(driver); if (typename) { driver = typename; - obj = object_class_by_name(driver); + oc = object_class_by_name(driver); } } - if (!obj) { + if (!oc) { qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "device type"); return NULL; } - k = DEVICE_CLASS(obj); + dc = DEVICE_CLASS(oc); /* find bus */ path = qemu_opt_get(opts, "bus"); @@ -490,16 +490,16 @@ DeviceState *qdev_device_add(QemuOpts *opts) if (!bus) { return NULL; } - if (!object_dynamic_cast(OBJECT(bus), k->bus_type)) { + if (!object_dynamic_cast(OBJECT(bus), dc->bus_type)) { qerror_report(QERR_BAD_BUS_FOR_DEVICE, driver, object_get_typename(OBJECT(bus))); return NULL; } - } else if (k->bus_type != NULL) { - bus = qbus_find_recursive(sysbus_get_default(), NULL, k->bus_type); + } else if (dc->bus_type != NULL) { + bus = qbus_find_recursive(sysbus_get_default(), NULL, dc->bus_type); if (!bus) { qerror_report(QERR_NO_BUS_FOR_DEVICE, - k->bus_type, driver); + dc->bus_type, driver); return NULL; } } From 2fa4e56d88aa0039062bbc7f9a88e9f90c77ed94 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Tue, 17 Sep 2013 15:32:32 +0200 Subject: [PATCH 44/54] qdev-monitor: Fix crash when device_add is called with abstract driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User is able to crash running QEMU when following monitor command is called: device_add intel-hda-generic Crash is caused by assertion in object_initialize_with_type() when type is abstract. Checking if type is abstract before instance is created in qdev_device_add() allows to prevent crash on incorrect user input. Cc: qemu-stable@nongnu.org Signed-off-by: Igor Mammedov Signed-off-by: Andreas Färber --- qdev-monitor.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/qdev-monitor.c b/qdev-monitor.c index 8f9f6cb45f..753bab7545 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -481,6 +481,12 @@ DeviceState *qdev_device_add(QemuOpts *opts) return NULL; } + if (object_class_is_abstract(oc)) { + qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", + "non-abstract device type"); + return NULL; + } + dc = DEVICE_CLASS(oc); /* find bus */ From ee6abeb6ec08473713848ce9028110f1684853b7 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 10 Sep 2013 18:21:08 +0200 Subject: [PATCH 45/54] qdev-monitor: Unref device when device_add fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qdev_device_add() leaks the created device upon failure. I suspect this problem crept in because qdev_free() unparents the device but does not drop a reference - confusing name. Cc: qemu-stable@nongnu.org Signed-off-by: Stefan Hajnoczi Reviewed-by: Eric Blake Signed-off-by: Andreas Färber --- qdev-monitor.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qdev-monitor.c b/qdev-monitor.c index 753bab7545..9099d3d8f1 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -527,6 +527,7 @@ DeviceState *qdev_device_add(QemuOpts *opts) } if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) { qdev_free(qdev); + object_unref(OBJECT(qdev)); return NULL; } if (qdev->id) { @@ -540,6 +541,7 @@ DeviceState *qdev_device_add(QemuOpts *opts) g_free(name); } if (qdev_init(qdev) < 0) { + object_unref(OBJECT(qdev)); qerror_report(QERR_DEVICE_INIT_FAILED, driver); return NULL; } From 02a5c4c97422b40034f31265e0f139f7846172a8 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 11 Sep 2013 14:54:09 +0200 Subject: [PATCH 46/54] qdev: Drop misleading qdev_free() function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The qdev_free() function name is misleading since all the function does is unlink the device from its parent. The device is not necessarily freed. The device will be freed when its QObject refcount reaches zero. It is usual for the parent (bus) to hold the final reference but there are cases where something else holds a reference so "free" is a misleading name. Call object_unparent(obj) directly instead of having a qdev wrapper function. Signed-off-by: Stefan Hajnoczi Reviewed-by: Eric Blake Signed-off-by: Andreas Färber --- hw/acpi/piix4.c | 2 +- hw/core/qdev.c | 12 +++--------- hw/pci/pci-hotplug-old.c | 2 +- hw/pci/pci_bridge.c | 2 +- hw/pci/pcie.c | 2 +- hw/pci/shpc.c | 2 +- hw/s390x/virtio-ccw.c | 2 +- hw/scsi/scsi-bus.c | 6 +++--- hw/usb/bus.c | 7 ++++--- hw/usb/dev-storage.c | 2 +- hw/usb/host-legacy.c | 2 +- hw/virtio/virtio-bus.c | 4 +--- hw/xen/xen_platform.c | 2 +- include/hw/qdev-core.h | 1 - qdev-monitor.c | 2 +- 15 files changed, 21 insertions(+), 29 deletions(-) diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index 3bcd890567..93849c8d36 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -328,7 +328,7 @@ static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots) if (pc->no_hotplug) { slot_free = false; } else { - qdev_free(qdev); + object_unparent(OBJECT(qdev)); } } } diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 533f6dd122..e374a9399f 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -164,7 +164,7 @@ int qdev_init(DeviceState *dev) if (local_err != NULL) { qerror_report_err(local_err); error_free(local_err); - qdev_free(dev); + object_unparent(OBJECT(dev)); return -1; } return 0; @@ -258,7 +258,7 @@ void qbus_reset_all_fn(void *opaque) int qdev_simple_unplug_cb(DeviceState *dev) { /* just zap it */ - qdev_free(dev); + object_unparent(OBJECT(dev)); return 0; } @@ -280,12 +280,6 @@ void qdev_init_nofail(DeviceState *dev) } } -/* Unlink device from bus and free the structure. */ -void qdev_free(DeviceState *dev) -{ - object_unparent(OBJECT(dev)); -} - void qdev_machine_creation_done(void) { /* @@ -458,7 +452,7 @@ static void bus_unparent(Object *obj) while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) { DeviceState *dev = kid->child; - qdev_free(dev); + object_unparent(OBJECT(dev)); } if (bus->parent) { QLIST_REMOVE(bus, sibling); diff --git a/hw/pci/pci-hotplug-old.c b/hw/pci/pci-hotplug-old.c index 619fe473e8..8dbc3c1cab 100644 --- a/hw/pci/pci-hotplug-old.c +++ b/hw/pci/pci-hotplug-old.c @@ -248,7 +248,7 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon, } dev = pci_create(bus, devfn, "virtio-blk-pci"); if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) { - qdev_free(&dev->qdev); + object_unparent(OBJECT(dev)); dev = NULL; break; } diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c index e6b22b860f..290ababb8b 100644 --- a/hw/pci/pci_bridge.c +++ b/hw/pci/pci_bridge.c @@ -391,7 +391,7 @@ void pci_bridge_exitfn(PCIDevice *pci_dev) pci_bridge_region_cleanup(s, s->windows); memory_region_destroy(&s->address_space_mem); memory_region_destroy(&s->address_space_io); - /* qbus_free() is called automatically by qdev_free() */ + /* qbus_free() is called automatically during device deletion */ } /* diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index 268a696646..ca60cf2177 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -251,7 +251,7 @@ static int pcie_cap_slot_hotplug(DeviceState *qdev, PCI_EXP_SLTSTA_PDS); pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC); } else { - qdev_free(&pci_dev->qdev); + object_unparent(OBJECT(pci_dev)); pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_PDS); pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC); diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c index 0bbd36e272..576244b9f6 100644 --- a/hw/pci/shpc.c +++ b/hw/pci/shpc.c @@ -254,7 +254,7 @@ static void shpc_free_devices_in_slot(SHPCDevice *shpc, int slot) ++devfn) { PCIDevice *affected_dev = shpc->sec_bus->devices[devfn]; if (affected_dev) { - qdev_free(&affected_dev->qdev); + object_unparent(OBJECT(affected_dev)); } } } diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index cd67db5e5b..f93a81c7cd 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -1239,7 +1239,7 @@ static int virtio_ccw_busdev_unplug(DeviceState *dev) css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, 1, 0); - qdev_free(dev); + object_unparent(OBJECT(dev)); return 0; } diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index 24ec52f8f9..ea916d1466 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -178,7 +178,7 @@ static int scsi_qdev_init(DeviceState *qdev) d = scsi_device_find(bus, dev->channel, dev->id, dev->lun); assert(d); if (d->lun == dev->lun && dev != d) { - qdev_free(&d->qdev); + object_unparent(OBJECT(d)); } } @@ -231,13 +231,13 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, } if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) { error_setg(errp, "Setting drive property failed"); - qdev_free(dev); + object_unparent(OBJECT(dev)); return NULL; } object_property_set_bool(OBJECT(dev), true, "realized", &err); if (err != NULL) { error_propagate(errp, err); - qdev_free(dev); + object_unparent(OBJECT(dev)); return NULL; } return SCSI_DEVICE(dev); diff --git a/hw/usb/bus.c b/hw/usb/bus.c index 72d5b92225..ca329bef29 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -356,8 +356,9 @@ void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr) void usb_unregister_port(USBBus *bus, USBPort *port) { - if (port->dev) - qdev_free(&port->dev->qdev); + if (port->dev) { + object_unparent(OBJECT(port->dev)); + } QTAILQ_REMOVE(&bus->free, port, next); bus->nfree--; } @@ -505,7 +506,7 @@ int usb_device_delete_addr(int busnr, int addr) return -1; dev = port->dev; - qdev_free(&dev->qdev); + object_unparent(OBJECT(dev)); return 0; } diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index 1d81ac2a6b..c434c5680f 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -703,7 +703,7 @@ static USBDevice *usb_msd_init(USBBus *bus, const char *filename) return NULL; } if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) { - qdev_free(&dev->qdev); + object_unparent(OBJECT(dev)); return NULL; } if (qdev_init(&dev->qdev) < 0) diff --git a/hw/usb/host-legacy.c b/hw/usb/host-legacy.c index 3a5f705721..3cc9c4282c 100644 --- a/hw/usb/host-legacy.c +++ b/hw/usb/host-legacy.c @@ -132,7 +132,7 @@ USBDevice *usb_host_device_open(USBBus *bus, const char *devname) return dev; fail: - qdev_free(&dev->qdev); + object_unparent(OBJECT(dev)); return NULL; } diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c index 6849a018a9..e6b103c991 100644 --- a/hw/virtio/virtio-bus.c +++ b/hw/virtio/virtio-bus.c @@ -67,7 +67,6 @@ void virtio_bus_reset(VirtioBusState *bus) /* Destroy the VirtIODevice */ void virtio_bus_destroy_device(VirtioBusState *bus) { - DeviceState *qdev; BusState *qbus = BUS(bus); VirtioBusClass *klass = VIRTIO_BUS_GET_CLASS(bus); DPRINTF("%s: remove device.\n", qbus->name); @@ -76,8 +75,7 @@ void virtio_bus_destroy_device(VirtioBusState *bus) if (klass->device_unplug != NULL) { klass->device_unplug(qbus->parent); } - qdev = DEVICE(bus->vdev); - qdev_free(qdev); + object_unparent(OBJECT(bus->vdev)); bus->vdev = NULL; } } diff --git a/hw/xen/xen_platform.c b/hw/xen/xen_platform.c index 79bf0b33d3..70875e4122 100644 --- a/hw/xen/xen_platform.c +++ b/hw/xen/xen_platform.c @@ -95,7 +95,7 @@ static void unplug_nic(PCIBus *b, PCIDevice *d, void *o) if (pci_get_word(d->config + PCI_CLASS_DEVICE) == PCI_CLASS_NETWORK_ETHERNET && strcmp(d->name, "xen-pci-passthrough") != 0) { - qdev_free(DEVICE(d)); + object_unparent(OBJECT(d)); } } diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index e191ca0bd2..f2043a69c2 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -221,7 +221,6 @@ void qdev_init_nofail(DeviceState *dev); void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id, int required_for_version); void qdev_unplug(DeviceState *dev, Error **errp); -void qdev_free(DeviceState *dev); int qdev_simple_unplug_cb(DeviceState *dev); void qdev_machine_creation_done(void); bool qdev_machine_modified(void); diff --git a/qdev-monitor.c b/qdev-monitor.c index 9099d3d8f1..8e8ed4c131 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -526,7 +526,7 @@ DeviceState *qdev_device_add(QemuOpts *opts) qdev->id = id; } if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) { - qdev_free(qdev); + object_unparent(OBJECT(qdev)); object_unref(OBJECT(qdev)); return NULL; } From 2bcb0c62f620a7033e9e25c5b645d50bf9e6a8f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 7 Oct 2013 16:17:54 +0200 Subject: [PATCH 47/54] qdev-monitor: Avoid qdev as variable name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prepares for bringing error cleanup code into canonical QOM form. Includes a whitespace removal after curly brace by Stefan. Signed-off-by: Stefan Hajnoczi Reviewed-by: Igor Mammedov Signed-off-by: Andreas Färber --- qdev-monitor.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/qdev-monitor.c b/qdev-monitor.c index 8e8ed4c131..a46da32e99 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -456,7 +456,7 @@ DeviceState *qdev_device_add(QemuOpts *opts) ObjectClass *oc; DeviceClass *dc; const char *driver, *path, *id; - DeviceState *qdev; + DeviceState *dev; BusState *bus = NULL; driver = qemu_opt_get(opts, "driver"); @@ -515,38 +515,38 @@ DeviceState *qdev_device_add(QemuOpts *opts) } /* create device, set properties */ - qdev = DEVICE(object_new(driver)); + dev = DEVICE(object_new(driver)); if (bus) { - qdev_set_parent_bus(qdev, bus); + qdev_set_parent_bus(dev, bus); } id = qemu_opts_id(opts); if (id) { - qdev->id = id; + dev->id = id; } - if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) { - object_unparent(OBJECT(qdev)); - object_unref(OBJECT(qdev)); + if (qemu_opt_foreach(opts, set_property, dev, 1) != 0) { + object_unparent(OBJECT(dev)); + object_unref(OBJECT(dev)); return NULL; } - if (qdev->id) { - object_property_add_child(qdev_get_peripheral(), qdev->id, - OBJECT(qdev), NULL); + if (dev->id) { + object_property_add_child(qdev_get_peripheral(), dev->id, + OBJECT(dev), NULL); } else { static int anon_count; gchar *name = g_strdup_printf("device[%d]", anon_count++); object_property_add_child(qdev_get_peripheral_anon(), name, - OBJECT(qdev), NULL); + OBJECT(dev), NULL); g_free(name); - } - if (qdev_init(qdev) < 0) { - object_unref(OBJECT(qdev)); + } + if (qdev_init(dev) < 0) { + object_unref(OBJECT(dev)); qerror_report(QERR_DEVICE_INIT_FAILED, driver); return NULL; } - qdev->opts = opts; - return qdev; + dev->opts = opts; + return dev; } From 852e2c5008563692a8868260480e76b95bb9018c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 7 Oct 2013 16:42:34 +0200 Subject: [PATCH 48/54] qdev-monitor: Inline qdev_init() for device_add MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For historic reasons, qdev_init() unparents the device on failure. Inline this to make the error paths clearer and consistent. Reviewed-by: Igor Mammedov Signed-off-by: Andreas Färber --- qdev-monitor.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/qdev-monitor.c b/qdev-monitor.c index a46da32e99..dc37a43dd9 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -458,6 +458,7 @@ DeviceState *qdev_device_add(QemuOpts *opts) const char *driver, *path, *id; DeviceState *dev; BusState *bus = NULL; + Error *err = NULL; driver = qemu_opt_get(opts, "driver"); if (!driver) { @@ -540,7 +541,11 @@ DeviceState *qdev_device_add(QemuOpts *opts) OBJECT(dev), NULL); g_free(name); } - if (qdev_init(dev) < 0) { + object_property_set_bool(OBJECT(dev), true, "realized", &err); + if (err != NULL) { + qerror_report_err(err); + error_free(err); + object_unparent(OBJECT(dev)); object_unref(OBJECT(dev)); qerror_report(QERR_DEVICE_INIT_FAILED, driver); return NULL; From a25ebcacdda4dd6e68ac62acb4c72f3f868b938d Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 7 Oct 2013 12:35:01 +0300 Subject: [PATCH 49/54] qom: Fix pointer to int property helpers' documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Relocate to alongside the other object_property_add_* helpers while at it. Signed-off-by: Andreas Färber --- include/qom/object.h | 73 +++++++++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 21 deletions(-) diff --git a/include/qom/object.h b/include/qom/object.h index d02172adca..a275db2092 100644 --- a/include/qom/object.h +++ b/include/qom/object.h @@ -794,27 +794,6 @@ void object_property_add(Object *obj, const char *name, const char *type, void object_property_del(Object *obj, const char *name, Error **errp); -/** - * object_property_add_uint8_ptr: - * object_property_add_uint16_ptr: - * object_property_add_uint32_ptr: - * object_property_add_uint64_ptr: - * @obj: the object to add a property to - * @name: the name of the property - * @v: pointer to value - * - * Add an integer property in memory. This function will add a - * property of the appropriate type. - */ -void object_property_add_uint8_ptr(Object *obj, const char *name, - const uint8_t *v, Error **errp); -void object_property_add_uint16_ptr(Object *obj, const char *name, - const uint16_t *v, Error **errp); -void object_property_add_uint32_ptr(Object *obj, const char *name, - const uint32_t *v, Error **errp); -void object_property_add_uint64_ptr(Object *obj, const char *name, - const uint64_t *v, Error **Errp); - /** * object_property_find: * @obj: the object @@ -1133,6 +1112,58 @@ void object_property_add_bool(Object *obj, const char *name, void (*set)(Object *, bool, Error **), Error **errp); +/** + * object_property_add_uint8_ptr: + * @obj: the object to add a property to + * @name: the name of the property + * @v: pointer to value + * @errp: if an error occurs, a pointer to an area to store the error + * + * Add an integer property in memory. This function will add a + * property of type 'uint8'. + */ +void object_property_add_uint8_ptr(Object *obj, const char *name, + const uint8_t *v, Error **errp); + +/** + * object_property_add_uint16_ptr: + * @obj: the object to add a property to + * @name: the name of the property + * @v: pointer to value + * @errp: if an error occurs, a pointer to an area to store the error + * + * Add an integer property in memory. This function will add a + * property of type 'uint16'. + */ +void object_property_add_uint16_ptr(Object *obj, const char *name, + const uint16_t *v, Error **errp); + +/** + * object_property_add_uint32_ptr: + * @obj: the object to add a property to + * @name: the name of the property + * @v: pointer to value + * @errp: if an error occurs, a pointer to an area to store the error + * + * Add an integer property in memory. This function will add a + * property of type 'uint32'. + */ +void object_property_add_uint32_ptr(Object *obj, const char *name, + const uint32_t *v, Error **errp); + +/** + * object_property_add_uint64_ptr: + * @obj: the object to add a property to + * @name: the name of the property + * @v: pointer to value + * @errp: if an error occurs, a pointer to an area to store the error + * + * Add an integer property in memory. This function will add a + * property of type 'uint64'. + */ +void object_property_add_uint64_ptr(Object *obj, const char *name, + const uint64_t *v, Error **Errp); + /** * object_child_foreach: * @obj: the object whose children will be navigated From 853ca11dafb625e36db036b8e83d6e2168703e1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 17 Jul 2013 19:06:47 +0200 Subject: [PATCH 50/54] pxa: Fix typo "dettach" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andreas Färber --- hw/misc/pxa2xx_pcmcia.c | 2 +- include/hw/arm/pxa.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/misc/pxa2xx_pcmcia.c b/hw/misc/pxa2xx_pcmcia.c index ef71a2af74..76724a6ac6 100644 --- a/hw/misc/pxa2xx_pcmcia.c +++ b/hw/misc/pxa2xx_pcmcia.c @@ -178,7 +178,7 @@ int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card) } /* Eject card from the slot */ -int pxa2xx_pcmcia_dettach(void *opaque) +int pxa2xx_pcmcia_detach(void *opaque) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; if (!s->slot.attached) diff --git a/include/hw/arm/pxa.h b/include/hw/arm/pxa.h index 668232cead..a4e1a66264 100644 --- a/include/hw/arm/pxa.h +++ b/include/hw/arm/pxa.h @@ -97,7 +97,7 @@ typedef struct PXA2xxPCMCIAState PXA2xxPCMCIAState; PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem, hwaddr base); int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card); -int pxa2xx_pcmcia_dettach(void *opaque); +int pxa2xx_pcmcia_detach(void *opaque); void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq); /* pxa2xx_keypad.c */ From d1f2c96a81a4d18b99b7f471bf58e65c9afab33f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 17 Jul 2013 19:46:16 +0200 Subject: [PATCH 51/54] pcmcia: QOM'ify PCMCIACardState and MicroDriveState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turn PCMCIACardState into a device. Move callbacks to new PCMCIACardClass. Derive TYPE_MICRODRIVE from TYPE_PCMCIA_CARD. Replace ide_init2_with_non_qdev_drives(). Signed-off-by: Othmar Pasteka Signed-off-by: Andreas Färber --- hw/Makefile.objs | 1 + hw/ide/microdrive.c | 172 +++++++++++++------ hw/misc/Makefile.objs | 1 - hw/pcmcia/Makefile.objs | 2 + hw/pcmcia/pcmcia.c | 24 +++ hw/{misc/pxa2xx_pcmcia.c => pcmcia/pxa2xx.c} | 52 ++++-- include/hw/pcmcia.h | 46 +++-- 7 files changed, 221 insertions(+), 77 deletions(-) create mode 100644 hw/pcmcia/Makefile.objs create mode 100644 hw/pcmcia/pcmcia.c rename hw/{misc/pxa2xx_pcmcia.c => pcmcia/pxa2xx.c} (81%) diff --git a/hw/Makefile.objs b/hw/Makefile.objs index 0243d6aa0e..d91b9cc6c6 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -18,6 +18,7 @@ devices-dirs-$(CONFIG_SOFTMMU) += net/ devices-dirs-$(CONFIG_SOFTMMU) += nvram/ devices-dirs-$(CONFIG_SOFTMMU) += pci/ devices-dirs-$(CONFIG_PCI) += pci-bridge/ pci-host/ +devices-dirs-$(CONFIG_SOFTMMU) += pcmcia/ devices-dirs-$(CONFIG_SOFTMMU) += scsi/ devices-dirs-$(CONFIG_SOFTMMU) += sd/ devices-dirs-$(CONFIG_SOFTMMU) += ssi/ diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c index 92c1df0460..cdf0eb9ce7 100644 --- a/hw/ide/microdrive.c +++ b/hw/ide/microdrive.c @@ -30,15 +30,22 @@ #include +#define TYPE_MICRODRIVE "microdrive" +#define MICRODRIVE(obj) OBJECT_CHECK(MicroDriveState, (obj), TYPE_MICRODRIVE) + /***********************************************************/ /* CF-ATA Microdrive */ #define METADATA_SIZE 0x20 /* DSCM-1XXXX Microdrive hard disk with CF+ II / PCMCIA interface. */ -typedef struct { + +typedef struct MicroDriveState { + /*< private >*/ + PCMCIACardState parent_obj; + /*< public >*/ + IDEBus bus; - PCMCIACardState card; uint32_t attr_base; uint32_t io_base; @@ -81,10 +88,13 @@ enum md_ctrl { static inline void md_interrupt_update(MicroDriveState *s) { - if (!s->card.slot) - return; + PCMCIACardState *card = PCMCIA_CARD(s); - qemu_set_irq(s->card.slot->irq, + if (card->slot == NULL) { + return; + } + + qemu_set_irq(card->slot->irq, !(s->stat & STAT_INT) && /* Inverted */ !(s->ctrl & (CTRL_IEN | CTRL_SRST)) && !(s->opt & OPT_SRESET)); @@ -101,8 +111,10 @@ static void md_set_irq(void *opaque, int irq, int level) md_interrupt_update(s); } -static void md_reset(MicroDriveState *s) +static void md_reset(DeviceState *dev) { + MicroDriveState *s = MICRODRIVE(dev); + s->opt = OPT_MODE_MMAP; s->stat = 0; s->pins = 0; @@ -111,14 +123,17 @@ static void md_reset(MicroDriveState *s) ide_bus_reset(&s->bus); } -static uint8_t md_attr_read(void *opaque, uint32_t at) +static uint8_t md_attr_read(PCMCIACardState *card, uint32_t at) { - MicroDriveState *s = opaque; + MicroDriveState *s = MICRODRIVE(card); + PCMCIACardClass *pcc = PCMCIA_CARD_GET_CLASS(card); + if (at < s->attr_base) { - if (at < s->card.cis_len) - return s->card.cis[at]; - else + if (at < pcc->cis_len) { + return pcc->cis[at]; + } else { return 0x00; + } } at -= s->attr_base; @@ -144,16 +159,18 @@ static uint8_t md_attr_read(void *opaque, uint32_t at) return 0; } -static void md_attr_write(void *opaque, uint32_t at, uint8_t value) +static void md_attr_write(PCMCIACardState *card, uint32_t at, uint8_t value) { - MicroDriveState *s = opaque; + MicroDriveState *s = MICRODRIVE(card); + at -= s->attr_base; switch (at) { case 0x00: /* Configuration Option Register */ s->opt = value & 0xcf; - if (value & OPT_SRESET) - md_reset(s); + if (value & OPT_SRESET) { + device_reset(DEVICE(s)); + } md_interrupt_update(s); break; case 0x02: /* Card Configuration Status Register */ @@ -175,9 +192,9 @@ static void md_attr_write(void *opaque, uint32_t at, uint8_t value) } } -static uint16_t md_common_read(void *opaque, uint32_t at) +static uint16_t md_common_read(PCMCIACardState *card, uint32_t at) { - MicroDriveState *s = opaque; + MicroDriveState *s = MICRODRIVE(card); IDEState *ifs; uint16_t ret; at -= s->io_base; @@ -237,9 +254,9 @@ static uint16_t md_common_read(void *opaque, uint32_t at) return 0; } -static void md_common_write(void *opaque, uint32_t at, uint16_t value) +static void md_common_write(PCMCIACardState *card, uint32_t at, uint16_t value) { - MicroDriveState *s = opaque; + MicroDriveState *s = MICRODRIVE(card); at -= s->io_base; switch (s->opt & OPT_MODE) { @@ -285,8 +302,9 @@ static void md_common_write(void *opaque, uint32_t at, uint16_t value) break; case 0xe: /* Device Control */ s->ctrl = value; - if (value & CTRL_SRST) - md_reset(s); + if (value & CTRL_SRST) { + device_reset(DEVICE(s)); + } md_interrupt_update(s); break; default: @@ -501,49 +519,107 @@ static const uint8_t dscm1xxxx_cis[0x14a] = { [0x146] = CISTPL_END, /* Tuple End */ }; -static int dscm1xxxx_attach(void *opaque) -{ - MicroDriveState *md = opaque; - md->card.attr_read = md_attr_read; - md->card.attr_write = md_attr_write; - md->card.common_read = md_common_read; - md->card.common_write = md_common_write; - md->card.io_read = md_common_read; - md->card.io_write = md_common_write; +#define TYPE_DSCM1XXXX "dscm1xxxx" - md->attr_base = md->card.cis[0x74] | (md->card.cis[0x76] << 8); +static int dscm1xxxx_attach(PCMCIACardState *card) +{ + MicroDriveState *md = MICRODRIVE(card); + PCMCIACardClass *pcc = PCMCIA_CARD_GET_CLASS(card); + + md->attr_base = pcc->cis[0x74] | (pcc->cis[0x76] << 8); md->io_base = 0x0; - md_reset(md); + device_reset(DEVICE(md)); md_interrupt_update(md); - md->card.slot->card_string = "DSCM-1xxxx Hitachi Microdrive"; + card->slot->card_string = "DSCM-1xxxx Hitachi Microdrive"; return 0; } -static int dscm1xxxx_detach(void *opaque) +static int dscm1xxxx_detach(PCMCIACardState *card) { - MicroDriveState *md = opaque; - md_reset(md); + MicroDriveState *md = MICRODRIVE(card); + + device_reset(DEVICE(md)); return 0; } -PCMCIACardState *dscm1xxxx_init(DriveInfo *bdrv) +PCMCIACardState *dscm1xxxx_init(DriveInfo *dinfo) { - MicroDriveState *md = (MicroDriveState *) g_malloc0(sizeof(MicroDriveState)); - md->card.state = md; - md->card.attach = dscm1xxxx_attach; - md->card.detach = dscm1xxxx_detach; - md->card.cis = dscm1xxxx_cis; - md->card.cis_len = sizeof(dscm1xxxx_cis); + MicroDriveState *md = MICRODRIVE(object_new(TYPE_DSCM1XXXX)); + PCMCIACardState *card = PCMCIA_CARD(md); - ide_init2_with_non_qdev_drives(&md->bus, bdrv, NULL, - qemu_allocate_irqs(md_set_irq, md, 1)[0]); + if (dinfo != NULL) { + ide_create_drive(&md->bus, 0, dinfo); + } md->bus.ifs[0].drive_kind = IDE_CFATA; md->bus.ifs[0].mdata_size = METADATA_SIZE; md->bus.ifs[0].mdata_storage = (uint8_t *) g_malloc0(METADATA_SIZE); - vmstate_register(NULL, -1, &vmstate_microdrive, md); - - return &md->card; + return card; } + +static void dscm1xxxx_class_init(ObjectClass *oc, void *data) +{ + PCMCIACardClass *pcc = PCMCIA_CARD_CLASS(oc); + + pcc->cis = dscm1xxxx_cis; + pcc->cis_len = sizeof(dscm1xxxx_cis); + + pcc->attach = dscm1xxxx_attach; + pcc->detach = dscm1xxxx_detach; +} + +static const TypeInfo dscm1xxxx_type_info = { + .name = TYPE_DSCM1XXXX, + .parent = TYPE_MICRODRIVE, + .class_init = dscm1xxxx_class_init, +}; + +static void microdrive_realize(DeviceState *dev, Error **errp) +{ + MicroDriveState *md = MICRODRIVE(dev); + + ide_init2(&md->bus, qemu_allocate_irqs(md_set_irq, md, 1)[0]); +} + +static void microdrive_init(Object *obj) +{ + MicroDriveState *md = MICRODRIVE(obj); + + ide_bus_new(&md->bus, sizeof(md->bus), DEVICE(obj), 0, 1); +} + +static void microdrive_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + PCMCIACardClass *pcc = PCMCIA_CARD_CLASS(oc); + + pcc->attr_read = md_attr_read; + pcc->attr_write = md_attr_write; + pcc->common_read = md_common_read; + pcc->common_write = md_common_write; + pcc->io_read = md_common_read; + pcc->io_write = md_common_write; + + dc->realize = microdrive_realize; + dc->reset = md_reset; + dc->vmsd = &vmstate_microdrive; +} + +static const TypeInfo microdrive_type_info = { + .name = TYPE_MICRODRIVE, + .parent = TYPE_PCMCIA_CARD, + .instance_size = sizeof(MicroDriveState), + .instance_init = microdrive_init, + .abstract = true, + .class_init = microdrive_class_init, +}; + +static void microdrive_register_types(void) +{ + type_register_static(µdrive_type_info); + type_register_static(&dscm1xxxx_type_info); +} + +type_init(microdrive_register_types) diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index 9fbcebd15b..f6743659f7 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -38,7 +38,6 @@ obj-$(CONFIG_OMAP) += omap_gpmc.o obj-$(CONFIG_OMAP) += omap_l4.o obj-$(CONFIG_OMAP) += omap_sdrc.o obj-$(CONFIG_OMAP) += omap_tap.o -obj-$(CONFIG_PXA2XX) += pxa2xx_pcmcia.o obj-$(CONFIG_SLAVIO) += slavio_misc.o obj-$(CONFIG_ZYNQ) += zynq_slcr.o diff --git a/hw/pcmcia/Makefile.objs b/hw/pcmcia/Makefile.objs new file mode 100644 index 0000000000..4eac060c93 --- /dev/null +++ b/hw/pcmcia/Makefile.objs @@ -0,0 +1,2 @@ +common-obj-y += pcmcia.o +obj-$(CONFIG_PXA2XX) += pxa2xx.o diff --git a/hw/pcmcia/pcmcia.c b/hw/pcmcia/pcmcia.c new file mode 100644 index 0000000000..78efe5a67a --- /dev/null +++ b/hw/pcmcia/pcmcia.c @@ -0,0 +1,24 @@ +/* + * PCMCIA emulation + * + * Copyright 2013 SUSE LINUX Products GmbH + */ + +#include "qemu-common.h" +#include "hw/hw.h" +#include "hw/pcmcia.h" + +static const TypeInfo pcmcia_card_type_info = { + .name = TYPE_PCMCIA_CARD, + .parent = TYPE_DEVICE, + .instance_size = sizeof(PCMCIACardState), + .abstract = true, + .class_size = sizeof(PCMCIACardClass), +}; + +static void pcmcia_register_types(void) +{ + type_register_static(&pcmcia_card_type_info); +} + +type_init(pcmcia_register_types) diff --git a/hw/misc/pxa2xx_pcmcia.c b/hw/pcmcia/pxa2xx.c similarity index 81% rename from hw/misc/pxa2xx_pcmcia.c rename to hw/pcmcia/pxa2xx.c index 76724a6ac6..2c515bee06 100644 --- a/hw/misc/pxa2xx_pcmcia.c +++ b/hw/pcmcia/pxa2xx.c @@ -30,9 +30,11 @@ static uint64_t pxa2xx_pcmcia_common_read(void *opaque, hwaddr offset, unsigned size) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; + PCMCIACardClass *pcc; if (s->slot.attached) { - return s->card->common_read(s->card->state, offset); + pcc = PCMCIA_CARD_GET_CLASS(s->card); + return pcc->common_read(s->card, offset); } return 0; @@ -42,9 +44,11 @@ static void pxa2xx_pcmcia_common_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; + PCMCIACardClass *pcc; if (s->slot.attached) { - s->card->common_write(s->card->state, offset, value); + pcc = PCMCIA_CARD_GET_CLASS(s->card); + pcc->common_write(s->card, offset, value); } } @@ -52,9 +56,11 @@ static uint64_t pxa2xx_pcmcia_attr_read(void *opaque, hwaddr offset, unsigned size) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; + PCMCIACardClass *pcc; if (s->slot.attached) { - return s->card->attr_read(s->card->state, offset); + pcc = PCMCIA_CARD_GET_CLASS(s->card); + return pcc->attr_read(s->card, offset); } return 0; @@ -64,9 +70,11 @@ static void pxa2xx_pcmcia_attr_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; + PCMCIACardClass *pcc; if (s->slot.attached) { - s->card->attr_write(s->card->state, offset, value); + pcc = PCMCIA_CARD_GET_CLASS(s->card); + pcc->attr_write(s->card, offset, value); } } @@ -74,9 +82,11 @@ static uint64_t pxa2xx_pcmcia_io_read(void *opaque, hwaddr offset, unsigned size) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; + PCMCIACardClass *pcc; if (s->slot.attached) { - return s->card->io_read(s->card->state, offset); + pcc = PCMCIA_CARD_GET_CLASS(s->card); + return pcc->io_read(s->card, offset); } return 0; @@ -86,9 +96,11 @@ static void pxa2xx_pcmcia_io_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; + PCMCIACardClass *pcc; if (s->slot.attached) { - s->card->io_write(s->card->state, offset, value); + pcc = PCMCIA_CARD_GET_CLASS(s->card); + pcc->io_write(s->card, offset, value); } } @@ -161,18 +173,22 @@ PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem, int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; - if (s->slot.attached) + PCMCIACardClass *pcc; + + if (s->slot.attached) { return -EEXIST; + } if (s->cd_irq) { qemu_irq_raise(s->cd_irq); } s->card = card; + pcc = PCMCIA_CARD_GET_CLASS(s->card); - s->slot.attached = 1; + s->slot.attached = true; s->card->slot = &s->slot; - s->card->attach(s->card->state); + pcc->attach(s->card); return 0; } @@ -181,19 +197,25 @@ int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card) int pxa2xx_pcmcia_detach(void *opaque) { PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; - if (!s->slot.attached) - return -ENOENT; + PCMCIACardClass *pcc; - s->card->detach(s->card->state); + if (!s->slot.attached) { + return -ENOENT; + } + + pcc = PCMCIA_CARD_GET_CLASS(s->card); + pcc->detach(s->card); s->card->slot = NULL; s->card = NULL; - s->slot.attached = 0; + s->slot.attached = false; - if (s->irq) + if (s->irq) { qemu_irq_lower(s->irq); - if (s->cd_irq) + } + if (s->cd_irq) { qemu_irq_lower(s->cd_irq); + } return 0; } diff --git a/include/hw/pcmcia.h b/include/hw/pcmcia.h index f91669305e..2695d3cba6 100644 --- a/include/hw/pcmcia.h +++ b/include/hw/pcmcia.h @@ -3,11 +3,11 @@ /* PCMCIA/Cardbus */ -#include "qemu-common.h" +#include "hw/qdev.h" -typedef struct { +typedef struct PCMCIASocket { qemu_irq irq; - int attached; + bool attached; const char *slot_string; const char *card_string; } PCMCIASocket; @@ -16,22 +16,42 @@ void pcmcia_socket_register(PCMCIASocket *socket); void pcmcia_socket_unregister(PCMCIASocket *socket); void pcmcia_info(Monitor *mon, const QDict *qdict); +#define TYPE_PCMCIA_CARD "pcmcia-card" +#define PCMCIA_CARD(obj) \ + OBJECT_CHECK(PCMCIACardState, (obj), TYPE_PCMCIA_CARD) +#define PCMCIA_CARD_GET_CLASS(obj) \ + OBJECT_GET_CLASS(PCMCIACardClass, obj, TYPE_PCMCIA_CARD) +#define PCMCIA_CARD_CLASS(cls) \ + OBJECT_CLASS_CHECK(PCMCIACardClass, cls, TYPE_PCMCIA_CARD) + struct PCMCIACardState { - void *state; + /*< private >*/ + DeviceState parent_obj; + /*< public >*/ + PCMCIASocket *slot; - int (*attach)(void *state); - int (*detach)(void *state); +}; + +typedef struct PCMCIACardClass { + /*< private >*/ + DeviceClass parent_class; + /*< public >*/ + + int (*attach)(PCMCIACardState *state); + int (*detach)(PCMCIACardState *state); + const uint8_t *cis; int cis_len; /* Only valid if attached */ - uint8_t (*attr_read)(void *state, uint32_t address); - void (*attr_write)(void *state, uint32_t address, uint8_t value); - uint16_t (*common_read)(void *state, uint32_t address); - void (*common_write)(void *state, uint32_t address, uint16_t value); - uint16_t (*io_read)(void *state, uint32_t address); - void (*io_write)(void *state, uint32_t address, uint16_t value); -}; + uint8_t (*attr_read)(PCMCIACardState *card, uint32_t address); + void (*attr_write)(PCMCIACardState *card, uint32_t address, uint8_t value); + uint16_t (*common_read)(PCMCIACardState *card, uint32_t address); + void (*common_write)(PCMCIACardState *card, + uint32_t address, uint16_t value); + uint16_t (*io_read)(PCMCIACardState *card, uint32_t address); + void (*io_write)(PCMCIACardState *card, uint32_t address, uint16_t value); +} PCMCIACardClass; #define CISTPL_DEVICE 0x01 /* 5V Device Information Tuple */ #define CISTPL_NO_LINK 0x14 /* No Link Tuple */ From a6cb20fcba97bffd893e532f8cc70442200d3e15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sat, 3 Aug 2013 10:32:49 +0200 Subject: [PATCH 52/54] microdrive: Coding Style cleanups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add missing braces. Signed-off-by: Andreas Färber --- hw/ide/microdrive.c | 62 +++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c index cdf0eb9ce7..21d6495817 100644 --- a/hw/ide/microdrive.c +++ b/hw/ide/microdrive.c @@ -103,10 +103,12 @@ static inline void md_interrupt_update(MicroDriveState *s) static void md_set_irq(void *opaque, int irq, int level) { MicroDriveState *s = opaque; - if (level) + + if (level) { s->stat |= STAT_INT; - else + } else { s->stat &= ~STAT_INT; + } md_interrupt_update(s); } @@ -142,10 +144,11 @@ static uint8_t md_attr_read(PCMCIACardState *card, uint32_t at) case 0x00: /* Configuration Option Register */ return s->opt; case 0x02: /* Card Configuration Status Register */ - if (s->ctrl & CTRL_IEN) + if (s->ctrl & CTRL_IEN) { return s->stat & ~STAT_INT; - else + } else { return s->stat; + } case 0x04: /* Pin Replacement Register */ return (s->pins & PINS_CRDY) | 0x0c; case 0x06: /* Socket and Copy Register */ @@ -174,8 +177,9 @@ static void md_attr_write(PCMCIACardState *card, uint32_t at, uint8_t value) md_interrupt_update(s); break; case 0x02: /* Card Configuration Status Register */ - if ((s->stat ^ value) & STAT_PWRDWN) + if ((s->stat ^ value) & STAT_PWRDWN) { s->pins |= PINS_CRDY; + } s->stat &= 0x82; s->stat |= value & 0x74; md_interrupt_update(s); @@ -201,23 +205,26 @@ static uint16_t md_common_read(PCMCIACardState *card, uint32_t at) switch (s->opt & OPT_MODE) { case OPT_MODE_MMAP: - if ((at & ~0x3ff) == 0x400) + if ((at & ~0x3ff) == 0x400) { at = 0; + } break; case OPT_MODE_IOMAP16: at &= 0xf; break; case OPT_MODE_IOMAP1: - if ((at & ~0xf) == 0x3f0) + if ((at & ~0xf) == 0x3f0) { at -= 0x3e8; - else if ((at & ~0xf) == 0x1f0) + } else if ((at & ~0xf) == 0x1f0) { at -= 0x1f0; + } break; case OPT_MODE_IOMAP2: - if ((at & ~0xf) == 0x370) + if ((at & ~0xf) == 0x370) { at -= 0x368; - else if ((at & ~0xf) == 0x170) + } else if ((at & ~0xf) == 0x170) { at -= 0x170; + } } switch (at) { @@ -226,9 +233,9 @@ static uint16_t md_common_read(PCMCIACardState *card, uint32_t at) return ide_data_readw(&s->bus, 0); /* TODO: 8-bit accesses */ - if (s->cycle) + if (s->cycle) { ret = s->io >> 8; - else { + } else { s->io = ide_data_readw(&s->bus, 0); ret = s->io & 0xff; } @@ -240,10 +247,11 @@ static uint16_t md_common_read(PCMCIACardState *card, uint32_t at) return ide_ioport_read(&s->bus, 0x1); case 0xe: /* Alternate Status */ ifs = idebus_active_if(&s->bus); - if (ifs->bs) + if (ifs->bs) { return ifs->status; - else + } else { return 0; + } case 0xf: /* Device Address */ ifs = idebus_active_if(&s->bus); return 0xc2 | ((~ifs->select << 2) & 0x3c); @@ -261,23 +269,26 @@ static void md_common_write(PCMCIACardState *card, uint32_t at, uint16_t value) switch (s->opt & OPT_MODE) { case OPT_MODE_MMAP: - if ((at & ~0x3ff) == 0x400) + if ((at & ~0x3ff) == 0x400) { at = 0; + } break; case OPT_MODE_IOMAP16: at &= 0xf; break; case OPT_MODE_IOMAP1: - if ((at & ~0xf) == 0x3f0) + if ((at & ~0xf) == 0x3f0) { at -= 0x3e8; - else if ((at & ~0xf) == 0x1f0) + } else if ((at & ~0xf) == 0x1f0) { at -= 0x1f0; + } break; case OPT_MODE_IOMAP2: - if ((at & ~0xf) == 0x370) + if ((at & ~0xf) == 0x370) { at -= 0x368; - else if ((at & ~0xf) == 0x170) + } else if ((at & ~0xf) == 0x170) { at -= 0x170; + } } switch (at) { @@ -287,10 +298,11 @@ static void md_common_write(PCMCIACardState *card, uint32_t at, uint16_t value) break; /* TODO: 8-bit accesses */ - if (s->cycle) + if (s->cycle) { ide_data_writew(&s->bus, 0, s->io | (value << 8)); - else + } else { s->io = value & 0xff; + } s->cycle = !s->cycle; break; case 0x9: @@ -546,8 +558,10 @@ static int dscm1xxxx_detach(PCMCIACardState *card) PCMCIACardState *dscm1xxxx_init(DriveInfo *dinfo) { - MicroDriveState *md = MICRODRIVE(object_new(TYPE_DSCM1XXXX)); - PCMCIACardState *card = PCMCIA_CARD(md); + MicroDriveState *md; + + md = MICRODRIVE(object_new(TYPE_DSCM1XXXX)); + qdev_init_nofail(DEVICE(md)); if (dinfo != NULL) { ide_create_drive(&md->bus, 0, dinfo); @@ -556,7 +570,7 @@ PCMCIACardState *dscm1xxxx_init(DriveInfo *dinfo) md->bus.ifs[0].mdata_size = METADATA_SIZE; md->bus.ifs[0].mdata_storage = (uint8_t *) g_malloc0(METADATA_SIZE); - return card; + return PCMCIA_CARD(md); } static void dscm1xxxx_class_init(ObjectClass *oc, void *data) From e3d4d36d1bff6b1a0b68b794c33bbe8666afc840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sat, 3 Aug 2013 11:30:50 +0200 Subject: [PATCH 53/54] ide: Drop ide_init2_with_non_qdev_drives() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All its users have finally been converted. Signed-off-by: Andreas Färber --- hw/ide/core.c | 49 ----------------------------------------------- hw/ide/internal.h | 2 -- 2 files changed, 51 deletions(-) diff --git a/hw/ide/core.c b/hw/ide/core.c index 399b1bae68..e1f4c33fb8 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -2215,55 +2215,6 @@ void ide_init2(IDEBus *bus, qemu_irq irq) bus->dma = &ide_dma_nop; } -/* TODO convert users to qdev and remove */ -void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0, - DriveInfo *hd1, qemu_irq irq) -{ - int i, trans; - DriveInfo *dinfo; - uint32_t cyls, heads, secs; - - for(i = 0; i < 2; i++) { - dinfo = i == 0 ? hd0 : hd1; - ide_init1(bus, i); - if (dinfo) { - cyls = dinfo->cyls; - heads = dinfo->heads; - secs = dinfo->secs; - trans = dinfo->trans; - if (!cyls && !heads && !secs) { - hd_geometry_guess(dinfo->bdrv, &cyls, &heads, &secs, &trans); - } else if (trans == BIOS_ATA_TRANSLATION_AUTO) { - trans = hd_bios_chs_auto_trans(cyls, heads, secs); - } - if (cyls < 1 || cyls > 65535) { - error_report("cyls must be between 1 and 65535"); - exit(1); - } - if (heads < 1 || heads > 16) { - error_report("heads must be between 1 and 16"); - exit(1); - } - if (secs < 1 || secs > 255) { - error_report("secs must be between 1 and 255"); - exit(1); - } - if (ide_init_drive(&bus->ifs[i], dinfo->bdrv, - dinfo->media_cd ? IDE_CD : IDE_HD, - NULL, dinfo->serial, NULL, 0, - cyls, heads, secs, trans) < 0) { - error_report("Can't set up IDE drive %s", dinfo->id); - exit(1); - } - bdrv_attach_dev_nofail(dinfo->bdrv, &bus->ifs[i]); - } else { - ide_reset(&bus->ifs[i]); - } - } - bus->irq = irq; - bus->dma = &ide_dma_nop; -} - static const MemoryRegionPortio ide_portio_list[] = { { 0, 8, 1, .read = ide_ioport_read, .write = ide_ioport_write }, { 0, 2, 2, .read = ide_data_readw, .write = ide_data_writew }, diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 5d1cf87742..0567a522f5 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -553,8 +553,6 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind, uint32_t cylinders, uint32_t heads, uint32_t secs, int chs_trans); void ide_init2(IDEBus *bus, qemu_irq irq); -void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0, - DriveInfo *hd1, qemu_irq irq); void ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2); void ide_exec_cmd(IDEBus *bus, uint32_t val); From 80bbaee66ac38bcb5fe5a6f285e20457afcc8bec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sat, 3 Aug 2013 12:23:05 +0200 Subject: [PATCH 54/54] pcmcia/pxa2xx: QOM'ify PXA2xxPCMCIAState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turn it into a SysBusDevice and use a container MemoryRegion. Add a link property to the PCMCIACardState. Signed-off-by: Andreas Färber --- hw/pcmcia/pxa2xx.c | 78 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 12 deletions(-) diff --git a/hw/pcmcia/pxa2xx.c b/hw/pcmcia/pxa2xx.c index 2c515bee06..8f17596cc3 100644 --- a/hw/pcmcia/pxa2xx.c +++ b/hw/pcmcia/pxa2xx.c @@ -11,19 +11,27 @@ */ #include "hw/hw.h" +#include "hw/sysbus.h" #include "hw/pcmcia.h" #include "hw/arm/pxa.h" +#define TYPE_PXA2XX_PCMCIA "pxa2xx-pcmcia" +#define PXA2XX_PCMCIA(obj) \ + OBJECT_CHECK(PXA2xxPCMCIAState, obj, TYPE_PXA2XX_PCMCIA) struct PXA2xxPCMCIAState { + SysBusDevice parent_obj; + PCMCIASocket slot; - PCMCIACardState *card; + MemoryRegion container_mem; MemoryRegion common_iomem; MemoryRegion attr_iomem; MemoryRegion iomem; qemu_irq irq; qemu_irq cd_irq; + + PCMCIACardState *card; }; static uint64_t pxa2xx_pcmcia_common_read(void *opaque, @@ -134,15 +142,43 @@ static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level) PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem, hwaddr base) { + DeviceState *dev; PXA2xxPCMCIAState *s; - s = (PXA2xxPCMCIAState *) - g_malloc0(sizeof(PXA2xxPCMCIAState)); + dev = qdev_create(NULL, TYPE_PXA2XX_PCMCIA); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); + s = PXA2XX_PCMCIA(dev); + + if (base == 0x30000000) { + s->slot.slot_string = "PXA PC Card Socket 1"; + } else { + s->slot.slot_string = "PXA PC Card Socket 0"; + } + + qdev_init_nofail(dev); + + return s; +} + +static void pxa2xx_pcmcia_realize(DeviceState *dev, Error **errp) +{ + PXA2xxPCMCIAState *s = PXA2XX_PCMCIA(dev); + + pcmcia_socket_register(&s->slot); +} + +static void pxa2xx_pcmcia_initfn(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + PXA2xxPCMCIAState *s = PXA2XX_PCMCIA(obj); + + memory_region_init(&s->container_mem, obj, "container", 0x10000000); + sysbus_init_mmio(sbd, &s->container_mem); /* Socket I/O Memory Space */ memory_region_init_io(&s->iomem, NULL, &pxa2xx_pcmcia_io_ops, s, "pxa2xx-pcmcia-io", 0x04000000); - memory_region_add_subregion(sysmem, base | 0x00000000, + memory_region_add_subregion(&s->container_mem, 0x00000000, &s->iomem); /* Then next 64 MB is reserved */ @@ -150,23 +186,19 @@ PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem, /* Socket Attribute Memory Space */ memory_region_init_io(&s->attr_iomem, NULL, &pxa2xx_pcmcia_attr_ops, s, "pxa2xx-pcmcia-attribute", 0x04000000); - memory_region_add_subregion(sysmem, base | 0x08000000, + memory_region_add_subregion(&s->container_mem, 0x08000000, &s->attr_iomem); /* Socket Common Memory Space */ memory_region_init_io(&s->common_iomem, NULL, &pxa2xx_pcmcia_common_ops, s, "pxa2xx-pcmcia-common", 0x04000000); - memory_region_add_subregion(sysmem, base | 0x0c000000, + memory_region_add_subregion(&s->container_mem, 0x0c000000, &s->common_iomem); - if (base == 0x30000000) - s->slot.slot_string = "PXA PC Card Socket 1"; - else - s->slot.slot_string = "PXA PC Card Socket 0"; s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0]; - pcmcia_socket_register(&s->slot); - return s; + object_property_add_link(obj, "card", TYPE_PCMCIA_CARD, + (Object **)&s->card, NULL); } /* Insert a new card into a slot */ @@ -227,3 +259,25 @@ void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq) s->irq = irq; s->cd_irq = cd_irq; } + +static void pxa2xx_pcmcia_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = pxa2xx_pcmcia_realize; +} + +static const TypeInfo pxa2xx_pcmcia_type_info = { + .name = TYPE_PXA2XX_PCMCIA, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(PXA2xxPCMCIAState), + .instance_init = pxa2xx_pcmcia_initfn, + .class_init = pxa2xx_pcmcia_class_init, +}; + +static void pxa2xx_pcmcia_register_types(void) +{ + type_register_static(&pxa2xx_pcmcia_type_info); +} + +type_init(pxa2xx_pcmcia_register_types)