diff options
author | Peter Maydell | 2020-12-11 14:50:35 +0100 |
---|---|---|
committer | Peter Maydell | 2020-12-11 14:50:35 +0100 |
commit | b785d25e91718a660546a6550f64b3c543af7754 (patch) | |
tree | a69f546d903351e4db899b8f080468ff12fe14e0 | |
parent | Merge remote-tracking branch 'remotes/ehabkost/tags/machine-next-pull-request... (diff) | |
parent | scripts: kernel-doc: remove unnecessary change wrt Linux (diff) | |
download | qemu-b785d25e91718a660546a6550f64b3c543af7754.tar.gz qemu-b785d25e91718a660546a6550f64b3c543af7754.tar.xz qemu-b785d25e91718a660546a6550f64b3c543af7754.zip |
Merge remote-tracking branch 'remotes/bonzini-gitlab/tags/for-upstream' into staging
* Fix for NULL segments (Bin Meng)
* Support for 32768 CPUs on x86 without IOMMU (David)
* PDEP/PEXT fix and testcase (myself)
* Remove bios_name and ram_size globals (myself)
* qemu_init rationalization (myself)
* Update kernel-doc (myself + upstream patches)
* Propagate MemTxResult across DMA and PCI functions (Philippe)
* Remove master/slave when applicable (Philippe)
* WHPX support for in-kernel irqchip (Sunil)
# gpg: Signature made Thu 10 Dec 2020 17:21:50 GMT
# gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83
# gpg: issuer "pbonzini@redhat.com"
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full]
# gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full]
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1
# Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83
* remotes/bonzini-gitlab/tags/for-upstream: (113 commits)
scripts: kernel-doc: remove unnecessary change wrt Linux
Revert "docs: temporarily disable the kernel-doc extension"
scripts: kernel-doc: use :c:union when needed
scripts: kernel-doc: split typedef complex regex
scripts: kernel-doc: fix typedef parsing
Revert "kernel-doc: Handle function typedefs that return pointers"
Revert "kernel-doc: Handle function typedefs without asterisks"
scripts: kernel-doc: try to use c:function if possible
scripts: kernel-doc: fix line number handling
scripts: kernel-doc: allow passing desired Sphinx C domain dialect
scripts: kernel-doc: don't mangle with parameter list
scripts: kernel-doc: fix typedef identification
scripts: kernel-doc: reimplement -nofunction argument
scripts: kernel-doc: fix troubles with line counts
scripts: kernel-doc: use a less pedantic markup for funcs on Sphinx 3.x
scripts: kernel-doc: make it more compatible with Sphinx 3.x
Revert "kernel-doc: Use c:struct for Sphinx 3.0 and later"
Revert "scripts/kerneldoc: For Sphinx 3 use c:macro for macros with arguments"
scripts: kernel-doc: add support for typedef enum
kernel-doc: add support for ____cacheline_aligned attribute
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
151 files changed, 2879 insertions, 1768 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index a83416d54c..aa39490a24 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -452,6 +452,7 @@ WHPX CPUs M: Sunil Muthuswamy <sunilmut@microsoft.com> S: Supported F: target/i386/whpx-all.c +F: target/i386/whpx-apic.c F: target/i386/whpx-cpus.c F: target/i386/whp-dispatch.h F: accel/stubs/whpx-stub.c diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst index 59c1225391..ee43f5dfee 100644 --- a/docs/devel/loads-stores.rst +++ b/docs/devel/loads-stores.rst @@ -483,6 +483,8 @@ make sure our existing code is doing things correctly. Regexes for git grep - ``\<dma_memory_\(read\|write\|rw\)\>`` + - ``\<ldu\?[bwlq]\(_[bl]e\)\?_dma\>`` + - ``\<st[bwlq]\(_[bl]e\)\?_dma\>`` ``pci_dma_*`` and ``{ld,st}*_pci_dma`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst index 5e9aef4db3..3be190343a 100644 --- a/docs/specs/tpm.rst +++ b/docs/specs/tpm.rst @@ -343,7 +343,7 @@ In case an Arm virt machine is emulated, use the following command line: -device tpm-tis-device,tpmdev=tpm0 \ -device virtio-blk-pci,drive=drv0 \ -drive format=qcow2,file=hda.qcow2,if=none,id=drv0 \ - -drive if=pflash,format=raw,file=flash0.img,readonly \ + -drive if=pflash,format=raw,file=flash0.img,readonly=on \ -drive if=pflash,format=raw,file=flash1.img In case SeaBIOS is used as firmware, it should show the TPM menu item diff --git a/docs/sphinx/kerneldoc.py b/docs/sphinx/kerneldoc.py index 3ac277d162..bf44215016 100644 --- a/docs/sphinx/kerneldoc.py +++ b/docs/sphinx/kerneldoc.py @@ -69,6 +69,11 @@ class KernelDocDirective(Directive): env = self.state.document.settings.env cmd = env.config.kerneldoc_bin + ['-rst', '-enable-lineno'] + # Pass the version string to kernel-doc, as it needs to use a different + # dialect, depending what the C domain supports for each specific + # Sphinx versions + cmd += ['-sphinx-version', sphinx.__version__] + filename = env.config.kerneldoc_srctree + '/' + self.arguments[0] export_file_patterns = [] @@ -99,7 +104,6 @@ class KernelDocDirective(Directive): env.note_dependency(os.path.abspath(f)) cmd += ['-export-file', f] - cmd += ['-sphinx-version', sphinx.__version__] cmd += [filename] try: diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c index 4d24518d1d..c8e300d93f 100644 --- a/hw/alpha/dp264.c +++ b/hw/alpha/dp264.c @@ -21,6 +21,7 @@ #include "hw/dma/i8257.h" #include "net/net.h" #include "qemu/cutils.h" +#include "qemu/datadir.h" #include "net/net.h" #define MAX_IDE_BUS 2 @@ -107,7 +108,7 @@ static void clipper_init(MachineState *machine) but one explicitly written for the emulation, we might as well load it directly from and ELF image. */ palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, - bios_name ? bios_name : "palcode-clipper"); + machine->firmware ?: "palcode-clipper"); if (palcode_filename == NULL) { error_report("no palcode provided"); exit(1); diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index bfe2051cfe..a17b75f494 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -309,7 +309,7 @@ static void aspeed_machine_init(MachineState *machine) /* * This will error out if isize is not supported by memory controller. */ - object_property_set_uint(OBJECT(&bmc->soc), "ram-size", ram_size, + object_property_set_uint(OBJECT(&bmc->soc), "ram-size", machine->ram_size, &error_fatal); for (i = 0; i < sc->macs_num; i++) { @@ -346,8 +346,8 @@ static void aspeed_machine_init(MachineState *machine) max_ram_size = object_property_get_uint(OBJECT(&bmc->soc), "max-ram-size", &error_abort); memory_region_init_io(&bmc->max_ram, NULL, &max_ram_ops, NULL, - "max_ram", max_ram_size - ram_size); - memory_region_add_subregion(&bmc->ram_container, ram_size, &bmc->max_ram); + "max_ram", max_ram_size - machine->ram_size); + memory_region_add_subregion(&bmc->ram_container, machine->ram_size, &bmc->max_ram); aspeed_board_init_flashes(&bmc->soc.fmc, bmc->fmc_model ? bmc->fmc_model : amc->fmc_model); @@ -392,7 +392,7 @@ static void aspeed_machine_init(MachineState *machine) aspeed_board_binfo.smp_loader_start = AST_SMP_MBOX_CODE; } - aspeed_board_binfo.ram_size = ram_size; + aspeed_board_binfo.ram_size = machine->ram_size; aspeed_board_binfo.loader_start = sc->memmap[ASPEED_DEV_SDRAM]; aspeed_board_binfo.nb_cpus = sc->num_cpus; diff --git a/hw/arm/boot.c b/hw/arm/boot.c index cf97600a91..4d9d47ba1c 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -9,6 +9,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/error-report.h" #include "qapi/error.h" #include <libfdt.h> diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c index 1c6c792eb6..9d0d728180 100644 --- a/hw/arm/cubieboard.c +++ b/hw/arm/cubieboard.c @@ -40,7 +40,7 @@ static void cubieboard_init(MachineState *machine) DeviceState *carddev; /* BIOS is not supported by this board */ - if (bios_name) { + if (machine->firmware) { error_report("BIOS not supported for this machine"); exit(1); } diff --git a/hw/arm/digic_boards.c b/hw/arm/digic_boards.c index d5524d3e72..be12873673 100644 --- a/hw/arm/digic_boards.c +++ b/hw/arm/digic_boards.c @@ -26,6 +26,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "cpu.h" #include "hw/boards.h" #include "exec/address-spaces.h" @@ -70,19 +71,20 @@ static void digic4_board_init(MachineState *machine, DigicBoard *board) memory_region_add_subregion(get_system_memory(), 0, machine->ram); if (board->add_rom0) { - board->add_rom0(s, DIGIC4_ROM0_BASE, board->rom0_def_filename); + board->add_rom0(s, DIGIC4_ROM0_BASE, + machine->firmware ?: board->rom0_def_filename); } if (board->add_rom1) { - board->add_rom1(s, DIGIC4_ROM1_BASE, board->rom1_def_filename); + board->add_rom1(s, DIGIC4_ROM1_BASE, + machine->firmware ?: board->rom1_def_filename); } } static void digic_load_rom(DigicState *s, hwaddr addr, - hwaddr max_size, const char *def_filename) + hwaddr max_size, const char *filename) { target_long rom_size; - const char *filename; if (qtest_enabled()) { /* qtest runs no code so don't attempt a ROM load which @@ -91,12 +93,6 @@ static void digic_load_rom(DigicState *s, hwaddr addr, return; } - if (bios_name) { - filename = bios_name; - } else { - filename = def_filename; - } - if (filename) { char *fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, filename); @@ -119,7 +115,7 @@ static void digic_load_rom(DigicState *s, hwaddr addr, * 64M Bit (4Mx16) Page Mode / Multi-Bank NOR Flash Memory */ static void digic4_add_k8p3215uqb_rom(DigicState *s, hwaddr addr, - const char *def_filename) + const char *filename) { #define FLASH_K8P3215UQB_SIZE (4 * 1024 * 1024) #define FLASH_K8P3215UQB_SECTOR_SIZE (64 * 1024) @@ -131,7 +127,7 @@ static void digic4_add_k8p3215uqb_rom(DigicState *s, hwaddr addr, 0x00EC, 0x007E, 0x0003, 0x0001, 0x0555, 0x2aa, 0); - digic_load_rom(s, addr, FLASH_K8P3215UQB_SIZE, def_filename); + digic_load_rom(s, addr, FLASH_K8P3215UQB_SIZE, filename); } static DigicBoard digic4_board_canon_a1100 = { diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c index f71087860d..bf7b8f4c64 100644 --- a/hw/arm/highbank.c +++ b/hw/arm/highbank.c @@ -19,6 +19,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qapi/error.h" #include "hw/sysbus.h" #include "migration/vmstate.h" @@ -297,16 +298,16 @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id) memory_region_init_ram(sysram, NULL, "highbank.sysram", 0x8000, &error_fatal); memory_region_add_subregion(sysmem, 0xfff88000, sysram); - if (bios_name != NULL) { - sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + if (machine->firmware != NULL) { + sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, machine->firmware); if (sysboot_filename != NULL) { if (load_image_targphys(sysboot_filename, 0xfff88000, 0x8000) < 0) { - error_report("Unable to load %s", bios_name); + error_report("Unable to load %s", machine->firmware); exit(1); } g_free(sysboot_filename); } else { - error_report("Unable to find %s", bios_name); + error_report("Unable to find %s", machine->firmware); exit(1); } } diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c index 79e2e2744c..306260fa67 100644 --- a/hw/arm/npcm7xx_boards.c +++ b/hw/arm/npcm7xx_boards.c @@ -23,6 +23,7 @@ #include "hw/qdev-properties.h" #include "qapi/error.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/units.h" #include "sysemu/sysemu.h" @@ -33,13 +34,10 @@ static const char npcm7xx_default_bootrom[] = "npcm7xx_bootrom.bin"; static void npcm7xx_load_bootrom(MachineState *machine, NPCM7xxState *soc) { + const char *bios_name = machine->firmware ?: npcm7xx_default_bootrom; g_autofree char *filename = NULL; int ret; - if (!bios_name) { - bios_name = npcm7xx_default_bootrom; - } - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (!filename) { error_report("Could not find ROM image '%s'", bios_name); diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c index 17a568a2b4..d6306dfdda 100644 --- a/hw/arm/orangepi.c +++ b/hw/arm/orangepi.c @@ -41,7 +41,7 @@ static void orangepi_init(MachineState *machine) DeviceState *carddev; /* BIOS is not supported by this board */ - if (bios_name) { + if (machine->firmware) { error_report("BIOS not supported for this machine"); exit(1); } diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c index 4a5ea42938..9f70735153 100644 --- a/hw/arm/sbsa-ref.c +++ b/hw/arm/sbsa-ref.c @@ -19,6 +19,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/units.h" @@ -319,6 +320,7 @@ static bool sbsa_firmware_init(SBSAMachineState *sms, MemoryRegion *sysmem, MemoryRegion *secure_sysmem) { + const char *bios_name; int i; BlockBackend *pflash_blk0; @@ -332,6 +334,7 @@ static bool sbsa_firmware_init(SBSAMachineState *sms, pflash_blk0 = pflash_cfi01_get_blk(sms->flash[0]); + bios_name = MACHINE(sms)->firmware; if (bios_name) { char *fname; MemoryRegion *mr; diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c index 772662f149..6b3bf9828b 100644 --- a/hw/arm/spitz.c +++ b/hw/arm/spitz.c @@ -578,7 +578,7 @@ static void spitz_keyboard_realize(DeviceState *dev, Error **errp) OBJECT_DECLARE_SIMPLE_TYPE(SpitzLCDTG, SPITZ_LCDTG) struct SpitzLCDTG { - SSISlave ssidev; + SSIPeripheral ssidev; uint32_t bl_intensity; uint32_t bl_power; }; @@ -612,7 +612,7 @@ static inline void spitz_bl_power(void *opaque, int line, int level) spitz_bl_update(s); } -static uint32_t spitz_lcdtg_transfer(SSISlave *dev, uint32_t value) +static uint32_t spitz_lcdtg_transfer(SSIPeripheral *dev, uint32_t value) { SpitzLCDTG *s = SPITZ_LCDTG(dev); int addr; @@ -641,7 +641,7 @@ static uint32_t spitz_lcdtg_transfer(SSISlave *dev, uint32_t value) return 0; } -static void spitz_lcdtg_realize(SSISlave *ssi, Error **errp) +static void spitz_lcdtg_realize(SSIPeripheral *ssi, Error **errp) { SpitzLCDTG *s = SPITZ_LCDTG(ssi); DeviceState *dev = DEVICE(s); @@ -667,12 +667,12 @@ OBJECT_DECLARE_SIMPLE_TYPE(CorgiSSPState, CORGI_SSP) /* "Demux" the signal based on current chipselect */ struct CorgiSSPState { - SSISlave ssidev; + SSIPeripheral ssidev; SSIBus *bus[3]; uint32_t enable[3]; }; -static uint32_t corgi_ssp_transfer(SSISlave *dev, uint32_t value) +static uint32_t corgi_ssp_transfer(SSIPeripheral *dev, uint32_t value) { CorgiSSPState *s = CORGI_SSP(dev); int i; @@ -700,7 +700,7 @@ static void corgi_ssp_gpio_cs(void *opaque, int line, int level) #define SPITZ_BATTERY_VOLT 0xd0 /* About 4.0V */ #define SPITZ_CHARGEON_ACIN 0x80 /* About 5.0V */ -static void corgi_ssp_realize(SSISlave *d, Error **errp) +static void corgi_ssp_realize(SSIPeripheral *d, Error **errp) { DeviceState *dev = DEVICE(d); CorgiSSPState *s = CORGI_SSP(d); @@ -715,14 +715,14 @@ static void spitz_ssp_attach(SpitzMachineState *sms) { void *bus; - sms->mux = ssi_create_slave(sms->mpu->ssp[CORGI_SSP_PORT - 1], - TYPE_CORGI_SSP); + sms->mux = ssi_create_peripheral(sms->mpu->ssp[CORGI_SSP_PORT - 1], + TYPE_CORGI_SSP); bus = qdev_get_child_bus(sms->mux, "ssi0"); - sms->lcdtg = ssi_create_slave(bus, TYPE_SPITZ_LCDTG); + sms->lcdtg = ssi_create_peripheral(bus, TYPE_SPITZ_LCDTG); bus = qdev_get_child_bus(sms->mux, "ssi1"); - sms->ads7846 = ssi_create_slave(bus, "ads7846"); + sms->ads7846 = ssi_create_peripheral(bus, "ads7846"); qdev_connect_gpio_out(sms->ads7846, 0, qdev_get_gpio_in(sms->mpu->gpio, SPITZ_GPIO_TP_INT)); @@ -1204,7 +1204,7 @@ static const VMStateDescription vmstate_corgi_ssp_regs = { .version_id = 2, .minimum_version_id = 2, .fields = (VMStateField[]) { - VMSTATE_SSI_SLAVE(ssidev, CorgiSSPState), + VMSTATE_SSI_PERIPHERAL(ssidev, CorgiSSPState), VMSTATE_UINT32_ARRAY(enable, CorgiSSPState, 3), VMSTATE_END_OF_LIST(), } @@ -1213,7 +1213,7 @@ static const VMStateDescription vmstate_corgi_ssp_regs = { static void corgi_ssp_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass); k->realize = corgi_ssp_realize; k->transfer = corgi_ssp_transfer; @@ -1222,7 +1222,7 @@ static void corgi_ssp_class_init(ObjectClass *klass, void *data) static const TypeInfo corgi_ssp_info = { .name = TYPE_CORGI_SSP, - .parent = TYPE_SSI_SLAVE, + .parent = TYPE_SSI_PERIPHERAL, .instance_size = sizeof(CorgiSSPState), .class_init = corgi_ssp_class_init, }; @@ -1232,7 +1232,7 @@ static const VMStateDescription vmstate_spitz_lcdtg_regs = { .version_id = 1, .minimum_version_id = 1, .fields = (VMStateField[]) { - VMSTATE_SSI_SLAVE(ssidev, SpitzLCDTG), + VMSTATE_SSI_PERIPHERAL(ssidev, SpitzLCDTG), VMSTATE_UINT32(bl_intensity, SpitzLCDTG), VMSTATE_UINT32(bl_power, SpitzLCDTG), VMSTATE_END_OF_LIST(), @@ -1242,7 +1242,7 @@ static const VMStateDescription vmstate_spitz_lcdtg_regs = { static void spitz_lcdtg_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass); k->realize = spitz_lcdtg_realize; k->transfer = spitz_lcdtg_transfer; @@ -1251,7 +1251,7 @@ static void spitz_lcdtg_class_init(ObjectClass *klass, void *data) static const TypeInfo spitz_lcdtg_info = { .name = TYPE_SPITZ_LCDTG, - .parent = TYPE_SSI_SLAVE, + .parent = TYPE_SSI_PERIPHERAL, .instance_size = sizeof(SpitzLCDTG), .class_init = spitz_lcdtg_class_init, }; diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c index 1237f5af02..652823195b 100644 --- a/hw/arm/stellaris.c +++ b/hw/arm/stellaris.c @@ -1397,8 +1397,8 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board) */ bus = qdev_get_child_bus(dev, "ssi"); - sddev = ssi_create_slave(bus, "ssi-sd"); - ssddev = ssi_create_slave(bus, "ssd0323"); + sddev = ssi_create_peripheral(bus, "ssi-sd"); + ssddev = ssi_create_peripheral(bus, "ssd0323"); gpio_out[GPIO_D][0] = qemu_irq_split( qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0), qdev_get_gpio_in_named(ssddev, SSI_GPIO_CS, 0)); diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c index 66b244aeff..d5a6763cf9 100644 --- a/hw/arm/tosa.c +++ b/hw/arm/tosa.c @@ -148,13 +148,13 @@ static void tosa_gpio_setup(PXA2xxState *cpu, qemu_irq_raise(qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_USB_IN)); } -static uint32_t tosa_ssp_tansfer(SSISlave *dev, uint32_t value) +static uint32_t tosa_ssp_tansfer(SSIPeripheral *dev, uint32_t value) { fprintf(stderr, "TG: %u %02x\n", value >> 5, value & 0x1f); return 0; } -static void tosa_ssp_realize(SSISlave *dev, Error **errp) +static void tosa_ssp_realize(SSIPeripheral *dev, Error **errp) { /* Nothing to do. */ } @@ -225,7 +225,7 @@ static void tosa_tg_init(PXA2xxState *cpu) { I2CBus *bus = pxa2xx_i2c_bus(cpu->i2c[0]); i2c_slave_create_simple(bus, TYPE_TOSA_DAC, DAC_BASE); - ssi_create_slave(cpu->ssp[1], "tosa-ssp"); + ssi_create_peripheral(cpu->ssp[1], "tosa-ssp"); } @@ -292,7 +292,7 @@ static const TypeInfo tosa_dac_info = { static void tosa_ssp_class_init(ObjectClass *klass, void *data) { - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass); k->realize = tosa_ssp_realize; k->transfer = tosa_ssp_tansfer; @@ -300,8 +300,8 @@ static void tosa_ssp_class_init(ObjectClass *klass, void *data) static const TypeInfo tosa_ssp_info = { .name = "tosa-ssp", - .parent = TYPE_SSI_SLAVE, - .instance_size = sizeof(SSISlave), + .parent = TYPE_SSI_PERIPHERAL, + .instance_size = sizeof(SSIPeripheral), .class_init = tosa_ssp_class_init, }; diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c index 531f3a122a..ac098375c1 100644 --- a/hw/arm/vexpress.c +++ b/hw/arm/vexpress.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "cpu.h" #include "hw/sysbus.h" #include "hw/arm/boot.h" @@ -560,7 +561,7 @@ static void vexpress_common_init(MachineState *machine) /* * If a bios file was provided, attempt to map it into memory */ - if (bios_name) { + if (machine->firmware) { char *fn; int image_size; @@ -570,16 +571,16 @@ static void vexpress_common_init(MachineState *machine) "but you cannot use both options at once"); exit(1); } - fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, machine->firmware); if (!fn) { - error_report("Could not find ROM image '%s'", bios_name); + error_report("Could not find ROM image '%s'", machine->firmware); exit(1); } image_size = load_image_targphys(fn, map[VE_NORFLASH0], VEXPRESS_FLASH_SIZE); g_free(fn); if (image_size < 0) { - error_report("Could not load ROM image '%s'", bios_name); + error_report("Could not load ROM image '%s'", machine->firmware); exit(1); } } diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 22572c32b7..556592012e 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -30,6 +30,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/units.h" #include "qemu/option.h" #include "monitor/qdev.h" @@ -1047,6 +1048,7 @@ static bool virt_firmware_init(VirtMachineState *vms, MemoryRegion *secure_sysmem) { int i; + const char *bios_name; BlockBackend *pflash_blk0; /* Map legacy -drive if=pflash to machine properties */ @@ -1059,6 +1061,7 @@ static bool virt_firmware_init(VirtMachineState *vms, pflash_blk0 = pflash_cfi01_get_blk(vms->flash[0]); + bios_name = MACHINE(vms)->firmware; if (bios_name) { char *fname; MemoryRegion *mr; diff --git a/hw/arm/z2.c b/hw/arm/z2.c index 4fc5699dae..308c4da956 100644 --- a/hw/arm/z2.c +++ b/hw/arm/z2.c @@ -104,7 +104,7 @@ static struct arm_boot_info z2_binfo = { #define Z2_GPIO_LCD_CS 88 struct ZipitLCD { - SSISlave ssidev; + SSIPeripheral ssidev; int32_t selected; int32_t enabled; uint8_t buf[3]; @@ -115,7 +115,7 @@ struct ZipitLCD { #define TYPE_ZIPIT_LCD "zipit-lcd" OBJECT_DECLARE_SIMPLE_TYPE(ZipitLCD, ZIPIT_LCD) -static uint32_t zipit_lcd_transfer(SSISlave *dev, uint32_t value) +static uint32_t zipit_lcd_transfer(SSIPeripheral *dev, uint32_t value) { ZipitLCD *z = ZIPIT_LCD(dev); uint16_t val; @@ -155,7 +155,7 @@ static void z2_lcd_cs(void *opaque, int line, int level) z2_lcd->selected = !level; } -static void zipit_lcd_realize(SSISlave *dev, Error **errp) +static void zipit_lcd_realize(SSIPeripheral *dev, Error **errp) { ZipitLCD *z = ZIPIT_LCD(dev); z->selected = 0; @@ -168,7 +168,7 @@ static VMStateDescription vmstate_zipit_lcd_state = { .version_id = 2, .minimum_version_id = 2, .fields = (VMStateField[]) { - VMSTATE_SSI_SLAVE(ssidev, ZipitLCD), + VMSTATE_SSI_PERIPHERAL(ssidev, ZipitLCD), VMSTATE_INT32(selected, ZipitLCD), VMSTATE_INT32(enabled, ZipitLCD), VMSTATE_BUFFER(buf, ZipitLCD), @@ -181,7 +181,7 @@ static VMStateDescription vmstate_zipit_lcd_state = { static void zipit_lcd_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass); k->realize = zipit_lcd_realize; k->transfer = zipit_lcd_transfer; @@ -190,7 +190,7 @@ static void zipit_lcd_class_init(ObjectClass *klass, void *data) static const TypeInfo zipit_lcd_info = { .name = TYPE_ZIPIT_LCD, - .parent = TYPE_SSI_SLAVE, + .parent = TYPE_SSI_PERIPHERAL, .instance_size = sizeof(ZipitLCD), .class_init = zipit_lcd_class_init, }; @@ -329,7 +329,7 @@ static void z2_init(MachineState *machine) type_register_static(&zipit_lcd_info); type_register_static(&aer915_info); - z2_lcd = ssi_create_slave(mpu->ssp[1], TYPE_ZIPIT_LCD); + z2_lcd = ssi_create_peripheral(mpu->ssp[1], TYPE_ZIPIT_LCD); bus = pxa2xx_i2c_bus(mpu->i2c[0]); i2c_slave_create_simple(bus, TYPE_AER915, 0x55); wm = DEVICE(i2c_slave_create_simple(bus, TYPE_WM8750, 0x1b)); diff --git a/hw/avr/boot.c b/hw/avr/boot.c index d16bb3dbe1..cbede775ce 100644 --- a/hw/avr/boot.c +++ b/hw/avr/boot.c @@ -10,6 +10,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "hw/loader.h" #include "elf.h" #include "boot.h" diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c index 483925f57a..d09a811767 100644 --- a/hw/block/m25p80.c +++ b/hw/block/m25p80.c @@ -416,7 +416,7 @@ typedef enum { #define M25P80_INTERNAL_DATA_BUFFER_SZ 16 struct Flash { - SSISlave parent_obj; + SSIPeripheral parent_obj; BlockBackend *blk; @@ -458,7 +458,7 @@ struct Flash { }; struct M25P80Class { - SSISlaveClass parent_class; + SSIPeripheralClass parent_class; FlashPartInfo *pi; }; @@ -1170,7 +1170,7 @@ static void decode_new_cmd(Flash *s, uint32_t value) } } -static int m25p80_cs(SSISlave *ss, bool select) +static int m25p80_cs(SSIPeripheral *ss, bool select) { Flash *s = M25P80(ss); @@ -1190,7 +1190,7 @@ static int m25p80_cs(SSISlave *ss, bool select) return 0; } -static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx) +static uint32_t m25p80_transfer8(SSIPeripheral *ss, uint32_t tx) { Flash *s = M25P80(ss); uint32_t r = 0; @@ -1265,7 +1265,7 @@ static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx) return r; } -static void m25p80_realize(SSISlave *ss, Error **errp) +static void m25p80_realize(SSIPeripheral *ss, Error **errp) { Flash *s = M25P80(ss); M25P80Class *mc = M25P80_GET_CLASS(s); @@ -1386,7 +1386,7 @@ static const VMStateDescription vmstate_m25p80 = { static void m25p80_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass); M25P80Class *mc = M25P80_CLASS(klass); k->realize = m25p80_realize; @@ -1401,7 +1401,7 @@ static void m25p80_class_init(ObjectClass *klass, void *data) static const TypeInfo m25p80_info = { .name = TYPE_M25P80, - .parent = TYPE_SSI_SLAVE, + .parent = TYPE_SSI_PERIPHERAL, .instance_size = sizeof(Flash), .class_size = sizeof(M25P80Class), .abstract = true, diff --git a/hw/char/serial.c b/hw/char/serial.c index 97f71879ff..62c627f486 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -24,6 +24,7 @@ */ #include "qemu/osdep.h" +#include "qemu/bitops.h" #include "hw/char/serial.h" #include "hw/irq.h" #include "migration/vmstate.h" @@ -338,11 +339,7 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val, default: case 0: if (s->lcr & UART_LCR_DLAB) { - if (size == 1) { - s->divider = (s->divider & 0xff00) | val; - } else { - s->divider = val; - } + s->divider = deposit32(s->divider, 8 * addr, 8, val); serial_update_parameters(s); } else { s->thr = (uint8_t) val; @@ -364,7 +361,7 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val, break; case 1: if (s->lcr & UART_LCR_DLAB) { - s->divider = (s->divider & 0x00ff) | (val << 8); + s->divider = deposit32(s->divider, 8 * addr, 8, val); serial_update_parameters(s); } else { uint8_t changed = (s->ier ^ val) & 0x0f; @@ -478,7 +475,7 @@ static uint64_t serial_ioport_read(void *opaque, hwaddr addr, unsigned size) default: case 0: if (s->lcr & UART_LCR_DLAB) { - ret = s->divider & 0xff; + ret = extract16(s->divider, 8 * addr, 8); } else { if(s->fcr & UART_FCR_FE) { ret = fifo8_is_empty(&s->recv_fifo) ? @@ -502,7 +499,7 @@ static uint64_t serial_ioport_read(void *opaque, hwaddr addr, unsigned size) break; case 1: if (s->lcr & UART_LCR_DLAB) { - ret = (s->divider >> 8) & 0xff; + ret = extract16(s->divider, 8 * addr, 8); } else { ret = s->ier; } diff --git a/hw/core/generic-loader.c b/hw/core/generic-loader.c index a242c076f6..2b2a7b5e9a 100644 --- a/hw/core/generic-loader.c +++ b/hw/core/generic-loader.c @@ -35,6 +35,7 @@ #include "hw/sysbus.h" #include "sysemu/dma.h" #include "sysemu/reset.h" +#include "hw/boards.h" #include "hw/loader.h" #include "hw/qdev-properties.h" #include "qapi/error.h" @@ -154,7 +155,7 @@ static void generic_loader_realize(DeviceState *dev, Error **errp) if (size < 0 || s->force_raw) { /* Default to the maximum size being the machine's ram size */ - size = load_image_targphys_as(s->file, s->addr, ram_size, as); + size = load_image_targphys_as(s->file, s->addr, current_machine->ram_size, as); } else { s->addr = entry; } diff --git a/hw/core/loader.c b/hw/core/loader.c index 8bbb1797a4..fea22d265c 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -44,6 +44,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qapi/error.h" #include "trace.h" #include "hw/hw.h" diff --git a/hw/core/machine.c b/hw/core/machine.c index 9c41b94e0d..d7f8fdee45 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -877,9 +877,13 @@ static void machine_initfn(Object *obj) MachineState *ms = MACHINE(obj); MachineClass *mc = MACHINE_GET_CLASS(obj); + container_get(obj, "/peripheral"); + container_get(obj, "/peripheral-anon"); + ms->dump_guest_core = true; ms->mem_merge = true; ms->enable_graphics = true; + ms->kernel_cmdline = g_strdup(""); if (mc->nvdimm_supported) { Object *obj = OBJECT(ms); @@ -1077,12 +1081,40 @@ MemoryRegion *machine_consume_memdev(MachineState *machine, return ret; } +bool machine_smp_parse(MachineState *ms, QemuOpts *opts, Error **errp) +{ + MachineClass *mc = MACHINE_GET_CLASS(ms); + + mc->smp_parse(ms, opts); + + /* sanity-check smp_cpus and max_cpus against mc */ + if (ms->smp.cpus < mc->min_cpus) { + error_setg(errp, "Invalid SMP CPUs %d. The min CPUs " + "supported by machine '%s' is %d", + ms->smp.cpus, + mc->name, mc->min_cpus); + return false; + } else if (ms->smp.max_cpus > mc->max_cpus) { + error_setg(errp, "Invalid SMP CPUs %d. The max CPUs " + "supported by machine '%s' is %d", + current_machine->smp.max_cpus, + mc->name, mc->max_cpus); + return false; + } + return true; +} + void machine_run_board_init(MachineState *machine) { MachineClass *machine_class = MACHINE_GET_CLASS(machine); ObjectClass *oc = object_class_by_name(machine->cpu_type); CPUClass *cc; + /* This checkpoint is required by replay to separate prior clock + reading from the other reads, because timer polling functions query + clock values from the log. */ + replay_checkpoint(CHECKPOINT_INIT); + if (machine->ram_memdev_id) { Object *o; o = object_resolve_path_type(machine->ram_memdev_id, @@ -1137,6 +1169,30 @@ void machine_run_board_init(MachineState *machine) machine_class->init(machine); } +static NotifierList machine_init_done_notifiers = + NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers); + +bool machine_init_done; + +void qemu_add_machine_init_done_notifier(Notifier *notify) +{ + notifier_list_add(&machine_init_done_notifiers, notify); + if (machine_init_done) { + notify->notify(notify, NULL); + } +} + +void qemu_remove_machine_init_done_notifier(Notifier *notify) +{ + notifier_remove(notify); +} + +void qemu_run_machine_init_done_notifiers(void) +{ + machine_init_done = true; + notifier_list_notify(&machine_init_done_notifiers, NULL); +} + static const TypeInfo machine_info = { .name = TYPE_MACHINE, .parent = TYPE_OBJECT, diff --git a/hw/core/numa.c b/hw/core/numa.c index 7c4dd4e68e..68cee65f61 100644 --- a/hw/core/numa.c +++ b/hw/core/numa.c @@ -642,7 +642,7 @@ void numa_complete_configuration(MachineState *ms) /* * If memory hotplug is enabled (slot > 0) or memory devices are enabled - * (ms->maxram_size > ram_size) but without '-numa' options explicitly on + * (ms->maxram_size > ms->ram_size) but without '-numa' options explicitly on * CLI, guests will break. * * Windows: won't enable memory hotplug without SRAT table at all @@ -663,7 +663,7 @@ void numa_complete_configuration(MachineState *ms) mc->auto_enable_numa)) { NumaNodeOptions node = { }; parse_numa_node(ms, &node, &error_abort); - numa_info[0].node_mem = ram_size; + numa_info[0].node_mem = ms->ram_size; } assert(max_numa_nodeid <= MAX_NODES); @@ -687,10 +687,10 @@ void numa_complete_configuration(MachineState *ms) for (i = 0; i < ms->numa_state->num_nodes; i++) { numa_total += numa_info[i].node_mem; } - if (numa_total != ram_size) { + if (numa_total != ms->ram_size) { error_report("total memory for NUMA nodes (0x%" PRIx64 ")" " should equal RAM size (0x" RAM_ADDR_FMT ")", - numa_total, ram_size); + numa_total, ms->ram_size); exit(1); } @@ -702,7 +702,7 @@ void numa_complete_configuration(MachineState *ms) } ms->ram = g_new(MemoryRegion, 1); memory_region_init(ms->ram, OBJECT(ms), mc->default_ram_id, - ram_size); + ms->ram_size); numa_init_memdev_container(ms, ms->ram); } /* QEMU needs at least all unique node pair distances to build diff --git a/hw/core/stream.c b/hw/core/stream.c index a65ad1208d..19477d0f2d 100644 --- a/hw/core/stream.c +++ b/hw/core/stream.c @@ -3,32 +3,32 @@ #include "qemu/module.h" size_t -stream_push(StreamSlave *sink, uint8_t *buf, size_t len, bool eop) +stream_push(StreamSink *sink, uint8_t *buf, size_t len, bool eop) { - StreamSlaveClass *k = STREAM_SLAVE_GET_CLASS(sink); + StreamSinkClass *k = STREAM_SINK_GET_CLASS(sink); return k->push(sink, buf, len, eop); } bool -stream_can_push(StreamSlave *sink, StreamCanPushNotifyFn notify, +stream_can_push(StreamSink *sink, StreamCanPushNotifyFn notify, void *notify_opaque) { - StreamSlaveClass *k = STREAM_SLAVE_GET_CLASS(sink); + StreamSinkClass *k = STREAM_SINK_GET_CLASS(sink); return k->can_push ? k->can_push(sink, notify, notify_opaque) : true; } -static const TypeInfo stream_slave_info = { - .name = TYPE_STREAM_SLAVE, +static const TypeInfo stream_sink_info = { + .name = TYPE_STREAM_SINK, .parent = TYPE_INTERFACE, - .class_size = sizeof(StreamSlaveClass), + .class_size = sizeof(StreamSinkClass), }; -static void stream_slave_register_types(void) +static void stream_sink_register_types(void) { - type_register_static(&stream_slave_info); + type_register_static(&stream_sink_info); } -type_init(stream_slave_register_types) +type_init(stream_sink_register_types) diff --git a/hw/cris/axis_dev88.c b/hw/cris/axis_dev88.c index dab7423c73..b0cb6d84af 100644 --- a/hw/cris/axis_dev88.c +++ b/hw/cris/axis_dev88.c @@ -333,6 +333,7 @@ void axisdev88_init(MachineState *machine) if (kernel_filename) { li.image_filename = kernel_filename; li.cmdline = kernel_cmdline; + li.ram_size = machine->ram_size; cris_load_image(cpu, &li); } else if (!qtest_enabled()) { fprintf(stderr, "Kernel image must be specified\n"); diff --git a/hw/cris/boot.c b/hw/cris/boot.c index aa8d2756d6..9fa09cfd83 100644 --- a/hw/cris/boot.c +++ b/hw/cris/boot.c @@ -81,7 +81,7 @@ void cris_load_image(CRISCPU *cpu, struct cris_load_info *li) if (image_size < 0) { /* Takes a kimage from the axis devboard SDK. */ image_size = load_image_targphys(li->image_filename, 0x40004000, - ram_size); + li->ram_size); li->entry = 0x40004000; } diff --git a/hw/cris/boot.h b/hw/cris/boot.h index 218854e5d1..9f1e0e340c 100644 --- a/hw/cris/boot.h +++ b/hw/cris/boot.h @@ -6,6 +6,7 @@ struct cris_load_info const char *image_filename; const char *cmdline; int image_size; + ram_addr_t ram_size; hwaddr entry; }; diff --git a/hw/display/ads7846.c b/hw/display/ads7846.c index cb3a431cfd..1d4e04a2dc 100644 --- a/hw/display/ads7846.c +++ b/hw/display/ads7846.c @@ -19,7 +19,7 @@ #include "qom/object.h" struct ADS7846State { - SSISlave ssidev; + SSIPeripheral ssidev; qemu_irq interrupt; int input[8]; @@ -63,7 +63,7 @@ static void ads7846_int_update(ADS7846State *s) qemu_set_irq(s->interrupt, s->pressure == 0); } -static uint32_t ads7846_transfer(SSISlave *dev, uint32_t value) +static uint32_t ads7846_transfer(SSIPeripheral *dev, uint32_t value) { ADS7846State *s = ADS7846(dev); @@ -131,7 +131,7 @@ static const VMStateDescription vmstate_ads7846 = { .minimum_version_id = 1, .post_load = ads7856_post_load, .fields = (VMStateField[]) { - VMSTATE_SSI_SLAVE(ssidev, ADS7846State), + VMSTATE_SSI_PERIPHERAL(ssidev, ADS7846State), VMSTATE_INT32_ARRAY(input, ADS7846State, 8), VMSTATE_INT32(noise, ADS7846State), VMSTATE_INT32(cycle, ADS7846State), @@ -140,7 +140,7 @@ static const VMStateDescription vmstate_ads7846 = { } }; -static void ads7846_realize(SSISlave *d, Error **errp) +static void ads7846_realize(SSIPeripheral *d, Error **errp) { DeviceState *dev = DEVICE(d); ADS7846State *s = ADS7846(d); @@ -164,7 +164,7 @@ static void ads7846_realize(SSISlave *d, Error **errp) static void ads7846_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass); k->realize = ads7846_realize; k->transfer = ads7846_transfer; @@ -173,7 +173,7 @@ static void ads7846_class_init(ObjectClass *klass, void *data) static const TypeInfo ads7846_info = { .name = TYPE_ADS7846, - .parent = TYPE_SSI_SLAVE, + .parent = TYPE_SSI_PERIPHERAL, .instance_size = sizeof(ADS7846State), .class_init = ads7846_class_init, }; diff --git a/hw/display/cg3.c b/hw/display/cg3.c index 42fcf40010..4b7e78d919 100644 --- a/hw/display/cg3.c +++ b/hw/display/cg3.c @@ -25,6 +25,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qapi/error.h" #include "qemu/error-report.h" #include "ui/console.h" diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c index ff90104b80..dfff994962 100644 --- a/hw/display/pxa2xx_lcd.c +++ b/hw/display/pxa2xx_lcd.c @@ -17,6 +17,7 @@ #include "ui/console.h" #include "hw/arm/pxa.h" #include "ui/pixel_ops.h" +#include "hw/boards.h" /* FIXME: For graphic_rotate. Should probably be done in common code. */ #include "sysemu/sysemu.h" #include "framebuffer.h" @@ -305,7 +306,7 @@ static void pxa2xx_descriptor_load(PXA2xxLCDState *s) descptr = s->dma_ch[i].descriptor; if (!((descptr >= PXA2XX_SDRAM_BASE && descptr + - sizeof(desc) <= PXA2XX_SDRAM_BASE + ram_size) || + sizeof(desc) <= PXA2XX_SDRAM_BASE + current_machine->ram_size) || (descptr >= PXA2XX_INTERNAL_BASE && descptr + sizeof(desc) <= PXA2XX_INTERNAL_BASE + PXA2XX_INTERNAL_SIZE))) { continue; @@ -850,7 +851,7 @@ static void pxa2xx_update_display(void *opaque) } fbptr = s->dma_ch[ch].source; if (!((fbptr >= PXA2XX_SDRAM_BASE && - fbptr <= PXA2XX_SDRAM_BASE + ram_size) || + fbptr <= PXA2XX_SDRAM_BASE + current_machine->ram_size) || (fbptr >= PXA2XX_INTERNAL_BASE && fbptr <= PXA2XX_INTERNAL_BASE + PXA2XX_INTERNAL_SIZE))) { pxa2xx_dma_ber_set(s, ch); diff --git a/hw/display/ssd0323.c b/hw/display/ssd0323.c index cbfd21dfd5..ab229d32b7 100644 --- a/hw/display/ssd0323.c +++ b/hw/display/ssd0323.c @@ -49,7 +49,7 @@ enum ssd0323_mode }; struct ssd0323_state { - SSISlave ssidev; + SSIPeripheral ssidev; QemuConsole *con; uint32_t cmd_len; @@ -71,7 +71,7 @@ struct ssd0323_state { OBJECT_DECLARE_SIMPLE_TYPE(ssd0323_state, SSD0323) -static uint32_t ssd0323_transfer(SSISlave *dev, uint32_t data) +static uint32_t ssd0323_transfer(SSIPeripheral *dev, uint32_t data) { ssd0323_state *s = SSD0323(dev); @@ -338,7 +338,7 @@ static const VMStateDescription vmstate_ssd0323 = { VMSTATE_INT32(remap, ssd0323_state), VMSTATE_UINT32(mode, ssd0323_state), VMSTATE_BUFFER(framebuffer, ssd0323_state), - VMSTATE_SSI_SLAVE(ssidev, ssd0323_state), + VMSTATE_SSI_PERIPHERAL(ssidev, ssd0323_state), VMSTATE_END_OF_LIST() } }; @@ -348,7 +348,7 @@ static const GraphicHwOps ssd0323_ops = { .gfx_update = ssd0323_update_display, }; -static void ssd0323_realize(SSISlave *d, Error **errp) +static void ssd0323_realize(SSIPeripheral *d, Error **errp) { DeviceState *dev = DEVICE(d); ssd0323_state *s = SSD0323(d); @@ -364,7 +364,7 @@ static void ssd0323_realize(SSISlave *d, Error **errp) static void ssd0323_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass); k->realize = ssd0323_realize; k->transfer = ssd0323_transfer; @@ -375,7 +375,7 @@ static void ssd0323_class_init(ObjectClass *klass, void *data) static const TypeInfo ssd0323_info = { .name = TYPE_SSD0323, - .parent = TYPE_SSI_SLAVE, + .parent = TYPE_SSI_PERIPHERAL, .instance_size = sizeof(ssd0323_state), .class_init = ssd0323_class_init, }; diff --git a/hw/display/tcx.c b/hw/display/tcx.c index 3799d29b75..965f92ff6b 100644 --- a/hw/display/tcx.c +++ b/hw/display/tcx.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qapi/error.h" #include "ui/console.h" #include "ui/pixel_ops.h" diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c index 0a7f5acb4b..bc383f53cc 100644 --- a/hw/dma/xilinx_axidma.c +++ b/hw/dma/xilinx_axidma.c @@ -45,11 +45,11 @@ OBJECT_DECLARE_SIMPLE_TYPE(XilinxAXIDMA, XILINX_AXI_DMA) -typedef struct XilinxAXIDMAStreamSlave XilinxAXIDMAStreamSlave; -DECLARE_INSTANCE_CHECKER(XilinxAXIDMAStreamSlave, XILINX_AXI_DMA_DATA_STREAM, +typedef struct XilinxAXIDMAStreamSink XilinxAXIDMAStreamSink; +DECLARE_INSTANCE_CHECKER(XilinxAXIDMAStreamSink, XILINX_AXI_DMA_DATA_STREAM, TYPE_XILINX_AXI_DMA_DATA_STREAM) -DECLARE_INSTANCE_CHECKER(XilinxAXIDMAStreamSlave, XILINX_AXI_DMA_CONTROL_STREAM, +DECLARE_INSTANCE_CHECKER(XilinxAXIDMAStreamSink, XILINX_AXI_DMA_CONTROL_STREAM, TYPE_XILINX_AXI_DMA_CONTROL_STREAM) #define R_DMACR (0x00 / 4) @@ -115,7 +115,7 @@ struct Stream { unsigned char txbuf[16 * 1024]; }; -struct XilinxAXIDMAStreamSlave { +struct XilinxAXIDMAStreamSink { Object parent; struct XilinxAXIDMA *dma; @@ -128,10 +128,10 @@ struct XilinxAXIDMA { AddressSpace as; uint32_t freqhz; - StreamSlave *tx_data_dev; - StreamSlave *tx_control_dev; - XilinxAXIDMAStreamSlave rx_data_dev; - XilinxAXIDMAStreamSlave rx_control_dev; + StreamSink *tx_data_dev; + StreamSink *tx_control_dev; + XilinxAXIDMAStreamSink rx_data_dev; + XilinxAXIDMAStreamSink rx_control_dev; struct Stream streams[2]; @@ -261,8 +261,8 @@ static void stream_complete(struct Stream *s) ptimer_transaction_commit(s->ptimer); } -static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev, - StreamSlave *tx_control_dev) +static void stream_process_mem2s(struct Stream *s, StreamSink *tx_data_dev, + StreamSink *tx_control_dev) { uint32_t prev_d; uint32_t txlen; @@ -384,10 +384,10 @@ static void xilinx_axidma_reset(DeviceState *dev) } static size_t -xilinx_axidma_control_stream_push(StreamSlave *obj, unsigned char *buf, +xilinx_axidma_control_stream_push(StreamSink *obj, unsigned char *buf, size_t len, bool eop) { - XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM(obj); + XilinxAXIDMAStreamSink *cs = XILINX_AXI_DMA_CONTROL_STREAM(obj); struct Stream *s = &cs->dma->streams[1]; if (len != CONTROL_PAYLOAD_SIZE) { @@ -400,11 +400,11 @@ xilinx_axidma_control_stream_push(StreamSlave *obj, unsigned char *buf, } static bool -xilinx_axidma_data_stream_can_push(StreamSlave *obj, +xilinx_axidma_data_stream_can_push(StreamSink *obj, StreamCanPushNotifyFn notify, void *notify_opaque) { - XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(obj); + XilinxAXIDMAStreamSink *ds = XILINX_AXI_DMA_DATA_STREAM(obj); struct Stream *s = &ds->dma->streams[1]; if (!stream_running(s) || stream_idle(s)) { @@ -417,10 +417,10 @@ xilinx_axidma_data_stream_can_push(StreamSlave *obj, } static size_t -xilinx_axidma_data_stream_push(StreamSlave *obj, unsigned char *buf, size_t len, +xilinx_axidma_data_stream_push(StreamSink *obj, unsigned char *buf, size_t len, bool eop) { - XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(obj); + XilinxAXIDMAStreamSink *ds = XILINX_AXI_DMA_DATA_STREAM(obj); struct Stream *s = &ds->dma->streams[1]; size_t ret; @@ -531,8 +531,8 @@ static const MemoryRegionOps axidma_ops = { static void xilinx_axidma_realize(DeviceState *dev, Error **errp) { XilinxAXIDMA *s = XILINX_AXI_DMA(dev); - XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(&s->rx_data_dev); - XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM( + XilinxAXIDMAStreamSink *ds = XILINX_AXI_DMA_DATA_STREAM(&s->rx_data_dev); + XilinxAXIDMAStreamSink *cs = XILINX_AXI_DMA_CONTROL_STREAM( &s->rx_control_dev); int i; @@ -588,9 +588,9 @@ static void xilinx_axidma_init(Object *obj) static Property axidma_properties[] = { DEFINE_PROP_UINT32("freqhz", XilinxAXIDMA, freqhz, 50000000), DEFINE_PROP_LINK("axistream-connected", XilinxAXIDMA, - tx_data_dev, TYPE_STREAM_SLAVE, StreamSlave *), + tx_data_dev, TYPE_STREAM_SINK, StreamSink *), DEFINE_PROP_LINK("axistream-control-connected", XilinxAXIDMA, - tx_control_dev, TYPE_STREAM_SLAVE, StreamSlave *), + tx_control_dev, TYPE_STREAM_SINK, StreamSink *), DEFINE_PROP_END_OF_LIST(), }; @@ -603,21 +603,21 @@ static void axidma_class_init(ObjectClass *klass, void *data) device_class_set_props(dc, axidma_properties); } -static StreamSlaveClass xilinx_axidma_data_stream_class = { +static StreamSinkClass xilinx_axidma_data_stream_class = { .push = xilinx_axidma_data_stream_push, .can_push = xilinx_axidma_data_stream_can_push, }; -static StreamSlaveClass xilinx_axidma_control_stream_class = { +static StreamSinkClass xilinx_axidma_control_stream_class = { .push = xilinx_axidma_control_stream_push, }; static void xilinx_axidma_stream_class_init(ObjectClass *klass, void *data) { - StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass); + StreamSinkClass *ssc = STREAM_SINK_CLASS(klass); - ssc->push = ((StreamSlaveClass *)data)->push; - ssc->can_push = ((StreamSlaveClass *)data)->can_push; + ssc->push = ((StreamSinkClass *)data)->push; + ssc->can_push = ((StreamSinkClass *)data)->can_push; } static const TypeInfo axidma_info = { @@ -631,11 +631,11 @@ static const TypeInfo axidma_info = { static const TypeInfo xilinx_axidma_data_stream_info = { .name = TYPE_XILINX_AXI_DMA_DATA_STREAM, .parent = TYPE_OBJECT, - .instance_size = sizeof(XilinxAXIDMAStreamSlave), + .instance_size = sizeof(XilinxAXIDMAStreamSink), .class_init = xilinx_axidma_stream_class_init, .class_data = &xilinx_axidma_data_stream_class, .interfaces = (InterfaceInfo[]) { - { TYPE_STREAM_SLAVE }, + { TYPE_STREAM_SINK }, { } } }; @@ -643,11 +643,11 @@ static const TypeInfo xilinx_axidma_data_stream_info = { static const TypeInfo xilinx_axidma_control_stream_info = { .name = TYPE_XILINX_AXI_DMA_CONTROL_STREAM, .parent = TYPE_OBJECT, - .instance_size = sizeof(XilinxAXIDMAStreamSlave), + .instance_size = sizeof(XilinxAXIDMAStreamSink), .class_init = xilinx_axidma_stream_class_init, .class_data = &xilinx_axidma_control_stream_class, .interfaces = (InterfaceInfo[]) { - { TYPE_STREAM_SLAVE }, + { TYPE_STREAM_SINK }, { } } }; diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c index d5164457ee..f2b71db9bd 100644 --- a/hw/hppa/machine.c +++ b/hw/hppa/machine.c @@ -5,6 +5,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "cpu.h" #include "elf.h" #include "hw/loader.h" @@ -97,7 +98,7 @@ static FWCfgState *create_fw_cfg(MachineState *ms) fw_cfg = fw_cfg_init_mem(FW_CFG_IO_BASE, FW_CFG_IO_BASE + 4); fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, ms->smp.cpus); fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, HPPA_MAX_CPUS); - fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, ram_size); + fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, ms->ram_size); val = cpu_to_le64(MIN_SEABIOS_HPPA_VERSION); fw_cfg_add_file(fw_cfg, "/etc/firmware-min-version", @@ -213,8 +214,7 @@ static void machine_hppa_init(MachineState *machine) but one explicitly written for the emulation, we might as well load it directly from an ELF image. */ firmware_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, - bios_name ? bios_name : - "hppa-firmware.img"); + machine->firmware ?: "hppa-firmware.img"); if (firmware_filename == NULL) { error_report("no firmware provided"); exit(1); @@ -289,7 +289,7 @@ static void machine_hppa_init(MachineState *machine) (1) Due to sign-extension problems and PDC, put the initrd no higher than 1G. (2) Reserve 64k for stack. */ - initrd_base = MIN(ram_size, 1 * GiB); + initrd_base = MIN(machine->ram_size, 1 * GiB); initrd_base = initrd_base - 64 * KiB; initrd_base = (initrd_base - initrd_size) & TARGET_PAGE_MASK; @@ -317,7 +317,7 @@ static void machine_hppa_init(MachineState *machine) * various parameters in registers. After firmware initialization, * firmware will start the Linux kernel with ramdisk and cmdline. */ - cpu[0]->env.gr[26] = ram_size; + cpu[0]->env.gr[26] = machine->ram_size; cpu[0]->env.gr[25] = kernel_entry; /* tell firmware how many SMP CPUs to present in inventory table */ @@ -343,11 +343,11 @@ static void hppa_machine_reset(MachineState *ms) } /* already initialized by machine_hppa_init()? */ - if (cpu[0]->env.gr[26] == ram_size) { + if (cpu[0]->env.gr[26] == ms->ram_size) { return; } - cpu[0]->env.gr[26] = ram_size; + cpu[0]->env.gr[26] = ms->ram_size; cpu[0]->env.gr[25] = 0; /* no firmware boot menu */ cpu[0]->env.gr[24] = 'c'; /* gr22/gr23 unused, no initrd while reboot. */ diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c index e06579490c..b87f0e5070 100644 --- a/hw/i386/fw_cfg.c +++ b/hw/i386/fw_cfg.c @@ -118,7 +118,7 @@ FWCfgState *fw_cfg_arch_create(MachineState *ms, * "etc/max-cpus" actually being apic_id_limit */ fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, apic_id_limit); - fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); + fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, ms->ram_size); #ifdef CONFIG_ACPI fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES, acpi_tables, acpi_tables_len); diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c index dd29906061..b226b674e8 100644 --- a/hw/i386/kvm/apic.c +++ b/hw/i386/kvm/apic.c @@ -183,6 +183,13 @@ static void kvm_send_msi(MSIMessage *msg) { int ret; + /* + * The message has already passed through interrupt remapping if enabled, + * but the legacy extended destination ID in low bits still needs to be + * handled. + */ + msg->address = kvm_swizzle_msi_ext_dest_id(msg->address); + ret = kvm_irqchip_send_msi(kvm_state, *msg); if (ret < 0) { fprintf(stderr, "KVM: injection failed, MSI lost (%s)\n", diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c index 5688608613..f111ef87d8 100644 --- a/hw/i386/microvm.c +++ b/hw/i386/microvm.c @@ -158,6 +158,7 @@ static int microvm_ioapics(MicrovmMachineState *mms) static void microvm_devices_init(MicrovmMachineState *mms) { + const char *default_firmware; X86MachineState *x86ms = X86_MACHINE(mms); ISABus *isa_bus; ISADevice *rtc_state; @@ -274,12 +275,10 @@ static void microvm_devices_init(MicrovmMachineState *mms) serial_hds_isa_init(isa_bus, 0, 1); } - if (bios_name == NULL) { - bios_name = x86_machine_is_acpi_enabled(x86ms) + default_firmware = x86_machine_is_acpi_enabled(x86ms) ? MICROVM_BIOS_FILENAME : MICROVM_QBOOT_FILENAME; - } - x86_bios_rom_init(get_system_memory(), true); + x86_bios_rom_init(MACHINE(mms), default_firmware, get_system_memory(), true); } static void microvm_memory_init(MicrovmMachineState *mms) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 9e29f3792b..640fb5b0b7 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -104,6 +104,7 @@ const size_t pc_compat_5_2_len = G_N_ELEMENTS(pc_compat_5_2); GlobalProperty pc_compat_5_1[] = { { "ICH9-LPC", "x-smi-cpu-hotplug", "off" }, + { TYPE_X86_CPU, "kvm-msi-ext-dest-id", "off" }, }; const size_t pc_compat_5_1_len = G_N_ELEMENTS(pc_compat_5_1); @@ -796,17 +797,12 @@ void pc_machine_done(Notifier *notifier, void *data) fw_cfg_modify_i16(x86ms->fw_cfg, FW_CFG_NB_CPUS, x86ms->boot_cpus); } - if (x86ms->apic_id_limit > 255 && !xen_enabled()) { - IntelIOMMUState *iommu = INTEL_IOMMU_DEVICE(x86_iommu_get_default()); - if (!iommu || !x86_iommu_ir_supported(X86_IOMMU_DEVICE(iommu)) || - iommu->intr_eim != ON_OFF_AUTO_ON) { - error_report("current -smp configuration requires " - "Extended Interrupt Mode enabled. " - "You can add an IOMMU using: " - "-device intel-iommu,intremap=on,eim=on"); - exit(EXIT_FAILURE); - } + if (x86ms->apic_id_limit > 255 && !xen_enabled() && + !kvm_irqchip_in_kernel()) { + error_report("current -smp configuration requires kernel " + "irqchip support."); + exit(EXIT_FAILURE); } } diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c index f8bd3a8b85..92e90ff013 100644 --- a/hw/i386/pc_sysfw.c +++ b/hw/i386/pc_sysfw.c @@ -213,7 +213,7 @@ void pc_system_firmware_init(PCMachineState *pcms, BlockBackend *pflash_blk[ARRAY_SIZE(pcms->flash)]; if (!pcmc->pci_enabled) { - x86_bios_rom_init(rom_memory, true); + x86_bios_rom_init(MACHINE(pcms), "bios.bin", rom_memory, true); return; } @@ -234,7 +234,7 @@ void pc_system_firmware_init(PCMachineState *pcms, if (!pflash_blk[0]) { /* Machine property pflash0 not set, use ROM mode */ - x86_bios_rom_init(rom_memory, false); + x86_bios_rom_init(MACHINE(pcms), "bios.bin", rom_memory, false); } else { if (kvm_enabled() && !kvm_readonly_mem_enabled()) { /* diff --git a/hw/i386/vmport.c b/hw/i386/vmport.c index 20d605506b..490a57f52c 100644 --- a/hw/i386/vmport.c +++ b/hw/i386/vmport.c @@ -32,6 +32,7 @@ #include "hw/isa/isa.h" #include "hw/i386/vmport.h" #include "hw/qdev-properties.h" +#include "hw/boards.h" #include "sysemu/sysemu.h" #include "sysemu/hw_accel.h" #include "sysemu/qtest.h" @@ -188,7 +189,7 @@ static uint32_t vmport_cmd_ram_size(void *opaque, uint32_t addr) return -1; } cpu->env.regs[R_EBX] = 0x1177; - return ram_size; + return current_machine->ram_size; } static uint32_t vmport_cmd_get_hz(void *opaque, uint32_t addr) diff --git a/hw/i386/x86.c b/hw/i386/x86.c index d68a9eaefc..49e1d419b2 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -26,11 +26,13 @@ #include "qemu/cutils.h" #include "qemu/units.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qapi/error.h" #include "qapi/qmp/qerror.h" #include "qapi/qapi-visit-common.h" #include "qapi/visitor.h" #include "sysemu/qtest.h" +#include "sysemu/whpx.h" #include "sysemu/numa.h" #include "sysemu/replay.h" #include "sysemu/sysemu.h" @@ -54,8 +56,6 @@ #include CONFIG_DEVICES #include "kvm_i386.h" -#define BIOS_FILENAME "bios.bin" - /* Physical Address of PVH entry point read from kernel ELF NOTE */ static size_t pvh_start_addr; @@ -532,7 +532,8 @@ static void pic_irq_request(void *opaque, int irq, int level) X86CPU *cpu = X86_CPU(cs); trace_x86_pic_interrupt(irq, level); - if (cpu->apic_state && !kvm_irqchip_in_kernel()) { + if (cpu->apic_state && !kvm_irqchip_in_kernel() && + !whpx_apic_in_platform()) { CPU_FOREACH(cs) { cpu = X86_CPU(cs); if (apic_accept_pic_intr(cpu->apic_state)) { @@ -558,7 +559,7 @@ int cpu_get_pic_interrupt(CPUX86State *env) X86CPU *cpu = env_archcpu(env); int intno; - if (!kvm_irqchip_in_kernel()) { + if (!kvm_irqchip_in_kernel() && !whpx_apic_in_platform()) { intno = apic_get_interrupt(cpu->apic_state); if (intno >= 0) { return intno; @@ -1078,17 +1079,17 @@ void x86_load_linux(X86MachineState *x86ms, nb_option_roms++; } -void x86_bios_rom_init(MemoryRegion *rom_memory, bool isapc_ram_fw) +void x86_bios_rom_init(MachineState *ms, const char *default_firmware, + MemoryRegion *rom_memory, bool isapc_ram_fw) { + const char *bios_name; char *filename; MemoryRegion *bios, *isa_bios; int bios_size, isa_bios_size; int ret; /* BIOS load */ - if (bios_name == NULL) { - bios_name = BIOS_FILENAME; - } + bios_name = ms->firmware ?: default_firmware; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (filename) { bios_size = get_image_size(filename); diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c index 9519c33c09..096c46fef1 100644 --- a/hw/i386/xen/xen-hvm.c +++ b/hw/i386/xen/xen-hvm.c @@ -1493,7 +1493,7 @@ void xen_hvm_init_pc(PCMachineState *pcms, MemoryRegion **ram_memory) #else xen_map_cache_init(NULL, state); #endif - xen_ram_init(pcms, ram_size, ram_memory); + xen_ram_init(pcms, ms->ram_size, ram_memory); qemu_add_vm_change_state_handler(xen_hvm_change_state_handler, state); diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c index 502e94effc..97dd96dffa 100644 --- a/hw/intc/apic_common.c +++ b/hw/intc/apic_common.c @@ -27,6 +27,7 @@ #include "hw/i386/apic.h" #include "hw/i386/apic_internal.h" #include "trace.h" +#include "hw/boards.h" #include "sysemu/hax.h" #include "sysemu/kvm.h" #include "hw/qdev-properties.h" @@ -297,7 +298,7 @@ static void apic_common_realize(DeviceState *dev, Error **errp) /* Note: We need at least 1M to map the VAPIC option ROM */ if (!vapic && s->vapic_control & VAPIC_ENABLE_MASK && - !hax_enabled() && ram_size >= 1024 * 1024) { + !hax_enabled() && current_machine->ram_size >= 1024 * 1024) { vapic = sysbus_create_simple("kvmvapic", -1, NULL); } s->vapic = vapic; diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c index 9ef94883d5..72d1326531 100644 --- a/hw/lm32/milkymist.c +++ b/hw/lm32/milkymist.c @@ -21,6 +21,7 @@ #include "qemu/units.h" #include "qemu/error-report.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "cpu.h" #include "hw/sysbus.h" #include "hw/irq.h" @@ -108,6 +109,7 @@ static void milkymist_init(MachineState *machine) { MachineClass *mc = MACHINE_GET_CLASS(machine); + const char *bios_name = machine->firmware ?: BIOS_FILENAME; const char *kernel_filename = machine->kernel_filename; const char *kernel_cmdline = machine->kernel_cmdline; const char *initrd_filename = machine->initrd_filename; @@ -162,9 +164,6 @@ milkymist_init(MachineState *machine) } /* load bios rom */ - if (bios_name == NULL) { - bios_name = BIOS_FILENAME; - } bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (bios_filename) { diff --git a/hw/m68k/mcf5206.c b/hw/m68k/mcf5206.c index 92a194dbc4..6d93d761a5 100644 --- a/hw/m68k/mcf5206.c +++ b/hw/m68k/mcf5206.c @@ -10,6 +10,7 @@ #include "qemu/error-report.h" #include "qemu/log.h" #include "cpu.h" +#include "hw/boards.h" #include "hw/irq.h" #include "hw/m68k/mcf.h" #include "qemu/timer.h" @@ -312,8 +313,9 @@ static uint64_t m5206_mbar_read(m5206_mbar_state *s, /* FIXME: currently hardcoded to 128Mb. */ { uint32_t mask = ~0; - while (mask > ram_size) + while (mask > current_machine->ram_size) { mask >>= 1; + } return mask & 0x0ffe0000; } case 0x5c: return 1; /* DRAM bank 1 empty. */ diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c index d310a98e7b..7a03c71059 100644 --- a/hw/m68k/mcf5208.c +++ b/hw/m68k/mcf5208.c @@ -12,6 +12,7 @@ #include "qemu/log.h" #include "qapi/error.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "cpu.h" #include "hw/irq.h" #include "hw/m68k/mcf.h" @@ -157,8 +158,9 @@ static uint64_t m5208_sys_read(void *opaque, hwaddr addr, { int n; for (n = 0; n < 32; n++) { - if (ram_size < (2u << n)) + if (current_machine->ram_size < (2u << n)) { break; + } } return (n - 1) | 0x40000000; } @@ -301,17 +303,17 @@ static void mcf5208evb_init(MachineState *machine) /* 0xfc0a8000 SDRAM controller. */ /* Load firmware */ - if (bios_name) { + if (machine->firmware) { char *fn; uint8_t *ptr; - fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, machine->firmware); if (!fn) { - error_report("Could not find ROM image '%s'", bios_name); + error_report("Could not find ROM image '%s'", machine->firmware); exit(1); } if (load_image_targphys(fn, 0x0, ROM_SIZE) < 8) { - error_report("Could not load ROM image '%s'", bios_name); + error_report("Could not load ROM image '%s'", machine->firmware); exit(1); } g_free(fn); @@ -323,7 +325,7 @@ static void mcf5208evb_init(MachineState *machine) /* Load kernel. */ if (!kernel_filename) { - if (qtest_enabled() || bios_name) { + if (qtest_enabled() || machine->firmware) { return; } error_report("Kernel image must be specified"); diff --git a/hw/m68k/next-cube.c b/hw/m68k/next-cube.c index e7045980b7..37bc35dfa4 100644 --- a/hw/m68k/next-cube.c +++ b/hw/m68k/next-cube.c @@ -868,6 +868,7 @@ static void next_cube_init(MachineState *machine) MemoryRegion *bmapm1 = g_new(MemoryRegion, 1); MemoryRegion *bmapm2 = g_new(MemoryRegion, 1); MemoryRegion *sysmem = get_system_memory(); + const char *bios_name = machine->firmware ?: ROM_FILE; NeXTState *ns = NEXT_MACHINE(machine); DeviceState *dev; @@ -924,9 +925,6 @@ static void next_cube_init(MachineState *machine) sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x0200e000); /* Load ROM here */ - if (bios_name == NULL) { - bios_name = ROM_FILE; - } /* still not sure if the rom should also be mapped at 0x0*/ memory_region_init_rom(rom, NULL, "next.rom", 0x20000, &error_fatal); memory_region_add_subregion(sysmem, 0x01000000, rom); diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c index ce4b47c3e3..4db2b9bbc7 100644 --- a/hw/m68k/q800.c +++ b/hw/m68k/q800.c @@ -23,6 +23,7 @@ #include "qemu/osdep.h" #include "qemu/units.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "sysemu/sysemu.h" #include "cpu.h" #include "hw/hw.h" @@ -167,6 +168,7 @@ static void q800_init(MachineState *machine) const char *kernel_filename = machine->kernel_filename; const char *initrd_filename = machine->initrd_filename; const char *kernel_cmdline = machine->kernel_cmdline; + const char *bios_name = machine->firmware ?: MACROM_FILENAME; hwaddr parameters_base; CPUState *cs; DeviceState *dev; @@ -400,9 +402,6 @@ static void q800_init(MachineState *machine) rom = g_malloc(sizeof(*rom)); memory_region_init_rom(rom, NULL, "m68k_mac.rom", MACROM_SIZE, &error_abort); - if (bios_name == NULL) { - bios_name = MACROM_FILENAME; - } filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); memory_region_add_subregion(get_system_memory(), MACROM_ADDR, rom); diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c index 8ad3c27f2c..6715ba2ff9 100644 --- a/hw/microblaze/boot.c +++ b/hw/microblaze/boot.c @@ -26,6 +26,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "cpu.h" #include "qemu/option.h" #include "qemu/config-file.h" @@ -170,7 +171,7 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base, /* Not an ELF image nor an u-boot image, try a RAW image. */ if (kernel_size < 0) { kernel_size = load_image_targphys(kernel_filename, ddr_base, - ram_size); + ramsize); boot_info.bootstrap_pc = ddr_base; high = (ddr_base + kernel_size + 3) & ~3; } @@ -185,11 +186,11 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base, initrd_size = load_ramdisk(initrd_filename, boot_info.initrd_start, - ram_size - initrd_offset); + ramsize - initrd_offset); if (initrd_size < 0) { initrd_size = load_image_targphys(initrd_filename, boot_info.initrd_start, - ram_size - initrd_offset); + ramsize - initrd_offset); } if (initrd_size < 0) { error_report("could not load initrd '%s'", @@ -206,7 +207,7 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base, } /* Provide a device-tree. */ boot_info.fdt = boot_info.cmdline + 4096; - microblaze_load_dtb(boot_info.fdt, ram_size, + microblaze_load_dtb(boot_info.fdt, ramsize, boot_info.initrd_start, boot_info.initrd_end, kernel_cmdline, diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c index a9e0c2f8d3..45c596f4fe 100644 --- a/hw/mips/fuloong2e.c +++ b/hw/mips/fuloong2e.c @@ -20,6 +20,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/units.h" #include "qapi/error.h" #include "cpu.h" @@ -134,14 +135,14 @@ static int64_t load_kernel(CPUMIPSState *env) initrd_size = get_image_size(loaderparams.initrd_filename); if (initrd_size > 0) { initrd_offset = ROUND_UP(kernel_high, INITRD_PAGE_SIZE); - if (initrd_offset + initrd_size > ram_size) { + if (initrd_offset + initrd_size > loaderparams.ram_size) { error_report("memory too small for initial ram disk '%s'", loaderparams.initrd_filename); exit(1); } initrd_size = load_image_targphys(loaderparams.initrd_filename, initrd_offset, - ram_size - initrd_offset); + loaderparams.ram_size - initrd_offset); } if (initrd_size == (target_ulong) -1) { error_report("could not load initial ram disk '%s'", @@ -338,7 +339,7 @@ static void mips_fuloong2e_init(MachineState *machine) write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry); } else { filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, - bios_name ?: FULOONG_BIOSNAME); + machine->firmware ?: FULOONG_BIOSNAME); if (filename) { bios_size = load_image_targphys(filename, 0x1fc00000LL, BIOS_SIZE); @@ -348,8 +349,8 @@ static void mips_fuloong2e_init(MachineState *machine) } if ((bios_size < 0 || bios_size > BIOS_SIZE) && - bios_name && !qtest_enabled()) { - error_report("Could not load MIPS bios '%s'", bios_name); + machine->firmware && !qtest_enabled()) { + error_report("Could not load MIPS bios '%s'", machine->firmware); exit(1); } } diff --git a/hw/mips/jazz.c b/hw/mips/jazz.c index 71448f72ac..f9442731dd 100644 --- a/hw/mips/jazz.c +++ b/hw/mips/jazz.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "hw/clock.h" #include "hw/mips/mips.h" #include "hw/mips/cpudevs.h" @@ -218,7 +219,7 @@ static void mips_jazz_init(MachineState *machine, memory_region_add_subregion(address_space, 0xfff00000LL, bios2); /* load the BIOS image. */ - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name ?: BIOS_FILENAME); + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, machine->firmware ?: BIOS_FILENAME); if (filename) { bios_size = load_image_targphys(filename, 0xfff00000LL, MAGNUM_BIOS_SIZE); @@ -227,8 +228,8 @@ static void mips_jazz_init(MachineState *machine, bios_size = -1; } if ((bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) - && bios_name && !qtest_enabled()) { - error_report("Could not load MIPS bios '%s'", bios_name); + && machine->firmware && !qtest_enabled()) { + error_report("Could not load MIPS bios '%s'", machine->firmware); exit(1); } diff --git a/hw/mips/malta.c b/hw/mips/malta.c index 9d1a3b50b7..5c11eecec1 100644 --- a/hw/mips/malta.c +++ b/hw/mips/malta.c @@ -25,6 +25,7 @@ #include "qemu/osdep.h" #include "qemu/units.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "cpu.h" #include "hw/clock.h" #include "hw/southbridge/piix.h" @@ -1087,7 +1088,7 @@ static int64_t load_kernel(void) } initrd_size = load_image_targphys(loaderparams.initrd_filename, initrd_offset, - ram_size - initrd_offset); + loaderparams.ram_size - initrd_offset); } if (initrd_size == (target_ulong) -1) { error_report("could not load initial ram disk '%s'", @@ -1333,7 +1334,7 @@ void mips_malta_init(MachineState *machine) if (!dinfo) { /* Load a BIOS image. */ filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, - bios_name ?: BIOS_FILENAME); + machine->firmware ?: BIOS_FILENAME); if (filename) { bios_size = load_image_targphys(filename, FLASH_ADDRESS, BIOS_SIZE); @@ -1342,8 +1343,8 @@ void mips_malta_init(MachineState *machine) bios_size = -1; } if ((bios_size < 0 || bios_size > BIOS_SIZE) && - bios_name && !qtest_enabled()) { - error_report("Could not load MIPS bios '%s'", bios_name); + machine->firmware && !qtest_enabled()) { + error_report("Could not load MIPS bios '%s'", machine->firmware); exit(1); } } diff --git a/hw/mips/mipssim.c b/hw/mips/mipssim.c index aaa62a0f4b..f2e6273525 100644 --- a/hw/mips/mipssim.c +++ b/hw/mips/mipssim.c @@ -28,6 +28,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "cpu.h" #include "hw/clock.h" #include "hw/mips/mips.h" @@ -177,7 +178,7 @@ mips_mipssim_init(MachineState *machine) /* Map the BIOS / boot exception handler. */ memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios); /* Load a BIOS / boot exception handler image. */ - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name ?: BIOS_FILENAME); + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, machine->firmware ?: BIOS_FILENAME); if (filename) { bios_size = load_image_targphys(filename, 0x1fc00000LL, BIOS_SIZE); g_free(filename); @@ -185,9 +186,9 @@ mips_mipssim_init(MachineState *machine) bios_size = -1; } if ((bios_size < 0 || bios_size > BIOS_SIZE) && - bios_name && !qtest_enabled()) { + machine->firmware && !qtest_enabled()) { /* Bail out if we have neither a kernel image nor boot vector code. */ - error_report("Could not load MIPS bios '%s'", bios_name); + error_report("Could not load MIPS bios '%s'", machine->firmware); exit(1); } else { /* We have a boot vector start address. */ diff --git a/hw/misc/max111x.c b/hw/misc/max111x.c index eae0f9b598..1b3234a519 100644 --- a/hw/misc/max111x.c +++ b/hw/misc/max111x.c @@ -85,7 +85,7 @@ static void max111x_write(MAX111xState *s, uint32_t value) qemu_irq_raise(s->interrupt); } -static uint32_t max111x_transfer(SSISlave *dev, uint32_t value) +static uint32_t max111x_transfer(SSIPeripheral *dev, uint32_t value) { MAX111xState *s = MAX_111X(dev); max111x_write(s, value); @@ -97,7 +97,7 @@ static const VMStateDescription vmstate_max111x = { .version_id = 1, .minimum_version_id = 1, .fields = (VMStateField[]) { - VMSTATE_SSI_SLAVE(parent_obj, MAX111xState), + VMSTATE_SSI_PERIPHERAL(parent_obj, MAX111xState), VMSTATE_UINT8(tb1, MAX111xState), VMSTATE_UINT8(rb2, MAX111xState), VMSTATE_UINT8(rb3, MAX111xState), @@ -117,7 +117,7 @@ static void max111x_input_set(void *opaque, int line, int value) s->input[line] = value; } -static int max111x_init(SSISlave *d, int inputs) +static int max111x_init(SSIPeripheral *d, int inputs) { DeviceState *dev = DEVICE(d); MAX111xState *s = MAX_111X(dev); @@ -130,12 +130,12 @@ static int max111x_init(SSISlave *d, int inputs) return 0; } -static void max1110_realize(SSISlave *dev, Error **errp) +static void max1110_realize(SSIPeripheral *dev, Error **errp) { max111x_init(dev, 8); } -static void max1111_realize(SSISlave *dev, Error **errp) +static void max1111_realize(SSIPeripheral *dev, Error **errp) { max111x_init(dev, 4); } @@ -179,7 +179,7 @@ static Property max1111_properties[] = { static void max111x_class_init(ObjectClass *klass, void *data) { - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); k->transfer = max111x_transfer; @@ -190,7 +190,7 @@ static void max111x_class_init(ObjectClass *klass, void *data) static const TypeInfo max111x_info = { .name = TYPE_MAX_111X, - .parent = TYPE_SSI_SLAVE, + .parent = TYPE_SSI_PERIPHERAL, .instance_size = sizeof(MAX111xState), .class_init = max111x_class_init, .abstract = true, @@ -198,7 +198,7 @@ static const TypeInfo max111x_info = { static void max1110_class_init(ObjectClass *klass, void *data) { - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); k->realize = max1110_realize; @@ -213,7 +213,7 @@ static const TypeInfo max1110_info = { static void max1111_class_init(ObjectClass *klass, void *data) { - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); k->realize = max1111_realize; diff --git a/hw/moxie/moxiesim.c b/hw/moxie/moxiesim.c index a765e9f6be..f7b57fcae1 100644 --- a/hw/moxie/moxiesim.c +++ b/hw/moxie/moxiesim.c @@ -82,7 +82,7 @@ static void load_kernel(MoxieCPU *cpu, LoaderParams *loader_params) } initrd_size = load_image_targphys(loader_params->initrd_filename, initrd_offset, - ram_size); + loader_params->ram_size); } if (initrd_size == (target_ulong)-1) { error_report("could not load initial ram disk '%s'", @@ -133,9 +133,9 @@ static void moxiesim_init(MachineState *machine) loader_params.initrd_filename = initrd_filename; load_kernel(cpu, &loader_params); } - if (bios_name) { - if (load_image_targphys(bios_name, FIRMWARE_BASE, FIRMWARE_SIZE) < 0) { - error_report("Failed to load firmware '%s'", bios_name); + if (machine->firmware) { + if (load_image_targphys(machine->firmware, FIRMWARE_BASE, FIRMWARE_SIZE) < 0) { + error_report("Failed to load firmware '%s'", machine->firmware); } } diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c index f8cf5290e1..990ff3a1c2 100644 --- a/hw/net/xilinx_axienet.c +++ b/hw/net/xilinx_axienet.c @@ -45,11 +45,11 @@ OBJECT_DECLARE_SIMPLE_TYPE(XilinxAXIEnet, XILINX_AXI_ENET) -typedef struct XilinxAXIEnetStreamSlave XilinxAXIEnetStreamSlave; -DECLARE_INSTANCE_CHECKER(XilinxAXIEnetStreamSlave, XILINX_AXI_ENET_DATA_STREAM, +typedef struct XilinxAXIEnetStreamSink XilinxAXIEnetStreamSink; +DECLARE_INSTANCE_CHECKER(XilinxAXIEnetStreamSink, XILINX_AXI_ENET_DATA_STREAM, TYPE_XILINX_AXI_ENET_DATA_STREAM) -DECLARE_INSTANCE_CHECKER(XilinxAXIEnetStreamSlave, XILINX_AXI_ENET_CONTROL_STREAM, +DECLARE_INSTANCE_CHECKER(XilinxAXIEnetStreamSink, XILINX_AXI_ENET_CONTROL_STREAM, TYPE_XILINX_AXI_ENET_CONTROL_STREAM) /* Advertisement control register. */ @@ -310,7 +310,7 @@ struct TEMAC { }; -struct XilinxAXIEnetStreamSlave { +struct XilinxAXIEnetStreamSink { Object parent; struct XilinxAXIEnet *enet; @@ -320,10 +320,10 @@ struct XilinxAXIEnet { SysBusDevice busdev; MemoryRegion iomem; qemu_irq irq; - StreamSlave *tx_data_dev; - StreamSlave *tx_control_dev; - XilinxAXIEnetStreamSlave rx_data_dev; - XilinxAXIEnetStreamSlave rx_control_dev; + StreamSink *tx_data_dev; + StreamSink *tx_control_dev; + XilinxAXIEnetStreamSink rx_data_dev; + XilinxAXIEnetStreamSink rx_control_dev; NICState *nic; NICConf conf; @@ -852,11 +852,11 @@ static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size) } static size_t -xilinx_axienet_control_stream_push(StreamSlave *obj, uint8_t *buf, size_t len, +xilinx_axienet_control_stream_push(StreamSink *obj, uint8_t *buf, size_t len, bool eop) { int i; - XilinxAXIEnetStreamSlave *cs = XILINX_AXI_ENET_CONTROL_STREAM(obj); + XilinxAXIEnetStreamSink *cs = XILINX_AXI_ENET_CONTROL_STREAM(obj); XilinxAXIEnet *s = cs->enet; assert(eop); @@ -874,10 +874,10 @@ xilinx_axienet_control_stream_push(StreamSlave *obj, uint8_t *buf, size_t len, } static size_t -xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size, +xilinx_axienet_data_stream_push(StreamSink *obj, uint8_t *buf, size_t size, bool eop) { - XilinxAXIEnetStreamSlave *ds = XILINX_AXI_ENET_DATA_STREAM(obj); + XilinxAXIEnetStreamSink *ds = XILINX_AXI_ENET_DATA_STREAM(obj); XilinxAXIEnet *s = ds->enet; /* TX enable ? */ @@ -951,8 +951,8 @@ static NetClientInfo net_xilinx_enet_info = { static void xilinx_enet_realize(DeviceState *dev, Error **errp) { XilinxAXIEnet *s = XILINX_AXI_ENET(dev); - XilinxAXIEnetStreamSlave *ds = XILINX_AXI_ENET_DATA_STREAM(&s->rx_data_dev); - XilinxAXIEnetStreamSlave *cs = XILINX_AXI_ENET_CONTROL_STREAM( + XilinxAXIEnetStreamSink *ds = XILINX_AXI_ENET_DATA_STREAM(&s->rx_data_dev); + XilinxAXIEnetStreamSink *cs = XILINX_AXI_ENET_CONTROL_STREAM( &s->rx_control_dev); object_property_add_link(OBJECT(ds), "enet", "xlnx.axi-ethernet", @@ -1002,9 +1002,9 @@ static Property xilinx_enet_properties[] = { DEFINE_PROP_UINT32("txmem", XilinxAXIEnet, c_txmem, 0x1000), DEFINE_NIC_PROPERTIES(XilinxAXIEnet, conf), DEFINE_PROP_LINK("axistream-connected", XilinxAXIEnet, - tx_data_dev, TYPE_STREAM_SLAVE, StreamSlave *), + tx_data_dev, TYPE_STREAM_SINK, StreamSink *), DEFINE_PROP_LINK("axistream-control-connected", XilinxAXIEnet, - tx_control_dev, TYPE_STREAM_SLAVE, StreamSlave *), + tx_control_dev, TYPE_STREAM_SINK, StreamSink *), DEFINE_PROP_END_OF_LIST(), }; @@ -1020,14 +1020,14 @@ static void xilinx_enet_class_init(ObjectClass *klass, void *data) static void xilinx_enet_control_stream_class_init(ObjectClass *klass, void *data) { - StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass); + StreamSinkClass *ssc = STREAM_SINK_CLASS(klass); ssc->push = xilinx_axienet_control_stream_push; } static void xilinx_enet_data_stream_class_init(ObjectClass *klass, void *data) { - StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass); + StreamSinkClass *ssc = STREAM_SINK_CLASS(klass); ssc->push = xilinx_axienet_data_stream_push; } @@ -1043,10 +1043,10 @@ static const TypeInfo xilinx_enet_info = { static const TypeInfo xilinx_enet_data_stream_info = { .name = TYPE_XILINX_AXI_ENET_DATA_STREAM, .parent = TYPE_OBJECT, - .instance_size = sizeof(XilinxAXIEnetStreamSlave), + .instance_size = sizeof(XilinxAXIEnetStreamSink), .class_init = xilinx_enet_data_stream_class_init, .interfaces = (InterfaceInfo[]) { - { TYPE_STREAM_SLAVE }, + { TYPE_STREAM_SINK }, { } } }; @@ -1054,10 +1054,10 @@ static const TypeInfo xilinx_enet_data_stream_info = { static const TypeInfo xilinx_enet_control_stream_info = { .name = TYPE_XILINX_AXI_ENET_CONTROL_STREAM, .parent = TYPE_OBJECT, - .instance_size = sizeof(XilinxAXIEnetStreamSlave), + .instance_size = sizeof(XilinxAXIEnetStreamSink), .class_init = xilinx_enet_control_stream_class_init, .interfaces = (InterfaceInfo[]) { - { TYPE_STREAM_SLAVE }, + { TYPE_STREAM_SINK }, { } } }; diff --git a/hw/nios2/boot.c b/hw/nios2/boot.c index 1df3b66c29..95a8697906 100644 --- a/hw/nios2/boot.c +++ b/hw/nios2/boot.c @@ -31,6 +31,7 @@ #include "qemu/osdep.h" #include "qemu/units.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "cpu.h" #include "qemu/option.h" #include "qemu/config-file.h" @@ -181,7 +182,7 @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base, /* Not an ELF image nor an u-boot image, try a RAW image. */ if (kernel_size < 0) { kernel_size = load_image_targphys(kernel_filename, ddr_base, - ram_size); + ramsize); boot_info.bootstrap_pc = ddr_base; high = ddr_base + kernel_size; } @@ -198,11 +199,11 @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base, initrd_size = load_ramdisk(initrd_filename, boot_info.initrd_start, - ram_size - initrd_offset); + ramsize - initrd_offset); if (initrd_size < 0) { initrd_size = load_image_targphys(initrd_filename, boot_info.initrd_start, - ram_size - initrd_offset); + ramsize - initrd_offset); } if (initrd_size < 0) { error_report("could not load initrd '%s'", @@ -216,7 +217,7 @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base, /* Device tree must be placed right after initrd (if available) */ boot_info.fdt = high; - fdt_size = nios2_load_dtb(boot_info, ram_size, kernel_cmdline, + fdt_size = nios2_load_dtb(boot_info, ramsize, kernel_cmdline, /* Preference a -dtb argument */ dtb_arg ? dtb_arg : filename); high += fdt_size; diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index 282ba93e2e..44cb274a32 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "sysemu/sysemu.h" #include "sysemu/dma.h" #include "sysemu/reset.h" diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c index d0323fefb1..0469db8c1d 100644 --- a/hw/pci-host/prep.c +++ b/hw/pci-host/prep.c @@ -25,6 +25,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/units.h" #include "qapi/error.h" #include "hw/pci/pci.h" diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 0131d9d02c..9424231542 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "hw/irq.h" #include "hw/pci/pci.h" #include "hw/pci/pci_bridge.h" diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index ae39b9358e..6a64eb31ab 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -16,6 +16,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/units.h" #include "qapi/error.h" #include "e500.h" @@ -1035,7 +1036,7 @@ void ppce500_init(MachineState *machine) * -kernel to users but allows them to run through u-boot as well. */ kernel_as_payload = false; - if (bios_name == NULL) { + if (machine->firmware == NULL) { if (machine->kernel_filename) { payload_name = machine->kernel_filename; kernel_as_payload = true; @@ -1043,7 +1044,7 @@ void ppce500_init(MachineState *machine) payload_name = "u-boot.e500"; } } else { - payload_name = bios_name; + payload_name = machine->firmware; } filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, payload_name); diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index f9a1cc8944..c0accda592 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -48,6 +48,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qapi/error.h" #include "hw/ppc/ppc.h" #include "hw/qdev-properties.h" @@ -109,6 +110,7 @@ static void ppc_core99_reset(void *opaque) static void ppc_core99_init(MachineState *machine) { ram_addr_t ram_size = machine->ram_size; + const char *bios_name = machine->firmware ?: PROM_FILENAME; const char *kernel_filename = machine->kernel_filename; const char *kernel_cmdline = machine->kernel_cmdline; const char *initrd_filename = machine->initrd_filename; @@ -161,9 +163,6 @@ static void ppc_core99_init(MachineState *machine) &error_fatal); memory_region_add_subregion(get_system_memory(), PROM_BASE, bios); - if (!bios_name) { - bios_name = PROM_FILENAME; - } filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (filename) { /* Load OpenBIOS (ELF) */ diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 6c59aa5601..04f98a4d81 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -26,6 +26,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/units.h" #include "qapi/error.h" #include "hw/ppc/ppc.h" @@ -83,6 +84,7 @@ static void ppc_heathrow_reset(void *opaque) static void ppc_heathrow_init(MachineState *machine) { ram_addr_t ram_size = machine->ram_size; + const char *bios_name = machine->firmware ?: PROM_FILENAME; const char *boot_device = machine->boot_order; PowerPCCPU *cpu = NULL; CPUPPCState *env = NULL; @@ -130,9 +132,6 @@ static void ppc_heathrow_init(MachineState *machine) &error_fatal); memory_region_add_subregion(get_system_memory(), PROM_BASE, bios); - if (!bios_name) { - bios_name = PROM_FILENAME; - } filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (filename) { /* Load OpenBIOS (ELF) */ diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 50ebd4a484..14fc9758a9 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -19,6 +19,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/units.h" #include "qapi/error.h" #include "sysemu/qtest.h" @@ -713,6 +714,7 @@ static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon) static void pnv_init(MachineState *machine) { + const char *bios_name = machine->firmware ?: FW_FILE_NAME; PnvMachineState *pnv = PNV_MACHINE(machine); MachineClass *mc = MACHINE_GET_CLASS(machine); char *fw_filename; @@ -739,10 +741,6 @@ static void pnv_init(MachineState *machine) pnv->pnor = PNV_PNOR(dev); /* load skiboot firmware */ - if (bios_name == NULL) { - bios_name = FW_FILE_NAME; - } - fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (!fw_filename) { error_report("Could not find OPAL firmware '%s'", bios_name); diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c index 4687715b15..b7249f21cf 100644 --- a/hw/ppc/ppc405_boards.c +++ b/hw/ppc/ppc405_boards.c @@ -26,6 +26,7 @@ #include "qemu/units.h" #include "qapi/error.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "cpu.h" #include "hw/ppc/ppc.h" #include "hw/qdev-properties.h" @@ -141,6 +142,7 @@ static void ref405ep_fpga_init(MemoryRegion *sysmem, uint32_t base) static void ref405ep_init(MachineState *machine) { MachineClass *mc = MACHINE_GET_CLASS(machine); + const char *bios_name = machine->firmware ?: BIOS_FILENAME; const char *kernel_filename = machine->kernel_filename; const char *kernel_cmdline = machine->kernel_cmdline; const char *initrd_filename = machine->initrd_filename; @@ -206,8 +208,6 @@ static void ref405ep_init(MachineState *machine) memory_region_init_rom(bios, NULL, "ef405ep.bios", BIOS_SIZE, &error_fatal); - if (bios_name == NULL) - bios_name = BIOS_FILENAME; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (filename) { bios_size = load_image_size(filename, @@ -425,6 +425,7 @@ static void taihu_cpld_init(MemoryRegion *sysmem, uint32_t base) static void taihu_405ep_init(MachineState *machine) { MachineClass *mc = MACHINE_GET_CLASS(machine); + const char *bios_name = machine->firmware ?: BIOS_FILENAME; const char *kernel_filename = machine->kernel_filename; const char *initrd_filename = machine->initrd_filename; char *filename; @@ -475,8 +476,6 @@ static void taihu_405ep_init(MachineState *machine) } else #endif { - if (bios_name == NULL) - bios_name = BIOS_FILENAME; bios = g_new(MemoryRegion, 1); memory_region_init_rom(bios, NULL, "taihu_405ep.bios", BIOS_SIZE, &error_fatal); diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c index 74028dc986..665bc1784e 100644 --- a/hw/ppc/ppc440_bamboo.c +++ b/hw/ppc/ppc440_bamboo.c @@ -15,6 +15,7 @@ #include "qemu/units.h" #include "qemu/error-report.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/error-report.h" #include "net/net.h" #include "hw/pci/pci.h" diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c index 4a0cb434a6..7e72f6e4a9 100644 --- a/hw/ppc/prep.c +++ b/hw/ppc/prep.c @@ -237,6 +237,7 @@ static int prep_set_cmos_checksum(DeviceState *dev, void *opaque) static void ibm_40p_init(MachineState *machine) { + const char *bios_name = machine->firmware ?: "openbios-ppc"; CPUPPCState *env = NULL; uint16_t cmos_checksum; PowerPCCPU *cpu; @@ -271,9 +272,6 @@ static void ibm_40p_init(MachineState *machine) /* PCI host */ dev = qdev_new("raven-pcihost"); - if (!bios_name) { - bios_name = "openbios-ppc"; - } qdev_prop_set_string(dev, "bios-name", bios_name); qdev_prop_set_uint32(dev, "elf-machine", PPC_ELF_MACHINE); pcihost = SYS_BUS_DEVICE(dev); @@ -422,7 +420,7 @@ static void ibm_40p_init(MachineState *machine) /* Prepare firmware configuration for Open Hack'Ware */ if (m48t59) { - PPC_NVRAM_set_params(m48t59, NVRAM_SIZE, "PREP", ram_size, + PPC_NVRAM_set_params(m48t59, NVRAM_SIZE, "PREP", machine->ram_size, boot_device, kernel_base, kernel_size, machine->kernel_cmdline, diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index 7e59a91981..14e6583eb0 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -14,6 +14,7 @@ #include "qemu/osdep.h" #include "qemu/units.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/error-report.h" #include "qapi/error.h" #include "hw/boards.h" diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index c060702013..6abb45d0ed 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -26,6 +26,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qapi/error.h" #include "qapi/visitor.h" #include "sysemu/sysemu.h" @@ -2657,6 +2658,7 @@ static void spapr_machine_init(MachineState *machine) SpaprMachineState *spapr = SPAPR_MACHINE(machine); SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); MachineClass *mc = MACHINE_GET_CLASS(machine); + const char *bios_name = machine->firmware ?: FW_FILE_NAME; const char *kernel_filename = machine->kernel_filename; const char *initrd_filename = machine->initrd_filename; PCIHostState *phb; @@ -2876,10 +2878,8 @@ static void spapr_machine_init(MachineState *machine) /* Set up VIO bus */ spapr->vio_bus = spapr_vio_bus_init(); - for (i = 0; i < serial_max_hds(); i++) { - if (serial_hd(i)) { - spapr_vty_create(spapr->vio_bus, serial_hd(i)); - } + for (i = 0; serial_hd(i); i++) { + spapr_vty_create(spapr->vio_bus, serial_hd(i)); } /* We always have at least the nvram device on VIO */ @@ -2980,9 +2980,6 @@ static void spapr_machine_init(MachineState *machine) } } - if (bios_name == NULL) { - bios_name = FW_FILE_NAME; - } filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (!filename) { error_report("Could not find LPAR firmware '%s'", bios_name); diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c index 5d6c56473f..3cc9421526 100644 --- a/hw/ppc/spapr_vio.c +++ b/hw/ppc/spapr_vio.c @@ -525,10 +525,10 @@ static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp) uint32_t liobn = SPAPR_VIO_LIOBN(dev->reg); memory_region_init(&dev->mrroot, OBJECT(dev), "iommu-spapr-root", - ram_size); + MACHINE(spapr)->ram_size); memory_region_init_alias(&dev->mrbypass, OBJECT(dev), "iommu-spapr-bypass", get_system_memory(), - 0, ram_size); + 0, MACHINE(spapr)->ram_size); memory_region_add_subregion_overlap(&dev->mrroot, 0, &dev->mrbypass, 1); address_space_init(&dev->as, &dev->mrroot, qdev->id); diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c index c790c1113f..7f1bca928c 100644 --- a/hw/ppc/virtex_ml507.c +++ b/hw/ppc/virtex_ml507.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/units.h" #include "cpu.h" #include "hw/sysbus.h" diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c index 9b3fe3fb1e..d62f3dc758 100644 --- a/hw/riscv/boot.c +++ b/hw/riscv/boot.c @@ -19,6 +19,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/units.h" #include "qemu/error-report.h" #include "exec/cpu-defs.h" @@ -120,7 +121,8 @@ target_ulong riscv_load_firmware(const char *firmware_filename, } firmware_size = load_image_targphys_as(firmware_filename, - firmware_load_addr, ram_size, NULL); + firmware_load_addr, + current_machine->ram_size, NULL); if (firmware_size > 0) { return firmware_load_addr + firmware_size; @@ -148,7 +150,7 @@ target_ulong riscv_load_kernel(const char *kernel_filename, } if (load_image_targphys_as(kernel_filename, kernel_start_addr, - ram_size, NULL) > 0) { + current_machine->ram_size, NULL) > 0) { return kernel_start_addr; } diff --git a/hw/rx/rx-gdbsim.c b/hw/rx/rx-gdbsim.c index 285549c79b..b1d7c2488f 100644 --- a/hw/rx/rx-gdbsim.c +++ b/hw/rx/rx-gdbsim.c @@ -106,6 +106,16 @@ static void rx_gdbsim_init(MachineState *machine) rxc->xtal_freq_hz, &error_abort); object_property_set_bool(OBJECT(&s->mcu), "load-kernel", kernel_filename != NULL, &error_abort); + + if (!kernel_filename) { + if (machine->firmware) { + rom_add_file_fixed(machine->firmware, RX62N_CFLASH_BASE, 0); + } else if (!qtest_enabled()) { + error_report("No bios or kernel specified"); + exit(1); + } + } + qdev_realize(DEVICE(&s->mcu), NULL, &error_abort); /* Load kernel and dtb */ diff --git a/hw/rx/rx62n.c b/hw/rx/rx62n.c index 6eb4eea700..17ec73fc7b 100644 --- a/hw/rx/rx62n.c +++ b/hw/rx/rx62n.c @@ -245,15 +245,6 @@ static void rx62n_realize(DeviceState *dev, Error **errp) rxc->rom_flash_size, &error_abort); memory_region_add_subregion(s->sysmem, RX62N_CFLASH_BASE, &s->c_flash); - if (!s->kernel) { - if (bios_name) { - rom_add_file_fixed(bios_name, RX62N_CFLASH_BASE, 0); - } else if (!qtest_enabled()) { - error_report("No bios or kernel specified"); - exit(1); - } - } - /* Initialize CPU */ object_initialize_child(OBJECT(s), "cpu", &s->cpu, TYPE_RX62N_CPU); qdev_realize(DEVICE(&s->cpu), NULL, &error_abort); diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c index 3d2652d75a..ff6b55e816 100644 --- a/hw/s390x/ipl.c +++ b/hw/s390x/ipl.c @@ -14,6 +14,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qapi/error.h" #include "sysemu/reset.h" #include "sysemu/runstate.h" @@ -112,6 +113,7 @@ static uint64_t bios_translate_addr(void *opaque, uint64_t srcaddr) static void s390_ipl_realize(DeviceState *dev, Error **errp) { + MachineState *ms = MACHINE(qdev_get_machine()); S390IPLState *ipl = S390_IPL(dev); uint32_t *ipl_psw; uint64_t pentry; @@ -126,13 +128,9 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) * even if an external kernel has been defined. */ if (!ipl->kernel || ipl->enforce_bios) { - uint64_t fwbase = (MIN(ram_size, 0x80000000U) - 0x200000) & ~0xffffUL; + uint64_t fwbase = (MIN(ms->ram_size, 0x80000000U) - 0x200000) & ~0xffffUL; - if (bios_name == NULL) { - bios_name = ipl->firmware; - } - - bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, ipl->firmware); if (bios_filename == NULL) { error_setg(errp, "could not find stage1 bootloader"); return; @@ -154,7 +152,7 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) g_free(bios_filename); if (bios_size == -1) { - error_setg(errp, "could not load bootloader '%s'", bios_name); + error_setg(errp, "could not load bootloader '%s'", ipl->firmware); return; } @@ -167,7 +165,7 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) &pentry, NULL, NULL, NULL, 1, EM_S390, 0, 0); if (kernel_size < 0) { - kernel_size = load_image_targphys(ipl->kernel, 0, ram_size); + kernel_size = load_image_targphys(ipl->kernel, 0, ms->ram_size); if (kernel_size < 0) { error_setg(errp, "could not load kernel '%s'", ipl->kernel); return; @@ -214,7 +212,7 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) initrd_offset += 0x100000; } initrd_size = load_image_targphys(ipl->initrd, initrd_offset, - ram_size - initrd_offset); + ms->ram_size - initrd_offset); if (initrd_size == -1) { error_setg(errp, "could not load initrd '%s'", ipl->initrd); return; @@ -452,6 +450,7 @@ int s390_ipl_set_loadparm(uint8_t *loadparm) static int load_netboot_image(Error **errp) { + MachineState *ms = MACHINE(qdev_get_machine()); S390IPLState *ipl = get_ipl_device(); char *netboot_filename; MemoryRegion *sysmem = get_system_memory(); @@ -484,7 +483,7 @@ static int load_netboot_image(Error **errp) false); if (img_size < 0) { - img_size = load_image_size(netboot_filename, ram_ptr, ram_size); + img_size = load_image_size(netboot_filename, ram_ptr, ms->ram_size); ipl->start_addr = KERN_IMAGE_START; } diff --git a/hw/s390x/s390-skeys.c b/hw/s390x/s390-skeys.c index 5cc559fe4c..9a8d60d1d9 100644 --- a/hw/s390x/s390-skeys.c +++ b/hw/s390x/s390-skeys.c @@ -109,7 +109,8 @@ void qmp_dump_skeys(const char *filename, Error **errp) { S390SKeysState *ss = s390_get_skeys_device(); S390SKeysClass *skeyclass = S390_SKEYS_GET_CLASS(ss); - const uint64_t total_count = ram_size / TARGET_PAGE_SIZE; + MachineState *ms = MACHINE(qdev_get_machine()); + const uint64_t total_count = ms->ram_size / TARGET_PAGE_SIZE; uint64_t handled_count = 0, cur_count; Error *lerr = NULL; vaddr cur_gfn = 0; @@ -256,7 +257,8 @@ static void s390_storage_keys_save(QEMUFile *f, void *opaque) { S390SKeysState *ss = S390_SKEYS(opaque); S390SKeysClass *skeyclass = S390_SKEYS_GET_CLASS(ss); - uint64_t pages_left = ram_size / TARGET_PAGE_SIZE; + MachineState *ms = MACHINE(qdev_get_machine()); + uint64_t pages_left = ms->ram_size / TARGET_PAGE_SIZE; uint64_t read_count, eos = S390_SKEYS_SAVE_FLAG_EOS; vaddr cur_gfn = 0; int error = 0; diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index f0ee8dae68..a2d9a79c84 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -17,6 +17,7 @@ #include "hw/boards.h" #include "exec/address-spaces.h" #include "exec/ram_addr.h" +#include "hw/boards.h" #include "hw/s390x/s390-virtio-hcall.h" #include "hw/s390x/sclp.h" #include "hw/s390x/s390_flic.h" @@ -142,8 +143,9 @@ static int virtio_ccw_hcall_notify(const uint64_t *args) static int virtio_ccw_hcall_early_printk(const uint64_t *args) { uint64_t mem = args[0]; + MachineState *ms = MACHINE(qdev_get_machine()); - if (mem < ram_size) { + if (mem < ms->ram_size) { /* Early printk */ return 0; } @@ -259,7 +261,8 @@ static void ccw_init(MachineState *machine) /* get a BUS */ css_bus = virtual_css_bus_init(); s390_init_ipl_dev(machine->kernel_filename, machine->kernel_cmdline, - machine->initrd_filename, "s390-ccw.img", + machine->initrd_filename, + machine->firmware ?: "s390-ccw.img", "s390-netboot.img", true); dev = qdev_new(TYPE_S390_PCI_HOST_BRIDGE); diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c index 14c8e04a89..9a75e0095c 100644 --- a/hw/sd/ssi-sd.c +++ b/hw/sd/ssi-sd.c @@ -42,7 +42,7 @@ typedef enum { } ssi_sd_mode; struct ssi_sd_state { - SSISlave ssidev; + SSIPeripheral ssidev; uint32_t mode; int cmd; uint8_t cmdarg[4]; @@ -73,7 +73,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(ssi_sd_state, SSI_SD) #define SSI_SDR_ADDRESS_ERROR 0x2000 #define SSI_SDR_PARAMETER_ERROR 0x4000 -static uint32_t ssi_sd_transfer(SSISlave *dev, uint32_t val) +static uint32_t ssi_sd_transfer(SSIPeripheral *dev, uint32_t val) { ssi_sd_state *s = SSI_SD(dev); @@ -235,12 +235,12 @@ static const VMStateDescription vmstate_ssi_sd = { VMSTATE_INT32(arglen, ssi_sd_state), VMSTATE_INT32(response_pos, ssi_sd_state), VMSTATE_INT32(stopping, ssi_sd_state), - VMSTATE_SSI_SLAVE(ssidev, ssi_sd_state), + VMSTATE_SSI_PERIPHERAL(ssidev, ssi_sd_state), VMSTATE_END_OF_LIST() } }; -static void ssi_sd_realize(SSISlave *d, Error **errp) +static void ssi_sd_realize(SSIPeripheral *d, Error **errp) { ERRP_GUARD(); ssi_sd_state *s = SSI_SD(d); @@ -291,7 +291,7 @@ static void ssi_sd_reset(DeviceState *dev) static void ssi_sd_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass); k->realize = ssi_sd_realize; k->transfer = ssi_sd_transfer; @@ -304,7 +304,7 @@ static void ssi_sd_class_init(ObjectClass *klass, void *data) static const TypeInfo ssi_sd_info = { .name = TYPE_SSI_SD, - .parent = TYPE_SSI_SLAVE, + .parent = TYPE_SSI_PERIPHERAL, .instance_size = sizeof(ssi_sd_state), .class_init = ssi_sd_class_init, }; diff --git a/hw/sh4/shix.c b/hw/sh4/shix.c index f410c08883..d9a9fcbc59 100644 --- a/hw/sh4/shix.c +++ b/hw/sh4/shix.c @@ -49,6 +49,7 @@ static void shix_init(MachineState *machine) MemoryRegion *sysmem = get_system_memory(); MemoryRegion *rom = g_new(MemoryRegion, 1); MemoryRegion *sdram = g_new(MemoryRegion, 2); + const char *bios_name = machine->firmware ?: BIOS_FILENAME; cpu = SUPERH_CPU(cpu_create(machine->cpu_type)); @@ -63,8 +64,6 @@ static void shix_init(MachineState *machine) memory_region_add_subregion(sysmem, 0x0c000000, &sdram[1]); /* Load BIOS in 0 (and access it through P2, 0xA0000000) */ - if (bios_name == NULL) - bios_name = BIOS_FILENAME; ret = load_image_targphys(bios_name, 0, 0x4000); if (ret < 0 && !qtest_enabled()) { error_report("Could not load SHIX bios '%s'", bios_name); diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c index 6a3d39793b..f22c4f5b73 100644 --- a/hw/smbios/smbios.c +++ b/hw/smbios/smbios.c @@ -678,13 +678,13 @@ static void smbios_build_type_16_table(unsigned dimm_cnt) t->location = 0x01; /* Other */ t->use = 0x03; /* System memory */ t->error_correction = 0x06; /* Multi-bit ECC (for Microsoft, per SeaBIOS) */ - size_kb = QEMU_ALIGN_UP(ram_size, KiB) / KiB; + size_kb = QEMU_ALIGN_UP(current_machine->ram_size, KiB) / KiB; if (size_kb < MAX_T16_STD_SZ) { t->maximum_capacity = cpu_to_le32(size_kb); t->extended_maximum_capacity = cpu_to_le64(0); } else { t->maximum_capacity = cpu_to_le32(MAX_T16_STD_SZ); - t->extended_maximum_capacity = cpu_to_le64(ram_size); + t->extended_maximum_capacity = cpu_to_le64(current_machine->ram_size); } t->memory_error_information_handle = cpu_to_le16(0xFFFE); /* Not provided */ t->number_of_memory_devices = cpu_to_le16(dimm_cnt); @@ -911,9 +911,9 @@ void smbios_get_tables(MachineState *ms, #define MAX_DIMM_SZ (16 * GiB) #define GET_DIMM_SZ ((i < dimm_cnt - 1) ? MAX_DIMM_SZ \ - : ((ram_size - 1) % MAX_DIMM_SZ) + 1) + : ((current_machine->ram_size - 1) % MAX_DIMM_SZ) + 1) - dimm_cnt = QEMU_ALIGN_UP(ram_size, MAX_DIMM_SZ) / MAX_DIMM_SZ; + dimm_cnt = QEMU_ALIGN_UP(current_machine->ram_size, MAX_DIMM_SZ) / MAX_DIMM_SZ; smbios_build_type_16_table(dimm_cnt); diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c index d40b7891f6..4bc4ebea84 100644 --- a/hw/sparc/leon3.c +++ b/hw/sparc/leon3.c @@ -27,6 +27,7 @@ #include "qemu/error-report.h" #include "qapi/error.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "cpu.h" #include "hw/irq.h" #include "qemu/timer.h" @@ -185,6 +186,7 @@ static void leon3_set_pil_in(void *opaque, int n, int level) static void leon3_generic_hw_init(MachineState *machine) { ram_addr_t ram_size = machine->ram_size; + const char *bios_name = machine->firmware ?: LEON3_PROM_FILENAME; const char *kernel_filename = machine->kernel_filename; SPARCCPU *cpu; CPUSPARCState *env; @@ -259,9 +261,6 @@ static void leon3_generic_hw_init(MachineState *machine) memory_region_add_subregion(address_space_mem, LEON3_PROM_OFFSET, prom); /* Load boot prom */ - if (bios_name == NULL) { - bios_name = LEON3_PROM_FILENAME; - } filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (filename) { diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 66fecb152a..8686371318 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -25,6 +25,7 @@ #include "qemu/osdep.h" #include "qemu/units.h" #include "qapi/error.h" +#include "qemu/datadir.h" #include "qemu-common.h" #include "cpu.h" #include "hw/sysbus.h" @@ -882,7 +883,7 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, hwdef->max_mem - machine->ram_size); } - prom_init(hwdef->slavio_base, bios_name); + prom_init(hwdef->slavio_base, machine->firmware); slavio_intctl = slavio_intctl_init(hwdef->intctl_base, hwdef->intctl_base + 0x10000ULL, diff --git a/hw/sparc64/sparc64.c b/hw/sparc64/sparc64.c index 100b2fab17..e3f9219a10 100644 --- a/hw/sparc64/sparc64.c +++ b/hw/sparc64/sparc64.c @@ -25,6 +25,7 @@ #include "qemu/osdep.h" #include "cpu.h" +#include "hw/boards.h" #include "hw/char/serial.h" #include "hw/sparc/sparc64.h" #include "qemu/timer.h" @@ -180,7 +181,7 @@ static void main_cpu_reset(void *opaque) cpu_timer_reset(env->hstick); env->gregs[1] = 0; /* Memory start */ - env->gregs[2] = ram_size; /* Memory size */ + env->gregs[2] = current_machine->ram_size; /* Memory size */ env->gregs[3] = 0; /* Machine description XXX */ if (nr_resets++ == 0) { /* Power on reset */ diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index 2f8fc670cf..0fa13a7330 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -27,6 +27,7 @@ #include "qemu/error-report.h" #include "qapi/error.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "cpu.h" #include "hw/pci/pci.h" #include "hw/pci/pci_bridge.h" @@ -578,7 +579,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem, /* set up devices */ ram_init(0, machine->ram_size); - prom_init(hwdef->prom_addr, bios_name); + prom_init(hwdef->prom_addr, machine->firmware); /* Init sabre (PCI host bridge) */ sabre = SABRE(qdev_new(TYPE_SABRE)); @@ -690,7 +691,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem, initrd_addr = 0; kernel_size = sun4u_load_kernel(machine->kernel_filename, machine->initrd_filename, - ram_size, &initrd_size, &initrd_addr, + machine->ram_size, &initrd_size, &initrd_addr, &kernel_addr, &kernel_entry); sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", machine->ram_size, @@ -713,7 +714,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem, fw_cfg = FW_CFG(dev); fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)machine->smp.cpus); fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)machine->smp.max_cpus); - fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); + fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)machine->ram_size); fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id); fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_entry); fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size); diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c index e3d5e26058..16addee4dc 100644 --- a/hw/ssi/aspeed_smc.c +++ b/hw/ssi/aspeed_smc.c @@ -191,7 +191,7 @@ #define SNOOP_START 0x0 /* - * Default segments mapping addresses and size for each slave per + * Default segments mapping addresses and size for each peripheral per * controller. These can be changed when board is initialized with the * Segment Address Registers. */ @@ -269,7 +269,7 @@ static const AspeedSMCController controllers[] = { .r_timings = R_TIMINGS, .nregs_timings = 1, .conf_enable_w0 = CONF_ENABLE_W0, - .max_slaves = 1, + .max_peripherals = 1, .segments = aspeed_segments_legacy, .flash_window_base = ASPEED_SOC_SMC_FLASH_BASE, .flash_window_size = 0x6000000, @@ -285,7 +285,7 @@ static const AspeedSMCController controllers[] = { .r_timings = R_TIMINGS, .nregs_timings = 1, .conf_enable_w0 = CONF_ENABLE_W0, - .max_slaves = 5, + .max_peripherals = 5, .segments = aspeed_segments_fmc, .flash_window_base = ASPEED_SOC_FMC_FLASH_BASE, .flash_window_size = 0x10000000, @@ -303,7 +303,7 @@ static const AspeedSMCController controllers[] = { .r_timings = R_SPI_TIMINGS, .nregs_timings = 1, .conf_enable_w0 = SPI_CONF_ENABLE_W0, - .max_slaves = 1, + .max_peripherals = 1, .segments = aspeed_segments_spi, .flash_window_base = ASPEED_SOC_SPI_FLASH_BASE, .flash_window_size = 0x10000000, @@ -319,7 +319,7 @@ static const AspeedSMCController controllers[] = { .r_timings = R_TIMINGS, .nregs_timings = 1, .conf_enable_w0 = CONF_ENABLE_W0, - .max_slaves = 3, + .max_peripherals = 3, .segments = aspeed_segments_ast2500_fmc, .flash_window_base = ASPEED_SOC_FMC_FLASH_BASE, .flash_window_size = 0x10000000, @@ -337,7 +337,7 @@ static const AspeedSMCController controllers[] = { .r_timings = R_TIMINGS, .nregs_timings = 1, .conf_enable_w0 = CONF_ENABLE_W0, - .max_slaves = 2, + .max_peripherals = 2, .segments = aspeed_segments_ast2500_spi1, .flash_window_base = ASPEED_SOC_SPI_FLASH_BASE, .flash_window_size = 0x8000000, @@ -353,7 +353,7 @@ static const AspeedSMCController controllers[] = { .r_timings = R_TIMINGS, .nregs_timings = 1, .conf_enable_w0 = CONF_ENABLE_W0, - .max_slaves = 2, + .max_peripherals = 2, .segments = aspeed_segments_ast2500_spi2, .flash_window_base = ASPEED_SOC_SPI2_FLASH_BASE, .flash_window_size = 0x8000000, @@ -369,7 +369,7 @@ static const AspeedSMCController controllers[] = { .r_timings = R_TIMINGS, .nregs_timings = 1, .conf_enable_w0 = CONF_ENABLE_W0, - .max_slaves = 3, + .max_peripherals = 3, .segments = aspeed_segments_ast2600_fmc, .flash_window_base = ASPEED26_SOC_FMC_FLASH_BASE, .flash_window_size = 0x10000000, @@ -387,7 +387,7 @@ static const AspeedSMCController controllers[] = { .r_timings = R_TIMINGS, .nregs_timings = 2, .conf_enable_w0 = CONF_ENABLE_W0, - .max_slaves = 2, + .max_peripherals = 2, .segments = aspeed_segments_ast2600_spi1, .flash_window_base = ASPEED26_SOC_SPI_FLASH_BASE, .flash_window_size = 0x10000000, @@ -405,7 +405,7 @@ static const AspeedSMCController controllers[] = { .r_timings = R_TIMINGS, .nregs_timings = 3, .conf_enable_w0 = CONF_ENABLE_W0, - .max_slaves = 3, + .max_peripherals = 3, .segments = aspeed_segments_ast2600_spi2, .flash_window_base = ASPEED26_SOC_SPI2_FLASH_BASE, .flash_window_size = 0x10000000, @@ -420,7 +420,7 @@ static const AspeedSMCController controllers[] = { /* * The Segment Registers of the AST2400 and AST2500 have a 8MB - * unit. The address range of a flash SPI slave is encoded with + * unit. The address range of a flash SPI peripheral is encoded with * absolute addresses which should be part of the overall controller * window. */ @@ -442,7 +442,7 @@ static void aspeed_smc_reg_to_segment(const AspeedSMCState *s, /* * The Segment Registers of the AST2600 have a 1MB unit. The address - * range of a flash SPI slave is encoded with offsets in the overall + * range of a flash SPI peripheral is encoded with offsets in the overall * controller window. The previous SoC AST2400 and AST2500 used * absolute addresses. Only bits [27:20] are relevant and the end * address is an upper bound limit. @@ -486,7 +486,7 @@ static bool aspeed_smc_flash_overlap(const AspeedSMCState *s, AspeedSegments seg; int i; - for (i = 0; i < s->ctrl->max_slaves; i++) { + for (i = 0; i < s->ctrl->max_peripherals; i++) { if (i == cs) { continue; } @@ -547,7 +547,7 @@ static void aspeed_smc_flash_set_segment(AspeedSMCState *s, int cs, */ if ((s->ctrl->segments == aspeed_segments_ast2500_spi1 || s->ctrl->segments == aspeed_segments_ast2500_spi2) && - cs == s->ctrl->max_slaves && + cs == s->ctrl->max_peripherals && seg.addr + seg.size != s->ctrl->segments[cs].addr + s->ctrl->segments[cs].size) { qemu_log_mask(LOG_GUEST_ERROR, @@ -949,14 +949,14 @@ static void aspeed_smc_reset(DeviceState *d) memset(s->regs, 0, sizeof s->regs); - /* Unselect all slaves */ + /* Unselect all peripherals */ for (i = 0; i < s->num_cs; ++i) { s->regs[s->r_ctrl0 + i] |= CTRL_CE_STOP_ACTIVE; qemu_set_irq(s->cs_lines[i], true); } /* setup the default segment register values and regions for all */ - for (i = 0; i < s->ctrl->max_slaves; ++i) { + for (i = 0; i < s->ctrl->max_peripherals; ++i) { aspeed_smc_flash_set_segment_region(s, i, s->ctrl->segment_to_reg(s, &s->ctrl->segments[i])); } @@ -1004,8 +1004,9 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size) (s->ctrl->has_dma && addr == R_DMA_DRAM_ADDR) || (s->ctrl->has_dma && addr == R_DMA_LEN) || (s->ctrl->has_dma && addr == R_DMA_CHECKSUM) || - (addr >= R_SEG_ADDR0 && addr < R_SEG_ADDR0 + s->ctrl->max_slaves) || - (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->ctrl->max_slaves)) { + (addr >= R_SEG_ADDR0 && + addr < R_SEG_ADDR0 + s->ctrl->max_peripherals) || + (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->ctrl->max_peripherals)) { trace_aspeed_smc_read(addr, size, s->regs[addr]); @@ -1279,7 +1280,7 @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data, int cs = addr - s->r_ctrl0; aspeed_smc_flash_update_ctrl(&s->flashes[cs], value); } else if (addr >= R_SEG_ADDR0 && - addr < R_SEG_ADDR0 + s->ctrl->max_slaves) { + addr < R_SEG_ADDR0 + s->ctrl->max_peripherals) { int cs = addr - R_SEG_ADDR0; if (value != s->regs[R_SEG_ADDR0 + cs]) { @@ -1352,10 +1353,10 @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp) s->conf_enable_w0 = s->ctrl->conf_enable_w0; /* Enforce some real HW limits */ - if (s->num_cs > s->ctrl->max_slaves) { + if (s->num_cs > s->ctrl->max_peripherals) { qemu_log_mask(LOG_GUEST_ERROR, "%s: num_cs cannot exceed: %d\n", - __func__, s->ctrl->max_slaves); - s->num_cs = s->ctrl->max_slaves; + __func__, s->ctrl->max_peripherals); + s->num_cs = s->ctrl->max_peripherals; } /* DMA irq. Keep it first for the initialization in the SoC */ @@ -1363,7 +1364,7 @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp) s->spi = ssi_create_bus(dev, "spi"); - /* Setup cs_lines for slaves */ + /* Setup cs_lines for peripherals */ s->cs_lines = g_new0(qemu_irq, s->num_cs); for (i = 0; i < s->num_cs; ++i) { @@ -1387,16 +1388,16 @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp) s->ctrl->flash_window_size); sysbus_init_mmio(sbd, &s->mmio_flash); - s->flashes = g_new0(AspeedSMCFlash, s->ctrl->max_slaves); + s->flashes = g_new0(AspeedSMCFlash, s->ctrl->max_peripherals); /* - * Let's create a sub memory region for each possible slave. All + * Let's create a sub memory region for each possible peripheral. All * have a configurable memory segment in the overall flash mapping * window of the controller but, there is not necessarily a flash * module behind to handle the memory accesses. This depends on * the board configuration. */ - for (i = 0; i < s->ctrl->max_slaves; ++i) { + for (i = 0; i < s->ctrl->max_peripherals; ++i) { AspeedSMCFlash *fl = &s->flashes[i]; snprintf(name, sizeof(name), "%s.%d", s->ctrl->name, i); diff --git a/hw/ssi/pl022.c b/hw/ssi/pl022.c index cade2e92a8..8954ffebb1 100644 --- a/hw/ssi/pl022.c +++ b/hw/ssi/pl022.c @@ -174,7 +174,7 @@ static void pl022_write(void *opaque, hwaddr offset, s->cr1 = value; if ((s->cr1 & (PL022_CR1_MS | PL022_CR1_SSE)) == (PL022_CR1_MS | PL022_CR1_SSE)) { - BADF("SPI slave mode not implemented\n"); + BADF("SPI peripheral mode not implemented\n"); } pl022_xfer(s); break; diff --git a/hw/ssi/ssi.c b/hw/ssi/ssi.c index 4278d0e444..e5d7ce9523 100644 --- a/hw/ssi/ssi.c +++ b/hw/ssi/ssi.c @@ -34,11 +34,11 @@ static const TypeInfo ssi_bus_info = { static void ssi_cs_default(void *opaque, int n, int level) { - SSISlave *s = SSI_SLAVE(opaque); + SSIPeripheral *s = SSI_PERIPHERAL(opaque); bool cs = !!level; assert(n == 0); if (s->cs != cs) { - SSISlaveClass *ssc = SSI_SLAVE_GET_CLASS(s); + SSIPeripheralClass *ssc = SSI_PERIPHERAL_GET_CLASS(s); if (ssc->set_cs) { ssc->set_cs(s, cs); } @@ -46,9 +46,9 @@ static void ssi_cs_default(void *opaque, int n, int level) s->cs = cs; } -static uint32_t ssi_transfer_raw_default(SSISlave *dev, uint32_t val) +static uint32_t ssi_transfer_raw_default(SSIPeripheral *dev, uint32_t val) { - SSISlaveClass *ssc = SSI_SLAVE_GET_CLASS(dev); + SSIPeripheralClass *ssc = SSI_PERIPHERAL_GET_CLASS(dev); if ((dev->cs && ssc->cs_polarity == SSI_CS_HIGH) || (!dev->cs && ssc->cs_polarity == SSI_CS_LOW) || @@ -58,10 +58,10 @@ static uint32_t ssi_transfer_raw_default(SSISlave *dev, uint32_t val) return 0; } -static void ssi_slave_realize(DeviceState *dev, Error **errp) +static void ssi_peripheral_realize(DeviceState *dev, Error **errp) { - SSISlave *s = SSI_SLAVE(dev); - SSISlaveClass *ssc = SSI_SLAVE_GET_CLASS(s); + SSIPeripheral *s = SSI_PERIPHERAL(dev); + SSIPeripheralClass *ssc = SSI_PERIPHERAL_GET_CLASS(s); if (ssc->transfer_raw == ssi_transfer_raw_default && ssc->cs_polarity != SSI_CS_NONE) { @@ -71,23 +71,23 @@ static void ssi_slave_realize(DeviceState *dev, Error **errp) ssc->realize(s, errp); } -static void ssi_slave_class_init(ObjectClass *klass, void *data) +static void ssi_peripheral_class_init(ObjectClass *klass, void *data) { - SSISlaveClass *ssc = SSI_SLAVE_CLASS(klass); + SSIPeripheralClass *ssc = SSI_PERIPHERAL_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - dc->realize = ssi_slave_realize; + dc->realize = ssi_peripheral_realize; dc->bus_type = TYPE_SSI_BUS; if (!ssc->transfer_raw) { ssc->transfer_raw = ssi_transfer_raw_default; } } -static const TypeInfo ssi_slave_info = { - .name = TYPE_SSI_SLAVE, +static const TypeInfo ssi_peripheral_info = { + .name = TYPE_SSI_PERIPHERAL, .parent = TYPE_DEVICE, - .class_init = ssi_slave_class_init, - .class_size = sizeof(SSISlaveClass), + .class_init = ssi_peripheral_class_init, + .class_size = sizeof(SSIPeripheralClass), .abstract = true, }; @@ -96,7 +96,7 @@ bool ssi_realize_and_unref(DeviceState *dev, SSIBus *bus, Error **errp) return qdev_realize_and_unref(dev, &bus->parent_obj, errp); } -DeviceState *ssi_create_slave(SSIBus *bus, const char *name) +DeviceState *ssi_create_peripheral(SSIBus *bus, const char *name) { DeviceState *dev = qdev_new(name); @@ -115,32 +115,32 @@ uint32_t ssi_transfer(SSIBus *bus, uint32_t val) { BusState *b = BUS(bus); BusChild *kid; - SSISlaveClass *ssc; + SSIPeripheralClass *ssc; uint32_t r = 0; QTAILQ_FOREACH(kid, &b->children, sibling) { - SSISlave *slave = SSI_SLAVE(kid->child); - ssc = SSI_SLAVE_GET_CLASS(slave); - r |= ssc->transfer_raw(slave, val); + SSIPeripheral *peripheral = SSI_PERIPHERAL(kid->child); + ssc = SSI_PERIPHERAL_GET_CLASS(peripheral); + r |= ssc->transfer_raw(peripheral, val); } return r; } -const VMStateDescription vmstate_ssi_slave = { +const VMStateDescription vmstate_ssi_peripheral = { .name = "SSISlave", .version_id = 1, .minimum_version_id = 1, .fields = (VMStateField[]) { - VMSTATE_BOOL(cs, SSISlave), + VMSTATE_BOOL(cs, SSIPeripheral), VMSTATE_END_OF_LIST() } }; -static void ssi_slave_register_types(void) +static void ssi_peripheral_register_types(void) { type_register_static(&ssi_bus_info); - type_register_static(&ssi_slave_info); + type_register_static(&ssi_peripheral_info); } -type_init(ssi_slave_register_types) +type_init(ssi_peripheral_register_types) diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c index b9371dbf8d..a897034601 100644 --- a/hw/ssi/xilinx_spips.c +++ b/hw/ssi/xilinx_spips.c @@ -236,7 +236,8 @@ static void xilinx_spips_update_cs(XilinxSPIPS *s, int field) if (old_state != new_state) { s->cs_lines_state[i] = new_state; s->rx_discard = ARRAY_FIELD_EX32(s->regs, CMND, RX_DISCARD); - DB_PRINT_L(1, "%sselecting slave %d\n", new_state ? "" : "de", i); + DB_PRINT_L(1, "%sselecting peripheral %d\n", + new_state ? "" : "de", i); } qemu_set_irq(s->cs_lines[i], !new_state); } @@ -1154,7 +1155,7 @@ static void lqspi_load_cache(void *opaque, hwaddr addr) int i; int flash_addr = ((addr & ~(LQSPI_CACHE_SIZE - 1)) / num_effective_busses(s)); - int slave = flash_addr >> LQSPI_ADDRESS_BITS; + int peripheral = flash_addr >> LQSPI_ADDRESS_BITS; int cache_entry = 0; uint32_t u_page_save = s->regs[R_LQSPI_STS] & ~LQSPI_CFG_U_PAGE; @@ -1162,7 +1163,7 @@ static void lqspi_load_cache(void *opaque, hwaddr addr) addr > q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) { xilinx_qspips_invalidate_mmio_ptr(q); s->regs[R_LQSPI_STS] &= ~LQSPI_CFG_U_PAGE; - s->regs[R_LQSPI_STS] |= slave ? LQSPI_CFG_U_PAGE : 0; + s->regs[R_LQSPI_STS] |= peripheral ? LQSPI_CFG_U_PAGE : 0; DB_PRINT_L(0, "config reg status: %08x\n", s->regs[R_LQSPI_CFG]); @@ -1353,7 +1354,7 @@ static void xlnx_zynqmp_qspips_init(Object *obj) { XlnxZynqMPQSPIPS *rq = XLNX_ZYNQMP_QSPIPS(obj); - object_property_add_link(obj, "stream-connected-dma", TYPE_STREAM_SLAVE, + object_property_add_link(obj, "stream-connected-dma", TYPE_STREAM_SINK, (Object **)&rq->dma, object_property_allow_set_link, OBJ_PROP_LINK_STRONG); diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c index b22b5beda3..e83017c02d 100644 --- a/hw/virtio/virtio-balloon.c +++ b/hw/virtio/virtio-balloon.c @@ -20,6 +20,7 @@ #include "hw/virtio/virtio.h" #include "hw/mem/pc-dimm.h" #include "hw/qdev-properties.h" +#include "hw/boards.h" #include "sysemu/balloon.h" #include "hw/virtio/virtio-balloon.h" #include "exec/address-spaces.h" @@ -748,7 +749,7 @@ static int build_dimm_list(Object *obj, void *opaque) static ram_addr_t get_current_ram_size(void) { GSList *list = NULL, *item; - ram_addr_t size = ram_size; + ram_addr_t size = current_machine->ram_size; build_dimm_list(qdev_get_machine(), &list); for (item = list; item; item = g_slist_next(item)) { diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index 19805ed6db..bd5e15dd7d 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -42,8 +42,6 @@ typedef uintptr_t ram_addr_t; # define RAM_ADDR_FMT "%" PRIxPTR #endif -extern ram_addr_t ram_size; - /* memory API */ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length); diff --git a/include/hw/boards.h b/include/hw/boards.h index f94f4ad5d8..17b1f3f0b9 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -26,6 +26,7 @@ OBJECT_DECLARE_TYPE(MachineState, MachineClass, MACHINE) extern MachineState *current_machine; void machine_run_board_init(MachineState *machine); +bool machine_smp_parse(MachineState *ms, QemuOpts *opts, Error **errp); bool machine_usb(MachineState *machine); int machine_phandle_start(MachineState *machine); bool machine_dump_guest_core(MachineState *machine); @@ -282,6 +283,7 @@ struct MachineState { ram_addr_t maxram_size; uint64_t ram_slots; const char *boot_order; + const char *boot_once; char *kernel_filename; char *kernel_cmdline; char *initrd_filename; diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h index 3f9b052cfc..56080bd1fb 100644 --- a/include/hw/i386/x86.h +++ b/include/hw/i386/x86.h @@ -102,7 +102,8 @@ void x86_cpu_unplug_request_cb(HotplugHandler *hotplug_dev, void x86_cpu_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp); -void x86_bios_rom_init(MemoryRegion *rom_memory, bool isapc_ram_fw); +void x86_bios_rom_init(MachineState *ms, const char *default_firmware, + MemoryRegion *rom_memory, bool isapc_ram_fw); void x86_load_linux(X86MachineState *x86ms, FWCfgState *fw_cfg, diff --git a/include/hw/misc/max111x.h b/include/hw/misc/max111x.h index 606cf1e0a2..beff59c815 100644 --- a/include/hw/misc/max111x.h +++ b/include/hw/misc/max111x.h @@ -33,7 +33,7 @@ * be lowered once it has been asserted. */ struct MAX111xState { - SSISlave parent_obj; + SSIPeripheral parent_obj; qemu_irq interrupt; /* Values of inputs at system reset (settable by QOM property) */ diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 72ce649eee..259f9c992d 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -781,20 +781,58 @@ static inline AddressSpace *pci_get_address_space(PCIDevice *dev) return &dev->bus_master_as; } -static inline int pci_dma_rw(PCIDevice *dev, dma_addr_t addr, - void *buf, dma_addr_t len, DMADirection dir) +/** + * pci_dma_rw: Read from or write to an address space from PCI device. + * + * Return a MemTxResult indicating whether the operation succeeded + * or failed (eg unassigned memory, device rejected the transaction, + * IOMMU fault). + * + * @dev: #PCIDevice doing the memory access + * @addr: address within the #PCIDevice address space + * @buf: buffer with the data transferred + * @len: the number of bytes to read or write + * @dir: indicates the transfer direction + */ +static inline MemTxResult pci_dma_rw(PCIDevice *dev, dma_addr_t addr, + void *buf, dma_addr_t len, + DMADirection dir) { return dma_memory_rw(pci_get_address_space(dev), addr, buf, len, dir); } -static inline int pci_dma_read(PCIDevice *dev, dma_addr_t addr, - void *buf, dma_addr_t len) +/** + * pci_dma_read: Read from an address space from PCI device. + * + * Return a MemTxResult indicating whether the operation succeeded + * or failed (eg unassigned memory, device rejected the transaction, + * IOMMU fault). Called within RCU critical section. + * + * @dev: #PCIDevice doing the memory access + * @addr: address within the #PCIDevice address space + * @buf: buffer with the data transferred + * @len: length of the data transferred + */ +static inline MemTxResult pci_dma_read(PCIDevice *dev, dma_addr_t addr, + void *buf, dma_addr_t len) { return pci_dma_rw(dev, addr, buf, len, DMA_DIRECTION_TO_DEVICE); } -static inline int pci_dma_write(PCIDevice *dev, dma_addr_t addr, - const void *buf, dma_addr_t len) +/** + * pci_dma_write: Write to address space from PCI device. + * + * Return a MemTxResult indicating whether the operation succeeded + * or failed (eg unassigned memory, device rejected the transaction, + * IOMMU fault). + * + * @dev: #PCIDevice doing the memory access + * @addr: address within the #PCIDevice address space + * @buf: buffer with the data transferred + * @len: the number of bytes to write + */ +static inline MemTxResult pci_dma_write(PCIDevice *dev, dma_addr_t addr, + const void *buf, dma_addr_t len) { return pci_dma_rw(dev, addr, (void *) buf, len, DMA_DIRECTION_FROM_DEVICE); } diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 6ac86db44e..9fbb22a48d 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -788,14 +788,6 @@ char *qdev_get_fw_dev_path(DeviceState *dev); char *qdev_get_own_fw_dev_path_from_handler(BusState *bus, DeviceState *dev); /** - * @qdev_machine_init - * - * Initialize platform devices before machine init. This is a hack until full - * support for composition is added. - */ -void qdev_machine_init(void); - -/** * device_legacy_reset: * * Reset a single device (by calling the reset method). diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h index 3dd354b52e..16c03fe64f 100644 --- a/include/hw/ssi/aspeed_smc.h +++ b/include/hw/ssi/aspeed_smc.h @@ -43,7 +43,7 @@ typedef struct AspeedSMCController { uint8_t r_timings; uint8_t nregs_timings; uint8_t conf_enable_w0; - uint8_t max_slaves; + uint8_t max_peripherals; const AspeedSegments *segments; hwaddr flash_window_base; uint32_t flash_window_size; diff --git a/include/hw/ssi/ssi.h b/include/hw/ssi/ssi.h index fe3028c39d..f411858ab0 100644 --- a/include/hw/ssi/ssi.h +++ b/include/hw/ssi/ssi.h @@ -1,12 +1,14 @@ /* QEMU Synchronous Serial Interface support. */ -/* In principle SSI is a point-point interface. As such the qemu - implementation has a single slave device on a "bus". - However it is fairly common for boards to have multiple slaves - connected to a single master, and select devices with an external - chip select. This is implemented in qemu by having an explicit mux device. - It is assumed that master and slave are both using the same transfer width. - */ +/* + * In principle SSI is a point-point interface. As such the qemu + * implementation has a single peripheral on a "bus". + * However it is fairly common for boards to have multiple peripherals + * connected to a single master, and select devices with an external + * chip select. This is implemented in qemu by having an explicit mux device. + * It is assumed that master and peripheral are both using the same transfer + * width. + */ #ifndef QEMU_SSI_H #define QEMU_SSI_H @@ -16,9 +18,9 @@ typedef enum SSICSMode SSICSMode; -#define TYPE_SSI_SLAVE "ssi-slave" -OBJECT_DECLARE_TYPE(SSISlave, SSISlaveClass, - SSI_SLAVE) +#define TYPE_SSI_PERIPHERAL "ssi-peripheral" +OBJECT_DECLARE_TYPE(SSIPeripheral, SSIPeripheralClass, + SSI_PERIPHERAL) #define SSI_GPIO_CS "ssi-gpio-cs" @@ -28,21 +30,21 @@ enum SSICSMode { SSI_CS_HIGH, }; -/* Slave devices. */ -struct SSISlaveClass { +/* Peripherals. */ +struct SSIPeripheralClass { DeviceClass parent_class; - void (*realize)(SSISlave *dev, Error **errp); + void (*realize)(SSIPeripheral *dev, Error **errp); /* if you have standard or no CS behaviour, just override transfer. * This is called when the device cs is active (true by default). */ - uint32_t (*transfer)(SSISlave *dev, uint32_t val); + uint32_t (*transfer)(SSIPeripheral *dev, uint32_t val); /* called when the CS line changes. Optional, devices only need to implement * this if they have side effects associated with the cs line (beyond * tristating the txrx lines). */ - int (*set_cs)(SSISlave *dev, bool select); + int (*set_cs)(SSIPeripheral *dev, bool select); /* define whether or not CS exists and is active low/high */ SSICSMode cs_polarity; @@ -51,30 +53,30 @@ struct SSISlaveClass { * cs_polarity are unused if this is overwritten. Transfer_raw will * always be called for the device for every txrx access to the parent bus */ - uint32_t (*transfer_raw)(SSISlave *dev, uint32_t val); + uint32_t (*transfer_raw)(SSIPeripheral *dev, uint32_t val); }; -struct SSISlave { +struct SSIPeripheral { DeviceState parent_obj; /* Chip select state */ bool cs; }; -extern const VMStateDescription vmstate_ssi_slave; +extern const VMStateDescription vmstate_ssi_peripheral; -#define VMSTATE_SSI_SLAVE(_field, _state) { \ +#define VMSTATE_SSI_PERIPHERAL(_field, _state) { \ .name = (stringify(_field)), \ - .size = sizeof(SSISlave), \ - .vmsd = &vmstate_ssi_slave, \ + .size = sizeof(SSIPeripheral), \ + .vmsd = &vmstate_ssi_peripheral, \ .flags = VMS_STRUCT, \ - .offset = vmstate_offset_value(_state, _field, SSISlave), \ + .offset = vmstate_offset_value(_state, _field, SSIPeripheral), \ } -DeviceState *ssi_create_slave(SSIBus *bus, const char *name); +DeviceState *ssi_create_peripheral(SSIBus *bus, const char *name); /** - * ssi_realize_and_unref: realize and unref an SSI slave device - * @dev: SSI slave device to realize + * ssi_realize_and_unref: realize and unref an SSI peripheral + * @dev: SSI peripheral to realize * @bus: SSI bus to put it on * @errp: error pointer * @@ -85,10 +87,10 @@ DeviceState *ssi_create_slave(SSIBus *bus, const char *name); * This function is useful if you have created @dev via qdev_new() * (which takes a reference to the device it returns to you), so that * you can set properties on it before realizing it. If you don't need - * to set properties then ssi_create_slave() is probably better (as it + * to set properties then ssi_create_peripheral() is probably better (as it * does the create, init and realize in one step). * - * If you are embedding the SSI slave into another QOM device and + * If you are embedding the SSI peripheral into another QOM device and * initialized it via some variant on object_initialize_child() then * do not use this function, because that family of functions arrange * for the only reference to the child device to be held by the parent diff --git a/include/hw/ssi/xilinx_spips.h b/include/hw/ssi/xilinx_spips.h index b96de21b34..3eae73480e 100644 --- a/include/hw/ssi/xilinx_spips.h +++ b/include/hw/ssi/xilinx_spips.h @@ -99,7 +99,7 @@ typedef struct XilinxQSPIPS XilinxQSPIPS; struct XlnxZynqMPQSPIPS { XilinxQSPIPS parent_obj; - StreamSlave *dma; + StreamSink *dma; int gqspi_irqline; uint32_t regs[XLNX_ZYNQMP_SPIPS_R_MAX]; diff --git a/include/hw/stream.h b/include/hw/stream.h index e39d5a5b55..f166facb09 100644 --- a/include/hw/stream.h +++ b/include/hw/stream.h @@ -3,51 +3,50 @@ #include "qom/object.h" -/* stream slave. Used until qdev provides a generic way. */ -#define TYPE_STREAM_SLAVE "stream-slave" +#define TYPE_STREAM_SINK "stream-sink" -typedef struct StreamSlaveClass StreamSlaveClass; -DECLARE_CLASS_CHECKERS(StreamSlaveClass, STREAM_SLAVE, - TYPE_STREAM_SLAVE) -#define STREAM_SLAVE(obj) \ - INTERFACE_CHECK(StreamSlave, (obj), TYPE_STREAM_SLAVE) +typedef struct StreamSinkClass StreamSinkClass; +DECLARE_CLASS_CHECKERS(StreamSinkClass, STREAM_SINK, + TYPE_STREAM_SINK) +#define STREAM_SINK(obj) \ + INTERFACE_CHECK(StreamSink, (obj), TYPE_STREAM_SINK) -typedef struct StreamSlave StreamSlave; +typedef struct StreamSink StreamSink; typedef void (*StreamCanPushNotifyFn)(void *opaque); -struct StreamSlaveClass { +struct StreamSinkClass { InterfaceClass parent; /** - * can push - determine if a stream slave is capable of accepting at least + * can push - determine if a stream sink is capable of accepting at least * one byte of data. Returns false if cannot accept. If not implemented, the - * slave is assumed to always be capable of receiving. - * @notify: Optional callback that the slave will call when the slave is + * sink is assumed to always be capable of receiving. + * @notify: Optional callback that the sink will call when the sink is * capable of receiving again. Only called if false is returned. * @notify_opaque: opaque data to pass to notify call. */ - bool (*can_push)(StreamSlave *obj, StreamCanPushNotifyFn notify, + bool (*can_push)(StreamSink *obj, StreamCanPushNotifyFn notify, void *notify_opaque); /** - * push - push data to a Stream slave. The number of bytes pushed is - * returned. If the slave short returns, the master must wait before trying - * again, the slave may continue to just return 0 waiting for the vm time to + * push - push data to a Stream sink. The number of bytes pushed is + * returned. If the sink short returns, the master must wait before trying + * again, the sink may continue to just return 0 waiting for the vm time to * advance. The can_push() function can be used to trap the point in time - * where the slave is ready to receive again, otherwise polling on a QEMU + * where the sink is ready to receive again, otherwise polling on a QEMU * timer will work. - * @obj: Stream slave to push to + * @obj: Stream sink to push to * @buf: Data to write * @len: Maximum number of bytes to write * @eop: End of packet flag */ - size_t (*push)(StreamSlave *obj, unsigned char *buf, size_t len, bool eop); + size_t (*push)(StreamSink *obj, unsigned char *buf, size_t len, bool eop); }; size_t -stream_push(StreamSlave *sink, uint8_t *buf, size_t len, bool eop); +stream_push(StreamSink *sink, uint8_t *buf, size_t len, bool eop); bool -stream_can_push(StreamSlave *sink, StreamCanPushNotifyFn notify, +stream_can_push(StreamSink *sink, StreamCanPushNotifyFn notify, void *notify_opaque); diff --git a/include/migration/misc.h b/include/migration/misc.h index 34e7d75713..bccc1b6b44 100644 --- a/include/migration/misc.h +++ b/include/migration/misc.h @@ -58,7 +58,6 @@ void dump_vmstate_json_to_file(FILE *out_fp); /* migration/migration.c */ void migration_object_init(void); void migration_shutdown(void); -void qemu_start_incoming_migration(const char *uri, Error **errp); bool migration_is_idle(void); bool migration_is_active(MigrationState *); void add_migration_state_change_notifier(Notifier *notify); diff --git a/include/qemu-common.h b/include/qemu-common.h index fda7dc6ca7..654621444e 100644 --- a/include/qemu-common.h +++ b/include/qemu-common.h @@ -108,27 +108,6 @@ void qemu_progress_end(void); void qemu_progress_print(float delta, int max); const char *qemu_get_vm_name(void); -#define QEMU_FILE_TYPE_BIOS 0 -#define QEMU_FILE_TYPE_KEYMAP 1 -/** - * qemu_find_file: - * @type: QEMU_FILE_TYPE_BIOS (for BIOS, VGA BIOS) - * or QEMU_FILE_TYPE_KEYMAP (for keymaps). - * @name: Relative or absolute file name - * - * If @name exists on disk as an absolute path, or a path relative - * to the current directory, then returns @name unchanged. - * Otherwise searches for @name file in the data directories, either - * configured at build time (DATADIR) or registered with the -L command - * line option. - * - * The caller must use g_free() to free the returned data when it is - * no longer required. - * - * Returns: a path that can access @name, or NULL if no matching file exists. - */ -char *qemu_find_file(int type, const char *name); - /* OS specific functions */ void os_setup_early_signal_handling(void); int os_parse_cmd_args(int index, const char *optarg); diff --git a/include/qemu/config-file.h b/include/qemu/config-file.h index d74f920152..29226107bd 100644 --- a/include/qemu/config-file.h +++ b/include/qemu/config-file.h @@ -8,7 +8,6 @@ QemuOpts *qemu_find_opts_singleton(const char *group); void qemu_add_opts(QemuOptsList *list); void qemu_add_drive_opts(QemuOptsList *list); -int qemu_set_option(const char *str); int qemu_global_option(const char *str); void qemu_config_write(FILE *fp); diff --git a/include/qemu/datadir.h b/include/qemu/datadir.h new file mode 100644 index 0000000000..21f9097f58 --- /dev/null +++ b/include/qemu/datadir.h @@ -0,0 +1,28 @@ +#ifndef QEMU_DATADIR_H +#define QEMU_DATADIR_H + +#define QEMU_FILE_TYPE_BIOS 0 +#define QEMU_FILE_TYPE_KEYMAP 1 +/** + * qemu_find_file: + * @type: QEMU_FILE_TYPE_BIOS (for BIOS, VGA BIOS) + * or QEMU_FILE_TYPE_KEYMAP (for keymaps). + * @name: Relative or absolute file name + * + * If @name exists on disk as an absolute path, or a path relative + * to the current directory, then returns @name unchanged. + * Otherwise searches for @name file in the data directories, either + * configured at build time (DATADIR) or registered with the -L command + * line option. + * + * The caller must use g_free() to free the returned data when it is + * no longer required. + * + * Returns: a path that can access @name, or NULL if no matching file exists. + */ +char *qemu_find_file(int type, const char *name); +void qemu_add_default_firmwarepath(void); +void qemu_add_data_dir(char *path); +void qemu_list_data_dirs(void); + +#endif diff --git a/include/qemu/option.h b/include/qemu/option.h index ac69352e0e..f73e0dc7d9 100644 --- a/include/qemu/option.h +++ b/include/qemu/option.h @@ -119,8 +119,7 @@ QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exists, Error **errp); void qemu_opts_reset(QemuOptsList *list); void qemu_opts_loc_restore(QemuOpts *opts); -bool qemu_opts_set(QemuOptsList *list, const char *id, - const char *name, const char *value, Error **errp); +bool qemu_opts_set(QemuOptsList *list, const char *name, const char *value, Error **errp); const char *qemu_opts_id(QemuOpts *opts); void qemu_opts_set_id(QemuOpts *opts, char *id); void qemu_opts_del(QemuOpts *opts); diff --git a/include/standard-headers/asm-x86/kvm_para.h b/include/standard-headers/asm-x86/kvm_para.h index 07877d3295..215d01b4ec 100644 --- a/include/standard-headers/asm-x86/kvm_para.h +++ b/include/standard-headers/asm-x86/kvm_para.h @@ -32,6 +32,7 @@ #define KVM_FEATURE_POLL_CONTROL 12 #define KVM_FEATURE_PV_SCHED_YIELD 13 #define KVM_FEATURE_ASYNC_PF_INT 14 +#define KVM_FEATURE_MSI_EXT_DEST_ID 15 #define KVM_HINTS_REALTIME 0 diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index 80c5bc3e02..a052f7bca3 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -1,7 +1,7 @@ /* * DMA helper functions * - * Copyright (c) 2009 Red Hat + * Copyright (c) 2009, 2020 Red Hat * * This work is licensed under the terms of the GNU General Public License * (GNU GPL), version 2 or later. @@ -80,51 +80,118 @@ static inline bool dma_memory_valid(AddressSpace *as, MEMTXATTRS_UNSPECIFIED); } -static inline int dma_memory_rw_relaxed(AddressSpace *as, dma_addr_t addr, - void *buf, dma_addr_t len, - DMADirection dir) +static inline MemTxResult dma_memory_rw_relaxed(AddressSpace *as, + dma_addr_t addr, + void *buf, dma_addr_t len, + DMADirection dir) { - return (bool)address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, - buf, len, dir == DMA_DIRECTION_FROM_DEVICE); + return address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, + buf, len, dir == DMA_DIRECTION_FROM_DEVICE); } -static inline int dma_memory_read_relaxed(AddressSpace *as, dma_addr_t addr, - void *buf, dma_addr_t len) +static inline MemTxResult dma_memory_read_relaxed(AddressSpace *as, + dma_addr_t addr, + void *buf, dma_addr_t len) { return dma_memory_rw_relaxed(as, addr, buf, len, DMA_DIRECTION_TO_DEVICE); } -static inline int dma_memory_write_relaxed(AddressSpace *as, dma_addr_t addr, - const void *buf, dma_addr_t len) +static inline MemTxResult dma_memory_write_relaxed(AddressSpace *as, + dma_addr_t addr, + const void *buf, + dma_addr_t len) { return dma_memory_rw_relaxed(as, addr, (void *)buf, len, DMA_DIRECTION_FROM_DEVICE); } -static inline int dma_memory_rw(AddressSpace *as, dma_addr_t addr, - void *buf, dma_addr_t len, - DMADirection dir) +/** + * dma_memory_rw: Read from or write to an address space from DMA controller. + * + * Return a MemTxResult indicating whether the operation succeeded + * or failed (eg unassigned memory, device rejected the transaction, + * IOMMU fault). + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @buf: buffer with the data transferred + * @len: the number of bytes to read or write + * @dir: indicates the transfer direction + */ +static inline MemTxResult dma_memory_rw(AddressSpace *as, dma_addr_t addr, + void *buf, dma_addr_t len, + DMADirection dir) { dma_barrier(as, dir); return dma_memory_rw_relaxed(as, addr, buf, len, dir); } -static inline int dma_memory_read(AddressSpace *as, dma_addr_t addr, - void *buf, dma_addr_t len) +/** + * dma_memory_read: Read from an address space from DMA controller. + * + * Return a MemTxResult indicating whether the operation succeeded + * or failed (eg unassigned memory, device rejected the transaction, + * IOMMU fault). Called within RCU critical section. + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @buf: buffer with the data transferred + * @len: length of the data transferred + */ +static inline MemTxResult dma_memory_read(AddressSpace *as, dma_addr_t addr, + void *buf, dma_addr_t len) { return dma_memory_rw(as, addr, buf, len, DMA_DIRECTION_TO_DEVICE); } -static inline int dma_memory_write(AddressSpace *as, dma_addr_t addr, - const void *buf, dma_addr_t len) +/** + * address_space_write: Write to address space from DMA controller. + * + * Return a MemTxResult indicating whether the operation succeeded + * or failed (eg unassigned memory, device rejected the transaction, + * IOMMU fault). + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @buf: buffer with the data transferred + * @len: the number of bytes to write + */ +static inline MemTxResult dma_memory_write(AddressSpace *as, dma_addr_t addr, + const void *buf, dma_addr_t len) { return dma_memory_rw(as, addr, (void *)buf, len, DMA_DIRECTION_FROM_DEVICE); } -int dma_memory_set(AddressSpace *as, dma_addr_t addr, uint8_t c, dma_addr_t len); +/** + * dma_memory_set: Fill memory with a constant byte from DMA controller. + * + * Return a MemTxResult indicating whether the operation succeeded + * or failed (eg unassigned memory, device rejected the transaction, + * IOMMU fault). + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @c: constant byte to fill the memory + * @len: the number of bytes to fill with the constant byte + */ +MemTxResult dma_memory_set(AddressSpace *as, dma_addr_t addr, + uint8_t c, dma_addr_t len); +/** + * address_space_map: Map a physical memory region into a host virtual address. + * + * May map a subset of the requested range, given by and returned in @plen. + * May return %NULL and set *@plen to zero(0), if resources needed to perform + * the mapping are exhausted. + * Use only for reads OR writes - not for read-modify-write operations. + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @len: pointer to length of buffer; updated on return + * @dir: indicates the transfer direction + */ static inline void *dma_memory_map(AddressSpace *as, dma_addr_t addr, dma_addr_t *len, DMADirection dir) @@ -138,6 +205,20 @@ static inline void *dma_memory_map(AddressSpace *as, return p; } +/** + * address_space_unmap: Unmaps a memory region previously mapped + * by dma_memory_map() + * + * Will also mark the memory as dirty if @dir == %DMA_DIRECTION_FROM_DEVICE. + * @access_len gives the amount of memory that was actually read or written + * by the caller. + * + * @as: #AddressSpace used + * @buffer: host pointer as returned by address_space_map() + * @len: buffer length as returned by address_space_map() + * @dir: indicates the transfer direction + * @access_len: amount of data actually transferred + */ static inline void dma_memory_unmap(AddressSpace *as, void *buffer, dma_addr_t len, DMADirection dir, dma_addr_t access_len) diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index 817ff4cf75..29c32f9851 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -8,22 +8,22 @@ /* vl.c */ -extern const char *bios_name; extern int only_migratable; extern const char *qemu_name; extern QemuUUID qemu_uuid; extern bool qemu_uuid_set; -void qemu_add_data_dir(char *path); - void qemu_add_exit_notifier(Notifier *notify); void qemu_remove_exit_notifier(Notifier *notify); extern bool machine_init_done; +void qemu_run_machine_init_done_notifiers(void); void qemu_add_machine_init_done_notifier(Notifier *notify); void qemu_remove_machine_init_done_notifier(Notifier *notify); +void configure_rtc(QemuOpts *opts); + extern int autostart; typedef enum { @@ -71,10 +71,6 @@ void hmp_pcie_aer_inject_error(Monitor *mon, const QDict *qdict); /* Return the Chardev for serial port i, or NULL if none */ Chardev *serial_hd(int i); -/* return the number of serial ports defined by the user. serial_hd(i) - * will always return NULL for any i which is greater than or equal to this. - */ -int serial_max_hds(void); /* parallel ports */ diff --git a/include/sysemu/whpx.h b/include/sysemu/whpx.h index 59edf13742..9346fd92e9 100644 --- a/include/sysemu/whpx.h +++ b/include/sysemu/whpx.h @@ -15,11 +15,33 @@ #ifdef CONFIG_WHPX +#include "whp-dispatch.h" + +struct whpx_state { + uint64_t mem_quota; + WHV_PARTITION_HANDLE partition; + bool kernel_irqchip_allowed; + bool kernel_irqchip_required; + bool apic_in_platform; +}; + +struct whpx_lapic_state { + struct { + uint32_t data; + uint32_t padding[3]; + } fields[256]; +}; + +extern struct whpx_state whpx_global; int whpx_enabled(void); +void whpx_apic_get(DeviceState *s); +#define whpx_apic_in_platform() (whpx_global.apic_in_platform) + #else /* CONFIG_WHPX */ #define whpx_enabled() (0) +#define whpx_apic_in_platform() (0) #endif /* CONFIG_WHPX */ diff --git a/migration/migration.c b/migration/migration.c index 87a9b59f83..e0dbde4091 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -118,8 +118,6 @@ static NotifierList migration_state_notifiers = NOTIFIER_LIST_INITIALIZER(migration_state_notifiers); -static bool deferred_incoming; - /* Messages sent on the return path from destination to source */ enum mig_rp_message_type { MIG_RP_MSG_INVALID = 0, /* Must be 0 */ @@ -182,6 +180,10 @@ void migration_object_init(void) error_report_err(err); exit(1); } + + blk_mig_init(); + ram_mig_init(); + dirty_bitmap_mig_init(); } void migration_shutdown(void) @@ -272,19 +274,6 @@ static bool migrate_late_block_activate(void) } /* - * Called on -incoming with a defer: uri. - * The migration can be started later after any parameters have been - * changed. - */ -static void deferred_incoming_migration(Error **errp) -{ - if (deferred_incoming) { - error_setg(errp, "Incoming migration already deferred"); - } - deferred_incoming = true; -} - -/* * Send a message on the return channel back to the source * of the migration. */ @@ -425,16 +414,14 @@ void migrate_add_address(SocketAddress *address) addrs->value = QAPI_CLONE(SocketAddress, address); } -void qemu_start_incoming_migration(const char *uri, Error **errp) +static void qemu_start_incoming_migration(const char *uri, Error **errp) { const char *p = NULL; qapi_event_send_migration(MIGRATION_STATUS_SETUP); - if (!strcmp(uri, "defer")) { - deferred_incoming_migration(errp); - } else if (strstart(uri, "tcp:", &p) || - strstart(uri, "unix:", NULL) || - strstart(uri, "vsock:", NULL)) { + if (strstart(uri, "tcp:", &p) || + strstart(uri, "unix:", NULL) || + strstart(uri, "vsock:", NULL)) { socket_start_incoming_migration(p ? p : uri, errp); #ifdef CONFIG_RDMA } else if (strstart(uri, "rdma:", &p)) { @@ -1984,14 +1971,14 @@ void qmp_migrate_incoming(const char *uri, Error **errp) Error *local_err = NULL; static bool once = true; - if (!deferred_incoming) { - error_setg(errp, "For use with '-incoming defer'"); - return; - } if (!once) { error_setg(errp, "The incoming migration has already been started"); return; } + if (!runstate_check(RUN_STATE_INMIGRATE)) { + error_setg(errp, "'-incoming' was not specified on the command line"); + return; + } qemu_start_incoming_migration(uri, &local_err); diff --git a/monitor/hmp.c b/monitor/hmp.c index 1204233999..d40f4f4391 100644 --- a/monitor/hmp.c +++ b/monitor/hmp.c @@ -213,6 +213,11 @@ static bool cmd_can_preconfig(const HMPCommand *cmd) return strchr(cmd->flags, 'p'); } +static bool cmd_available(const HMPCommand *cmd) +{ + return !runstate_check(RUN_STATE_PRECONFIG) || cmd_can_preconfig(cmd); +} + static void help_cmd_dump_one(Monitor *mon, const HMPCommand *cmd, char **prefix_args, @@ -220,7 +225,7 @@ static void help_cmd_dump_one(Monitor *mon, { int i; - if (runstate_check(RUN_STATE_PRECONFIG) && !cmd_can_preconfig(cmd)) { + if (!cmd_available(cmd)) { return; } @@ -248,8 +253,7 @@ static void help_cmd_dump(Monitor *mon, const HMPCommand *cmds, /* Find one entry to dump */ for (cmd = cmds; cmd->name != NULL; cmd++) { if (hmp_compare_cmd(args[arg_index], cmd->name) && - ((!runstate_check(RUN_STATE_PRECONFIG) || - cmd_can_preconfig(cmd)))) { + cmd_available(cmd)) { if (cmd->sub_table) { /* continue with next arg */ help_cmd_dump(mon, cmd->sub_table, @@ -653,7 +657,7 @@ static const HMPCommand *monitor_parse_command(MonitorHMP *hmp_mon, (int)(p - cmdp_start), cmdp_start); return NULL; } - if (runstate_check(RUN_STATE_PRECONFIG) && !cmd_can_preconfig(cmd)) { + if (!cmd_available(cmd)) { monitor_printf(mon, "Command '%.*s' not available with -preconfig " "until after exit_preconfig.\n", (int)(p - cmdp_start), cmdp_start); @@ -1225,8 +1229,7 @@ static void monitor_find_completion_by_table(MonitorHMP *mon, } readline_set_completion_index(mon->rs, strlen(cmdname)); for (cmd = cmd_table; cmd->name != NULL; cmd++) { - if (!runstate_check(RUN_STATE_PRECONFIG) || - cmd_can_preconfig(cmd)) { + if (cmd_available(cmd)) { cmd_completion(mon, cmdname, cmd->name); } } @@ -1234,8 +1237,7 @@ static void monitor_find_completion_by_table(MonitorHMP *mon, /* find the command */ for (cmd = cmd_table; cmd->name != NULL; cmd++) { if (hmp_compare_cmd(args[0], cmd->name) && - (!runstate_check(RUN_STATE_PRECONFIG) || - cmd_can_preconfig(cmd))) { + cmd_available(cmd)) { break; } } diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c index ffbf948d55..6223a28e8b 100644 --- a/monitor/qmp-cmds.c +++ b/monitor/qmp-cmds.c @@ -384,8 +384,9 @@ ACPIOSTInfoList *qmp_query_acpi_ospm_status(Error **errp) MemoryInfo *qmp_query_memory_size_summary(Error **errp) { MemoryInfo *mem_info = g_malloc0(sizeof(MemoryInfo)); + MachineState *ms = MACHINE(qdev_get_machine()); - mem_info->base_memory = ram_size; + mem_info->base_memory = ms->ram_size; mem_info->plugged_memory = get_plugged_memory_size(); mem_info->has_plugged_memory = diff --git a/python/qemu/machine.py b/python/qemu/machine.py index 64d966aeeb..7a40f4604b 100644 --- a/python/qemu/machine.py +++ b/python/qemu/machine.py @@ -292,7 +292,7 @@ class QEMUMachine: for _ in range(self._console_index): args.extend(['-serial', 'null']) if self._console_set: - chardev = ('socket,id=console,path=%s,server,nowait' % + chardev = ('socket,id=console,path=%s,server=on,wait=off' % self._console_address) args.extend(['-chardev', chardev]) if self._console_device_type is None: diff --git a/qemu-options.hx b/qemu-options.hx index 104632ea34..e60ad42976 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1406,25 +1406,25 @@ ERST DEF("fsdev", HAS_ARG, QEMU_OPTION_fsdev, "-fsdev local,id=id,path=path,security_model=mapped-xattr|mapped-file|passthrough|none\n" - " [,writeout=immediate][,readonly][,fmode=fmode][,dmode=dmode]\n" + " [,writeout=immediate][,readonly=on][,fmode=fmode][,dmode=dmode]\n" " [[,throttling.bps-total=b]|[[,throttling.bps-read=r][,throttling.bps-write=w]]]\n" " [[,throttling.iops-total=i]|[[,throttling.iops-read=r][,throttling.iops-write=w]]]\n" " [[,throttling.bps-total-max=bm]|[[,throttling.bps-read-max=rm][,throttling.bps-write-max=wm]]]\n" " [[,throttling.iops-total-max=im]|[[,throttling.iops-read-max=irm][,throttling.iops-write-max=iwm]]]\n" " [[,throttling.iops-size=is]]\n" - "-fsdev proxy,id=id,socket=socket[,writeout=immediate][,readonly]\n" - "-fsdev proxy,id=id,sock_fd=sock_fd[,writeout=immediate][,readonly]\n" + "-fsdev proxy,id=id,socket=socket[,writeout=immediate][,readonly=on]\n" + "-fsdev proxy,id=id,sock_fd=sock_fd[,writeout=immediate][,readonly=on]\n" "-fsdev synth,id=id\n", QEMU_ARCH_ALL) SRST -``-fsdev local,id=id,path=path,security_model=security_model [,writeout=writeout][,readonly][,fmode=fmode][,dmode=dmode] [,throttling.option=value[,throttling.option=value[,...]]]`` +``-fsdev local,id=id,path=path,security_model=security_model [,writeout=writeout][,readonly=on][,fmode=fmode][,dmode=dmode] [,throttling.option=value[,throttling.option=value[,...]]]`` \ -``-fsdev proxy,id=id,socket=socket[,writeout=writeout][,readonly]`` +``-fsdev proxy,id=id,socket=socket[,writeout=writeout][,readonly=on]`` \ -``-fsdev proxy,id=id,sock_fd=sock_fd[,writeout=writeout][,readonly]`` +``-fsdev proxy,id=id,sock_fd=sock_fd[,writeout=writeout][,readonly=on]`` \ -``-fsdev synth,id=id[,readonly]`` +``-fsdev synth,id=id[,readonly=on]`` Define a new file system device. Valid options are: ``local`` @@ -1467,7 +1467,7 @@ SRST guest only when the data has been reported as written by the storage subsystem. - ``readonly`` + ``readonly=on`` Enables exporting 9p share as a readonly mount for guests. By default read-write access is given. @@ -1532,18 +1532,18 @@ ERST DEF("virtfs", HAS_ARG, QEMU_OPTION_virtfs, "-virtfs local,path=path,mount_tag=tag,security_model=mapped-xattr|mapped-file|passthrough|none\n" - " [,id=id][,writeout=immediate][,readonly][,fmode=fmode][,dmode=dmode][,multidevs=remap|forbid|warn]\n" - "-virtfs proxy,mount_tag=tag,socket=socket[,id=id][,writeout=immediate][,readonly]\n" - "-virtfs proxy,mount_tag=tag,sock_fd=sock_fd[,id=id][,writeout=immediate][,readonly]\n" - "-virtfs synth,mount_tag=tag[,id=id][,readonly]\n", + " [,id=id][,writeout=immediate][,readonly=on][,fmode=fmode][,dmode=dmode][,multidevs=remap|forbid|warn]\n" + "-virtfs proxy,mount_tag=tag,socket=socket[,id=id][,writeout=immediate][,readonly=on]\n" + "-virtfs proxy,mount_tag=tag,sock_fd=sock_fd[,id=id][,writeout=immediate][,readonly=on]\n" + "-virtfs synth,mount_tag=tag[,id=id][,readonly=on]\n", QEMU_ARCH_ALL) SRST -``-virtfs local,path=path,mount_tag=mount_tag ,security_model=security_model[,writeout=writeout][,readonly] [,fmode=fmode][,dmode=dmode][,multidevs=multidevs]`` +``-virtfs local,path=path,mount_tag=mount_tag ,security_model=security_model[,writeout=writeout][,readonly=on] [,fmode=fmode][,dmode=dmode][,multidevs=multidevs]`` \ -``-virtfs proxy,socket=socket,mount_tag=mount_tag [,writeout=writeout][,readonly]`` +``-virtfs proxy,socket=socket,mount_tag=mount_tag [,writeout=writeout][,readonly=on]`` \ -``-virtfs proxy,sock_fd=sock_fd,mount_tag=mount_tag [,writeout=writeout][,readonly]`` +``-virtfs proxy,sock_fd=sock_fd,mount_tag=mount_tag [,writeout=writeout][,readonly=on]`` \ ``-virtfs synth,mount_tag=mount_tag`` Define a new virtual filesystem device and expose it to the guest using @@ -1598,7 +1598,7 @@ SRST guest only when the data has been reported as written by the storage subsystem. - ``readonly`` + ``readonly=on`` Enables exporting 9p share as a readonly mount for guests. By default read-write access is given. diff --git a/qom/object.c b/qom/object.c index e73d70a993..f2ae6e6b2a 100644 --- a/qom/object.c +++ b/qom/object.c @@ -2175,11 +2175,10 @@ static void property_set_str(Object *obj, Visitor *v, const char *name, g_free(value); } -static void property_release_str(Object *obj, const char *name, - void *opaque) +static void property_release_data(Object *obj, const char *name, + void *opaque) { - StringProperty *prop = opaque; - g_free(prop); + g_free(opaque); } ObjectProperty * @@ -2195,7 +2194,7 @@ object_property_add_str(Object *obj, const char *name, return object_property_add(obj, name, "string", get ? property_get_str : NULL, set ? property_set_str : NULL, - property_release_str, + property_release_data, prop); } @@ -2252,13 +2251,6 @@ static void property_set_bool(Object *obj, Visitor *v, const char *name, prop->set(obj, value, errp); } -static void property_release_bool(Object *obj, const char *name, - void *opaque) -{ - BoolProperty *prop = opaque; - g_free(prop); -} - ObjectProperty * object_property_add_bool(Object *obj, const char *name, bool (*get)(Object *, Error **), @@ -2272,7 +2264,7 @@ object_property_add_bool(Object *obj, const char *name, return object_property_add(obj, name, "bool", get ? property_get_bool : NULL, set ? property_set_bool : NULL, - property_release_bool, + property_release_data, prop); } @@ -2321,13 +2313,6 @@ static void property_set_enum(Object *obj, Visitor *v, const char *name, prop->set(obj, value, errp); } -static void property_release_enum(Object *obj, const char *name, - void *opaque) -{ - EnumProperty *prop = opaque; - g_free(prop); -} - ObjectProperty * object_property_add_enum(Object *obj, const char *name, const char *typename, @@ -2344,7 +2329,7 @@ object_property_add_enum(Object *obj, const char *name, return object_property_add(obj, name, typename, get ? property_get_enum : NULL, set ? property_set_enum : NULL, - property_release_enum, + property_release_data, prop); } @@ -2411,13 +2396,6 @@ out_end: visit_end_struct(v, NULL); } -static void property_release_tm(Object *obj, const char *name, - void *opaque) -{ - TMProperty *prop = opaque; - g_free(prop); -} - ObjectProperty * object_property_add_tm(Object *obj, const char *name, void (*get)(Object *, struct tm *, Error **)) @@ -2428,7 +2406,7 @@ object_property_add_tm(Object *obj, const char *name, return object_property_add(obj, name, "struct tm", get ? property_get_tm : NULL, NULL, - property_release_tm, + property_release_data, prop); } diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 4fbaaa05e3..4b19851b2d 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -56,6 +56,13 @@ Output format selection (mutually exclusive): -rst Output reStructuredText format. -none Do not output documentation, only warnings. +Output format selection modifier (affects only ReST output): + + -sphinx-version Use the ReST C domain dialect compatible with an + specific Sphinx Version. + If not specified, kernel-doc will auto-detect using + the sphinx-build version found on PATH. + Output selection (mutually exclusive): -export Only output documentation for symbols that have been exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL() @@ -66,13 +73,10 @@ Output selection (mutually exclusive): -function NAME Only output documentation for the given function(s) or DOC: section title(s). All other functions and DOC: sections are ignored. May be specified multiple times. - -nofunction NAME Do NOT output documentation for the given function(s); - only output documentation for the other functions and - DOC: sections. May be specified multiple times. + -nosymbol NAME Exclude the specified symbols from the output + documentation. May be specified multiple times. Output selection modifiers: - -sphinx-version VER Generate rST syntax for the specified Sphinx version. - Only works with reStructuredTextFormat. -no-doc-sections Do not output DOC: sections. -enable-lineno Enable output of #define LINENO lines. Only works with reStructuredText format. @@ -83,6 +87,7 @@ Output selection modifiers: Other parameters: -v Verbose output, more warnings and other information. -h Print this help. + -Werror Treat warnings as errors. EOF print $message; @@ -215,7 +220,9 @@ my $type_constant = '\b``([^\`]+)``\b'; my $type_constant2 = '\%([-_\w]+)'; my $type_func = '(\w+)\(\)'; my $type_param = '\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)'; +my $type_param_ref = '([\!]?)\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)'; my $type_fp_param = '\@(\w+)\(\)'; # Special RST handling for func ptr params +my $type_fp_param2 = '\@(\w+->\S+)\(\)'; # Special RST handling for structs with func ptr params my $type_env = '(\$\w+)'; my $type_enum = '#(enum\s*([_\w]+))'; my $type_struct = '#(struct\s*([_\w]+))'; @@ -238,6 +245,7 @@ my @highlights_man = ( [$type_typedef, "\\\\fI\$1\\\\fP"], [$type_union, "\\\\fI\$1\\\\fP"], [$type_param, "\\\\fI\$1\\\\fP"], + [$type_param_ref, "\\\\fI\$1\$2\\\\fP"], [$type_member, "\\\\fI\$1\$2\$3\\\\fP"], [$type_fallback, "\\\\fI\$1\\\\fP"] ); @@ -251,6 +259,7 @@ my @highlights_rst = ( [$type_member_func, "\\:c\\:type\\:`\$1\$2\$3\\\\(\\\\) <\$1>`"], [$type_member, "\\:c\\:type\\:`\$1\$2\$3 <\$1>`"], [$type_fp_param, "**\$1\\\\(\\\\)**"], + [$type_fp_param2, "**\$1\\\\(\\\\)**"], [$type_func, "\$1()"], [$type_enum, "\\:c\\:type\\:`\$1 <\$2>`"], [$type_struct, "\\:c\\:type\\:`\$1 <\$2>`"], @@ -258,7 +267,7 @@ my @highlights_rst = ( [$type_union, "\\:c\\:type\\:`\$1 <\$2>`"], # in rst this can refer to any type [$type_fallback, "\\:c\\:type\\:`\$1`"], - [$type_param, "**\$1**"] + [$type_param_ref, "**\$1\$2**"] ); my $blankline_rst = "\n"; @@ -268,9 +277,12 @@ if ($#ARGV == -1) { } my $kernelversion; +my ($sphinx_major, $sphinx_minor, $sphinx_patch); + my $dohighlight = ""; my $verbose = 0; +my $Werror = 0; my $output_mode = "rst"; my $output_preformatted = 0; my $no_doc_sections = 0; @@ -282,13 +294,11 @@ my $modulename = "Kernel API"; use constant { OUTPUT_ALL => 0, # output all symbols and doc sections OUTPUT_INCLUDE => 1, # output only specified symbols - OUTPUT_EXCLUDE => 2, # output everything except specified symbols - OUTPUT_EXPORTED => 3, # output exported symbols - OUTPUT_INTERNAL => 4, # output non-exported symbols + OUTPUT_EXPORTED => 2, # output exported symbols + OUTPUT_INTERNAL => 3, # output non-exported symbols }; my $output_selection = OUTPUT_ALL; my $show_not_found = 0; # No longer used -my $sphinx_version = "0.0"; # if not specified, assume old my @export_file_list; @@ -310,6 +320,7 @@ my $man_date = ('January', 'February', 'March', 'April', 'May', 'June', # CAVEAT EMPTOR! Some of the others I localised may not want to be, which # could cause "use of undefined value" or other bugs. my ($function, %function_table, %parametertypes, $declaration_purpose); +my %nosymbol_table = (); my $declaration_start_line; my ($type, $declaration_name, $return_type); my ($newsection, $newcontents, $prototype, $brcount, %source_map); @@ -318,9 +329,21 @@ if (defined($ENV{'KBUILD_VERBOSE'})) { $verbose = "$ENV{'KBUILD_VERBOSE'}"; } +if (defined($ENV{'KDOC_WERROR'})) { + $Werror = "$ENV{'KDOC_WERROR'}"; +} + +if (defined($ENV{'KCFLAGS'})) { + my $kcflags = "$ENV{'KCFLAGS'}"; + + if ($kcflags =~ /Werror/) { + $Werror = 1; + } +} + # Generated docbook code is inserted in a template at a point where # docbook v3.1 requires a non-zero sequence of RefEntry's; see: -# http://www.oasis-open.org/docbook/documentation/reference/html/refentry.html +# https://www.oasis-open.org/docbook/documentation/reference/html/refentry.html # We keep track of number of generated entries and generate a dummy # if needs be to ensure the expanded template can be postprocessed # into html. @@ -330,13 +353,14 @@ my $lineprefix=""; # Parser states use constant { - STATE_NORMAL => 0, # normal code - STATE_NAME => 1, # looking for function name - STATE_BODY_MAYBE => 2, # body - or maybe more description - STATE_BODY => 3, # the body of the comment - STATE_PROTO => 4, # scanning prototype - STATE_DOCBLOCK => 5, # documentation block - STATE_INLINE => 6, # gathering documentation outside main block + STATE_NORMAL => 0, # normal code + STATE_NAME => 1, # looking for function name + STATE_BODY_MAYBE => 2, # body - or maybe more description + STATE_BODY => 3, # the body of the comment + STATE_BODY_WITH_BLANK_LINE => 4, # the body, which has a blank line + STATE_PROTO => 5, # scanning prototype + STATE_DOCBLOCK => 6, # documentation block + STATE_INLINE => 7, # gathering doc outside main block }; my $state; my $in_doc_sect; @@ -416,10 +440,9 @@ while ($ARGV[0] =~ m/^--?(.*)/) { $output_selection = OUTPUT_INCLUDE; $function = shift @ARGV; $function_table{$function} = 1; - } elsif ($cmd eq "nofunction") { # output all except specific functions - $output_selection = OUTPUT_EXCLUDE; - $function = shift @ARGV; - $function_table{$function} = 1; + } elsif ($cmd eq "nosymbol") { # Exclude specific symbols + my $symbol = shift @ARGV; + $nosymbol_table{$symbol} = 1; } elsif ($cmd eq "export") { # only exported symbols $output_selection = OUTPUT_EXPORTED; %function_table = (); @@ -431,6 +454,8 @@ while ($ARGV[0] =~ m/^--?(.*)/) { push(@export_file_list, $file); } elsif ($cmd eq "v") { $verbose = 1; + } elsif ($cmd eq "Werror") { + $Werror = 1; } elsif (($cmd eq "h") || ($cmd eq "help")) { usage(); } elsif ($cmd eq 'no-doc-sections') { @@ -439,8 +464,23 @@ while ($ARGV[0] =~ m/^--?(.*)/) { $enable_lineno = 1; } elsif ($cmd eq 'show-not-found') { $show_not_found = 1; # A no-op but don't fail - } elsif ($cmd eq 'sphinx-version') { - $sphinx_version = shift @ARGV; + } elsif ($cmd eq "sphinx-version") { + my $ver_string = shift @ARGV; + if ($ver_string =~ m/^(\d+)(\.\d+)?(\.\d+)?/) { + $sphinx_major = $1; + if (defined($2)) { + $sphinx_minor = substr($2,1); + } else { + $sphinx_minor = 0; + } + if (defined($3)) { + $sphinx_patch = substr($3,1) + } else { + $sphinx_patch = 0; + } + } else { + die "Sphinx version should either major.minor or major.minor.patch format\n"; + } } else { # Unknown argument usage(); @@ -449,6 +489,51 @@ while ($ARGV[0] =~ m/^--?(.*)/) { # continue execution near EOF; +# The C domain dialect changed on Sphinx 3. So, we need to check the +# version in order to produce the right tags. +sub findprog($) +{ + foreach(split(/:/, $ENV{PATH})) { + return "$_/$_[0]" if(-x "$_/$_[0]"); + } +} + +sub get_sphinx_version() +{ + my $ver; + + my $cmd = "sphinx-build"; + if (!findprog($cmd)) { + my $cmd = "sphinx-build3"; + if (!findprog($cmd)) { + $sphinx_major = 1; + $sphinx_minor = 2; + $sphinx_patch = 0; + printf STDERR "Warning: Sphinx version not found. Using default (Sphinx version %d.%d.%d)\n", + $sphinx_major, $sphinx_minor, $sphinx_patch; + return; + } + } + + open IN, "$cmd --version 2>&1 |"; + while (<IN>) { + if (m/^\s*sphinx-build\s+([\d]+)\.([\d\.]+)(\+\/[\da-f]+)?$/) { + $sphinx_major = $1; + $sphinx_minor = $2; + $sphinx_patch = $3; + last; + } + # Sphinx 1.2.x uses a different format + if (m/^\s*Sphinx.*\s+([\d]+)\.([\d\.]+)$/) { + $sphinx_major = $1; + $sphinx_minor = $2; + $sphinx_patch = $3; + last; + } + } + close IN; +} + # get kernel version from env sub get_kernel_version() { my $version = 'unknown kernel version'; @@ -515,11 +600,11 @@ sub dump_doc_section { return; } + return if (defined($nosymbol_table{$name})); + if (($output_selection == OUTPUT_ALL) || - ($output_selection == OUTPUT_INCLUDE && - defined($function_table{$name})) || - ($output_selection == OUTPUT_EXCLUDE && - !defined($function_table{$name}))) + (($output_selection == OUTPUT_INCLUDE) && + defined($function_table{$name}))) { dump_section($file, $name, $contents); output_blockhead({'sectionlist' => \@sectionlist, @@ -602,10 +687,10 @@ sub output_function_man(%) { $type = $args{'parametertypes'}{$parameter}; if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { # pointer-to-function - print ".BI \"" . $parenth . $1 . "\" " . $parameter . " \") (" . $2 . ")" . $post . "\"\n"; + print ".BI \"" . $parenth . $1 . "\" " . " \") (" . $2 . ")" . $post . "\"\n"; } else { $type =~ s/([^\*])$/$1 /; - print ".BI \"" . $parenth . $type . "\" " . $parameter . " \"" . $post . "\"\n"; + print ".BI \"" . $parenth . $type . "\" " . " \"" . $post . "\"\n"; } $count++; $parenth = ""; @@ -745,6 +830,8 @@ sub output_blockhead_rst(%) { my ($parameter, $section); foreach $section (@{$args{'sectionlist'}}) { + next if (defined($nosymbol_table{$section})); + if ($output_selection != OUTPUT_INCLUDE) { print "**$section**\n\n"; } @@ -830,32 +917,37 @@ sub output_function_rst(%) { my ($parameter, $section); my $oldprefix = $lineprefix; my $start = ""; - - if ($args{'typedef'}) { - print ".. c:type:: ". $args{'function'} . "\n\n"; - print_lineno($declaration_start_line); - print " **Typedef**: "; - $lineprefix = ""; - output_highlight_rst($args{'purpose'}); - $start = "\n\n**Syntax**\n\n ``"; + my $is_macro = 0; + + if ($sphinx_major < 3) { + if ($args{'typedef'}) { + print ".. c:type:: ". $args{'function'} . "\n\n"; + print_lineno($declaration_start_line); + print " **Typedef**: "; + $lineprefix = ""; + output_highlight_rst($args{'purpose'}); + $start = "\n\n**Syntax**\n\n ``"; + $is_macro = 1; + } else { + print ".. c:function:: "; + } } else { - if ((split(/\./, $sphinx_version))[0] >= 3) { - # Sphinx 3 and later distinguish macros and functions and - # complain if you use c:function with something that's not - # syntactically valid as a function declaration. - # We assume that anything with a return type is a function - # and anything without is a macro. - if ($args{'functiontype'} ne "") { - print ".. c:function:: "; - } else { - print ".. c:macro:: "; - } - } else { - # Older Sphinx don't support documenting macros that take - # arguments with c:macro, and don't complain about the use - # of c:function for this. - print ".. c:function:: "; - } + if ($args{'typedef'} || $args{'functiontype'} eq "") { + $is_macro = 1; + print ".. c:macro:: ". $args{'function'} . "\n\n"; + } else { + print ".. c:function:: "; + } + + if ($args{'typedef'}) { + print_lineno($declaration_start_line); + print " **Typedef**: "; + $lineprefix = ""; + output_highlight_rst($args{'purpose'}); + $start = "\n\n**Syntax**\n\n ``"; + } else { + print "``" if ($is_macro); + } } if ($args{'functiontype'} ne "") { $start .= $args{'functiontype'} . " " . $args{'function'} . " ("; @@ -876,13 +968,15 @@ sub output_function_rst(%) { # pointer-to-function print $1 . $parameter . ") (" . $2 . ")"; } else { - print $type . " " . $parameter; + print $type; } } - if ($args{'typedef'}) { - print ");``\n\n"; + if ($is_macro) { + print ")``\n\n"; } else { print ")\n\n"; + } + if (!$args{'typedef'}) { print_lineno($declaration_start_line); $lineprefix = " "; output_highlight_rst($args{'purpose'}); @@ -897,7 +991,7 @@ sub output_function_rst(%) { $type = $args{'parametertypes'}{$parameter}; if ($type ne "") { - print "``$type $parameter``\n"; + print "``$type``\n"; } else { print "``$parameter``\n"; } @@ -938,9 +1032,14 @@ sub output_enum_rst(%) { my ($parameter); my $oldprefix = $lineprefix; my $count; - my $name = "enum " . $args{'enum'}; - print "\n\n.. c:type:: " . $name . "\n\n"; + if ($sphinx_major < 3) { + my $name = "enum " . $args{'enum'}; + print "\n\n.. c:type:: " . $name . "\n\n"; + } else { + my $name = $args{'enum'}; + print "\n\n.. c:enum:: " . $name . "\n\n"; + } print_lineno($declaration_start_line); $lineprefix = " "; output_highlight_rst($args{'purpose'}); @@ -966,8 +1065,13 @@ sub output_typedef_rst(%) { my %args = %{$_[0]}; my ($parameter); my $oldprefix = $lineprefix; - my $name = "typedef " . $args{'typedef'}; + my $name; + if ($sphinx_major < 3) { + $name = "typedef " . $args{'typedef'}; + } else { + $name = $args{'typedef'}; + } print "\n\n.. c:type:: " . $name . "\n\n"; print_lineno($declaration_start_line); $lineprefix = " "; @@ -982,17 +1086,17 @@ sub output_struct_rst(%) { my %args = %{$_[0]}; my ($parameter); my $oldprefix = $lineprefix; - my $name = $args{'type'} . " " . $args{'struct'}; - - # Sphinx 3.0 and up will emit warnings for "c:type:: struct Foo". - # It wants to see "c:struct:: Foo" (and will add the word 'struct' in - # the rendered output). - if ((split(/\./, $sphinx_version))[0] >= 3) { - my $sname = $name; - $sname =~ s/^struct //; - print "\n\n.. c:struct:: " . $sname . "\n\n"; + + if ($sphinx_major < 3) { + my $name = $args{'type'} . " " . $args{'struct'}; + print "\n\n.. c:type:: " . $name . "\n\n"; } else { - print "\n\n.. c:type:: " . $name . "\n\n"; + my $name = $args{'struct'}; + if ($args{'type'} eq 'union') { + print "\n\n.. c:union:: " . $name . "\n\n"; + } else { + print "\n\n.. c:struct:: " . $name . "\n\n"; + } } print_lineno($declaration_start_line); $lineprefix = " "; @@ -1052,12 +1156,14 @@ sub output_declaration { my $name = shift; my $functype = shift; my $func = "output_${functype}_$output_mode"; + + return if (defined($nosymbol_table{$name})); + if (($output_selection == OUTPUT_ALL) || (($output_selection == OUTPUT_INCLUDE || $output_selection == OUTPUT_EXPORTED) && defined($function_table{$name})) || - (($output_selection == OUTPUT_EXCLUDE || - $output_selection == OUTPUT_INTERNAL) && + ($output_selection == OUTPUT_INTERNAL && !($functype eq "function" && defined($function_table{$name})))) { &$func(@_); @@ -1092,7 +1198,7 @@ sub dump_struct($$) { my $x = shift; my $file = shift; - if ($x =~ /(struct|union)\s+(\w+)\s*\{(.*)\}(\s*(__packed|__aligned|__attribute__\s*\(\([a-z0-9,_\s\(\)]*\)\)))*/) { + if ($x =~ /(struct|union)\s+(\w+)\s*\{(.*)\}(\s*(__packed|__aligned|____cacheline_aligned_in_smp|____cacheline_aligned|__attribute__\s*\(\([a-z0-9,_\s\(\)]*\)\)))*/) { my $decl_type = $1; $declaration_name = $2; my $members = $3; @@ -1103,11 +1209,15 @@ sub dump_struct($$) { # strip comments: $members =~ s/\/\*.*?\*\///gos; # strip attributes - $members =~ s/\s*__attribute__\s*\(\([a-z0-9,_\*\s\(\)]*\)\)//gi; - $members =~ s/\s*__aligned\s*\([^;]*\)//gos; - $members =~ s/\s*__packed\s*//gos; - $members =~ s/\s*CRYPTO_MINALIGN_ATTR//gos; + $members =~ s/\s*__attribute__\s*\(\([a-z0-9,_\*\s\(\)]*\)\)/ /gi; + $members =~ s/\s*__aligned\s*\([^;]*\)/ /gos; + $members =~ s/\s*__packed\s*/ /gos; + $members =~ s/\s*CRYPTO_MINALIGN_ATTR/ /gos; + $members =~ s/\s*____cacheline_aligned_in_smp/ /gos; + $members =~ s/\s*____cacheline_aligned/ /gos; + # replace DECLARE_BITMAP + $members =~ s/__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, __ETHTOOL_LINK_MODE_MASK_NBITS)/gos; $members =~ s/DECLARE_BITMAP\s*\(([^,)]+),\s*([^,)]+)\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos; # replace DECLARE_HASHTABLE $members =~ s/DECLARE_HASHTABLE\s*\(([^,)]+),\s*([^,)]+)\)/unsigned long $1\[1 << (($2) - 1)\]/gos; @@ -1234,6 +1344,8 @@ sub show_warnings($$) { my $functype = shift; my $name = shift; + return 0 if (defined($nosymbol_table{$name})); + return 1 if ($output_selection == OUTPUT_ALL); if ($output_selection == OUTPUT_EXPORTED) { @@ -1257,27 +1369,28 @@ sub show_warnings($$) { return 0; } } - if ($output_selection == OUTPUT_EXCLUDE) { - if (!defined($function_table{$name})) { - return 1; - } else { - return 0; - } - } die("Please add the new output type at show_warnings()"); } sub dump_enum($$) { my $x = shift; my $file = shift; + my $members; + $x =~ s@/\*.*?\*/@@gos; # strip comments. # strip #define macros inside enums $x =~ s@#\s*((define|ifdef)\s+|endif)[^;]*;@@gos; - if ($x =~ /enum\s+(\w*)\s*\{(.*)\}/) { + if ($x =~ /typedef\s+enum\s*\{(.*)\}\s*(\w*)\s*;/) { + $declaration_name = $2; + $members = $1; + } elsif ($x =~ /enum\s+(\w*)\s*\{(.*)\}/) { $declaration_name = $1; - my $members = $2; + $members = $2; + } + + if ($declaration_name) { my %_members; $members =~ s/\s+$//; @@ -1312,27 +1425,31 @@ sub dump_enum($$) { 'sections' => \%sections, 'purpose' => $declaration_purpose }); - } - else { + } else { print STDERR "${file}:$.: error: Cannot parse enum!\n"; ++$errors; } } +my $typedef_type = qr { ((?:\s+[\w\*]+){1,8})\s* }x; +my $typedef_ident = qr { \*?\s*(\w\S+)\s* }x; +my $typedef_args = qr { \s*\((.*)\); }x; + +my $typedef1 = qr { typedef$typedef_type\($typedef_ident\)$typedef_args }x; +my $typedef2 = qr { typedef$typedef_type$typedef_ident$typedef_args }x; + sub dump_typedef($$) { my $x = shift; my $file = shift; $x =~ s@/\*.*?\*/@@gos; # strip comments. - # Parse function prototypes - if ($x =~ /typedef\s+(\w+\s*\**)\s*\(\*?\s*(\w\S+)\s*\)\s*\((.*)\);/ || - $x =~ /typedef\s+(\w+\s*\**)\s*(\w\S+)\s*\s*\((.*)\);/) { - - # Function typedefs + # Parse function typedef prototypes + if ($x =~ $typedef1 || $x =~ $typedef2) { $return_type = $1; $declaration_name = $2; my $args = $3; + $return_type =~ s/^\s+//; create_parameterlist($args, ',', $file, $declaration_name); @@ -1408,7 +1525,7 @@ sub create_parameterlist($$$$) { # Treat preprocessor directive as a typeless variable just to fill # corresponding data structures "correctly". Catch it later in # output_* subs. - push_parameter($arg, "", $file); + push_parameter($arg, "", "", $file); } elsif ($arg =~ m/\(.+\)\s*\(/) { # pointer-to-function $arg =~ tr/#/,/; @@ -1417,7 +1534,7 @@ sub create_parameterlist($$$$) { $type = $arg; $type =~ s/([^\(]+\(\*?)\s*$param/$1/; save_struct_actual($param); - push_parameter($param, $type, $file, $declaration_name); + push_parameter($param, $type, $arg, $file, $declaration_name); } elsif ($arg) { $arg =~ s/\s*:\s*/:/g; $arg =~ s/\s*\[/\[/g; @@ -1442,26 +1559,28 @@ sub create_parameterlist($$$$) { foreach $param (@args) { if ($param =~ m/^(\*+)\s*(.*)/) { save_struct_actual($2); - push_parameter($2, "$type $1", $file, $declaration_name); + + push_parameter($2, "$type $1", $arg, $file, $declaration_name); } elsif ($param =~ m/(.*?):(\d+)/) { if ($type ne "") { # skip unnamed bit-fields save_struct_actual($1); - push_parameter($1, "$type:$2", $file, $declaration_name) + push_parameter($1, "$type:$2", $arg, $file, $declaration_name) } } else { save_struct_actual($param); - push_parameter($param, $type, $file, $declaration_name); + push_parameter($param, $type, $arg, $file, $declaration_name); } } } } } -sub push_parameter($$$$) { +sub push_parameter($$$$$) { my $param = shift; my $type = shift; + my $org_arg = shift; my $file = shift; my $declaration_name = shift; @@ -1479,6 +1598,10 @@ sub push_parameter($$$$) { # handles unnamed variable parameters $param = "..."; } + elsif ($param =~ /\w\.\.\.$/) { + # for named variable parameters of the form `x...`, remove the dots + $param =~ s/\.\.\.$//; + } if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") { $parameterdescs{$param} = "variable arguments"; } @@ -1521,8 +1644,8 @@ sub push_parameter($$$$) { # "[blah" in a parameter string; ###$param =~ s/\s*//g; push @parameterlist, $param; - $type =~ s/\s\s+/ /g; - $parametertypes{$param} = $type; + $org_arg =~ s/\s\s+/ /g; + $parametertypes{$param} = $org_arg; } sub check_sections($$$$$) { @@ -1596,6 +1719,8 @@ sub dump_function($$) { my $file = shift; my $noret = 0; + print_lineno($new_start_line); + $prototype =~ s/^static +//; $prototype =~ s/^extern +//; $prototype =~ s/^asmlinkage +//; @@ -1633,7 +1758,7 @@ sub dump_function($$) { # If you mess with these regexps, it's a good idea to check that # the following functions' documentation still comes out right: # - parport_register_device (function pointer parameters) - # - qatomic_set (macro) + # - atomic_set (macro) # - pci_match_device, __copy_to_user (long return type) if ($define && $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s+/) { @@ -1671,30 +1796,48 @@ sub dump_function($$) { return; } - my $prms = join " ", @parameterlist; - check_sections($file, $declaration_name, "function", $sectcheck, $prms); + my $prms = join " ", @parameterlist; + check_sections($file, $declaration_name, "function", $sectcheck, $prms); - # This check emits a lot of warnings at the moment, because many - # functions don't have a 'Return' doc section. So until the number - # of warnings goes sufficiently down, the check is only performed in - # verbose mode. - # TODO: always perform the check. - if ($verbose && !$noret) { - check_return_section($file, $declaration_name, $return_type); - } + # This check emits a lot of warnings at the moment, because many + # functions don't have a 'Return' doc section. So until the number + # of warnings goes sufficiently down, the check is only performed in + # verbose mode. + # TODO: always perform the check. + if ($verbose && !$noret) { + check_return_section($file, $declaration_name, $return_type); + } - output_declaration($declaration_name, - 'function', - {'function' => $declaration_name, - 'module' => $modulename, - 'functiontype' => $return_type, - 'parameterlist' => \@parameterlist, - 'parameterdescs' => \%parameterdescs, - 'parametertypes' => \%parametertypes, - 'sectionlist' => \@sectionlist, - 'sections' => \%sections, - 'purpose' => $declaration_purpose - }); + # The function parser can be called with a typedef parameter. + # Handle it. + if ($return_type =~ /typedef/) { + output_declaration($declaration_name, + 'function', + {'function' => $declaration_name, + 'typedef' => 1, + 'module' => $modulename, + 'functiontype' => $return_type, + 'parameterlist' => \@parameterlist, + 'parameterdescs' => \%parameterdescs, + 'parametertypes' => \%parametertypes, + 'sectionlist' => \@sectionlist, + 'sections' => \%sections, + 'purpose' => $declaration_purpose + }); + } else { + output_declaration($declaration_name, + 'function', + {'function' => $declaration_name, + 'module' => $modulename, + 'functiontype' => $return_type, + 'parameterlist' => \@parameterlist, + 'parameterdescs' => \%parameterdescs, + 'parametertypes' => \%parametertypes, + 'sectionlist' => \@sectionlist, + 'sections' => \%sections, + 'purpose' => $declaration_purpose + }); + } } sub reset_state { @@ -1789,6 +1932,11 @@ sub process_proto_function($$) { $prototype =~ s@/\*.*?\*/@@gos; # strip comments. $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's. $prototype =~ s@^\s+@@gos; # strip leading spaces + + # Handle prototypes for function pointers like: + # int (*pcs_config)(struct foo) + $prototype =~ s@^(\S+\s+)\(\s*\*(\S+)\)@$1$2@gos; + if ($prototype =~ /SYSCALL_DEFINE/) { syscall_munge(); } @@ -1867,6 +2015,7 @@ sub process_export_file($) { while (<IN>) { if (/$export_symbol/) { + next if (defined($nosymbol_table{$2})); $function_table{$2} = 1; } } @@ -1898,7 +2047,7 @@ sub process_name($$) { if (/$doc_block/o) { $state = STATE_DOCBLOCK; $contents = ""; - $new_start_line = $. + 1; + $new_start_line = $.; if ( $1 eq "" ) { $section = $section_intro; @@ -1966,6 +2115,25 @@ sub process_name($$) { sub process_body($$) { my $file = shift; + # Until all named variable macro parameters are + # documented using the bare name (`x`) rather than with + # dots (`x...`), strip the dots: + if ($section =~ /\w\.\.\.$/) { + $section =~ s/\.\.\.$//; + + if ($verbose) { + print STDERR "${file}:$.: warning: Variable macro arguments should be documented without dots\n"; + ++$warnings; + } + } + + if ($state == STATE_BODY_WITH_BLANK_LINE && /^\s*\*\s?\S/) { + dump_section($file, $section, $contents); + $section = $section_default; + $new_start_line = $.; + $contents = ""; + } + if (/$doc_sect/i) { # case insensitive for supported section names $newsection = $1; $newcontents = $2; @@ -2018,19 +2186,23 @@ sub process_body($$) { $prototype = ""; $state = STATE_PROTO; $brcount = 0; + $new_start_line = $. + 1; } elsif (/$doc_content/) { - # miguel-style comment kludge, look for blank lines after - # @parameter line to signify start of description if ($1 eq "") { - if ($section =~ m/^@/ || $section eq $section_context) { + if ($section eq $section_context) { dump_section($file, $section, $contents); $section = $section_default; $contents = ""; $new_start_line = $.; + $state = STATE_BODY; } else { + if ($section ne $section_default) { + $state = STATE_BODY_WITH_BLANK_LINE; + } else { + $state = STATE_BODY; + } $contents .= "\n"; } - $state = STATE_BODY; } elsif ($state == STATE_BODY_MAYBE) { # Continued declaration purpose chomp($declaration_purpose); @@ -2162,7 +2334,7 @@ sub process_file($) { $file = map_filename($orig_file); - if (!open(IN,"<$file")) { + if (!open(IN_FILE,"<$file")) { print STDERR "Error: Cannot open file $file\n"; ++$errors; return; @@ -2171,9 +2343,9 @@ sub process_file($) { $. = 1; $section_counter = 0; - while (<IN>) { + while (<IN_FILE>) { while (s/\\\s*$//) { - $_ .= <IN>; + $_ .= <IN_FILE>; } # Replace tabs by spaces while ($_ =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}; @@ -2182,7 +2354,8 @@ sub process_file($) { process_normal(); } elsif ($state == STATE_NAME) { process_name($file, $_); - } elsif ($state == STATE_BODY || $state == STATE_BODY_MAYBE) { + } elsif ($state == STATE_BODY || $state == STATE_BODY_MAYBE || + $state == STATE_BODY_WITH_BLANK_LINE) { process_body($file, $_); } elsif ($state == STATE_INLINE) { # scanning for inline parameters process_inline($file, $_); @@ -2204,9 +2377,14 @@ sub process_file($) { print STDERR "${file}:1: warning: no structured comments found\n"; } } + close IN_FILE; } +if ($output_mode eq "rst") { + get_sphinx_version() if (!$sphinx_major); +} + $kernelversion = get_kernel_version(); # generate a sequence of code that will splice in highlighting information @@ -2253,4 +2431,9 @@ if ($verbose && $warnings) { print STDERR "$warnings warnings\n"; } -exit($output_mode eq "none" ? 0 : $errors); +if ($Werror && $warnings) { + print STDERR "$warnings warnings as Errors\n"; + exit($warnings); +} else { + exit($output_mode eq "none" ? 0 : $errors) +} diff --git a/softmmu/cpus.c b/softmmu/cpus.c index e46ac68ad0..1dc20b9dc3 100644 --- a/softmmu/cpus.c +++ b/softmmu/cpus.c @@ -41,6 +41,7 @@ #include "sysemu/replay.h" #include "sysemu/runstate.h" #include "sysemu/cpu-timers.h" +#include "sysemu/whpx.h" #include "hw/boards.h" #include "hw/hw.h" @@ -88,7 +89,7 @@ bool cpu_thread_is_idle(CPUState *cpu) return true; } if (!cpu->halted || cpu_has_work(cpu) || - kvm_halt_in_kernel()) { + kvm_halt_in_kernel() || whpx_apic_in_platform()) { return false; } return true; diff --git a/softmmu/datadir.c b/softmmu/datadir.c new file mode 100644 index 0000000000..504c4665be --- /dev/null +++ b/softmmu/datadir.c @@ -0,0 +1,129 @@ +/* + * QEMU firmware and keymap file search + * + * Copyright (c) 2003-2020 QEMU contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qemu/datadir.h" +#include "qemu/cutils.h" +#include "trace.h" + +static const char *data_dir[16]; +static int data_dir_idx; + +char *qemu_find_file(int type, const char *name) +{ + int i; + const char *subdir; + char *buf; + + /* Try the name as a straight path first */ + if (access(name, R_OK) == 0) { + trace_load_file(name, name); + return g_strdup(name); + } + + switch (type) { + case QEMU_FILE_TYPE_BIOS: + subdir = ""; + break; + case QEMU_FILE_TYPE_KEYMAP: + subdir = "keymaps/"; + break; + default: + abort(); + } + + for (i = 0; i < data_dir_idx; i++) { + buf = g_strdup_printf("%s/%s%s", data_dir[i], subdir, name); + if (access(buf, R_OK) == 0) { + trace_load_file(name, buf); + return buf; + } + g_free(buf); + } + return NULL; +} + +void qemu_add_data_dir(char *path) +{ + int i; + + if (path == NULL) { + return; + } + if (data_dir_idx == ARRAY_SIZE(data_dir)) { + return; + } + for (i = 0; i < data_dir_idx; i++) { + if (strcmp(data_dir[i], path) == 0) { + g_free(path); /* duplicate */ + return; + } + } + data_dir[data_dir_idx++] = path; +} + +/* + * Find a likely location for support files using the location of the binary. + * When running from the build tree this will be "$bindir/pc-bios". + * Otherwise, this is CONFIG_QEMU_DATADIR (possibly relocated). + * + * The caller must use g_free() to free the returned data when it is + * no longer required. + */ +static char *find_datadir(void) +{ + g_autofree char *dir = NULL; + + dir = g_build_filename(qemu_get_exec_dir(), "pc-bios", NULL); + if (g_file_test(dir, G_FILE_TEST_IS_DIR)) { + return g_steal_pointer(&dir); + } + + return get_relocated_path(CONFIG_QEMU_DATADIR); +} + +void qemu_add_default_firmwarepath(void) +{ + char **dirs; + size_t i; + + /* add configured firmware directories */ + dirs = g_strsplit(CONFIG_QEMU_FIRMWAREPATH, G_SEARCHPATH_SEPARATOR_S, 0); + for (i = 0; dirs[i] != NULL; i++) { + qemu_add_data_dir(get_relocated_path(dirs[i])); + } + g_strfreev(dirs); + + /* try to find datadir relative to the executable path */ + qemu_add_data_dir(find_datadir()); +} + +void qemu_list_data_dirs(void) +{ + int i; + for (i = 0; i < data_dir_idx; i++) { + printf("%s\n", data_dir[i]); + } +} diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c index 03c92e0cc6..29001b5459 100644 --- a/softmmu/dma-helpers.c +++ b/softmmu/dma-helpers.c @@ -1,7 +1,7 @@ /* * DMA helper functions * - * Copyright (c) 2009 Red Hat + * Copyright (c) 2009,2020 Red Hat * * This work is licensed under the terms of the GNU General Public License * (GNU GPL), version 2 or later. @@ -18,14 +18,15 @@ /* #define DEBUG_IOMMU */ -int dma_memory_set(AddressSpace *as, dma_addr_t addr, uint8_t c, dma_addr_t len) +MemTxResult dma_memory_set(AddressSpace *as, dma_addr_t addr, + uint8_t c, dma_addr_t len) { dma_barrier(as, DMA_DIRECTION_FROM_DEVICE); #define FILLBUF_SIZE 512 uint8_t fillbuf[FILLBUF_SIZE]; int l; - bool error = false; + MemTxResult error = MEMTX_OK; memset(fillbuf, c, FILLBUF_SIZE); while (len > 0) { diff --git a/softmmu/meson.build b/softmmu/meson.build index 8f7210b4f0..d098d89653 100644 --- a/softmmu/meson.build +++ b/softmmu/meson.build @@ -3,8 +3,10 @@ specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files( 'balloon.c', 'cpus.c', 'cpu-throttle.c', + 'datadir.c', 'physmem.c', 'ioport.c', + 'rtc.c', 'memory.c', 'memory_mapping.c', 'qtest.c', diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c index 31e5b589b7..832e254842 100644 --- a/softmmu/qdev-monitor.c +++ b/softmmu/qdev-monitor.c @@ -928,12 +928,6 @@ BlockBackend *blk_by_qdev_id(const char *id, Error **errp) return blk; } -void qdev_machine_init(void) -{ - qdev_get_peripheral_anon(); - qdev_get_peripheral(); -} - QemuOptsList qemu_device_opts = { .name = "device", .implied_opt_name = "driver", diff --git a/softmmu/rtc.c b/softmmu/rtc.c new file mode 100644 index 0000000000..e1e15ef613 --- /dev/null +++ b/softmmu/rtc.c @@ -0,0 +1,190 @@ +/* + * RTC configuration and clock read + * + * Copyright (c) 2003-2020 QEMU contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qemu/cutils.h" +#include "qapi/error.h" +#include "qapi/qmp/qerror.h" +#include "qemu/error-report.h" +#include "qemu/option.h" +#include "qemu/timer.h" +#include "qom/object.h" +#include "sysemu/replay.h" +#include "sysemu/sysemu.h" + +static enum { + RTC_BASE_UTC, + RTC_BASE_LOCALTIME, + RTC_BASE_DATETIME, +} rtc_base_type = RTC_BASE_UTC; +static time_t rtc_ref_start_datetime; +static int rtc_realtime_clock_offset; /* used only with QEMU_CLOCK_REALTIME */ +static int rtc_host_datetime_offset = -1; /* valid & used only with + RTC_BASE_DATETIME */ +QEMUClockType rtc_clock; +/***********************************************************/ +/* RTC reference time/date access */ +static time_t qemu_ref_timedate(QEMUClockType clock) +{ + time_t value = qemu_clock_get_ms(clock) / 1000; + switch (clock) { + case QEMU_CLOCK_REALTIME: + value -= rtc_realtime_clock_offset; + /* fall through */ + case QEMU_CLOCK_VIRTUAL: + value += rtc_ref_start_datetime; + break; + case QEMU_CLOCK_HOST: + if (rtc_base_type == RTC_BASE_DATETIME) { + value -= rtc_host_datetime_offset; + } + break; + default: + assert(0); + } + return value; +} + +void qemu_get_timedate(struct tm *tm, int offset) +{ + time_t ti = qemu_ref_timedate(rtc_clock); + + ti += offset; + + switch (rtc_base_type) { + case RTC_BASE_DATETIME: + case RTC_BASE_UTC: + gmtime_r(&ti, tm); + break; + case RTC_BASE_LOCALTIME: + localtime_r(&ti, tm); + break; + } +} + +int qemu_timedate_diff(struct tm *tm) +{ + time_t seconds; + + switch (rtc_base_type) { + case RTC_BASE_DATETIME: + case RTC_BASE_UTC: + seconds = mktimegm(tm); + break; + case RTC_BASE_LOCALTIME: + { + struct tm tmp = *tm; + tmp.tm_isdst = -1; /* use timezone to figure it out */ + seconds = mktime(&tmp); + break; + } + default: + abort(); + } + + return seconds - qemu_ref_timedate(QEMU_CLOCK_HOST); +} + +static void configure_rtc_base_datetime(const char *startdate) +{ + time_t rtc_start_datetime; + struct tm tm; + + if (sscanf(startdate, "%d-%d-%dT%d:%d:%d", &tm.tm_year, &tm.tm_mon, + &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 6) { + /* OK */ + } else if (sscanf(startdate, "%d-%d-%d", + &tm.tm_year, &tm.tm_mon, &tm.tm_mday) == 3) { + tm.tm_hour = 0; + tm.tm_min = 0; + tm.tm_sec = 0; + } else { + goto date_fail; + } + tm.tm_year -= 1900; + tm.tm_mon--; + rtc_start_datetime = mktimegm(&tm); + if (rtc_start_datetime == -1) { + date_fail: + error_report("invalid datetime format"); + error_printf("valid formats: " + "'2006-06-17T16:01:21' or '2006-06-17'\n"); + exit(1); + } + rtc_host_datetime_offset = rtc_ref_start_datetime - rtc_start_datetime; + rtc_ref_start_datetime = rtc_start_datetime; +} + +void configure_rtc(QemuOpts *opts) +{ + const char *value; + + /* Set defaults */ + rtc_clock = QEMU_CLOCK_HOST; + rtc_ref_start_datetime = qemu_clock_get_ms(QEMU_CLOCK_HOST) / 1000; + rtc_realtime_clock_offset = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) / 1000; + + value = qemu_opt_get(opts, "base"); + if (value) { + if (!strcmp(value, "utc")) { + rtc_base_type = RTC_BASE_UTC; + } else if (!strcmp(value, "localtime")) { + Error *blocker = NULL; + rtc_base_type = RTC_BASE_LOCALTIME; + error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED, + "-rtc base=localtime"); + replay_add_blocker(blocker); + } else { + rtc_base_type = RTC_BASE_DATETIME; + configure_rtc_base_datetime(value); + } + } + value = qemu_opt_get(opts, "clock"); + if (value) { + if (!strcmp(value, "host")) { + rtc_clock = QEMU_CLOCK_HOST; + } else if (!strcmp(value, "rt")) { + rtc_clock = QEMU_CLOCK_REALTIME; + } else if (!strcmp(value, "vm")) { + rtc_clock = QEMU_CLOCK_VIRTUAL; + } else { + error_report("invalid option value '%s'", value); + exit(1); + } + } + value = qemu_opt_get(opts, "driftfix"); + if (value) { + if (!strcmp(value, "slew")) { + object_register_sugar_prop("mc146818rtc", + "lost_tick_policy", + "slew"); + } else if (!strcmp(value, "none")) { + /* discard is default */ + } else { + error_report("invalid option value '%s'", value); + exit(1); + } + } +} diff --git a/softmmu/vl.c b/softmmu/vl.c index e6e0ad5a92..7146fbe219 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/units.h" #include "hw/boards.h" #include "hw/qdev-properties.h" @@ -109,6 +110,8 @@ #include "qapi/qapi-visit-block-core.h" #include "qapi/qapi-visit-ui.h" #include "qapi/qapi-commands-block-core.h" +#include "qapi/qapi-commands-migration.h" +#include "qapi/qapi-commands-misc.h" #include "qapi/qapi-commands-run-state.h" #include "qapi/qapi-commands-ui.h" #include "qapi/qmp/qerror.h" @@ -117,32 +120,44 @@ #define MAX_VIRTIO_CONSOLES 1 -static const char *data_dir[16]; -static int data_dir_idx; -const char *bios_name = NULL; +typedef struct BlockdevOptionsQueueEntry { + BlockdevOptions *bdo; + Location loc; + QSIMPLEQ_ENTRY(BlockdevOptionsQueueEntry) entry; +} BlockdevOptionsQueueEntry; + +typedef QSIMPLEQ_HEAD(, BlockdevOptionsQueueEntry) BlockdevOptionsQueue; + +static const char *cpu_option; +static const char *mem_path; +static const char *incoming; +static const char *loadvm; +static ram_addr_t maxram_size; +static uint64_t ram_slots; +static int display_remote; +static int snapshot; +static bool preconfig_requested; +static QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list); +static BlockdevOptionsQueue bdo_queue = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue); +static bool nographic = false; enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; +static int mem_prealloc; /* force preallocation of physical target memory */ int display_opengl; const char* keyboard_layout = NULL; -ram_addr_t ram_size; +static ram_addr_t ram_size; bool enable_mlock = false; bool enable_cpu_pm = false; int nb_nics; NICInfo nd_table[MAX_NICS]; -int autostart; -static enum { - RTC_BASE_UTC, - RTC_BASE_LOCALTIME, - RTC_BASE_DATETIME, -} rtc_base_type = RTC_BASE_UTC; -static time_t rtc_ref_start_datetime; -static int rtc_realtime_clock_offset; /* used only with QEMU_CLOCK_REALTIME */ -static int rtc_host_datetime_offset = -1; /* valid & used only with - RTC_BASE_DATETIME */ -QEMUClockType rtc_clock; +int autostart = 1; int vga_interface_type = VGA_NONE; +static const char *vga_model = NULL; static DisplayOptions dpy; static int num_serial_hds; static Chardev **serial_hds; +static const char *log_mask; +static const char *log_file; +static bool list_data_dirs; Chardev *parallel_hds[MAX_PARALLEL_PORTS]; int win2k_install_hack = 0; int singlestep = 0; @@ -150,7 +165,7 @@ int fd_bootchk = 1; static int no_reboot; int no_shutdown = 0; int graphic_rotate = 0; -const char *watchdog; +static const char *watchdog; QEMUOptionRom option_rom[MAX_OPTION_ROMS]; int nb_option_roms; int old_param = 0; @@ -177,9 +192,6 @@ bool qemu_uuid_set; static NotifierList exit_notifiers = NOTIFIER_LIST_INITIALIZER(exit_notifiers); -static NotifierList machine_init_done_notifiers = - NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers); - uint32_t xen_domid; enum xen_mode xen_mode = XEN_EMULATE; bool xen_domid_restrict; @@ -748,152 +760,6 @@ void qemu_system_vmstop_request(RunState state) qemu_mutex_unlock(&vmstop_lock); qemu_notify_event(); } - -/***********************************************************/ -/* RTC reference time/date access */ -static time_t qemu_ref_timedate(QEMUClockType clock) -{ - time_t value = qemu_clock_get_ms(clock) / 1000; - switch (clock) { - case QEMU_CLOCK_REALTIME: - value -= rtc_realtime_clock_offset; - /* fall through */ - case QEMU_CLOCK_VIRTUAL: - value += rtc_ref_start_datetime; - break; - case QEMU_CLOCK_HOST: - if (rtc_base_type == RTC_BASE_DATETIME) { - value -= rtc_host_datetime_offset; - } - break; - default: - assert(0); - } - return value; -} - -void qemu_get_timedate(struct tm *tm, int offset) -{ - time_t ti = qemu_ref_timedate(rtc_clock); - - ti += offset; - - switch (rtc_base_type) { - case RTC_BASE_DATETIME: - case RTC_BASE_UTC: - gmtime_r(&ti, tm); - break; - case RTC_BASE_LOCALTIME: - localtime_r(&ti, tm); - break; - } -} - -int qemu_timedate_diff(struct tm *tm) -{ - time_t seconds; - - switch (rtc_base_type) { - case RTC_BASE_DATETIME: - case RTC_BASE_UTC: - seconds = mktimegm(tm); - break; - case RTC_BASE_LOCALTIME: - { - struct tm tmp = *tm; - tmp.tm_isdst = -1; /* use timezone to figure it out */ - seconds = mktime(&tmp); - break; - } - default: - abort(); - } - - return seconds - qemu_ref_timedate(QEMU_CLOCK_HOST); -} - -static void configure_rtc_base_datetime(const char *startdate) -{ - time_t rtc_start_datetime; - struct tm tm; - - if (sscanf(startdate, "%d-%d-%dT%d:%d:%d", &tm.tm_year, &tm.tm_mon, - &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 6) { - /* OK */ - } else if (sscanf(startdate, "%d-%d-%d", - &tm.tm_year, &tm.tm_mon, &tm.tm_mday) == 3) { - tm.tm_hour = 0; - tm.tm_min = 0; - tm.tm_sec = 0; - } else { - goto date_fail; - } - tm.tm_year -= 1900; - tm.tm_mon--; - rtc_start_datetime = mktimegm(&tm); - if (rtc_start_datetime == -1) { - date_fail: - error_report("invalid datetime format"); - error_printf("valid formats: " - "'2006-06-17T16:01:21' or '2006-06-17'\n"); - exit(1); - } - rtc_host_datetime_offset = rtc_ref_start_datetime - rtc_start_datetime; - rtc_ref_start_datetime = rtc_start_datetime; -} - -static void configure_rtc(QemuOpts *opts) -{ - const char *value; - - /* Set defaults */ - rtc_clock = QEMU_CLOCK_HOST; - rtc_ref_start_datetime = qemu_clock_get_ms(QEMU_CLOCK_HOST) / 1000; - rtc_realtime_clock_offset = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) / 1000; - - value = qemu_opt_get(opts, "base"); - if (value) { - if (!strcmp(value, "utc")) { - rtc_base_type = RTC_BASE_UTC; - } else if (!strcmp(value, "localtime")) { - Error *blocker = NULL; - rtc_base_type = RTC_BASE_LOCALTIME; - error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED, - "-rtc base=localtime"); - replay_add_blocker(blocker); - } else { - rtc_base_type = RTC_BASE_DATETIME; - configure_rtc_base_datetime(value); - } - } - value = qemu_opt_get(opts, "clock"); - if (value) { - if (!strcmp(value, "host")) { - rtc_clock = QEMU_CLOCK_HOST; - } else if (!strcmp(value, "rt")) { - rtc_clock = QEMU_CLOCK_REALTIME; - } else if (!strcmp(value, "vm")) { - rtc_clock = QEMU_CLOCK_VIRTUAL; - } else { - error_report("invalid option value '%s'", value); - exit(1); - } - } - value = qemu_opt_get(opts, "driftfix"); - if (value) { - if (!strcmp(value, "slew")) { - object_register_sugar_prop("mc146818rtc", - "lost_tick_policy", - "slew"); - } else if (!strcmp(value, "none")) { - /* discard is default */ - } else { - error_report("invalid option value '%s'", value); - exit(1); - } - } -} - static int parse_name(void *opaque, QemuOpts *opts, Error **errp) { const char *proc_name; @@ -1030,14 +896,6 @@ static void default_drive(int enable, int snapshot, BlockInterfaceType type, } -typedef struct BlockdevOptionsQueueEntry { - BlockdevOptions *bdo; - Location loc; - QSIMPLEQ_ENTRY(BlockdevOptionsQueueEntry) entry; -} BlockdevOptionsQueueEntry; - -typedef QSIMPLEQ_HEAD(, BlockdevOptionsQueueEntry) BlockdevOptionsQueue; - static void configure_blockdev(BlockdevOptionsQueue *bdo_queue, MachineClass *machine_class, int snapshot) { @@ -1225,7 +1083,8 @@ struct VMChangeStateEntry { int priority; }; -static QTAILQ_HEAD(, VMChangeStateEntry) vm_change_state_head; +static QTAILQ_HEAD(, VMChangeStateEntry) vm_change_state_head = + QTAILQ_HEAD_INITIALIZER(vm_change_state_head); /** * qemu_add_vm_change_state_handler_prio: @@ -1973,59 +1832,6 @@ static void parse_display(const char *p) } } -char *qemu_find_file(int type, const char *name) -{ - int i; - const char *subdir; - char *buf; - - /* Try the name as a straight path first */ - if (access(name, R_OK) == 0) { - trace_load_file(name, name); - return g_strdup(name); - } - - switch (type) { - case QEMU_FILE_TYPE_BIOS: - subdir = ""; - break; - case QEMU_FILE_TYPE_KEYMAP: - subdir = "keymaps/"; - break; - default: - abort(); - } - - for (i = 0; i < data_dir_idx; i++) { - buf = g_strdup_printf("%s/%s%s", data_dir[i], subdir, name); - if (access(buf, R_OK) == 0) { - trace_load_file(name, buf); - return buf; - } - g_free(buf); - } - return NULL; -} - -void qemu_add_data_dir(char *path) -{ - int i; - - if (path == NULL) { - return; - } - if (data_dir_idx == ARRAY_SIZE(data_dir)) { - return; - } - for (i = 0; i < data_dir_idx; i++) { - if (strcmp(data_dir[i], path) == 0) { - g_free(path); /* duplicate */ - return; - } - } - data_dir[data_dir_idx++] = path; -} - static inline bool nonempty_str(const char *str) { return str && *str; @@ -2213,6 +2019,115 @@ static int foreach_device_config(int type, int (*func)(const char *cmdline)) return 0; } +static void qemu_disable_default_devices(void) +{ + MachineClass *machine_class = MACHINE_GET_CLASS(current_machine); + + qemu_opts_foreach(qemu_find_opts("device"), + default_driver_check, NULL, NULL); + qemu_opts_foreach(qemu_find_opts("global"), + default_driver_check, NULL, NULL); + + if (!vga_model && !default_vga) { + vga_interface_type = VGA_DEVICE; + } + if (!has_defaults || machine_class->no_serial) { + default_serial = 0; + } + if (!has_defaults || machine_class->no_parallel) { + default_parallel = 0; + } + if (!has_defaults || machine_class->no_floppy) { + default_floppy = 0; + } + if (!has_defaults || machine_class->no_cdrom) { + default_cdrom = 0; + } + if (!has_defaults || machine_class->no_sdcard) { + default_sdcard = 0; + } + if (!has_defaults) { + default_monitor = 0; + default_net = 0; + default_vga = 0; + } +} + +static void qemu_create_default_devices(void) +{ + MachineClass *machine_class = MACHINE_GET_CLASS(current_machine); + + if (is_daemonized()) { + /* According to documentation and historically, -nographic redirects + * serial port, parallel port and monitor to stdio, which does not work + * with -daemonize. We can redirect these to null instead, but since + * -nographic is legacy, let's just error out. + * We disallow -nographic only if all other ports are not redirected + * explicitly, to not break existing legacy setups which uses + * -nographic _and_ redirects all ports explicitly - this is valid + * usage, -nographic is just a no-op in this case. + */ + if (nographic + && (default_parallel || default_serial || default_monitor)) { + error_report("-nographic cannot be used with -daemonize"); + exit(1); + } + } + + if (nographic) { + if (default_parallel) + add_device_config(DEV_PARALLEL, "null"); + if (default_serial && default_monitor) { + add_device_config(DEV_SERIAL, "mon:stdio"); + } else { + if (default_serial) + add_device_config(DEV_SERIAL, "stdio"); + if (default_monitor) + monitor_parse("stdio", "readline", false); + } + } else { + if (default_serial) + add_device_config(DEV_SERIAL, "vc:80Cx24C"); + if (default_parallel) + add_device_config(DEV_PARALLEL, "vc:80Cx24C"); + if (default_monitor) + monitor_parse("vc:80Cx24C", "readline", false); + } + + if (default_net) { + QemuOptsList *net = qemu_find_opts("net"); + qemu_opts_parse(net, "nic", true, &error_abort); +#ifdef CONFIG_SLIRP + qemu_opts_parse(net, "user", true, &error_abort); +#endif + } + +#if defined(CONFIG_VNC) + if (!QTAILQ_EMPTY(&(qemu_find_opts("vnc")->head))) { + display_remote++; + } +#endif + if (dpy.type == DISPLAY_TYPE_DEFAULT && !display_remote) { + if (!qemu_display_find_default(&dpy)) { + dpy.type = DISPLAY_TYPE_NONE; +#if defined(CONFIG_VNC) + vnc_parse("localhost:0,to=99,id=default", &error_abort); +#endif + } + } + if (dpy.type == DISPLAY_TYPE_DEFAULT) { + dpy.type = DISPLAY_TYPE_NONE; + } + + /* If no default VGA is requested, the default is "none". */ + if (default_vga) { + vga_model = get_default_vga_model(machine_class); + } + if (vga_model) { + select_vgahw(machine_class, vga_model); + } +} + static int serial_parse(const char *devname) { int index = num_serial_hds; @@ -2242,11 +2157,6 @@ Chardev *serial_hd(int i) return NULL; } -int serial_max_hds(void) -{ - return num_serial_hds; -} - static int parallel_parse(const char *devname) { static int index = 0; @@ -2375,27 +2285,6 @@ static void qemu_unlink_pidfile(Notifier *n, void *data) } } -bool machine_init_done; - -void qemu_add_machine_init_done_notifier(Notifier *notify) -{ - notifier_list_add(&machine_init_done_notifiers, notify); - if (machine_init_done) { - notify->notify(notify, NULL); - } -} - -void qemu_remove_machine_init_done_notifier(Notifier *notify) -{ - notifier_remove(notify); -} - -static void qemu_run_machine_init_done_notifiers(void) -{ - machine_init_done = true; - notifier_list_notify(&machine_init_done_notifiers, NULL); -} - static const QEMUOption *lookup_opt(int argc, char **argv, const char **poptarg, int *poptind) { @@ -2501,11 +2390,15 @@ static int machine_set_property(void *opaque, object_register_sugar_prop(ACCEL_CLASS_NAME("xen"), qom_name, value); return 0; } - if (g_str_equal(qom_name, "kvm-shadow-mem") || - g_str_equal(qom_name, "kernel-irqchip")) { + if (g_str_equal(qom_name, "kvm-shadow-mem")) { object_register_sugar_prop(ACCEL_CLASS_NAME("kvm"), qom_name, value); return 0; } + if (g_str_equal(qom_name, "kernel-irqchip")) { + object_register_sugar_prop(ACCEL_CLASS_NAME("kvm"), qom_name, value); + object_register_sugar_prop(ACCEL_CLASS_NAME("whpx"), qom_name, value); + return 0; + } return object_parse_property_opt(opaque, name, value, "type", errp); } @@ -2517,7 +2410,7 @@ static int machine_set_property(void *opaque, * cannot be created here, as it depends on the chardev * already existing. */ -static bool object_create_initial(const char *type, QemuOpts *opts) +static bool object_create_early(const char *type, QemuOpts *opts) { if (user_creatable_print_help(type, opts)) { exit(0); @@ -2573,19 +2466,187 @@ static bool object_create_initial(const char *type, QemuOpts *opts) return true; } +static void qemu_apply_machine_options(void) +{ + MachineClass *machine_class = MACHINE_GET_CLASS(current_machine); + QemuOpts *machine_opts = qemu_get_machine_opts(); + const char *boot_order = NULL; + const char *boot_once = NULL; + QemuOpts *opts; + + qemu_opt_foreach(machine_opts, machine_set_property, current_machine, + &error_fatal); + current_machine->ram_size = ram_size; + current_machine->maxram_size = maxram_size; + current_machine->ram_slots = ram_slots; + + opts = qemu_opts_find(qemu_find_opts("boot-opts"), NULL); + if (opts) { + boot_order = qemu_opt_get(opts, "order"); + if (boot_order) { + validate_bootdevices(boot_order, &error_fatal); + } + + boot_once = qemu_opt_get(opts, "once"); + if (boot_once) { + validate_bootdevices(boot_once, &error_fatal); + } + + boot_menu = qemu_opt_get_bool(opts, "menu", boot_menu); + boot_strict = qemu_opt_get_bool(opts, "strict", false); + } + + if (!boot_order) { + boot_order = machine_class->default_boot_order; + } + + current_machine->boot_order = boot_order; + current_machine->boot_once = boot_once; + + if (semihosting_enabled() && !semihosting_get_argc()) { + const char *kernel_filename = qemu_opt_get(machine_opts, "kernel"); + const char *kernel_cmdline = qemu_opt_get(machine_opts, "append") ?: ""; + /* fall back to the -kernel/-append */ + semihosting_arg_fallback(kernel_filename, kernel_cmdline); + } +} + +static void qemu_create_early_backends(void) +{ + MachineClass *machine_class = MACHINE_GET_CLASS(current_machine); + + if ((alt_grab || ctrl_grab) && dpy.type != DISPLAY_TYPE_SDL) { + error_report("-alt-grab and -ctrl-grab are only valid " + "for SDL, ignoring option"); + } + if (dpy.has_window_close && + (dpy.type != DISPLAY_TYPE_GTK && dpy.type != DISPLAY_TYPE_SDL)) { + error_report("-no-quit is only valid for GTK and SDL, " + "ignoring option"); + } + + qemu_display_early_init(&dpy); + qemu_console_early_init(); + + if (dpy.has_gl && dpy.gl != DISPLAYGL_MODE_OFF && display_opengl == 0) { +#if defined(CONFIG_OPENGL) + error_report("OpenGL is not supported by the display"); +#else + error_report("OpenGL support is disabled"); +#endif + exit(1); + } + + qemu_opts_foreach(qemu_find_opts("object"), + user_creatable_add_opts_foreach, + object_create_early, &error_fatal); + + /* spice needs the timers to be initialized by this point */ + /* spice must initialize before audio as it changes the default auiodev */ + /* spice must initialize before chardevs (for spicevmc and spiceport) */ + qemu_spice.init(); + + qemu_opts_foreach(qemu_find_opts("chardev"), + chardev_init_func, NULL, &error_fatal); + +#ifdef CONFIG_VIRTFS + qemu_opts_foreach(qemu_find_opts("fsdev"), + fsdev_init_func, NULL, &error_fatal); +#endif + + /* + * Note: we need to create audio and block backends before + * machine_set_property(), so machine properties can refer to + * them. + */ + configure_blockdev(&bdo_queue, machine_class, snapshot); + audio_init_audiodevs(); +} + /* * The remainder of object creation happens after the * creation of chardev, fsdev, net clients and device data types. */ -static bool object_create_delayed(const char *type, QemuOpts *opts) +static bool object_create_late(const char *type, QemuOpts *opts) { - return !object_create_initial(type, opts); + return !object_create_early(type, opts); } +static void qemu_create_late_backends(void) +{ + if (qtest_chrdev) { + qtest_server_init(qtest_chrdev, qtest_log, &error_fatal); + } + + net_init_clients(&error_fatal); + + qemu_opts_foreach(qemu_find_opts("object"), + user_creatable_add_opts_foreach, + object_create_late, &error_fatal); + + if (tpm_init() < 0) { + exit(1); + } + + qemu_opts_foreach(qemu_find_opts("mon"), + mon_init_func, NULL, &error_fatal); -static bool set_memory_options(uint64_t *ram_slots, ram_addr_t *maxram_size, - MachineClass *mc) + if (foreach_device_config(DEV_SERIAL, serial_parse) < 0) + exit(1); + if (foreach_device_config(DEV_PARALLEL, parallel_parse) < 0) + exit(1); + if (foreach_device_config(DEV_DEBUGCON, debugcon_parse) < 0) + exit(1); + + /* now chardevs have been created we may have semihosting to connect */ + qemu_semihosting_connect_chardevs(); + qemu_semihosting_console_init(); +} + +static bool have_custom_ram_size(void) +{ + QemuOpts *opts = qemu_find_opts_singleton("memory"); + return !!qemu_opt_get_size(opts, "size", 0); +} + +static void qemu_resolve_machine_memdev(void) +{ + if (current_machine->ram_memdev_id) { + Object *backend; + ram_addr_t backend_size; + + backend = object_resolve_path_type(current_machine->ram_memdev_id, + TYPE_MEMORY_BACKEND, NULL); + if (!backend) { + error_report("Memory backend '%s' not found", + current_machine->ram_memdev_id); + exit(EXIT_FAILURE); + } + backend_size = object_property_get_uint(backend, "size", &error_abort); + if (have_custom_ram_size() && backend_size != ram_size) { + error_report("Size specified by -m option must match size of " + "explicitly specified 'memory-backend' property"); + exit(EXIT_FAILURE); + } + if (mem_path) { + error_report("'-mem-path' can't be used together with" + "'-machine memory-backend'"); + exit(EXIT_FAILURE); + } + ram_size = backend_size; + } + + if (!xen_enabled()) { + /* On 32-bit hosts, QEMU is limited by virtual address space */ + if (ram_size > (2047 << 20) && HOST_LONG_BITS == 32) { + error_report("at most 2047 MB RAM can be simulated"); + exit(1); + } + } +} + +static void set_memory_options(MachineClass *mc) { uint64_t sz; const char *mem_str; @@ -2635,7 +2696,7 @@ static bool set_memory_options(uint64_t *ram_slots, ram_addr_t *maxram_size, /* store value for the future use */ qemu_opt_set_number(opts, "size", ram_size, &error_abort); - *maxram_size = ram_size; + maxram_size = ram_size; if (qemu_opt_get(opts, "maxmem")) { uint64_t slots; @@ -2656,15 +2717,59 @@ static bool set_memory_options(uint64_t *ram_slots, ram_addr_t *maxram_size, exit(EXIT_FAILURE); } - *maxram_size = sz; - *ram_slots = slots; + maxram_size = sz; + ram_slots = slots; } else if (qemu_opt_get(opts, "slots")) { error_report("invalid -m option value: missing 'maxmem' option"); exit(EXIT_FAILURE); } loc_pop(&loc); - return !!mem_str; +} + +static void qemu_create_machine(MachineClass *machine_class) +{ + object_set_machine_compat_props(machine_class->compat_props); + + set_memory_options(machine_class); + + current_machine = MACHINE(object_new_with_class(OBJECT_CLASS(machine_class))); + if (machine_help_func(qemu_get_machine_opts(), current_machine)) { + exit(0); + } + object_property_add_child(object_get_root(), "machine", + OBJECT(current_machine)); + object_property_add_child(container_get(OBJECT(current_machine), + "/unattached"), + "sysbus", OBJECT(sysbus_get_default())); + + if (machine_class->minimum_page_bits) { + if (!set_preferred_target_page_bits(machine_class->minimum_page_bits)) { + /* This would be a board error: specifying a minimum smaller than + * a target's compile-time fixed setting. + */ + g_assert_not_reached(); + } + } + + cpu_exec_init_all(); + page_size_init(); + + if (machine_class->hw_version) { + qemu_set_hw_version(machine_class->hw_version); + } + + machine_smp_parse(current_machine, + qemu_opts_find(qemu_find_opts("smp-opts"), NULL), &error_fatal); + + /* + * Get the default machine options from the machine if it is not already + * specified either by the configuration file or by the command line. + */ + if (machine_class->default_machine_opts) { + qemu_opts_set_defaults(qemu_find_opts("machine"), + machine_class->default_machine_opts, 0); + } } static int global_init_func(void *opaque, QemuOpts *opts, Error **errp) @@ -2692,6 +2797,39 @@ static int qemu_read_default_config_file(void) return 0; } +static int qemu_set_option(const char *str) +{ + Error *local_err = NULL; + char group[64], id[64], arg[64]; + QemuOptsList *list; + QemuOpts *opts; + int rc, offset; + + rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset); + if (rc < 3 || str[offset] != '=') { + error_report("can't parse: \"%s\"", str); + return -1; + } + + list = qemu_find_opts(group); + if (list == NULL) { + return -1; + } + + opts = qemu_opts_find(list, id); + if (!opts) { + error_report("there is no %s \"%s\" defined", + list->name, id); + return -1; + } + + if (!qemu_opt_set(opts, arg, str + offset + 1, &local_err)) { + error_report_err(local_err); + return -1; + } + return 0; +} + static void user_register_global_props(void) { qemu_opts_foreach(qemu_find_opts("global"), @@ -2843,79 +2981,328 @@ static void create_default_memdev(MachineState *ms, const char *path) &error_fatal); } -/* - * Find a likely location for support files using the location of the binary. - * When running from the build tree this will be "$bindir/pc-bios". - * Otherwise, this is CONFIG_QEMU_DATADIR (possibly relocated). - * - * The caller must use g_free() to free the returned data when it is - * no longer required. - */ -static char *find_datadir(void) +static void qemu_validate_options(void) { - g_autofree char *dir = NULL; + QemuOpts *machine_opts = qemu_get_machine_opts(); + const char *kernel_filename = qemu_opt_get(machine_opts, "kernel"); + const char *initrd_filename = qemu_opt_get(machine_opts, "initrd"); + const char *kernel_cmdline = qemu_opt_get(machine_opts, "append"); + + if (kernel_filename == NULL) { + if (kernel_cmdline != NULL) { + error_report("-append only allowed with -kernel option"); + exit(1); + } - dir = g_build_filename(qemu_get_exec_dir(), "pc-bios", NULL); - if (g_file_test(dir, G_FILE_TEST_IS_DIR)) { - return g_steal_pointer(&dir); + if (initrd_filename != NULL) { + error_report("-initrd only allowed with -kernel option"); + exit(1); + } } - return get_relocated_path(CONFIG_QEMU_DATADIR); + if (loadvm && preconfig_requested) { + error_report("'preconfig' and 'loadvm' options are " + "mutually exclusive"); + exit(EXIT_FAILURE); + } + if (incoming && preconfig_requested) { + error_report("'preconfig' and 'incoming' options are " + "mutually exclusive"); + exit(EXIT_FAILURE); + } + +#ifdef CONFIG_CURSES + if (is_daemonized() && dpy.type == DISPLAY_TYPE_CURSES) { + error_report("curses display cannot be used with -daemonize"); + exit(1); + } +#endif } -void qemu_init(int argc, char **argv, char **envp) +static void qemu_process_sugar_options(void) { - int i; - int snapshot, linux_boot; - const char *initrd_filename; - const char *kernel_filename, *kernel_cmdline; - const char *boot_order = NULL; - const char *boot_once = NULL; - DisplayState *ds; - QemuOpts *opts, *machine_opts; - QemuOpts *icount_opts = NULL, *accel_opts = NULL; - QemuOptsList *olist; - int optind; - const char *optarg; - const char *loadvm = NULL; - MachineClass *machine_class; - const char *cpu_option; - const char *vga_model = NULL; - const char *incoming = NULL; - bool userconfig = true; - bool nographic = false; - int display_remote = 0; - const char *log_mask = NULL; - const char *log_file = NULL; - ram_addr_t maxram_size; - uint64_t ram_slots = 0; - FILE *vmstate_dump_file = NULL; - Error *main_loop_err = NULL; - Error *err = NULL; - bool list_data_dirs = false; - char **dirs; - const char *mem_path = NULL; - bool have_custom_ram_size; - BlockdevOptionsQueue bdo_queue = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue); - QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list); - int mem_prealloc = 0; /* force preallocation of physical target memory */ + if (mem_prealloc) { + char *val; + + val = g_strdup_printf("%d", + (uint32_t) qemu_opt_get_number(qemu_find_opts_singleton("smp-opts"), "cpus", 1)); + object_register_sugar_prop("memory-backend", "prealloc-threads", val); + g_free(val); + object_register_sugar_prop("memory-backend", "prealloc", "on"); + } + + if (watchdog) { + int i = select_watchdog(watchdog); + if (i > 0) + exit (i == 1 ? 1 : 0); + } +} + +static void qemu_process_early_options(void) +{ +#ifdef CONFIG_SECCOMP + QemuOptsList *olist = qemu_find_opts_err("sandbox", NULL); + if (olist) { + qemu_opts_foreach(olist, parse_sandbox, NULL, &error_fatal); + } +#endif + + qemu_opts_foreach(qemu_find_opts("name"), + parse_name, NULL, &error_fatal); + +#ifndef _WIN32 + qemu_opts_foreach(qemu_find_opts("add-fd"), + parse_add_fd, NULL, &error_fatal); + + qemu_opts_foreach(qemu_find_opts("add-fd"), + cleanup_add_fd, NULL, &error_fatal); +#endif + + if (!trace_init_backends()) { + exit(1); + } + trace_init_file(); + + /* Open the logfile at this point and set the log mask if necessary. */ + qemu_set_log_filename(log_file, &error_fatal); + if (log_mask) { + int mask; + mask = qemu_str_to_log_mask(log_mask); + if (!mask) { + qemu_print_log_usage(stdout); + exit(1); + } + qemu_set_log(mask); + } else { + qemu_set_log(0); + } + + qemu_add_default_firmwarepath(); +} + +static void qemu_process_help_options(void) +{ + /* + * Check for -cpu help and -device help before we call select_machine(), + * which will return an error if the architecture has no default machine + * type and the user did not specify one, so that the user doesn't need + * to say '-cpu help -machine something'. + */ + if (cpu_option && is_help_option(cpu_option)) { + list_cpus(cpu_option); + exit(0); + } + + if (qemu_opts_foreach(qemu_find_opts("device"), + device_help_func, NULL, NULL)) { + exit(0); + } + + /* -L help lists the data directories and exits. */ + if (list_data_dirs) { + qemu_list_data_dirs(); + exit(0); + } +} + +static void qemu_maybe_daemonize(const char *pid_file) +{ + Error *err; + + os_daemonize(); + rcu_disable_atfork(); + + if (pid_file && !qemu_write_pidfile(pid_file, &err)) { + error_reportf_err(err, "cannot create PID file: "); + exit(1); + } + + qemu_unlink_pidfile_notifier.notify = qemu_unlink_pidfile; + qemu_add_exit_notifier(&qemu_unlink_pidfile_notifier); +} + +static void qemu_init_subsystems(void) +{ + Error *err; os_set_line_buffering(); - error_init(argv[0]); module_call_init(MODULE_INIT_TRACE); qemu_init_cpu_list(); qemu_init_cpu_loop(); - qemu_mutex_lock_iothread(); atexit(qemu_run_exit_notifiers); - qemu_init_exec_dir(argv[0]); module_call_init(MODULE_INIT_QOM); module_call_init(MODULE_INIT_MIGRATION); + runstate_init(); + precopy_infrastructure_init(); + postcopy_infrastructure_init(); + monitor_init_globals(); + + if (qcrypto_init(&err) < 0) { + error_reportf_err(err, "cannot initialize crypto: "); + exit(1); + } + + os_setup_early_signal_handling(); + + bdrv_init_with_whitelist(); + socket_init(); +} + +static void qemu_init_displays(void) +{ + DisplayState *ds; + + /* init local displays */ + ds = init_displaystate(); + qemu_display_init(ds, &dpy); + + /* must be after terminal init, SDL library changes signal handlers */ + os_setup_signal_handling(); + + /* init remote displays */ +#ifdef CONFIG_VNC + qemu_opts_foreach(qemu_find_opts("vnc"), + vnc_init_func, NULL, &error_fatal); +#endif + + if (using_spice) { + qemu_spice.display_init(); + } +} + +/* + * Called after leaving preconfig state. From here on runstate is + * RUN_STATE_PRELAUNCH or RUN_STATE_INMIGRATE. + */ +static void qemu_init_board(void) +{ + MachineClass *machine_class = MACHINE_GET_CLASS(current_machine); + + if (machine_class->default_ram_id && current_machine->ram_size && + numa_uses_legacy_mem() && !current_machine->ram_memdev_id) { + create_default_memdev(current_machine, mem_path); + } + + /* process plugin before CPUs are created, but once -smp has been parsed */ + if (qemu_plugin_load_list(&plugin_list)) { + exit(1); + } + + machine_run_board_init(current_machine); + + /* + * TODO To drop support for deprecated bogus if=..., move + * drive_check_orphaned() here, replacing this call. Also drop + * its deprecation warning, along with DriveInfo member + * @claimed_by_board. + */ + drive_mark_claimed_by_board(); + + realtime_init(); + + if (hax_enabled()) { + /* FIXME: why isn't cpu_synchronize_all_post_init enough? */ + hax_sync_vcpus(); + } +} + +static void qemu_create_cli_devices(void) +{ + soundhw_init(); + + qemu_opts_foreach(qemu_find_opts("fw_cfg"), + parse_fw_cfg, fw_cfg_find(), &error_fatal); + + /* init USB devices */ + if (machine_usb(current_machine)) { + if (foreach_device_config(DEV_USB, usb_parse) < 0) + exit(1); + } + + /* init generic devices */ + rom_set_order_override(FW_CFG_ORDER_OVERRIDE_DEVICE); + qemu_opts_foreach(qemu_find_opts("device"), + device_init_func, NULL, &error_fatal); + rom_reset_order_override(); +} + +static void qemu_machine_creation_done(void) +{ + cpu_synchronize_all_post_init(); + + /* Did we create any drives that we failed to create a device for? */ + drive_check_orphaned(); + + /* Don't warn about the default network setup that you get if + * no command line -net or -netdev options are specified. There + * are two cases that we would otherwise complain about: + * (1) board doesn't support a NIC but the implicit "-net nic" + * requested one + * (2) CONFIG_SLIRP not set, in which case the implicit "-net nic" + * sets up a nic that isn't connected to anything. + */ + if (!default_net && (!qtest_enabled() || has_defaults)) { + net_check_clients(); + } + + qdev_prop_check_globals(); + + if (current_machine->boot_once) { + qemu_boot_set(current_machine->boot_once, &error_fatal); + qemu_register_reset(restore_boot_order, g_strdup(current_machine->boot_order)); + } + + if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) { + exit(1); + } + + qdev_machine_creation_done(); + + /* TODO: once all bus devices are qdevified, this should be done + * when bus is created by qdev.c */ + /* + * TODO: If we had a main 'reset container' that the whole system + * lived in, we could reset that using the multi-phase reset + * APIs. For the moment, we just reset the sysbus, which will cause + * all devices hanging off it (and all their child buses, recursively) + * to be reset. Note that this will *not* reset any Device objects + * which are not attached to some part of the qbus tree! + */ + qemu_register_reset(resettable_cold_reset_fn, sysbus_get_default()); + qemu_run_machine_init_done_notifiers(); + + if (rom_check_and_register_reset() != 0) { + error_report("rom check and register reset failed"); + exit(1); + } + + replay_start(); + + /* This checkpoint is required by replay to separate prior clock + reading from the other reads, because timer polling functions query + clock values from the log. */ + replay_checkpoint(CHECKPOINT_RESET); + qemu_system_reset(SHUTDOWN_CAUSE_NONE); + register_global_state(); +} + +void qemu_init(int argc, char **argv, char **envp) +{ + QemuOpts *opts; + QemuOpts *icount_opts = NULL, *accel_opts = NULL; + QemuOptsList *olist; + int optind; + const char *optarg; + MachineClass *machine_class; + bool userconfig = true; + FILE *vmstate_dump_file = NULL; + qemu_add_opts(&qemu_drive_opts); qemu_add_drive_opts(&qemu_legacy_drive_opts); qemu_add_drive_opts(&qemu_common_drive_opts); @@ -2950,27 +3337,10 @@ void qemu_init(int argc, char **argv, char **envp) qemu_add_opts(&qemu_fw_cfg_opts); module_call_init(MODULE_INIT_OPTS); - runstate_init(); - precopy_infrastructure_init(); - postcopy_infrastructure_init(); - monitor_init_globals(); - - if (qcrypto_init(&err) < 0) { - error_reportf_err(err, "cannot initialize crypto: "); - exit(1); - } - - QTAILQ_INIT(&vm_change_state_head); - os_setup_early_signal_handling(); - - cpu_option = NULL; - snapshot = 0; - - nb_nics = 0; - - bdrv_init_with_whitelist(); + error_init(argv[0]); + qemu_init_exec_dir(argv[0]); - autostart = 1; + qemu_init_subsystems(); /* first pass of option parsing */ optind = 1; @@ -3107,20 +3477,16 @@ void qemu_init(int argc, char **argv, char **envp) } break; case QEMU_OPTION_kernel: - qemu_opts_set(qemu_find_opts("machine"), NULL, "kernel", optarg, - &error_abort); + qemu_opts_set(qemu_find_opts("machine"), "kernel", optarg, &error_abort); break; case QEMU_OPTION_initrd: - qemu_opts_set(qemu_find_opts("machine"), NULL, "initrd", optarg, - &error_abort); + qemu_opts_set(qemu_find_opts("machine"), "initrd", optarg, &error_abort); break; case QEMU_OPTION_append: - qemu_opts_set(qemu_find_opts("machine"), NULL, "append", optarg, - &error_abort); + qemu_opts_set(qemu_find_opts("machine"), "append", optarg, &error_abort); break; case QEMU_OPTION_dtb: - qemu_opts_set(qemu_find_opts("machine"), NULL, "dtb", optarg, - &error_abort); + qemu_opts_set(qemu_find_opts("machine"), "dtb", optarg, &error_abort); break; case QEMU_OPTION_cdrom: drive_add(IF_DEFAULT, 2, optarg, CDROM_OPTS); @@ -3230,8 +3596,7 @@ void qemu_init(int argc, char **argv, char **envp) } break; case QEMU_OPTION_bios: - qemu_opts_set(qemu_find_opts("machine"), NULL, "firmware", optarg, - &error_abort); + qemu_opts_set(qemu_find_opts("machine"), "firmware", optarg, &error_abort); break; case QEMU_OPTION_singlestep: singlestep = 1; @@ -3492,6 +3857,7 @@ void qemu_init(int argc, char **argv, char **envp) break; case QEMU_OPTION_preconfig: preconfig_exit_requested = false; + preconfig_requested = true; break; case QEMU_OPTION_enable_kvm: olist = qemu_find_opts("machine"); @@ -3842,330 +4208,33 @@ void qemu_init(int argc, char **argv, char **envp) */ loc_set_none(); + qemu_validate_options(); + qemu_process_sugar_options(); + /* - * Check for -cpu help and -device help before we call select_machine(), - * which will return an error if the architecture has no default machine - * type and the user did not specify one, so that the user doesn't need - * to say '-cpu help -machine something'. + * These options affect everything else and should be processed + * before daemonizing. */ - if (cpu_option && is_help_option(cpu_option)) { - list_cpus(cpu_option); - exit(0); - } + qemu_process_early_options(); - if (qemu_opts_foreach(qemu_find_opts("device"), - device_help_func, NULL, NULL)) { - exit(0); - } + qemu_process_help_options(); + qemu_maybe_daemonize(pid_file); - user_register_global_props(); + qemu_init_main_loop(&error_fatal); + cpu_timers_init(); + user_register_global_props(); replay_configure(icount_opts); - if (incoming && !preconfig_exit_requested) { - error_report("'preconfig' and 'incoming' options are " - "mutually exclusive"); - exit(EXIT_FAILURE); - } - configure_rtc(qemu_find_opts_singleton("rtc")); - machine_class = select_machine(); - object_set_machine_compat_props(machine_class->compat_props); - - have_custom_ram_size = set_memory_options(&ram_slots, &maxram_size, - machine_class); - - os_daemonize(); - rcu_disable_atfork(); - - if (pid_file && !qemu_write_pidfile(pid_file, &err)) { - error_reportf_err(err, "cannot create PID file: "); - exit(1); - } - - qemu_unlink_pidfile_notifier.notify = qemu_unlink_pidfile; - qemu_add_exit_notifier(&qemu_unlink_pidfile_notifier); - - if (qemu_init_main_loop(&main_loop_err)) { - error_report_err(main_loop_err); - exit(1); - } - -#ifdef CONFIG_SECCOMP - olist = qemu_find_opts_err("sandbox", NULL); - if (olist) { - qemu_opts_foreach(olist, parse_sandbox, NULL, &error_fatal); - } -#endif - - qemu_opts_foreach(qemu_find_opts("name"), - parse_name, NULL, &error_fatal); - -#ifndef _WIN32 - qemu_opts_foreach(qemu_find_opts("add-fd"), - parse_add_fd, NULL, &error_fatal); - - qemu_opts_foreach(qemu_find_opts("add-fd"), - cleanup_add_fd, NULL, &error_fatal); -#endif - - current_machine = MACHINE(object_new_with_class(OBJECT_CLASS(machine_class))); - if (machine_help_func(qemu_get_machine_opts(), current_machine)) { - exit(0); - } - object_property_add_child(object_get_root(), "machine", - OBJECT(current_machine)); - object_property_add_child(container_get(OBJECT(current_machine), - "/unattached"), - "sysbus", OBJECT(sysbus_get_default())); - - if (machine_class->minimum_page_bits) { - if (!set_preferred_target_page_bits(machine_class->minimum_page_bits)) { - /* This would be a board error: specifying a minimum smaller than - * a target's compile-time fixed setting. - */ - g_assert_not_reached(); - } - } - - cpu_exec_init_all(); - - if (machine_class->hw_version) { - qemu_set_hw_version(machine_class->hw_version); - } - - if (!trace_init_backends()) { - exit(1); - } - trace_init_file(); - - /* Open the logfile at this point and set the log mask if necessary. - */ - qemu_set_log_filename(log_file, &error_fatal); - if (log_mask) { - int mask; - mask = qemu_str_to_log_mask(log_mask); - if (!mask) { - qemu_print_log_usage(stdout); - exit(1); - } - qemu_set_log(mask); - } else { - qemu_set_log(0); - } - - /* add configured firmware directories */ - dirs = g_strsplit(CONFIG_QEMU_FIRMWAREPATH, G_SEARCHPATH_SEPARATOR_S, 0); - for (i = 0; dirs[i] != NULL; i++) { - qemu_add_data_dir(get_relocated_path(dirs[i])); - } - g_strfreev(dirs); - - /* try to find datadir relative to the executable path */ - qemu_add_data_dir(find_datadir()); - - /* -L help lists the data directories and exits. */ - if (list_data_dirs) { - for (i = 0; i < data_dir_idx; i++) { - printf("%s\n", data_dir[i]); - } - exit(0); - } - - machine_class->smp_parse(current_machine, - qemu_opts_find(qemu_find_opts("smp-opts"), NULL)); - - /* sanity-check smp_cpus and max_cpus against machine_class */ - if (current_machine->smp.cpus < machine_class->min_cpus) { - error_report("Invalid SMP CPUs %d. The min CPUs " - "supported by machine '%s' is %d", - current_machine->smp.cpus, - machine_class->name, machine_class->min_cpus); - exit(1); - } - if (current_machine->smp.max_cpus > machine_class->max_cpus) { - error_report("Invalid SMP CPUs %d. The max CPUs " - "supported by machine '%s' is %d", - current_machine->smp.max_cpus, - machine_class->name, machine_class->max_cpus); - exit(1); - } + qemu_create_machine(select_machine()); - if (mem_prealloc) { - char *val; + qemu_disable_default_devices(); + qemu_create_default_devices(); + qemu_create_early_backends(); - val = g_strdup_printf("%d", current_machine->smp.cpus); - object_register_sugar_prop("memory-backend", "prealloc-threads", val); - g_free(val); - object_register_sugar_prop("memory-backend", "prealloc", "on"); - } - - /* - * Get the default machine options from the machine if it is not already - * specified either by the configuration file or by the command line. - */ - if (machine_class->default_machine_opts) { - qemu_opts_set_defaults(qemu_find_opts("machine"), - machine_class->default_machine_opts, 0); - } - - /* process plugin before CPUs are created, but once -smp has been parsed */ - if (qemu_plugin_load_list(&plugin_list)) { - exit(1); - } - - qemu_opts_foreach(qemu_find_opts("device"), - default_driver_check, NULL, NULL); - qemu_opts_foreach(qemu_find_opts("global"), - default_driver_check, NULL, NULL); - - if (!vga_model && !default_vga) { - vga_interface_type = VGA_DEVICE; - } - if (!has_defaults || machine_class->no_serial) { - default_serial = 0; - } - if (!has_defaults || machine_class->no_parallel) { - default_parallel = 0; - } - if (!has_defaults || machine_class->no_floppy) { - default_floppy = 0; - } - if (!has_defaults || machine_class->no_cdrom) { - default_cdrom = 0; - } - if (!has_defaults || machine_class->no_sdcard) { - default_sdcard = 0; - } - if (!has_defaults) { - default_monitor = 0; - default_net = 0; - default_vga = 0; - } - - if (is_daemonized()) { - if (!preconfig_exit_requested) { - error_report("'preconfig' and 'daemonize' options are " - "mutually exclusive"); - exit(EXIT_FAILURE); - } - - /* According to documentation and historically, -nographic redirects - * serial port, parallel port and monitor to stdio, which does not work - * with -daemonize. We can redirect these to null instead, but since - * -nographic is legacy, let's just error out. - * We disallow -nographic only if all other ports are not redirected - * explicitly, to not break existing legacy setups which uses - * -nographic _and_ redirects all ports explicitly - this is valid - * usage, -nographic is just a no-op in this case. - */ - if (nographic - && (default_parallel || default_serial || default_monitor)) { - error_report("-nographic cannot be used with -daemonize"); - exit(1); - } -#ifdef CONFIG_CURSES - if (dpy.type == DISPLAY_TYPE_CURSES) { - error_report("curses display cannot be used with -daemonize"); - exit(1); - } -#endif - } - - if (nographic) { - if (default_parallel) - add_device_config(DEV_PARALLEL, "null"); - if (default_serial && default_monitor) { - add_device_config(DEV_SERIAL, "mon:stdio"); - } else { - if (default_serial) - add_device_config(DEV_SERIAL, "stdio"); - if (default_monitor) - monitor_parse("stdio", "readline", false); - } - } else { - if (default_serial) - add_device_config(DEV_SERIAL, "vc:80Cx24C"); - if (default_parallel) - add_device_config(DEV_PARALLEL, "vc:80Cx24C"); - if (default_monitor) - monitor_parse("vc:80Cx24C", "readline", false); - } - -#if defined(CONFIG_VNC) - if (!QTAILQ_EMPTY(&(qemu_find_opts("vnc")->head))) { - display_remote++; - } -#endif - if (dpy.type == DISPLAY_TYPE_DEFAULT && !display_remote) { - if (!qemu_display_find_default(&dpy)) { - dpy.type = DISPLAY_TYPE_NONE; -#if defined(CONFIG_VNC) - vnc_parse("localhost:0,to=99,id=default", &error_abort); -#endif - } - } - if (dpy.type == DISPLAY_TYPE_DEFAULT) { - dpy.type = DISPLAY_TYPE_NONE; - } - - if ((alt_grab || ctrl_grab) && dpy.type != DISPLAY_TYPE_SDL) { - error_report("-alt-grab and -ctrl-grab are only valid " - "for SDL, ignoring option"); - } - if (dpy.has_window_close && - (dpy.type != DISPLAY_TYPE_GTK && dpy.type != DISPLAY_TYPE_SDL)) { - error_report("-no-quit is only valid for GTK and SDL, " - "ignoring option"); - } - - qemu_display_early_init(&dpy); - qemu_console_early_init(); - - if (dpy.has_gl && dpy.gl != DISPLAYGL_MODE_OFF && display_opengl == 0) { -#if defined(CONFIG_OPENGL) - error_report("OpenGL is not supported by the display"); -#else - error_report("OpenGL support is disabled"); -#endif - exit(1); - } - - page_size_init(); - socket_init(); - - qemu_opts_foreach(qemu_find_opts("object"), - user_creatable_add_opts_foreach, - object_create_initial, &error_fatal); - - /* spice needs the timers to be initialized by this point */ - /* spice must initialize before audio as it changes the default auiodev */ - /* spice must initialize before chardevs (for spicevmc and spiceport) */ - qemu_spice.init(); - - qemu_opts_foreach(qemu_find_opts("chardev"), - chardev_init_func, NULL, &error_fatal); - -#ifdef CONFIG_VIRTFS - qemu_opts_foreach(qemu_find_opts("fsdev"), - fsdev_init_func, NULL, &error_fatal); -#endif - - /* - * Note: we need to create audio and block backends before - * machine_set_property(), so machine properties can refer to - * them. - */ - configure_blockdev(&bdo_queue, machine_class, snapshot); - audio_init_audiodevs(); - - machine_opts = qemu_get_machine_opts(); - qemu_opt_foreach(machine_opts, machine_set_property, current_machine, - &error_fatal); - current_machine->ram_size = ram_size; - current_machine->maxram_size = maxram_size; - current_machine->ram_slots = ram_slots; + qemu_apply_machine_options(); /* * Note: uses machine properties such as kernel-irqchip, must run @@ -4189,6 +4258,7 @@ void qemu_init(int argc, char **argv, char **envp) * called from configure_accelerator(). */ + machine_class = MACHINE_GET_CLASS(current_machine); if (!qtest_enabled() && machine_class->deprecation_reason) { error_report("Machine type '%s' is deprecated: %s", machine_class->name, machine_class->deprecation_reason); @@ -4200,121 +4270,7 @@ void qemu_init(int argc, char **argv, char **envp) */ migration_object_init(); - if (qtest_chrdev) { - qtest_server_init(qtest_chrdev, qtest_log, &error_fatal); - } - - machine_opts = qemu_get_machine_opts(); - kernel_filename = qemu_opt_get(machine_opts, "kernel"); - initrd_filename = qemu_opt_get(machine_opts, "initrd"); - kernel_cmdline = qemu_opt_get(machine_opts, "append"); - bios_name = qemu_opt_get(machine_opts, "firmware"); - - opts = qemu_opts_find(qemu_find_opts("boot-opts"), NULL); - if (opts) { - boot_order = qemu_opt_get(opts, "order"); - if (boot_order) { - validate_bootdevices(boot_order, &error_fatal); - } - - boot_once = qemu_opt_get(opts, "once"); - if (boot_once) { - validate_bootdevices(boot_once, &error_fatal); - } - - boot_menu = qemu_opt_get_bool(opts, "menu", boot_menu); - boot_strict = qemu_opt_get_bool(opts, "strict", false); - } - - if (!boot_order) { - boot_order = machine_class->default_boot_order; - } - - if (!kernel_cmdline) { - kernel_cmdline = ""; - current_machine->kernel_cmdline = (char *)kernel_cmdline; - } - - linux_boot = (kernel_filename != NULL); - - if (!linux_boot && *kernel_cmdline != '\0') { - error_report("-append only allowed with -kernel option"); - exit(1); - } - - if (!linux_boot && initrd_filename != NULL) { - error_report("-initrd only allowed with -kernel option"); - exit(1); - } - - if (semihosting_enabled() && !semihosting_get_argc() && kernel_filename) { - /* fall back to the -kernel/-append */ - semihosting_arg_fallback(kernel_filename, kernel_cmdline); - } - - /* initialize cpu timers and VCPU throttle modules */ - cpu_timers_init(); - - if (default_net) { - QemuOptsList *net = qemu_find_opts("net"); - qemu_opts_set(net, NULL, "type", "nic", &error_abort); -#ifdef CONFIG_SLIRP - qemu_opts_set(net, NULL, "type", "user", &error_abort); -#endif - } - - if (net_init_clients(&err) < 0) { - error_report_err(err); - exit(1); - } - - qemu_opts_foreach(qemu_find_opts("object"), - user_creatable_add_opts_foreach, - object_create_delayed, &error_fatal); - - if (tpm_init() < 0) { - exit(1); - } - - blk_mig_init(); - ram_mig_init(); - dirty_bitmap_mig_init(); - - qemu_opts_foreach(qemu_find_opts("mon"), - mon_init_func, NULL, &error_fatal); - - if (foreach_device_config(DEV_SERIAL, serial_parse) < 0) - exit(1); - if (foreach_device_config(DEV_PARALLEL, parallel_parse) < 0) - exit(1); - if (foreach_device_config(DEV_DEBUGCON, debugcon_parse) < 0) - exit(1); - - /* now chardevs have been created we may have semihosting to connect */ - qemu_semihosting_connect_chardevs(); - qemu_semihosting_console_init(); - - /* If no default VGA is requested, the default is "none". */ - if (default_vga) { - vga_model = get_default_vga_model(machine_class); - } - if (vga_model) { - select_vgahw(machine_class, vga_model); - } - - if (watchdog) { - i = select_watchdog(watchdog); - if (i > 0) - exit (i == 1 ? 1 : 0); - } - - /* This checkpoint is required by replay to separate prior clock - reading from the other reads, because timer polling functions query - clock values from the log. */ - replay_checkpoint(CHECKPOINT_INIT); - qdev_machine_init(); - - current_machine->boot_order = boot_order; + qemu_create_late_backends(); /* parse features once if machine provides default cpu_type */ current_machine->cpu_type = machine_class->default_cpu_type; @@ -4322,155 +4278,26 @@ void qemu_init(int argc, char **argv, char **envp) current_machine->cpu_type = parse_cpu_option(cpu_option); } - if (current_machine->ram_memdev_id) { - Object *backend; - ram_addr_t backend_size; - - backend = object_resolve_path_type(current_machine->ram_memdev_id, - TYPE_MEMORY_BACKEND, NULL); - if (!backend) { - error_report("Memory backend '%s' not found", - current_machine->ram_memdev_id); - exit(EXIT_FAILURE); - } - backend_size = object_property_get_uint(backend, "size", &error_abort); - if (have_custom_ram_size && backend_size != ram_size) { - error_report("Size specified by -m option must match size of " - "explicitly specified 'memory-backend' property"); - exit(EXIT_FAILURE); - } - if (mem_path) { - error_report("'-mem-path' can't be used together with" - "'-machine memory-backend'"); - exit(EXIT_FAILURE); - } - ram_size = backend_size; - } + qemu_resolve_machine_memdev(); + parse_numa_opts(current_machine); - if (!xen_enabled()) { - /* On 32-bit hosts, QEMU is limited by virtual address space */ - if (ram_size > (2047 << 20) && HOST_LONG_BITS == 32) { - error_report("at most 2047 MB RAM can be simulated"); - exit(1); - } + if (preconfig_requested) { + qemu_init_displays(); } - parse_numa_opts(current_machine); - /* do monitor/qmp handling at preconfig state if requested */ qemu_main_loop(); - if (machine_class->default_ram_id && current_machine->ram_size && - numa_uses_legacy_mem() && !current_machine->ram_memdev_id) { - create_default_memdev(current_machine, mem_path); - } - - /* from here on runstate is RUN_STATE_PRELAUNCH */ - machine_run_board_init(current_machine); - - /* - * TODO To drop support for deprecated bogus if=..., move - * drive_check_orphaned() here, replacing this call. Also drop - * its deprecation warning, along with DriveInfo member - * @claimed_by_board. - */ - drive_mark_claimed_by_board(); - - realtime_init(); + qemu_init_board(); - soundhw_init(); + qemu_create_cli_devices(); - if (hax_enabled()) { - hax_sync_vcpus(); + /* initialize displays after all errors have been reported */ + if (!preconfig_requested) { + qemu_init_displays(); } + qemu_machine_creation_done(); - qemu_opts_foreach(qemu_find_opts("fw_cfg"), - parse_fw_cfg, fw_cfg_find(), &error_fatal); - - /* init USB devices */ - if (machine_usb(current_machine)) { - if (foreach_device_config(DEV_USB, usb_parse) < 0) - exit(1); - } - - /* init generic devices */ - rom_set_order_override(FW_CFG_ORDER_OVERRIDE_DEVICE); - qemu_opts_foreach(qemu_find_opts("device"), - device_init_func, NULL, &error_fatal); - - cpu_synchronize_all_post_init(); - - rom_reset_order_override(); - - /* Did we create any drives that we failed to create a device for? */ - drive_check_orphaned(); - - /* Don't warn about the default network setup that you get if - * no command line -net or -netdev options are specified. There - * are two cases that we would otherwise complain about: - * (1) board doesn't support a NIC but the implicit "-net nic" - * requested one - * (2) CONFIG_SLIRP not set, in which case the implicit "-net nic" - * sets up a nic that isn't connected to anything. - */ - if (!default_net && (!qtest_enabled() || has_defaults)) { - net_check_clients(); - } - - if (boot_once) { - qemu_boot_set(boot_once, &error_fatal); - qemu_register_reset(restore_boot_order, g_strdup(boot_order)); - } - - /* init local displays */ - ds = init_displaystate(); - qemu_display_init(ds, &dpy); - - /* must be after terminal init, SDL library changes signal handlers */ - os_setup_signal_handling(); - - /* init remote displays */ -#ifdef CONFIG_VNC - qemu_opts_foreach(qemu_find_opts("vnc"), - vnc_init_func, NULL, &error_fatal); -#endif - - if (using_spice) { - qemu_spice.display_init(); - } - - if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) { - exit(1); - } - - qdev_machine_creation_done(); - - /* TODO: once all bus devices are qdevified, this should be done - * when bus is created by qdev.c */ - /* - * TODO: If we had a main 'reset container' that the whole system - * lived in, we could reset that using the multi-phase reset - * APIs. For the moment, we just reset the sysbus, which will cause - * all devices hanging off it (and all their child buses, recursively) - * to be reset. Note that this will *not* reset any Device objects - * which are not attached to some part of the qbus tree! - */ - qemu_register_reset(resettable_cold_reset_fn, sysbus_get_default()); - qemu_run_machine_init_done_notifiers(); - - if (rom_check_and_register_reset() != 0) { - error_report("rom check and register reset failed"); - exit(1); - } - - replay_start(); - - /* This checkpoint is required by replay to separate prior clock - reading from the other reads, because timer polling functions query - clock values from the log. */ - replay_checkpoint(CHECKPOINT_RESET); - qemu_system_reset(SHUTDOWN_CAUSE_NONE); - register_global_state(); if (loadvm) { Error *local_err = NULL; if (load_snapshot(loadvm, &local_err) < 0) { @@ -4483,22 +4310,22 @@ void qemu_init(int argc, char **argv, char **envp) replay_vmstate_init(); } - qdev_prop_check_globals(); if (vmstate_dump_file) { /* dump and exit */ dump_vmstate_json_to_file(vmstate_dump_file); exit(0); } - if (incoming) { Error *local_err = NULL; - qemu_start_incoming_migration(incoming, &local_err); - if (local_err) { - error_reportf_err(local_err, "-incoming %s: ", incoming); - exit(1); + if (strcmp(incoming, "defer") != 0) { + qmp_migrate_incoming(incoming, &local_err); + if (local_err) { + error_reportf_err(local_err, "-incoming %s: ", incoming); + exit(1); + } } } else if (autostart) { - vm_start(); + qmp_cont(NULL); } accel_setup_post(current_machine); diff --git a/target/arm/arm-semi.c b/target/arm/arm-semi.c index c892e0e674..f7b7bff522 100644 --- a/target/arm/arm-semi.c +++ b/target/arm/arm-semi.c @@ -37,6 +37,7 @@ #include "exec/gdbstub.h" #include "qemu/cutils.h" #include "hw/arm/boot.h" +#include "hw/boards.h" #endif #define TARGET_SYS_OPEN 0x01 @@ -1048,7 +1049,7 @@ target_ulong do_arm_semihosting(CPUARMState *env) retvals[2] = ts->stack_base; retvals[3] = 0; /* Stack limit. */ #else - limit = ram_size; + limit = current_machine->ram_size; /* TODO: Make this use the limit of the loaded application. */ retvals[0] = rambase + limit / 2; retvals[1] = rambase + limit; diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 900ea08283..6c11feeb92 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -30,6 +30,7 @@ #include "sysemu/hvf.h" #include "sysemu/cpus.h" #include "sysemu/xen.h" +#include "sysemu/whpx.h" #include "kvm_i386.h" #include "sev_i386.h" @@ -800,7 +801,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { "kvmclock", "kvm-nopiodelay", "kvm-mmu", "kvmclock", "kvm-asyncpf", "kvm-steal-time", "kvm-pv-eoi", "kvm-pv-unhalt", NULL, "kvm-pv-tlb-flush", NULL, "kvm-pv-ipi", - "kvm-poll-control", "kvm-pv-sched-yield", "kvm-asyncpf-int", NULL, + "kvm-poll-control", "kvm-pv-sched-yield", "kvm-asyncpf-int", "kvm-msi-ext-dest-id", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "kvmclock-stable-bit", NULL, NULL, NULL, @@ -4139,6 +4140,7 @@ static PropValue kvm_default_props[] = { { "kvm-pv-eoi", "on" }, { "kvmclock-stable-bit", "on" }, { "x2apic", "on" }, + { "kvm-msi-ext-dest-id", "off" }, { "acpi", "off" }, { "monitor", "off" }, { "svm", "off" }, @@ -5165,6 +5167,8 @@ static void x86_cpu_load_model(X86CPU *cpu, X86CPUModel *model) if (kvm_enabled()) { if (!kvm_irqchip_in_kernel()) { x86_cpu_change_kvm_default("x2apic", "off"); + } else if (kvm_irqchip_is_split() && kvm_enable_x2apic()) { + x86_cpu_change_kvm_default("kvm-msi-ext-dest-id", "on"); } x86_cpu_apply_props(cpu, kvm_default_props); @@ -6173,6 +6177,8 @@ APICCommonClass *apic_get_class(void) apic_type = "kvm-apic"; } else if (xen_enabled()) { apic_type = "xen-apic"; + } else if (whpx_apic_in_platform()) { + apic_type = "whpx-apic"; } return APIC_COMMON_CLASS(object_class_by_name(apic_type)); diff --git a/target/i386/kvm.c b/target/i386/kvm.c index a2934dda02..bcfa4b03e0 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -416,6 +416,9 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, if (!kvm_irqchip_in_kernel()) { ret &= ~(1U << KVM_FEATURE_PV_UNHALT); } + if (kvm_irqchip_is_split()) { + ret |= 1U << KVM_FEATURE_MSI_EXT_DEST_ID; + } } else if (function == KVM_CPUID_FEATURES && reg == R_EDX) { ret |= 1U << KVM_HINTS_REALTIME; } @@ -4589,38 +4592,74 @@ int kvm_arch_irqchip_create(KVMState *s) } } +uint64_t kvm_swizzle_msi_ext_dest_id(uint64_t address) +{ + CPUX86State *env; + uint64_t ext_id; + + if (!first_cpu) { + return address; + } + env = &X86_CPU(first_cpu)->env; + if (!(env->features[FEAT_KVM] & (1 << KVM_FEATURE_MSI_EXT_DEST_ID))) { + return address; + } + + /* + * If the remappable format bit is set, or the upper bits are + * already set in address_hi, or the low extended bits aren't + * there anyway, do nothing. + */ + ext_id = address & (0xff << MSI_ADDR_DEST_IDX_SHIFT); + if (!ext_id || (ext_id & (1 << MSI_ADDR_DEST_IDX_SHIFT)) || (address >> 32)) { + return address; + } + + address &= ~ext_id; + address |= ext_id << 35; + return address; +} + int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, uint64_t address, uint32_t data, PCIDevice *dev) { X86IOMMUState *iommu = x86_iommu_get_default(); if (iommu) { - int ret; - MSIMessage src, dst; X86IOMMUClass *class = X86_IOMMU_DEVICE_GET_CLASS(iommu); - if (!class->int_remap) { - return 0; - } + if (class->int_remap) { + int ret; + MSIMessage src, dst; - src.address = route->u.msi.address_hi; - src.address <<= VTD_MSI_ADDR_HI_SHIFT; - src.address |= route->u.msi.address_lo; - src.data = route->u.msi.data; + src.address = route->u.msi.address_hi; + src.address <<= VTD_MSI_ADDR_HI_SHIFT; + src.address |= route->u.msi.address_lo; + src.data = route->u.msi.data; - ret = class->int_remap(iommu, &src, &dst, dev ? \ - pci_requester_id(dev) : \ - X86_IOMMU_SID_INVALID); - if (ret) { - trace_kvm_x86_fixup_msi_error(route->gsi); - return 1; - } + ret = class->int_remap(iommu, &src, &dst, dev ? \ + pci_requester_id(dev) : \ + X86_IOMMU_SID_INVALID); + if (ret) { + trace_kvm_x86_fixup_msi_error(route->gsi); + return 1; + } + + /* + * Handled untranslated compatibilty format interrupt with + * extended destination ID in the low bits 11-5. */ + dst.address = kvm_swizzle_msi_ext_dest_id(dst.address); - route->u.msi.address_hi = dst.address >> VTD_MSI_ADDR_HI_SHIFT; - route->u.msi.address_lo = dst.address & VTD_MSI_ADDR_LO_MASK; - route->u.msi.data = dst.data; + route->u.msi.address_hi = dst.address >> VTD_MSI_ADDR_HI_SHIFT; + route->u.msi.address_lo = dst.address & VTD_MSI_ADDR_LO_MASK; + route->u.msi.data = dst.data; + return 0; + } } + address = kvm_swizzle_msi_ext_dest_id(address); + route->u.msi.address_hi = address >> VTD_MSI_ADDR_HI_SHIFT; + route->u.msi.address_lo = address & VTD_MSI_ADDR_LO_MASK; return 0; } diff --git a/target/i386/kvm_i386.h b/target/i386/kvm_i386.h index a4a619cebb..dc72508389 100644 --- a/target/i386/kvm_i386.h +++ b/target/i386/kvm_i386.h @@ -48,4 +48,6 @@ bool kvm_has_waitpkg(void); bool kvm_hv_vpindex_settable(void); +uint64_t kvm_swizzle_msi_ext_dest_id(uint64_t address); + #endif diff --git a/target/i386/meson.build b/target/i386/meson.build index a1a02f3e99..fc3ee80386 100644 --- a/target/i386/meson.build +++ b/target/i386/meson.build @@ -33,6 +33,7 @@ i386_softmmu_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c')) i386_softmmu_ss.add(when: 'CONFIG_WHPX', if_true: files( 'whpx-all.c', 'whpx-cpus.c', + 'whpx-apic.c', )) i386_softmmu_ss.add(when: 'CONFIG_HAX', if_true: files( 'hax-all.c', diff --git a/target/i386/seg_helper.c b/target/i386/seg_helper.c index 09b6554660..e6ffa1f018 100644 --- a/target/i386/seg_helper.c +++ b/target/i386/seg_helper.c @@ -2108,7 +2108,10 @@ static inline void validate_seg(CPUX86State *env, int seg_reg, int cpl) if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) { /* data or non conforming code segment */ if (dpl < cpl) { - cpu_x86_load_seg_cache(env, seg_reg, 0, 0, 0, 0); + cpu_x86_load_seg_cache(env, seg_reg, 0, + env->segs[seg_reg].base, + env->segs[seg_reg].limit, + env->segs[seg_reg].flags & ~DESC_P_MASK); } } } diff --git a/target/i386/translate.c b/target/i386/translate.c index 4c57307e42..e8f5f5803a 100644 --- a/target/i386/translate.c +++ b/target/i386/translate.c @@ -3936,14 +3936,14 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } ot = mo_64_32(s->dflag); gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); - /* Note that by zero-extending the mask operand, we + /* Note that by zero-extending the source operand, we automatically handle zero-extending the result. */ if (ot == MO_64) { tcg_gen_mov_tl(s->T1, cpu_regs[s->vex_v]); } else { tcg_gen_ext32u_tl(s->T1, cpu_regs[s->vex_v]); } - gen_helper_pdep(cpu_regs[reg], s->T0, s->T1); + gen_helper_pdep(cpu_regs[reg], s->T1, s->T0); break; case 0x2f5: /* pext Gy, By, Ey */ @@ -3954,14 +3954,14 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } ot = mo_64_32(s->dflag); gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); - /* Note that by zero-extending the mask operand, we + /* Note that by zero-extending the source operand, we automatically handle zero-extending the result. */ if (ot == MO_64) { tcg_gen_mov_tl(s->T1, cpu_regs[s->vex_v]); } else { tcg_gen_ext32u_tl(s->T1, cpu_regs[s->vex_v]); } - gen_helper_pext(cpu_regs[reg], s->T0, s->T1); + gen_helper_pext(cpu_regs[reg], s->T1, s->T0); break; case 0x1f6: /* adcx Gy, Ey */ diff --git a/target/i386/whp-dispatch.h b/target/i386/whp-dispatch.h index b18aba20ed..cef5d848bd 100644 --- a/target/i386/whp-dispatch.h +++ b/target/i386/whp-dispatch.h @@ -30,6 +30,14 @@ */ #define LIST_WINHVPLATFORM_FUNCTIONS_SUPPLEMENTAL(X) \ X(HRESULT, WHvSuspendPartitionTime, (WHV_PARTITION_HANDLE Partition)) \ + X(HRESULT, WHvRequestInterrupt, (WHV_PARTITION_HANDLE Partition, \ + WHV_INTERRUPT_CONTROL* Interrupt, UINT32 InterruptControlSize)) \ + X(HRESULT, WHvGetVirtualProcessorInterruptControllerState2, \ + (WHV_PARTITION_HANDLE Partition, UINT32 VpIndex, PVOID State, \ + UINT32 StateSize, UINT32* WrittenSize)) \ + X(HRESULT, WHvSetVirtualProcessorInterruptControllerState2, \ + (WHV_PARTITION_HANDLE Partition, UINT32 VpIndex, PVOID State, \ + UINT32 StateSize)) \ #define LIST_WINHVEMULATION_FUNCTIONS(X) \ X(HRESULT, WHvEmulatorCreateEmulator, (const WHV_EMULATOR_CALLBACKS* Callbacks, WHV_EMULATOR_HANDLE* Emulator)) \ @@ -37,7 +45,6 @@ X(HRESULT, WHvEmulatorTryIoEmulation, (WHV_EMULATOR_HANDLE Emulator, VOID* Context, const WHV_VP_EXIT_CONTEXT* VpContext, const WHV_X64_IO_PORT_ACCESS_CONTEXT* IoInstructionContext, WHV_EMULATOR_STATUS* EmulatorReturnStatus)) \ X(HRESULT, WHvEmulatorTryMmioEmulation, (WHV_EMULATOR_HANDLE Emulator, VOID* Context, const WHV_VP_EXIT_CONTEXT* VpContext, const WHV_MEMORY_ACCESS_CONTEXT* MmioInstructionContext, WHV_EMULATOR_STATUS* EmulatorReturnStatus)) \ - #define WHP_DEFINE_TYPE(return_type, function_name, signature) \ typedef return_type (WINAPI *function_name ## _t) signature; diff --git a/target/i386/whpx-all.c b/target/i386/whpx-all.c index f4f3e33eac..3b824fc9d7 100644 --- a/target/i386/whpx-all.c +++ b/target/i386/whpx-all.c @@ -19,10 +19,15 @@ #include "sysemu/runstate.h" #include "qemu/main-loop.h" #include "hw/boards.h" +#include "hw/i386/ioapic.h" +#include "hw/i386/apic_internal.h" #include "qemu/error-report.h" #include "qapi/error.h" +#include "qapi/qapi-types-common.h" +#include "qapi/qapi-visit-common.h" #include "migration/blocker.h" #include "whp-dispatch.h" +#include <winerror.h> #include "whpx-cpus.h" @@ -31,11 +36,6 @@ #define HYPERV_APIC_BUS_FREQUENCY (200000000ULL) -struct whpx_state { - uint64_t mem_quota; - WHV_PARTITION_HANDLE partition; -}; - static const WHV_REGISTER_NAME whpx_register_names[] = { /* X64 General purpose registers */ @@ -152,6 +152,7 @@ struct whpx_vcpu { WHV_EMULATOR_HANDLE emulator; bool window_registered; bool interruptable; + bool ready_for_pic_interrupt; uint64_t tpr; uint64_t apic_base; bool interruption_pending; @@ -163,7 +164,7 @@ struct whpx_vcpu { static bool whpx_allowed; static bool whp_dispatch_initialized; static HMODULE hWinHvPlatform, hWinHvEmulation; - +static uint32_t max_vcpu_index; struct whpx_state whpx_global; struct WHPDispatch whp_dispatch; @@ -599,6 +600,10 @@ static void whpx_get_registers(CPUState *cpu) assert(idx == RTL_NUMBER_OF(whpx_register_names)); + if (whpx_apic_in_platform()) { + whpx_apic_get(x86_cpu->apic_state); + } + return; } @@ -820,26 +825,42 @@ static void whpx_vcpu_pre_run(CPUState *cpu) } /* Get pending hard interruption or replay one that was overwritten */ - if (!vcpu->interruption_pending && - vcpu->interruptable && (env->eflags & IF_MASK)) { - assert(!new_int.InterruptionPending); - if (cpu->interrupt_request & CPU_INTERRUPT_HARD) { - cpu->interrupt_request &= ~CPU_INTERRUPT_HARD; - irq = cpu_get_pic_interrupt(env); - if (irq >= 0) { - new_int.InterruptionType = WHvX64PendingInterrupt; - new_int.InterruptionPending = 1; - new_int.InterruptionVector = irq; + if (!whpx_apic_in_platform()) { + if (!vcpu->interruption_pending && + vcpu->interruptable && (env->eflags & IF_MASK)) { + assert(!new_int.InterruptionPending); + if (cpu->interrupt_request & CPU_INTERRUPT_HARD) { + cpu->interrupt_request &= ~CPU_INTERRUPT_HARD; + irq = cpu_get_pic_interrupt(env); + if (irq >= 0) { + new_int.InterruptionType = WHvX64PendingInterrupt; + new_int.InterruptionPending = 1; + new_int.InterruptionVector = irq; + } } } - } - /* Setup interrupt state if new one was prepared */ - if (new_int.InterruptionPending) { - reg_values[reg_count].PendingInterruption = new_int; - reg_names[reg_count] = WHvRegisterPendingInterruption; - reg_count += 1; - } + /* Setup interrupt state if new one was prepared */ + if (new_int.InterruptionPending) { + reg_values[reg_count].PendingInterruption = new_int; + reg_names[reg_count] = WHvRegisterPendingInterruption; + reg_count += 1; + } + } else if (vcpu->ready_for_pic_interrupt && + (cpu->interrupt_request & CPU_INTERRUPT_HARD)) { + cpu->interrupt_request &= ~CPU_INTERRUPT_HARD; + irq = cpu_get_pic_interrupt(env); + if (irq >= 0) { + reg_names[reg_count] = WHvRegisterPendingEvent; + reg_values[reg_count].ExtIntEvent = (WHV_X64_PENDING_EXT_INT_EVENT) + { + .EventPending = 1, + .EventType = WHvX64PendingEventExtInt, + .Vector = irq, + }; + reg_count += 1; + } + } /* Sync the TPR to the CR8 if was modified during the intercept */ tpr = cpu_get_apic_tpr(x86_cpu->apic_state); @@ -854,14 +875,17 @@ static void whpx_vcpu_pre_run(CPUState *cpu) /* Update the state of the interrupt delivery notification */ if (!vcpu->window_registered && cpu->interrupt_request & CPU_INTERRUPT_HARD) { - reg_values[reg_count].DeliverabilityNotifications.InterruptNotification - = 1; + reg_values[reg_count].DeliverabilityNotifications = + (WHV_X64_DELIVERABILITY_NOTIFICATIONS_REGISTER) { + .InterruptNotification = 1 + }; vcpu->window_registered = 1; reg_names[reg_count] = WHvX64RegisterDeliverabilityNotifications; reg_count += 1; } qemu_mutex_unlock_iothread(); + vcpu->ready_for_pic_interrupt = false; if (reg_count) { hr = whp_dispatch.WHvSetVirtualProcessorRegisters( @@ -948,7 +972,7 @@ static int whpx_vcpu_run(CPUState *cpu) int ret; whpx_vcpu_process_async_events(cpu); - if (cpu->halted) { + if (cpu->halted && !whpx_apic_in_platform()) { cpu->exception_index = EXCP_HLT; qatomic_set(&cpu->exit_request, false); return 0; @@ -992,14 +1016,114 @@ static int whpx_vcpu_run(CPUState *cpu) break; case WHvRunVpExitReasonX64InterruptWindow: + vcpu->ready_for_pic_interrupt = 1; vcpu->window_registered = 0; ret = 0; break; + case WHvRunVpExitReasonX64ApicEoi: + assert(whpx_apic_in_platform()); + ioapic_eoi_broadcast(vcpu->exit_ctx.ApicEoi.InterruptVector); + break; + case WHvRunVpExitReasonX64Halt: ret = whpx_handle_halt(cpu); break; + case WHvRunVpExitReasonX64ApicInitSipiTrap: { + WHV_INTERRUPT_CONTROL ipi = {0}; + uint64_t icr = vcpu->exit_ctx.ApicInitSipi.ApicIcr; + uint32_t delivery_mode = + (icr & APIC_ICR_DELIV_MOD) >> APIC_ICR_DELIV_MOD_SHIFT; + int dest_shorthand = + (icr & APIC_ICR_DEST_SHORT) >> APIC_ICR_DEST_SHORT_SHIFT; + bool broadcast = false; + bool include_self = false; + uint32_t i; + + /* We only registered for INIT and SIPI exits. */ + if ((delivery_mode != APIC_DM_INIT) && + (delivery_mode != APIC_DM_SIPI)) { + error_report( + "WHPX: Unexpected APIC exit that is not a INIT or SIPI"); + break; + } + + if (delivery_mode == APIC_DM_INIT) { + ipi.Type = WHvX64InterruptTypeInit; + } else { + ipi.Type = WHvX64InterruptTypeSipi; + } + + ipi.DestinationMode = + ((icr & APIC_ICR_DEST_MOD) >> APIC_ICR_DEST_MOD_SHIFT) ? + WHvX64InterruptDestinationModeLogical : + WHvX64InterruptDestinationModePhysical; + + ipi.TriggerMode = + ((icr & APIC_ICR_TRIGGER_MOD) >> APIC_ICR_TRIGGER_MOD_SHIFT) ? + WHvX64InterruptTriggerModeLevel : + WHvX64InterruptTriggerModeEdge; + + ipi.Vector = icr & APIC_VECTOR_MASK; + switch (dest_shorthand) { + /* no shorthand. Bits 56-63 contain the destination. */ + case 0: + ipi.Destination = (icr >> 56) & APIC_VECTOR_MASK; + hr = whp_dispatch.WHvRequestInterrupt(whpx->partition, + &ipi, sizeof(ipi)); + if (FAILED(hr)) { + error_report("WHPX: Failed to request interrupt hr=%08lx", + hr); + } + + break; + + /* self */ + case 1: + include_self = true; + break; + + /* broadcast, including self */ + case 2: + broadcast = true; + include_self = true; + break; + + /* broadcast, excluding self */ + case 3: + broadcast = true; + break; + } + + if (!broadcast && !include_self) { + break; + } + + for (i = 0; i <= max_vcpu_index; i++) { + if (i == cpu->cpu_index && !include_self) { + continue; + } + + /* + * Assuming that APIC Ids are identity mapped since + * WHvX64RegisterApicId & WHvX64RegisterInitialApicId registers + * are not handled yet and the hypervisor doesn't allow the + * guest to modify the APIC ID. + */ + ipi.Destination = i; + hr = whp_dispatch.WHvRequestInterrupt(whpx->partition, + &ipi, sizeof(ipi)); + if (FAILED(hr)) { + error_report( + "WHPX: Failed to request SIPI for %d, hr=%08lx", + i, hr); + } + } + + break; + } + case WHvRunVpExitReasonCanceled: cpu->exception_index = EXCP_INTERRUPT; ret = 1; @@ -1314,6 +1438,7 @@ int whpx_init_vcpu(CPUState *cpu) vcpu->interruptable = true; cpu->vcpu_dirty = true; cpu->hax_vcpu = (struct hax_vcpu_state *)vcpu; + max_vcpu_index = max(max_vcpu_index, cpu->cpu_index); qemu_add_vm_change_state_handler(whpx_cpu_update_state, cpu->env_ptr); return 0; @@ -1549,6 +1674,43 @@ error: return false; } +static void whpx_set_kernel_irqchip(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + struct whpx_state *whpx = &whpx_global; + OnOffSplit mode; + + if (!visit_type_OnOffSplit(v, name, &mode, errp)) { + return; + } + + switch (mode) { + case ON_OFF_SPLIT_ON: + whpx->kernel_irqchip_allowed = true; + whpx->kernel_irqchip_required = true; + break; + + case ON_OFF_SPLIT_OFF: + whpx->kernel_irqchip_allowed = false; + whpx->kernel_irqchip_required = false; + break; + + case ON_OFF_SPLIT_SPLIT: + error_setg(errp, "WHPX: split irqchip currently not supported"); + error_append_hint(errp, + "Try without kernel-irqchip or with kernel-irqchip=on|off"); + break; + + default: + /* + * The value was checked in visit_type_OnOffSplit() above. If + * we get here, then something is wrong in QEMU. + */ + abort(); + } +} + /* * Partition support */ @@ -1562,6 +1724,7 @@ static int whpx_accel_init(MachineState *ms) UINT32 whpx_cap_size; WHV_PARTITION_PROPERTY prop; UINT32 cpuidExitList[] = {1, 0x80000001}; + WHV_CAPABILITY_FEATURES features = {0}; whpx = &whpx_global; @@ -1570,7 +1733,6 @@ static int whpx_accel_init(MachineState *ms) goto error; } - memset(whpx, 0, sizeof(struct whpx_state)); whpx->mem_quota = ms->ram_size; hr = whp_dispatch.WHvGetCapability( @@ -1582,6 +1744,14 @@ static int whpx_accel_init(MachineState *ms) goto error; } + hr = whp_dispatch.WHvGetCapability( + WHvCapabilityCodeFeatures, &features, sizeof(features), NULL); + if (FAILED(hr)) { + error_report("WHPX: Failed to query capabilities, hr=%08lx", hr); + ret = -EINVAL; + goto error; + } + hr = whp_dispatch.WHvCreatePartition(&whpx->partition); if (FAILED(hr)) { error_report("WHPX: Failed to create partition, hr=%08lx", hr); @@ -1604,18 +1774,55 @@ static int whpx_accel_init(MachineState *ms) goto error; } + /* + * Error out if WHP doesn't support apic emulation and user is requiring + * it. + */ + if (whpx->kernel_irqchip_required && (!features.LocalApicEmulation || + !whp_dispatch.WHvSetVirtualProcessorInterruptControllerState2)) { + error_report("WHPX: kernel irqchip requested, but unavailable. " + "Try without kernel-irqchip or with kernel-irqchip=off"); + ret = -EINVAL; + goto error; + } + + if (whpx->kernel_irqchip_allowed && features.LocalApicEmulation && + whp_dispatch.WHvSetVirtualProcessorInterruptControllerState2) { + WHV_X64_LOCAL_APIC_EMULATION_MODE mode = + WHvX64LocalApicEmulationModeXApic; + printf("WHPX: setting APIC emulation mode in the hypervisor\n"); + hr = whp_dispatch.WHvSetPartitionProperty( + whpx->partition, + WHvPartitionPropertyCodeLocalApicEmulationMode, + &mode, + sizeof(mode)); + if (FAILED(hr)) { + error_report("WHPX: Failed to enable kernel irqchip hr=%08lx", hr); + if (whpx->kernel_irqchip_required) { + error_report("WHPX: kernel irqchip requested, but unavailable"); + ret = -EINVAL; + goto error; + } + } else { + whpx->apic_in_platform = true; + } + } + + /* Register for MSR and CPUID exits */ memset(&prop, 0, sizeof(WHV_PARTITION_PROPERTY)); prop.ExtendedVmExits.X64MsrExit = 1; prop.ExtendedVmExits.X64CpuidExit = 1; - hr = whp_dispatch.WHvSetPartitionProperty( - whpx->partition, - WHvPartitionPropertyCodeExtendedVmExits, - &prop, - sizeof(WHV_PARTITION_PROPERTY)); + if (whpx_apic_in_platform()) { + prop.ExtendedVmExits.X64ApicInitSipiExitTrap = 1; + } + hr = whp_dispatch.WHvSetPartitionProperty( + whpx->partition, + WHvPartitionPropertyCodeExtendedVmExits, + &prop, + sizeof(WHV_PARTITION_PROPERTY)); if (FAILED(hr)) { - error_report("WHPX: Failed to enable partition extended X64MsrExit and" - " X64CpuidExit hr=%08lx", hr); + error_report("WHPX: Failed to enable MSR & CPUIDexit, hr=%08lx", hr); ret = -EINVAL; goto error; } @@ -1668,11 +1875,27 @@ static void whpx_accel_class_init(ObjectClass *oc, void *data) ac->name = "WHPX"; ac->init_machine = whpx_accel_init; ac->allowed = &whpx_allowed; + + object_class_property_add(oc, "kernel-irqchip", "on|off|split", + NULL, whpx_set_kernel_irqchip, + NULL, NULL); + object_class_property_set_description(oc, "kernel-irqchip", + "Configure WHPX in-kernel irqchip"); +} + +static void whpx_accel_instance_init(Object *obj) +{ + struct whpx_state *whpx = &whpx_global; + + memset(whpx, 0, sizeof(struct whpx_state)); + /* Turn on kernel-irqchip, by default */ + whpx->kernel_irqchip_allowed = true; } static const TypeInfo whpx_accel_type = { .name = ACCEL_CLASS_NAME("whpx"), .parent = TYPE_ACCEL, + .instance_init = whpx_accel_instance_init, .class_init = whpx_accel_class_init, }; diff --git a/target/i386/whpx-apic.c b/target/i386/whpx-apic.c new file mode 100644 index 0000000000..b127a3cb8a --- /dev/null +++ b/target/i386/whpx-apic.c @@ -0,0 +1,274 @@ +/* + * WHPX platform APIC support + * + * Copyright (c) 2011 Siemens AG + * + * Authors: + * Jan Kiszka <jan.kiszka@siemens.com> + * John Starks <jostarks@microsoft.com> + * + * This work is licensed under the terms of the GNU GPL version 2. + * See the COPYING file in the top-level directory. + */ +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "cpu.h" +#include "hw/i386/apic_internal.h" +#include "hw/i386/apic-msidef.h" +#include "hw/pci/msi.h" +#include "sysemu/hw_accel.h" +#include "sysemu/whpx.h" +#include "whp-dispatch.h" + +static void whpx_put_apic_state(APICCommonState *s, + struct whpx_lapic_state *kapic) +{ + int i; + + memset(kapic, 0, sizeof(*kapic)); + kapic->fields[0x2].data = s->id << 24; + kapic->fields[0x3].data = s->version | ((APIC_LVT_NB - 1) << 16); + kapic->fields[0x8].data = s->tpr; + kapic->fields[0xd].data = s->log_dest << 24; + kapic->fields[0xe].data = s->dest_mode << 28 | 0x0fffffff; + kapic->fields[0xf].data = s->spurious_vec; + for (i = 0; i < 8; i++) { + kapic->fields[0x10 + i].data = s->isr[i]; + kapic->fields[0x18 + i].data = s->tmr[i]; + kapic->fields[0x20 + i].data = s->irr[i]; + } + + kapic->fields[0x28].data = s->esr; + kapic->fields[0x30].data = s->icr[0]; + kapic->fields[0x31].data = s->icr[1]; + for (i = 0; i < APIC_LVT_NB; i++) { + kapic->fields[0x32 + i].data = s->lvt[i]; + } + + kapic->fields[0x38].data = s->initial_count; + kapic->fields[0x3e].data = s->divide_conf; +} + +static void whpx_get_apic_state(APICCommonState *s, + struct whpx_lapic_state *kapic) +{ + int i, v; + + s->id = kapic->fields[0x2].data >> 24; + s->tpr = kapic->fields[0x8].data; + s->arb_id = kapic->fields[0x9].data; + s->log_dest = kapic->fields[0xd].data >> 24; + s->dest_mode = kapic->fields[0xe].data >> 28; + s->spurious_vec = kapic->fields[0xf].data; + for (i = 0; i < 8; i++) { + s->isr[i] = kapic->fields[0x10 + i].data; + s->tmr[i] = kapic->fields[0x18 + i].data; + s->irr[i] = kapic->fields[0x20 + i].data; + } + + s->esr = kapic->fields[0x28].data; + s->icr[0] = kapic->fields[0x30].data; + s->icr[1] = kapic->fields[0x31].data; + for (i = 0; i < APIC_LVT_NB; i++) { + s->lvt[i] = kapic->fields[0x32 + i].data; + } + + s->initial_count = kapic->fields[0x38].data; + s->divide_conf = kapic->fields[0x3e].data; + + v = (s->divide_conf & 3) | ((s->divide_conf >> 1) & 4); + s->count_shift = (v + 1) & 7; + + s->initial_count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + apic_next_timer(s, s->initial_count_load_time); +} + +static void whpx_apic_set_base(APICCommonState *s, uint64_t val) +{ + s->apicbase = val; +} + +static void whpx_put_apic_base(CPUState *cpu, uint64_t val) +{ + HRESULT hr; + WHV_REGISTER_VALUE reg_value = {.Reg64 = val}; + WHV_REGISTER_NAME reg_name = WHvX64RegisterApicBase; + + hr = whp_dispatch.WHvSetVirtualProcessorRegisters( + whpx_global.partition, + cpu->cpu_index, + ®_name, 1, + ®_value); + + if (FAILED(hr)) { + error_report("WHPX: Failed to set MSR APIC base, hr=%08lx", hr); + } +} + +static void whpx_apic_set_tpr(APICCommonState *s, uint8_t val) +{ + s->tpr = val; +} + +static uint8_t whpx_apic_get_tpr(APICCommonState *s) +{ + return s->tpr; +} + +static void whpx_apic_vapic_base_update(APICCommonState *s) +{ + /* not implemented yet */ +} + +static void whpx_apic_put(CPUState *cs, run_on_cpu_data data) +{ + APICCommonState *s = data.host_ptr; + struct whpx_lapic_state kapic; + HRESULT hr; + + whpx_put_apic_base(CPU(s->cpu), s->apicbase); + whpx_put_apic_state(s, &kapic); + + hr = whp_dispatch.WHvSetVirtualProcessorInterruptControllerState2( + whpx_global.partition, + cs->cpu_index, + &kapic, + sizeof(kapic)); + if (FAILED(hr)) { + fprintf(stderr, + "WHvSetVirtualProcessorInterruptControllerState failed: %08lx\n", + hr); + + abort(); + } +} + +void whpx_apic_get(DeviceState *dev) +{ + APICCommonState *s = APIC_COMMON(dev); + CPUState *cpu = CPU(s->cpu); + struct whpx_lapic_state kapic; + + HRESULT hr = whp_dispatch.WHvGetVirtualProcessorInterruptControllerState2( + whpx_global.partition, + cpu->cpu_index, + &kapic, + sizeof(kapic), + NULL); + if (FAILED(hr)) { + fprintf(stderr, + "WHvSetVirtualProcessorInterruptControllerState failed: %08lx\n", + hr); + + abort(); + } + + whpx_get_apic_state(s, &kapic); +} + +static void whpx_apic_post_load(APICCommonState *s) +{ + run_on_cpu(CPU(s->cpu), whpx_apic_put, RUN_ON_CPU_HOST_PTR(s)); +} + +static void whpx_apic_external_nmi(APICCommonState *s) +{ +} + +static void whpx_send_msi(MSIMessage *msg) +{ + uint64_t addr = msg->address; + uint32_t data = msg->data; + uint8_t dest = (addr & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT; + uint8_t vector = (data & MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT; + uint8_t dest_mode = (addr >> MSI_ADDR_DEST_MODE_SHIFT) & 0x1; + uint8_t trigger_mode = (data >> MSI_DATA_TRIGGER_SHIFT) & 0x1; + uint8_t delivery = (data >> MSI_DATA_DELIVERY_MODE_SHIFT) & 0x7; + + WHV_INTERRUPT_CONTROL interrupt = { + /* Values correspond to delivery modes */ + .Type = delivery, + .DestinationMode = dest_mode ? + WHvX64InterruptDestinationModeLogical : + WHvX64InterruptDestinationModePhysical, + + .TriggerMode = trigger_mode ? + WHvX64InterruptTriggerModeLevel : WHvX64InterruptTriggerModeEdge, + .Reserved = 0, + .Vector = vector, + .Destination = dest, + }; + HRESULT hr = whp_dispatch.WHvRequestInterrupt(whpx_global.partition, + &interrupt, sizeof(interrupt)); + if (FAILED(hr)) { + fprintf(stderr, "whpx: injection failed, MSI (%llx, %x) delivery: %d, " + "dest_mode: %d, trigger mode: %d, vector: %d, lost (%08lx)\n", + addr, data, delivery, dest_mode, trigger_mode, vector, hr); + } +} + +static uint64_t whpx_apic_mem_read(void *opaque, hwaddr addr, + unsigned size) +{ + return ~(uint64_t)0; +} + +static void whpx_apic_mem_write(void *opaque, hwaddr addr, + uint64_t data, unsigned size) +{ + MSIMessage msg = { .address = addr, .data = data }; + whpx_send_msi(&msg); +} + +static const MemoryRegionOps whpx_apic_io_ops = { + .read = whpx_apic_mem_read, + .write = whpx_apic_mem_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void whpx_apic_reset(APICCommonState *s) +{ + /* Not used by WHPX. */ + s->wait_for_sipi = 0; + + run_on_cpu(CPU(s->cpu), whpx_apic_put, RUN_ON_CPU_HOST_PTR(s)); +} + +static void whpx_apic_realize(DeviceState *dev, Error **errp) +{ + APICCommonState *s = APIC_COMMON(dev); + + memory_region_init_io(&s->io_memory, OBJECT(s), &whpx_apic_io_ops, s, + "whpx-apic-msi", APIC_SPACE_SIZE); + + msi_nonbroken = true; +} + +static void whpx_apic_class_init(ObjectClass *klass, void *data) +{ + APICCommonClass *k = APIC_COMMON_CLASS(klass); + + k->realize = whpx_apic_realize; + k->reset = whpx_apic_reset; + k->set_base = whpx_apic_set_base; + k->set_tpr = whpx_apic_set_tpr; + k->get_tpr = whpx_apic_get_tpr; + k->post_load = whpx_apic_post_load; + k->vapic_base_update = whpx_apic_vapic_base_update; + k->external_nmi = whpx_apic_external_nmi; + k->send_msi = whpx_send_msi; +} + +static const TypeInfo whpx_apic_info = { + .name = "whpx-apic", + .parent = TYPE_APIC_COMMON, + .instance_size = sizeof(APICCommonState), + .class_init = whpx_apic_class_init, +}; + +static void whpx_apic_register_types(void) +{ + type_register_static(&whpx_apic_info); +} + +type_init(whpx_apic_register_types) diff --git a/target/m68k/m68k-semi.c b/target/m68k/m68k-semi.c index 8e5fbfc8fa..27600e0cc0 100644 --- a/target/m68k/m68k-semi.c +++ b/target/m68k/m68k-semi.c @@ -26,6 +26,7 @@ #else #include "exec/gdbstub.h" #include "exec/softmmu-semi.h" +#include "hw/boards.h" #endif #include "qemu/log.h" @@ -455,8 +456,8 @@ void do_m68k_semihosting(CPUM68KState *env, int nr) * FIXME: This is wrong for boards where RAM does not start at * address zero. */ - env->dregs[1] = ram_size; - env->aregs[7] = ram_size; + env->dregs[1] = current_machine->ram_size; + env->aregs[7] = current_machine->ram_size; #endif return; default: diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c index 0adfbbda27..9cf66d3690 100644 --- a/target/s390x/excp_helper.c +++ b/target/s390x/excp_helper.c @@ -156,9 +156,10 @@ bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size, !address_space_access_valid(&address_space_memory, raddr, TARGET_PAGE_SIZE, access_type, MEMTXATTRS_UNSPECIFIED)) { + MachineState *ms = MACHINE(qdev_get_machine()); qemu_log_mask(CPU_LOG_MMU, "%s: raddr %" PRIx64 " > ram_size %" PRIx64 "\n", - __func__, (uint64_t)raddr, (uint64_t)ram_size); + __func__, (uint64_t)raddr, (uint64_t)ms->ram_size); excp = PGM_ADDRESSING; tec = 0; /* unused */ } diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index bd25eed3e8..0108611cc9 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -31,6 +31,7 @@ #if !defined(CONFIG_USER_ONLY) #include "hw/s390x/storage-keys.h" +#include "hw/boards.h" #endif /*****************************************************************************/ @@ -2075,12 +2076,13 @@ uint32_t HELPER(tprot)(CPUS390XState *env, uint64_t a1, uint64_t a2) /* insert storage key extended */ uint64_t HELPER(iske)(CPUS390XState *env, uint64_t r2) { + MachineState *ms = MACHINE(qdev_get_machine()); static S390SKeysState *ss; static S390SKeysClass *skeyclass; uint64_t addr = wrap_address(env, r2); uint8_t key; - if (addr > ram_size) { + if (addr > ms->ram_size) { return 0; } @@ -2098,12 +2100,13 @@ uint64_t HELPER(iske)(CPUS390XState *env, uint64_t r2) /* set storage key extended */ void HELPER(sske)(CPUS390XState *env, uint64_t r1, uint64_t r2) { + MachineState *ms = MACHINE(qdev_get_machine()); static S390SKeysState *ss; static S390SKeysClass *skeyclass; uint64_t addr = wrap_address(env, r2); uint8_t key; - if (addr > ram_size) { + if (addr > ms->ram_size) { return; } @@ -2124,11 +2127,12 @@ void HELPER(sske)(CPUS390XState *env, uint64_t r1, uint64_t r2) /* reset reference bit extended */ uint32_t HELPER(rrbe)(CPUS390XState *env, uint64_t r2) { + MachineState *ms = MACHINE(qdev_get_machine()); static S390SKeysState *ss; static S390SKeysClass *skeyclass; uint8_t re, key; - if (r2 > ram_size) { + if (r2 > ms->ram_size) { return 0; } diff --git a/target/s390x/mmu_helper.c b/target/s390x/mmu_helper.c index 7d9f3059cd..d492b23a17 100644 --- a/target/s390x/mmu_helper.c +++ b/target/s390x/mmu_helper.c @@ -27,6 +27,7 @@ #include "trace.h" #include "hw/hw.h" #include "hw/s390x/storage-keys.h" +#include "hw/boards.h" /* Fetch/store bits in the translation exception code: */ #define FS_READ 0x800 @@ -292,10 +293,11 @@ static void mmu_handle_skey(target_ulong addr, int rw, int *flags) { static S390SKeysClass *skeyclass; static S390SKeysState *ss; + MachineState *ms = MACHINE(qdev_get_machine()); uint8_t key; int rc; - if (unlikely(addr >= ram_size)) { + if (unlikely(addr >= ms->ram_size)) { return; } diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index f2f79dd6a4..4e026f90d0 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -674,14 +674,14 @@ static void test_acpi_one(const char *params, test_data *data) if (data->cd) { args = g_strdup_printf("-machine %s %s -accel tcg " "-nodefaults -nographic " - "-drive if=pflash,format=raw,file=%s,readonly " + "-drive if=pflash,format=raw,file=%s,readonly=on " "-drive if=pflash,format=raw,file=%s,snapshot=on -cdrom %s %s", data->machine, data->tcg_only ? "" : "-accel kvm", data->uefi_fl1, data->uefi_fl2, data->cd, params ? params : ""); } else { args = g_strdup_printf("-machine %s %s -accel tcg " "-nodefaults -nographic " - "-drive if=pflash,format=raw,file=%s,readonly " + "-drive if=pflash,format=raw,file=%s,readonly=on " "-drive if=pflash,format=raw,file=%s,snapshot=on %s", data->machine, data->tcg_only ? "" : "-accel kvm", data->uefi_fl1, data->uefi_fl2, params ? params : ""); diff --git a/tests/qtest/fuzz/fuzz.c b/tests/qtest/fuzz/fuzz.c index 7be7226bc0..238866a037 100644 --- a/tests/qtest/fuzz/fuzz.c +++ b/tests/qtest/fuzz/fuzz.c @@ -15,6 +15,7 @@ #include <wordexp.h> +#include "qemu/datadir.h" #include "sysemu/qtest.h" #include "sysemu/runstate.h" #include "sysemu/sysemu.h" diff --git a/tests/qtest/pflash-cfi02-test.c b/tests/qtest/pflash-cfi02-test.c index afb702b565..60db81a3a2 100644 --- a/tests/qtest/pflash-cfi02-test.c +++ b/tests/qtest/pflash-cfi02-test.c @@ -261,7 +261,7 @@ static void test_geometry(const void *opaque) const FlashConfig *config = opaque; QTestState *qtest; qtest = qtest_initf("-M musicpal" - " -drive if=pflash,file=%s,format=raw,copy-on-read" + " -drive if=pflash,file=%s,format=raw,copy-on-read=on" /* Device geometry properties. */ " -global driver=cfi.pflash02," "property=num-blocks0,value=%d" @@ -581,7 +581,7 @@ static void test_cfi_in_autoselect(const void *opaque) const FlashConfig *config = opaque; QTestState *qtest; qtest = qtest_initf("-M musicpal" - " -drive if=pflash,file=%s,format=raw,copy-on-read", + " -drive if=pflash,file=%s,format=raw,copy-on-read=on", image_path); FlashConfig explicit_config = expand_config_defaults(config); explicit_config.qtest = qtest; diff --git a/tests/qtest/test-filter-redirector.c b/tests/qtest/test-filter-redirector.c index 829db8c2ea..4269b2cdd9 100644 --- a/tests/qtest/test-filter-redirector.c +++ b/tests/qtest/test-filter-redirector.c @@ -95,8 +95,8 @@ static void test_redirector_tx(void) qts = qtest_initf( "-netdev socket,id=qtest-bn0,fd=%d " "-device %s,netdev=qtest-bn0,id=qtest-e0 " - "-chardev socket,id=redirector0,path=%s,server,nowait " - "-chardev socket,id=redirector1,path=%s,server,nowait " + "-chardev socket,id=redirector0,path=%s,server=on,wait=off " + "-chardev socket,id=redirector1,path=%s,server=on,wait=off " "-chardev socket,id=redirector2,path=%s " "-object filter-redirector,id=qtest-f0,netdev=qtest-bn0," "queue=tx,outdev=redirector0 " @@ -165,8 +165,8 @@ static void test_redirector_rx(void) qts = qtest_initf( "-netdev socket,id=qtest-bn0,fd=%d " "-device %s,netdev=qtest-bn0,id=qtest-e0 " - "-chardev socket,id=redirector0,path=%s,server,nowait " - "-chardev socket,id=redirector1,path=%s,server,nowait " + "-chardev socket,id=redirector0,path=%s,server=on,wait=off " + "-chardev socket,id=redirector1,path=%s,server=on,wait=off " "-chardev socket,id=redirector2,path=%s " "-object filter-redirector,id=qtest-f0,netdev=qtest-bn0," "queue=rx,indev=redirector0 " diff --git a/tests/qtest/vhost-user-test.c b/tests/qtest/vhost-user-test.c index 3df5322614..1a5f5313ff 100644 --- a/tests/qtest/vhost-user-test.c +++ b/tests/qtest/vhost-user-test.c @@ -537,7 +537,7 @@ static void test_server_create_chr(TestServer *server, const gchar *opt) static void test_server_listen(TestServer *server) { - test_server_create_chr(server, ",server,nowait"); + test_server_create_chr(server, ",server=on,wait=off"); } static void test_server_free(TestServer *server) @@ -846,7 +846,7 @@ static void *vhost_user_test_setup_reconnect(GString *cmd_line, void *arg) g_thread_new("connect", connect_thread, s); append_mem_opts(s, cmd_line, 256, TEST_MEMFD_AUTO); - s->vu_ops->append_opts(s, cmd_line, ",server"); + s->vu_ops->append_opts(s, cmd_line, ",server=on"); g_test_queue_destroy(vhost_user_test_cleanup, s); @@ -883,7 +883,7 @@ static void *vhost_user_test_setup_connect_fail(GString *cmd_line, void *arg) g_thread_new("connect", connect_thread, s); append_mem_opts(s, cmd_line, 256, TEST_MEMFD_AUTO); - s->vu_ops->append_opts(s, cmd_line, ",server"); + s->vu_ops->append_opts(s, cmd_line, ",server=on"); g_test_queue_destroy(vhost_user_test_cleanup, s); @@ -898,7 +898,7 @@ static void *vhost_user_test_setup_flags_mismatch(GString *cmd_line, void *arg) g_thread_new("connect", connect_thread, s); append_mem_opts(s, cmd_line, 256, TEST_MEMFD_AUTO); - s->vu_ops->append_opts(s, cmd_line, ",server"); + s->vu_ops->append_opts(s, cmd_line, ",server=on"); g_test_queue_destroy(vhost_user_test_cleanup, s); diff --git a/tests/tcg/i386/Makefile.target b/tests/tcg/i386/Makefile.target index a66232a67d..ad187cb2c9 100644 --- a/tests/tcg/i386/Makefile.target +++ b/tests/tcg/i386/Makefile.target @@ -18,6 +18,9 @@ test-i386-pcmpistri: CFLAGS += -msse4.2 run-test-i386-pcmpistri: QEMU_OPTS += -cpu max run-plugin-test-i386-pcmpistri-%: QEMU_OPTS += -cpu max +run-test-i386-bmi2: QEMU_OPTS += -cpu max +run-plugin-test-i386-bmi2-%: QEMU_OPTS += -cpu max + # # hello-i386 is a barebones app # diff --git a/tests/tcg/i386/test-i386-bmi2.c b/tests/tcg/i386/test-i386-bmi2.c new file mode 100644 index 0000000000..935a4d2a73 --- /dev/null +++ b/tests/tcg/i386/test-i386-bmi2.c @@ -0,0 +1,42 @@ +/* See if various BMI2 instructions give expected results */ +#include <assert.h> +#include <stdint.h> + +int main(int argc, char *argv[]) { + uint64_t ehlo = 0x202020204f4c4845ull; + uint64_t mask = 0xa080800302020001ull; + uint32_t result32; + +#ifdef __x86_64 + uint64_t result64; + + /* 64 bits */ + asm volatile ("pextq %2, %1, %0" : "=r"(result64) : "r"(ehlo), "m"(mask)); + assert(result64 == 133); + + asm volatile ("pdepq %2, %1, %0" : "=r"(result64) : "r"(result64), "m"(mask)); + assert(result64 == (ehlo & mask)); + + asm volatile ("pextq %2, %1, %0" : "=r"(result64) : "r"(-1ull), "m"(mask)); + assert(result64 == 511); /* mask has 9 bits set */ + + asm volatile ("pdepq %2, %1, %0" : "=r"(result64) : "r"(-1ull), "m"(mask)); + assert(result64 == mask); +#endif + + /* 32 bits */ + asm volatile ("pextl %2, %k1, %k0" : "=r"(result32) : "r"((uint32_t) ehlo), "m"(mask)); + assert(result32 == 5); + + asm volatile ("pdepl %2, %k1, %k0" : "=r"(result32) : "r"(result32), "m"(mask)); + assert(result32 == (uint32_t)(ehlo & mask)); + + asm volatile ("pextl %2, %k1, %k0" : "=r"(result32) : "r"(-1ull), "m"(mask)); + assert(result32 == 7); /* mask has 3 bits set */ + + asm volatile ("pdepl %2, %k1, %k0" : "=r"(result32) : "r"(-1ull), "m"(mask)); + assert(result32 == (uint32_t)mask); + + return 0; +} + diff --git a/tests/test-char.c b/tests/test-char.c index 9196e566e9..953e0d1c1f 100644 --- a/tests/test-char.c +++ b/tests/test-char.c @@ -413,7 +413,7 @@ static void char_websock_test(void) CharBackend client_be; Chardev *chr_client; Chardev *chr = qemu_chr_new("server", - "websocket:127.0.0.1:0,server,nowait", NULL); + "websocket:127.0.0.1:0,server=on,wait=off", NULL); const char handshake[] = "GET / HTTP/1.1\r\n" "Upgrade: websocket\r\n" "Connection: Upgrade\r\n" @@ -696,7 +696,7 @@ char_socket_addr_to_opt_str(SocketAddress *addr, bool fd_pass, fd = ioc->fd; ioc->fd = -1; optstr = g_strdup_printf("socket,id=cdev0,fd=%d%s", - fd, is_listen ? ",server,nowait" : ""); + fd, is_listen ? ",server=on,wait=off" : ""); object_unref(OBJECT(ioc)); return optstr; } else { @@ -706,13 +706,13 @@ char_socket_addr_to_opt_str(SocketAddress *addr, bool fd_pass, addr->u.inet.host, addr->u.inet.port, reconnect ? reconnect : "", - is_listen ? ",server,nowait" : ""); + is_listen ? ",server=on,wait=off" : ""); case SOCKET_ADDRESS_TYPE_UNIX: return g_strdup_printf("socket,id=cdev0,path=%s%s%s", addr->u.q_unix.path, reconnect ? reconnect : "", - is_listen ? ",server,nowait" : ""); + is_listen ? ",server=on,wait=off" : ""); default: g_assert_not_reached(); diff --git a/tests/test-qemu-opts.c b/tests/test-qemu-opts.c index 297ffe79dd..2aab831d10 100644 --- a/tests/test-qemu-opts.c +++ b/tests/test-qemu-opts.c @@ -84,11 +84,25 @@ static QemuOptsList opts_list_03 = { }, }; +static QemuOptsList opts_list_04 = { + .name = "opts_list_04", + .head = QTAILQ_HEAD_INITIALIZER(opts_list_04.head), + .merge_lists = true, + .desc = { + { + .name = "str3", + .type = QEMU_OPT_STRING, + }, + { /* end of list */ } + }, +}; + static void register_opts(void) { qemu_add_opts(&opts_list_01); qemu_add_opts(&opts_list_02); qemu_add_opts(&opts_list_03); + qemu_add_opts(&opts_list_04); } static void test_find_unknown_opts(void) @@ -402,17 +416,17 @@ static void test_qemu_opts_set(void) QemuOpts *opts; const char *opt; - list = qemu_find_opts("opts_list_01"); + list = qemu_find_opts("opts_list_04"); g_assert(list != NULL); g_assert(QTAILQ_EMPTY(&list->head)); - g_assert_cmpstr(list->name, ==, "opts_list_01"); + g_assert_cmpstr(list->name, ==, "opts_list_04"); /* should not find anything at this point */ opts = qemu_opts_find(list, NULL); g_assert(opts == NULL); /* implicitly create opts and set str3 value */ - qemu_opts_set(list, NULL, "str3", "value", &error_abort); + qemu_opts_set(list, "str3", "value", &error_abort); g_assert(!QTAILQ_EMPTY(&list->head)); /* get the just created opts */ diff --git a/ui/keymaps.c b/ui/keymaps.c index 4e5fca57a8..d4a647464b 100644 --- a/ui/keymaps.c +++ b/ui/keymaps.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "keymaps.h" #include "trace.h" #include "qemu/ctype.h" diff --git a/util/qemu-config.c b/util/qemu-config.c index 660f47b005..725e3d7e4b 100644 --- a/util/qemu-config.c +++ b/util/qemu-config.c @@ -313,39 +313,6 @@ void qemu_add_opts(QemuOptsList *list) abort(); } -int qemu_set_option(const char *str) -{ - Error *local_err = NULL; - char group[64], id[64], arg[64]; - QemuOptsList *list; - QemuOpts *opts; - int rc, offset; - - rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset); - if (rc < 3 || str[offset] != '=') { - error_report("can't parse: \"%s\"", str); - return -1; - } - - list = qemu_find_opts(group); - if (list == NULL) { - return -1; - } - - opts = qemu_opts_find(list, id); - if (!opts) { - error_report("there is no %s \"%s\" defined", - list->name, id); - return -1; - } - - if (!qemu_opt_set(opts, arg, str + offset + 1, &local_err)) { - error_report_err(local_err); - return -1; - } - return 0; -} - struct ConfigWriteData { QemuOptsList *list; FILE *fp; diff --git a/util/qemu-option.c b/util/qemu-option.c index acefbc23fa..25792159ba 100644 --- a/util/qemu-option.c +++ b/util/qemu-option.c @@ -670,15 +670,12 @@ void qemu_opts_loc_restore(QemuOpts *opts) loc_restore(&opts->loc); } -bool qemu_opts_set(QemuOptsList *list, const char *id, - const char *name, const char *value, Error **errp) +bool qemu_opts_set(QemuOptsList *list, const char *name, const char *value, Error **errp) { QemuOpts *opts; - opts = qemu_opts_create(list, id, 1, errp); - if (!opts) { - return false; - } + assert(list->merge_lists); + opts = qemu_opts_create(list, NULL, 0, &error_abort); return qemu_opt_set(opts, name, value, errp); } |