aboutsummaryrefslogtreecommitdiff
path: root/include/hw
diff options
context:
space:
mode:
Diffstat (limited to 'include/hw')
-rw-r--r--include/hw/acpi/acpi-defs.h562
-rw-r--r--include/hw/acpi/acpi.h12
-rw-r--r--include/hw/acpi/acpi_aml_interface.h52
-rw-r--r--include/hw/acpi/acpi_dev_interface.h18
-rw-r--r--include/hw/acpi/acpi_generic_initiator.h47
-rw-r--r--include/hw/acpi/aml-build.h98
-rw-r--r--include/hw/acpi/cpu.h12
-rw-r--r--include/hw/acpi/cxl.h30
-rw-r--r--include/hw/acpi/erst.h27
-rw-r--r--include/hw/acpi/generic_event_device.h25
-rw-r--r--include/hw/acpi/ghes.h12
-rw-r--r--include/hw/acpi/ich9.h18
-rw-r--r--include/hw/acpi/ich9_tco.h (renamed from include/hw/acpi/tco.h)3
-rw-r--r--include/hw/acpi/ipmi.h9
-rw-r--r--include/hw/acpi/memory_hotplug.h1
-rw-r--r--include/hw/acpi/pc-hotplug.h2
-rw-r--r--include/hw/acpi/pci.h8
-rw-r--r--include/hw/acpi/pcihp.h17
-rw-r--r--include/hw/acpi/piix4.h73
-rw-r--r--include/hw/acpi/tpm.h45
-rw-r--r--include/hw/acpi/utils.h3
-rw-r--r--include/hw/acpi/vmgenid.h17
-rw-r--r--include/hw/adc/aspeed_adc.h56
-rw-r--r--include/hw/adc/max111x.h (renamed from include/hw/misc/max111x.h)10
-rw-r--r--include/hw/adc/npcm7xx_adc.h68
-rw-r--r--include/hw/adc/stm32f2xx_adc.h8
-rw-r--r--include/hw/adc/zynq-xadc.h (renamed from include/hw/misc/zynq-xadc.h)13
-rw-r--r--include/hw/arm/allwinner-a10.h41
-rw-r--r--include/hw/arm/allwinner-h3.h83
-rw-r--r--include/hw/arm/allwinner-r40.h157
-rw-r--r--include/hw/arm/armsse-version.h42
-rw-r--r--include/hw/arm/armsse.h87
-rw-r--r--include/hw/arm/armv7m.h50
-rw-r--r--include/hw/arm/aspeed.h15
-rw-r--r--include/hw/arm/aspeed_soc.h237
-rw-r--r--include/hw/arm/bcm2835_peripherals.h52
-rw-r--r--include/hw/arm/bcm2836.h39
-rw-r--r--include/hw/arm/bcm2838.h31
-rw-r--r--include/hw/arm/bcm2838_peripherals.h84
-rw-r--r--include/hw/arm/boot.h68
-rw-r--r--include/hw/arm/bsa.h35
-rw-r--r--include/hw/arm/digic.h7
-rw-r--r--include/hw/arm/exynos4210.h62
-rw-r--r--include/hw/arm/fsl-imx25.h12
-rw-r--r--include/hw/arm/fsl-imx31.h10
-rw-r--r--include/hw/arm/fsl-imx6.h54
-rw-r--r--include/hw/arm/fsl-imx6ul.h150
-rw-r--r--include/hw/arm/fsl-imx7.h365
-rw-r--r--include/hw/arm/linux-boot-if.h11
-rw-r--r--include/hw/arm/msf2-soc.h18
-rw-r--r--include/hw/arm/npcm7xx.h139
-rw-r--r--include/hw/arm/nrf51_soc.h10
-rw-r--r--include/hw/arm/omap.h36
-rw-r--r--include/hw/arm/pxa.h27
-rw-r--r--include/hw/arm/raspberrypi-fw-defs.h173
-rw-r--r--include/hw/arm/raspi_platform.h105
-rw-r--r--include/hw/arm/smmu-common.h80
-rw-r--r--include/hw/arm/smmuv3.h24
-rw-r--r--include/hw/arm/stm32f100_soc.h61
-rw-r--r--include/hw/arm/stm32f205_soc.h22
-rw-r--r--include/hw/arm/stm32f405_soc.h22
-rw-r--r--include/hw/arm/stm32l4x5_soc.h67
-rw-r--r--include/hw/arm/virt.h91
-rw-r--r--include/hw/arm/xen_arch_hvm.h9
-rw-r--r--include/hw/arm/xlnx-versal.h195
-rw-r--r--include/hw/arm/xlnx-zynqmp.h55
-rw-r--r--include/hw/audio/asc.h85
-rw-r--r--include/hw/audio/pcspk.h10
-rw-r--r--include/hw/audio/soundhw.h8
-rw-r--r--include/hw/audio/virtio-snd.h250
-rw-r--r--include/hw/block/block.h15
-rw-r--r--include/hw/block/fdc.h6
-rw-r--r--include/hw/block/flash.h37
-rw-r--r--include/hw/block/swim.h36
-rw-r--r--include/hw/boards.h206
-rw-r--r--include/hw/char/avr_usart.h11
-rw-r--r--include/hw/char/bcm2835_aux.h7
-rw-r--r--include/hw/char/cadence_uart.h25
-rw-r--r--include/hw/char/cmsdk-apb-uart.h41
-rw-r--r--include/hw/char/digic-uart.h8
-rw-r--r--include/hw/char/escc.h8
-rw-r--r--include/hw/char/goldfish_tty.h36
-rw-r--r--include/hw/char/grlib_uart.h32
-rw-r--r--include/hw/char/ibex_uart.h46
-rw-r--r--include/hw/char/imx_serial.h28
-rw-r--r--include/hw/char/lm32_juart.h13
-rw-r--r--include/hw/char/mchp_pfsoc_mmuart.h68
-rw-r--r--include/hw/char/nrf51_uart.h7
-rw-r--r--include/hw/char/parallel-isa.h35
-rw-r--r--include/hw/char/parallel.h19
-rw-r--r--include/hw/char/pl011.h50
-rw-r--r--include/hw/char/renesas_sci.h9
-rw-r--r--include/hw/char/riscv_htif.h (renamed from include/hw/riscv/riscv_htif.h)17
-rw-r--r--include/hw/char/serial.h27
-rw-r--r--include/hw/char/shakti_uart.h74
-rw-r--r--include/hw/char/sifive_uart.h (renamed from include/hw/riscv/sifive_uart.h)15
-rw-r--r--include/hw/char/stm32f2xx_usart.h18
-rw-r--r--include/hw/char/xilinx_uartlite.h21
-rw-r--r--include/hw/clock.h210
-rw-r--r--include/hw/core/accel-cpu.h38
-rw-r--r--include/hw/core/cpu.h675
-rw-r--r--include/hw/core/generic-loader.h8
-rw-r--r--include/hw/core/resetcontainer.h48
-rw-r--r--include/hw/core/split-irq.h3
-rw-r--r--include/hw/core/sysbus-fdt.h (renamed from include/hw/arm/sysbus-fdt.h)0
-rw-r--r--include/hw/core/sysemu-cpu-ops.h92
-rw-r--r--include/hw/core/tcg-cpu-ops.h224
-rw-r--r--include/hw/cpu/a15mpcore.h8
-rw-r--r--include/hw/cpu/a9mpcore.h8
-rw-r--r--include/hw/cpu/arm11mpcore.h8
-rw-r--r--include/hw/cpu/cluster.h8
-rw-r--r--include/hw/cpu/core.h8
-rw-r--r--include/hw/cris/etraxfs.h5
-rw-r--r--include/hw/cxl/cxl.h70
-rw-r--r--include/hw/cxl/cxl_cdat.h172
-rw-r--r--include/hw/cxl/cxl_component.h280
-rw-r--r--include/hw/cxl/cxl_device.h506
-rw-r--r--include/hw/cxl/cxl_events.h169
-rw-r--r--include/hw/cxl/cxl_host.h22
-rw-r--r--include/hw/cxl/cxl_pci.h194
-rw-r--r--include/hw/display/bcm2835_fb.h9
-rw-r--r--include/hw/display/dpcd.h4
-rw-r--r--include/hw/display/edid.h17
-rw-r--r--include/hw/display/i2c-ddc.h4
-rw-r--r--include/hw/display/macfb.h69
-rw-r--r--include/hw/display/milkymist_tmu2.h42
-rw-r--r--include/hw/display/ramfb.h4
-rw-r--r--include/hw/display/vga.h10
-rw-r--r--include/hw/display/xlnx_dp.h19
-rw-r--r--include/hw/dma/bcm2835_dma.h8
-rw-r--r--include/hw/dma/i8257.h8
-rw-r--r--include/hw/dma/pl080.h14
-rw-r--r--include/hw/dma/sifive_pdma.h59
-rw-r--r--include/hw/dma/xlnx-zdma.h10
-rw-r--r--include/hw/dma/xlnx-zynq-devcfg.h8
-rw-r--r--include/hw/dma/xlnx_csu_dma.h72
-rw-r--r--include/hw/dma/xlnx_dpdma.h4
-rw-r--r--include/hw/elf_ops.h122
-rw-r--r--include/hw/firmware/smbios.h92
-rw-r--r--include/hw/fsi/aspeed_apb2opb.h46
-rw-r--r--include/hw/fsi/cfam.h34
-rw-r--r--include/hw/fsi/fsi-master.h32
-rw-r--r--include/hw/fsi/fsi.h37
-rw-r--r--include/hw/fsi/lbus.h43
-rw-r--r--include/hw/fw-path-provider.h11
-rw-r--r--include/hw/gpio/aspeed_gpio.h38
-rw-r--r--include/hw/gpio/bcm2835_gpio.h8
-rw-r--r--include/hw/gpio/bcm2838_gpio.h45
-rw-r--r--include/hw/gpio/imx_gpio.h7
-rw-r--r--include/hw/gpio/npcm7xx_gpio.h55
-rw-r--r--include/hw/gpio/nrf51_gpio.h8
-rw-r--r--include/hw/gpio/pca9552.h (renamed from include/hw/misc/pca9552.h)12
-rw-r--r--include/hw/gpio/pca9552_regs.h (renamed from include/hw/misc/pca9552_regs.h)0
-rw-r--r--include/hw/gpio/pca9554.h36
-rw-r--r--include/hw/gpio/pca9554_regs.h19
-rw-r--r--include/hw/gpio/pcf8574.h15
-rw-r--r--include/hw/gpio/sifive_gpio.h (renamed from include/hw/riscv/sifive_gpio.h)9
-rw-r--r--include/hw/gpio/stm32l4x5_gpio.h71
-rw-r--r--include/hw/hotplug.h13
-rw-r--r--include/hw/hw.h2
-rw-r--r--include/hw/hyperv/dynmem-proto.h430
-rw-r--r--include/hw/hyperv/hv-balloon.h18
-rw-r--r--include/hw/hyperv/hyperv-proto.h52
-rw-r--r--include/hw/hyperv/hyperv.h62
-rw-r--r--include/hw/hyperv/vmbus-bridge.h10
-rw-r--r--include/hw/hyperv/vmbus.h22
-rw-r--r--include/hw/i2c/allwinner-i2c.h61
-rw-r--r--include/hw/i2c/arm_sbcon_i2c.h19
-rw-r--r--include/hw/i2c/aspeed_i2c.h335
-rw-r--r--include/hw/i2c/bcm2835_i2c.h80
-rw-r--r--include/hw/i2c/bitbang_i2c.h2
-rw-r--r--include/hw/i2c/i2c.h115
-rw-r--r--include/hw/i2c/i2c_mux_pca954x.h19
-rw-r--r--include/hw/i2c/imx_i2c.h7
-rw-r--r--include/hw/i2c/microbit_i2c.h8
-rw-r--r--include/hw/i2c/npcm7xx_smbus.h112
-rw-r--r--include/hw/i2c/pmbus_device.h564
-rw-r--r--include/hw/i2c/pnv_i2c_regs.h143
-rw-r--r--include/hw/i2c/ppc4xx_i2c.h7
-rw-r--r--include/hw/i2c/smbus_slave.h15
-rw-r--r--include/hw/i386/apic.h11
-rw-r--r--include/hw/i386/apic_internal.h31
-rw-r--r--include/hw/i386/hostmem-epc.h28
-rw-r--r--include/hw/i386/intel_iommu.h119
-rw-r--r--include/hw/i386/ioapic_internal.h123
-rw-r--r--include/hw/i386/microvm.h74
-rw-r--r--include/hw/i386/pc.h161
-rw-r--r--include/hw/i386/sgx-epc.h71
-rw-r--r--include/hw/i386/topology.h132
-rw-r--r--include/hw/i386/vmport.h2
-rw-r--r--include/hw/i386/x86-iommu.h77
-rw-r--r--include/hw/i386/x86.h96
-rw-r--r--include/hw/i386/xen_arch_hvm.h11
-rw-r--r--include/hw/ide.h24
-rw-r--r--include/hw/ide/ahci-pci.h22
-rw-r--r--include/hw/ide/ahci-sysbus.h35
-rw-r--r--include/hw/ide/ahci.h37
-rw-r--r--include/hw/ide/ide-bus.h42
-rw-r--r--include/hw/ide/ide-dev.h186
-rw-r--r--include/hw/ide/ide-dma.h37
-rw-r--r--include/hw/ide/internal.h649
-rw-r--r--include/hw/ide/isa.h20
-rw-r--r--include/hw/ide/mmio.h26
-rw-r--r--include/hw/ide/pci.h20
-rw-r--r--include/hw/ide/piix.h7
-rw-r--r--include/hw/input/adb.h14
-rw-r--r--include/hw/input/gamepad.h18
-rw-r--r--include/hw/input/i8042.h93
-rw-r--r--include/hw/input/lasips2.h68
-rw-r--r--include/hw/input/lm832x.h28
-rw-r--r--include/hw/input/pl050.h58
-rw-r--r--include/hw/input/ps2.h77
-rw-r--r--include/hw/input/stellaris_gamepad.h37
-rw-r--r--include/hw/input/tsc2xxx.h12
-rw-r--r--include/hw/intc/allwinner-a10-pic.h7
-rw-r--r--include/hw/intc/arm_gic.h17
-rw-r--r--include/hw/intc/arm_gic_common.h21
-rw-r--r--include/hw/intc/arm_gicv3.h14
-rw-r--r--include/hw/intc/arm_gicv3_common.h75
-rw-r--r--include/hw/intc/arm_gicv3_its_common.h65
-rw-r--r--include/hw/intc/armv7m_nvic.h140
-rw-r--r--include/hw/intc/aspeed_vic.h7
-rw-r--r--include/hw/intc/bcm2835_ic.h7
-rw-r--r--include/hw/intc/bcm2836_control.h8
-rw-r--r--include/hw/intc/exynos4210_combiner.h57
-rw-r--r--include/hw/intc/exynos4210_gic.h43
-rw-r--r--include/hw/intc/goldfish_pic.h35
-rw-r--r--include/hw/intc/grlib_irqmp.h (renamed from include/hw/sparc/grlib.h)24
-rw-r--r--include/hw/intc/heathrow_pic.h7
-rw-r--r--include/hw/intc/i8259.h16
-rw-r--r--include/hw/intc/ibex_plic.h63
-rw-r--r--include/hw/intc/imx_avic.h7
-rw-r--r--include/hw/intc/imx_gpcv2.h7
-rw-r--r--include/hw/intc/intc.h11
-rw-r--r--include/hw/intc/ioapic.h (renamed from include/hw/i386/ioapic.h)10
-rw-r--r--include/hw/intc/kvm_irqcount.h10
-rw-r--r--include/hw/intc/loongarch_extioi.h68
-rw-r--r--include/hw/intc/loongarch_ipi.h54
-rw-r--r--include/hw/intc/loongarch_pch_msi.h25
-rw-r--r--include/hw/intc/loongarch_pch_pic.h69
-rw-r--r--include/hw/intc/loongson_liointc.h22
-rw-r--r--include/hw/intc/m68k_irqc.h42
-rw-r--r--include/hw/intc/mips_gic.h8
-rw-r--r--include/hw/intc/ppc-uic.h78
-rw-r--r--include/hw/intc/realview_gic.h8
-rw-r--r--include/hw/intc/riscv_aclint.h83
-rw-r--r--include/hw/intc/riscv_aplic.h79
-rw-r--r--include/hw/intc/riscv_imsic.h68
-rw-r--r--include/hw/intc/rx_icu.h6
-rw-r--r--include/hw/intc/sifive_plic.h (renamed from include/hw/riscv/sifive_plic.h)28
-rw-r--r--include/hw/intc/xlnx-pmu-iomod-intc.h8
-rw-r--r--include/hw/intc/xlnx-zynqmp-ipi.h8
-rw-r--r--include/hw/ipack/ipack.h22
-rw-r--r--include/hw/ipmi/ipmi.h35
-rw-r--r--include/hw/irq.h5
-rw-r--r--include/hw/isa/i8259_internal.h20
-rw-r--r--include/hw/isa/isa.h88
-rw-r--r--include/hw/isa/pc87312.h9
-rw-r--r--include/hw/isa/superio.h21
-rw-r--r--include/hw/isa/vt82c686.h39
-rw-r--r--include/hw/kvm/clock.h28
-rw-r--r--include/hw/lm32/lm32_pic.h10
-rw-r--r--include/hw/loader-fit.h2
-rw-r--r--include/hw/loader.h186
-rw-r--r--include/hw/loongarch/virt.h64
-rw-r--r--include/hw/m68k/mcf.h8
-rw-r--r--include/hw/m68k/mcf_fec.h3
-rw-r--r--include/hw/m68k/next-cube.h15
-rw-r--r--include/hw/m68k/q800-glue.h51
-rw-r--r--include/hw/m68k/q800.h78
-rw-r--r--include/hw/mem/memory-device.h86
-rw-r--r--include/hw/mem/npcm7xx_mc.h36
-rw-r--r--include/hw/mem/nvdimm.h27
-rw-r--r--include/hw/mem/pc-dimm.h25
-rw-r--r--include/hw/mem/sparse-mem.h19
-rw-r--r--include/hw/mips/bios.h14
-rw-r--r--include/hw/mips/bootloader.h26
-rw-r--r--include/hw/mips/cps.h11
-rw-r--r--include/hw/mips/cpudevs.h21
-rw-r--r--include/hw/mips/mips.h7
-rw-r--r--include/hw/misc/a9scu.h7
-rw-r--r--include/hw/misc/allwinner-a10-ccm.h67
-rw-r--r--include/hw/misc/allwinner-a10-dramc.h68
-rw-r--r--include/hw/misc/allwinner-cpucfg.h7
-rw-r--r--include/hw/misc/allwinner-h3-ccu.h7
-rw-r--r--include/hw/misc/allwinner-h3-dramc.h7
-rw-r--r--include/hw/misc/allwinner-h3-sysctrl.h7
-rw-r--r--include/hw/misc/allwinner-r40-ccu.h65
-rw-r--r--include/hw/misc/allwinner-r40-dramc.h108
-rw-r--r--include/hw/misc/allwinner-sid.h7
-rw-r--r--include/hw/misc/allwinner-sramc.h69
-rw-r--r--include/hw/misc/arm11scu.h7
-rw-r--r--include/hw/misc/arm_integrator_debug.h2
-rw-r--r--include/hw/misc/armsse-cpu-pwrctrl.h40
-rw-r--r--include/hw/misc/armsse-cpuid.h9
-rw-r--r--include/hw/misc/armsse-mhu.h9
-rw-r--r--include/hw/misc/armv7m_ras.h37
-rw-r--r--include/hw/misc/aspeed_hace.h50
-rw-r--r--include/hw/misc/aspeed_i3c.h48
-rw-r--r--include/hw/misc/aspeed_lpc.h45
-rw-r--r--include/hw/misc/aspeed_peci.h29
-rw-r--r--include/hw/misc/aspeed_sbc.h45
-rw-r--r--include/hw/misc/aspeed_scu.h65
-rw-r--r--include/hw/misc/aspeed_sdmc.h28
-rw-r--r--include/hw/misc/aspeed_xdma.h24
-rw-r--r--include/hw/misc/auxbus.h13
-rw-r--r--include/hw/misc/avr_power.h8
-rw-r--r--include/hw/misc/bcm2835_cprman.h210
-rw-r--r--include/hw/misc/bcm2835_cprman_internals.h1019
-rw-r--r--include/hw/misc/bcm2835_mbox.h8
-rw-r--r--include/hw/misc/bcm2835_mphi.h4
-rw-r--r--include/hw/misc/bcm2835_powermgt.h29
-rw-r--r--include/hw/misc/bcm2835_property.h9
-rw-r--r--include/hw/misc/bcm2835_rng.h8
-rw-r--r--include/hw/misc/bcm2835_thermal.h8
-rw-r--r--include/hw/misc/djmemc.h30
-rw-r--r--include/hw/misc/grlib_ahb_apb_pnp.h13
-rw-r--r--include/hw/misc/imx25_ccm.h7
-rw-r--r--include/hw/misc/imx31_ccm.h7
-rw-r--r--include/hw/misc/imx6_ccm.h7
-rw-r--r--include/hw/misc/imx6_src.h7
-rw-r--r--include/hw/misc/imx6ul_ccm.h7
-rw-r--r--include/hw/misc/imx7_ccm.h13
-rw-r--r--include/hw/misc/imx7_gpr.h7
-rw-r--r--include/hw/misc/imx7_snvs.h14
-rw-r--r--include/hw/misc/imx7_src.h66
-rw-r--r--include/hw/misc/imx_ccm.h16
-rw-r--r--include/hw/misc/imx_rngc.h7
-rw-r--r--include/hw/misc/iosb.h25
-rw-r--r--include/hw/misc/iotkit-secctl.h8
-rw-r--r--include/hw/misc/iotkit-sysctl.h23
-rw-r--r--include/hw/misc/iotkit-sysinfo.h12
-rw-r--r--include/hw/misc/lasi.h79
-rw-r--r--include/hw/misc/led.h98
-rw-r--r--include/hw/misc/mac_via.h133
-rw-r--r--include/hw/misc/macio/cuda.h15
-rw-r--r--include/hw/misc/macio/gpio.h9
-rw-r--r--include/hw/misc/macio/macio.h64
-rw-r--r--include/hw/misc/macio/pmu.h19
-rw-r--r--include/hw/misc/mchp_pfsoc_dmc.h58
-rw-r--r--include/hw/misc/mchp_pfsoc_ioscb.h56
-rw-r--r--include/hw/misc/mchp_pfsoc_sysreg.h42
-rw-r--r--include/hw/misc/mips_cmgcr.h6
-rw-r--r--include/hw/misc/mips_cpc.h9
-rw-r--r--include/hw/misc/mips_itu.h18
-rw-r--r--include/hw/misc/mos6522.h66
-rw-r--r--include/hw/misc/mps2-fpgaio.h17
-rw-r--r--include/hw/misc/mps2-scc.h41
-rw-r--r--include/hw/misc/msf2-sysreg.h7
-rw-r--r--include/hw/misc/npcm7xx_clk.h180
-rw-r--r--include/hw/misc/npcm7xx_gcr.h73
-rw-r--r--include/hw/misc/npcm7xx_mft.h69
-rw-r--r--include/hw/misc/npcm7xx_pwm.h106
-rw-r--r--include/hw/misc/npcm7xx_rng.h34
-rw-r--r--include/hw/misc/nrf51_rng.h7
-rw-r--r--include/hw/misc/pvpanic.h22
-rw-r--r--include/hw/misc/sifive_e_aon.h60
-rw-r--r--include/hw/misc/sifive_e_prci.h (renamed from include/hw/riscv/sifive_e_prci.h)11
-rw-r--r--include/hw/misc/sifive_test.h (renamed from include/hw/riscv/sifive_test.h)10
-rw-r--r--include/hw/misc/sifive_u_otp.h (renamed from include/hw/riscv/sifive_u_otp.h)16
-rw-r--r--include/hw/misc/sifive_u_prci.h (renamed from include/hw/riscv/sifive_u_prci.h)11
-rw-r--r--include/hw/misc/stm32f2xx_syscfg.h10
-rw-r--r--include/hw/misc/stm32f4xx_exti.h13
-rw-r--r--include/hw/misc/stm32f4xx_syscfg.h13
-rw-r--r--include/hw/misc/stm32l4x5_exti.h51
-rw-r--r--include/hw/misc/stm32l4x5_rcc.h239
-rw-r--r--include/hw/misc/stm32l4x5_rcc_internals.h1042
-rw-r--r--include/hw/misc/stm32l4x5_syscfg.h53
-rw-r--r--include/hw/misc/tz-mpc.h4
-rw-r--r--include/hw/misc/tz-msc.h7
-rw-r--r--include/hw/misc/tz-ppc.h4
-rw-r--r--include/hw/misc/unimp.h9
-rw-r--r--include/hw/misc/virt_ctrl.h24
-rw-r--r--include/hw/misc/vmcoreinfo.h11
-rw-r--r--include/hw/misc/xlnx-cfi-if.h59
-rw-r--r--include/hw/misc/xlnx-versal-cframe-reg.h303
-rw-r--r--include/hw/misc/xlnx-versal-cfu.h258
-rw-r--r--include/hw/misc/xlnx-versal-crl.h235
-rw-r--r--include/hw/misc/xlnx-versal-pmc-iou-slcr.h79
-rw-r--r--include/hw/misc/xlnx-versal-trng.h58
-rw-r--r--include/hw/misc/xlnx-versal-xramc.h97
-rw-r--r--include/hw/misc/xlnx-zynqmp-apu-ctrl.h93
-rw-r--r--include/hw/misc/xlnx-zynqmp-crf.h211
-rw-r--r--include/hw/net/allwinner-sun8i-emac.h15
-rw-r--r--include/hw/net/allwinner_emac.h7
-rw-r--r--include/hw/net/cadence_gem.h9
-rw-r--r--include/hw/net/dp8393x.h60
-rw-r--r--include/hw/net/ftgmac100.h13
-rw-r--r--include/hw/net/imx_fec.h9
-rw-r--r--include/hw/net/lan9118.h2
-rw-r--r--include/hw/net/lance.h10
-rw-r--r--include/hw/net/lasi_82596.h14
-rw-r--r--include/hw/net/mii.h16
-rw-r--r--include/hw/net/msf2-emac.h8
-rw-r--r--include/hw/net/mv88w8618_eth.h13
-rw-r--r--include/hw/net/ne2000-isa.h2
-rw-r--r--include/hw/net/npcm7xx_emc.h283
-rw-r--r--include/hw/net/npcm_gmac.h343
-rw-r--r--include/hw/net/smc91c111.h2
-rw-r--r--include/hw/net/xlnx-versal-canfd.h87
-rw-r--r--include/hw/net/xlnx-zynqmp-can.h79
-rw-r--r--include/hw/nmi.h11
-rw-r--r--include/hw/nubus/mac-nubus-bridge.h21
-rw-r--r--include/hw/nubus/nubus-virtio-mmio.h36
-rw-r--r--include/hw/nubus/nubus.h64
-rw-r--r--include/hw/nvram/chrp_nvram.h3
-rw-r--r--include/hw/nvram/eeprom_at24c.h39
-rw-r--r--include/hw/nvram/fw_cfg.h48
-rw-r--r--include/hw/nvram/fw_cfg_acpi.h14
-rw-r--r--include/hw/nvram/mac_nvram.h52
-rw-r--r--include/hw/nvram/npcm7xx_otp.h79
-rw-r--r--include/hw/nvram/nrf51_nvm.h7
-rw-r--r--include/hw/nvram/xlnx-bbram.h54
-rw-r--r--include/hw/nvram/xlnx-efuse.h132
-rw-r--r--include/hw/nvram/xlnx-versal-efuse.h68
-rw-r--r--include/hw/nvram/xlnx-zynqmp-efuse.h44
-rw-r--r--include/hw/openrisc/boot.h34
-rw-r--r--include/hw/or-irq.h4
-rw-r--r--include/hw/pci-bridge/cxl_upstream_port.h19
-rw-r--r--include/hw/pci-bridge/pci_expander_bridge.h12
-rw-r--r--include/hw/pci-bridge/simba.h8
-rw-r--r--include/hw/pci-bridge/xio3130_downstream.h15
-rw-r--r--include/hw/pci-host/articia.h17
-rw-r--r--include/hw/pci-host/astro.h94
-rw-r--r--include/hw/pci-host/bonito.h18
-rw-r--r--include/hw/pci-host/designware.h17
-rw-r--r--include/hw/pci-host/dino.h146
-rw-r--r--include/hw/pci-host/gpex.h45
-rw-r--r--include/hw/pci-host/grackle.h44
-rw-r--r--include/hw/pci-host/i440fx.h30
-rw-r--r--include/hw/pci-host/ls7a.h50
-rw-r--r--include/hw/pci-host/mv64361.h8
-rw-r--r--include/hw/pci-host/pam.h7
-rw-r--r--include/hw/pci-host/pnv_phb3.h44
-rw-r--r--include/hw/pci-host/pnv_phb3_regs.h16
-rw-r--r--include/hw/pci-host/pnv_phb4.h144
-rw-r--r--include/hw/pci-host/pnv_phb4_regs.h7
-rw-r--r--include/hw/pci-host/ppc4xx.h17
-rw-r--r--include/hw/pci-host/q35.h26
-rw-r--r--include/hw/pci-host/remote.h30
-rw-r--r--include/hw/pci-host/sabre.h17
-rw-r--r--include/hw/pci-host/spapr.h56
-rw-r--r--include/hw/pci-host/uninorth.h31
-rw-r--r--include/hw/pci-host/xilinx-pcie.h18
-rw-r--r--include/hw/pci/msi.h4
-rw-r--r--include/hw/pci/msix.h3
-rw-r--r--include/hw/pci/pci.h448
-rw-r--r--include/hw/pci/pci_bridge.h61
-rw-r--r--include/hw/pci/pci_bus.h15
-rw-r--r--include/hw/pci/pci_device.h350
-rw-r--r--include/hw/pci/pci_host.h15
-rw-r--r--include/hw/pci/pci_ids.h22
-rw-r--r--include/hw/pci/pci_regs.h1
-rw-r--r--include/hw/pci/pcie.h20
-rw-r--r--include/hw/pci/pcie_aer.h3
-rw-r--r--include/hw/pci/pcie_doe.h122
-rw-r--r--include/hw/pci/pcie_host.h10
-rw-r--r--include/hw/pci/pcie_port.h29
-rw-r--r--include/hw/pci/pcie_regs.h23
-rw-r--r--include/hw/pci/pcie_sriov.h82
-rw-r--r--include/hw/pci/shpc.h4
-rw-r--r--include/hw/pcmcia.h48
-rw-r--r--include/hw/platform-bus.h11
-rw-r--r--include/hw/ppc/fdt.h8
-rw-r--r--include/hw/ppc/mac_dbdma.h8
-rw-r--r--include/hw/ppc/openpic.h36
-rw-r--r--include/hw/ppc/pnv.h232
-rw-r--r--include/hw/ppc/pnv_chip.h162
-rw-r--r--include/hw/ppc/pnv_chiptod.h53
-rw-r--r--include/hw/ppc/pnv_core.h48
-rw-r--r--include/hw/ppc/pnv_homer.h29
-rw-r--r--include/hw/ppc/pnv_i2c.h38
-rw-r--r--include/hw/ppc/pnv_lpc.h47
-rw-r--r--include/hw/ppc/pnv_n1_chiplet.h32
-rw-r--r--include/hw/ppc/pnv_nest_pervasive.h32
-rw-r--r--include/hw/ppc/pnv_occ.h34
-rw-r--r--include/hw/ppc/pnv_pnor.h15
-rw-r--r--include/hw/ppc/pnv_psi.h40
-rw-r--r--include/hw/ppc/pnv_sbe.h56
-rw-r--r--include/hw/ppc/pnv_xive.h92
-rw-r--r--include/hw/ppc/pnv_xscom.h85
-rw-r--r--include/hw/ppc/ppc.h20
-rw-r--r--include/hw/ppc/ppc4xx.h138
-rw-r--r--include/hw/ppc/spapr.h195
-rw-r--r--include/hw/ppc/spapr_cpu_core.h23
-rw-r--r--include/hw/ppc/spapr_drc.h63
-rw-r--r--include/hw/ppc/spapr_irq.h62
-rw-r--r--include/hw/ppc/spapr_nested.h524
-rw-r--r--include/hw/ppc/spapr_numa.h37
-rw-r--r--include/hw/ppc/spapr_nvdimm.h25
-rw-r--r--include/hw/ppc/spapr_ovec.h2
-rw-r--r--include/hw/ppc/spapr_rtas.h10
-rw-r--r--include/hw/ppc/spapr_tpm_proxy.h7
-rw-r--r--include/hw/ppc/spapr_vio.h49
-rw-r--r--include/hw/ppc/spapr_xive.h15
-rw-r--r--include/hw/ppc/vof.h65
-rw-r--r--include/hw/ppc/xics.h33
-rw-r--r--include/hw/ppc/xics_spapr.h7
-rw-r--r--include/hw/ppc/xive.h151
-rw-r--r--include/hw/ppc/xive2.h111
-rw-r--r--include/hw/ppc/xive2_regs.h212
-rw-r--r--include/hw/ppc/xive_regs.h18
-rw-r--r--include/hw/ptimer.h38
-rw-r--r--include/hw/qdev-clock.h25
-rw-r--r--include/hw/qdev-core.h701
-rw-r--r--include/hw/qdev-properties-system.h97
-rw-r--r--include/hw/qdev-properties.h275
-rw-r--r--include/hw/rdma/rdma.h40
-rw-r--r--include/hw/register.h15
-rw-r--r--include/hw/registerfields.h126
-rw-r--r--include/hw/remote/iohub.h42
-rw-r--r--include/hw/remote/iommu.h40
-rw-r--r--include/hw/remote/machine.h42
-rw-r--r--include/hw/remote/memory.h19
-rw-r--r--include/hw/remote/mpqemu-link.h99
-rw-r--r--include/hw/remote/proxy-memory-listener.h28
-rw-r--r--include/hw/remote/proxy.h48
-rw-r--r--include/hw/remote/vfio-user-obj.h6
-rw-r--r--include/hw/resettable.h11
-rw-r--r--include/hw/riscv/boot.h46
-rw-r--r--include/hw/riscv/boot_opensbi.h7
-rw-r--r--include/hw/riscv/microchip_pfsoc.h168
-rw-r--r--include/hw/riscv/numa.h114
-rw-r--r--include/hw/riscv/opentitan.h106
-rw-r--r--include/hw/riscv/riscv_hart.h11
-rw-r--r--include/hw/riscv/shakti_c.h75
-rw-r--r--include/hw/riscv/sifive_clint.h57
-rw-r--r--include/hw/riscv/sifive_e.h61
-rw-r--r--include/hw/riscv/sifive_u.h80
-rw-r--r--include/hw/riscv/spike.h26
-rw-r--r--include/hw/riscv/virt.h101
-rw-r--r--include/hw/rtc/allwinner-rtc.h15
-rw-r--r--include/hw/rtc/aspeed_rtc.h9
-rw-r--r--include/hw/rtc/goldfish_rtc.h10
-rw-r--r--include/hw/rtc/m48t59.h19
-rw-r--r--include/hw/rtc/mc146818rtc.h25
-rw-r--r--include/hw/rtc/pl031.h7
-rw-r--r--include/hw/rtc/sun4v-rtc.h6
-rw-r--r--include/hw/rtc/xlnx-zynqmp-rtc.h12
-rw-r--r--include/hw/rx/rx62n.h15
-rw-r--r--include/hw/s390x/3270-ccw.h16
-rw-r--r--include/hw/s390x/ap-device.h12
-rw-r--r--include/hw/s390x/cpu-topology.h83
-rw-r--r--include/hw/s390x/css-bridge.h14
-rw-r--r--include/hw/s390x/css.h19
-rw-r--r--include/hw/s390x/event-facility.h35
-rw-r--r--include/hw/s390x/ioinst.h14
-rw-r--r--include/hw/s390x/pv.h58
-rw-r--r--include/hw/s390x/s390-ccw.h19
-rw-r--r--include/hw/s390x/s390-pci-bus.h406
-rw-r--r--include/hw/s390x/s390-pci-clp.h216
-rw-r--r--include/hw/s390x/s390-pci-inst.h119
-rw-r--r--include/hw/s390x/s390-pci-kvm.h38
-rw-r--r--include/hw/s390x/s390-pci-vfio.h44
-rw-r--r--include/hw/s390x/s390-virtio-ccw.h21
-rw-r--r--include/hw/s390x/s390_flic.h32
-rw-r--r--include/hw/s390x/sclp.h44
-rw-r--r--include/hw/s390x/storage-attributes.h36
-rw-r--r--include/hw/s390x/storage-keys.h90
-rw-r--r--include/hw/s390x/tod.h17
-rw-r--r--include/hw/s390x/vfio-ccw.h7
-rw-r--r--include/hw/scsi/esp.h66
-rw-r--r--include/hw/scsi/scsi.h108
-rw-r--r--include/hw/sd/allwinner-sdhost.h31
-rw-r--r--include/hw/sd/aspeed_sdhci.h10
-rw-r--r--include/hw/sd/bcm2835_sdhost.h8
-rw-r--r--include/hw/sd/cadence_sdhci.h47
-rw-r--r--include/hw/sd/npcm7xx_sdhci.h65
-rw-r--r--include/hw/sd/sd.h154
-rw-r--r--include/hw/sd/sdcard_legacy.h50
-rw-r--r--include/hw/sd/sdhci.h16
-rw-r--r--include/hw/semihosting/console.h69
-rw-r--r--include/hw/semihosting/semihost.h77
-rw-r--r--include/hw/sensor/emc141x_regs.h37
-rw-r--r--include/hw/sensor/isl_pmbus_vr.h57
-rw-r--r--include/hw/sensor/tmp105.h55
-rw-r--r--include/hw/sensor/tmp105_regs.h (renamed from include/hw/misc/tmp105_regs.h)0
-rw-r--r--include/hw/sh4/sh.h50
-rw-r--r--include/hw/sh4/sh_intc.h2
-rw-r--r--include/hw/southbridge/ich9.h (renamed from include/hw/i386/ich9.h)56
-rw-r--r--include/hw/southbridge/piix.h43
-rw-r--r--include/hw/sparc/sparc32_dma.h34
-rw-r--r--include/hw/sparc/sun4m_iommu.h9
-rw-r--r--include/hw/sparc/sun4u_iommu.h9
-rw-r--r--include/hw/ssi/aspeed_smc.h100
-rw-r--r--include/hw/ssi/bcm2835_spi.h81
-rw-r--r--include/hw/ssi/ibex_spi_host.h92
-rw-r--r--include/hw/ssi/imx_spi.h12
-rw-r--r--include/hw/ssi/mss-spi.h7
-rw-r--r--include/hw/ssi/npcm7xx_fiu.h73
-rw-r--r--include/hw/ssi/npcm_pspi.h53
-rw-r--r--include/hw/ssi/pl022.h12
-rw-r--r--include/hw/ssi/sifive_spi.h50
-rw-r--r--include/hw/ssi/ssi.h71
-rw-r--r--include/hw/ssi/stm32f2xx_spi.h8
-rw-r--r--include/hw/ssi/xilinx_spips.h36
-rw-r--r--include/hw/ssi/xlnx-versal-ospi.h111
-rw-r--r--include/hw/stream.h44
-rw-r--r--include/hw/sysbus.h20
-rw-r--r--include/hw/timer/a9gtimer.h4
-rw-r--r--include/hw/timer/allwinner-a10-pit.h4
-rw-r--r--include/hw/timer/arm_mptimer.h8
-rw-r--r--include/hw/timer/armv7m_systick.h46
-rw-r--r--include/hw/timer/aspeed_timer.h17
-rw-r--r--include/hw/timer/avr_timer16.h9
-rw-r--r--include/hw/timer/bcm2835_systmr.h27
-rw-r--r--include/hw/timer/cadence_ttc.h54
-rw-r--r--include/hw/timer/cmsdk-apb-dualtimer.h10
-rw-r--r--include/hw/timer/cmsdk-apb-timer.h39
-rw-r--r--include/hw/timer/digic-timer.h7
-rw-r--r--include/hw/timer/grlib_gptimer.h32
-rw-r--r--include/hw/timer/hpet.h2
-rw-r--r--include/hw/timer/i8254.h11
-rw-r--r--include/hw/timer/i8254_internal.h10
-rw-r--r--include/hw/timer/ibex_timer.h55
-rw-r--r--include/hw/timer/imx_epit.h15
-rw-r--r--include/hw/timer/imx_gpt.h10
-rw-r--r--include/hw/timer/mss-timer.h8
-rw-r--r--include/hw/timer/npcm7xx_timer.h113
-rw-r--r--include/hw/timer/nrf51_timer.h7
-rw-r--r--include/hw/timer/renesas_cmt.h9
-rw-r--r--include/hw/timer/renesas_tmr.h9
-rw-r--r--include/hw/timer/sifive_pwm.h62
-rw-r--r--include/hw/timer/sse-counter.h105
-rw-r--r--include/hw/timer/sse-timer.h54
-rw-r--r--include/hw/timer/stellaris-gptm.h51
-rw-r--r--include/hw/timer/stm32f2xx_timer.h10
-rw-r--r--include/hw/tricore/tc27x_soc.h129
-rw-r--r--include/hw/tricore/triboard.h48
-rw-r--r--include/hw/tricore/tricore_testdevice.h33
-rw-r--r--include/hw/unicore32/puv3.h40
-rw-r--r--include/hw/usb.h161
-rw-r--r--include/hw/usb/chipidea.h7
-rw-r--r--include/hw/usb/dwc2-regs.h1618
-rw-r--r--include/hw/usb/hcd-dwc3.h56
-rw-r--r--include/hw/usb/hcd-musb.h6
-rw-r--r--include/hw/usb/hid.h17
-rw-r--r--include/hw/usb/imx-usb-phy.h7
-rw-r--r--include/hw/usb/msd.h55
-rw-r--r--include/hw/usb/xhci.h21
-rw-r--r--include/hw/usb/xlnx-usb-subsystem.h47
-rw-r--r--include/hw/usb/xlnx-versal-usb2-ctrl-regs.h48
-rw-r--r--include/hw/vfio/vfio-amd-xgbe.h11
-rw-r--r--include/hw/vfio/vfio-calxeda-xgmac.h21
-rw-r--r--include/hw/vfio/vfio-common.h126
-rw-r--r--include/hw/vfio/vfio-container-base.h141
-rw-r--r--include/hw/vfio/vfio-platform.h19
-rw-r--r--include/hw/vfio/vfio.h7
-rw-r--r--include/hw/virtio/vdpa-dev.h43
-rw-r--r--include/hw/virtio/vhost-backend.h75
-rw-r--r--include/hw/virtio/vhost-scsi-common.h12
-rw-r--r--include/hw/virtio/vhost-scsi.h8
-rw-r--r--include/hw/virtio/vhost-user-base.h49
-rw-r--r--include/hw/virtio/vhost-user-blk.h21
-rw-r--r--include/hw/virtio/vhost-user-fs.h15
-rw-r--r--include/hw/virtio/vhost-user-gpio.h24
-rw-r--r--include/hw/virtio/vhost-user-i2c.h25
-rw-r--r--include/hw/virtio/vhost-user-rng.h24
-rw-r--r--include/hw/virtio/vhost-user-scmi.h31
-rw-r--r--include/hw/virtio/vhost-user-scsi.h14
-rw-r--r--include/hw/virtio/vhost-user-snd.h24
-rw-r--r--include/hw/virtio/vhost-user-vsock.h14
-rw-r--r--include/hw/virtio/vhost-user.h89
-rw-r--r--include/hw/virtio/vhost-vdpa.h79
-rw-r--r--include/hw/virtio/vhost-vsock-common.h22
-rw-r--r--include/hw/virtio/vhost-vsock.h8
-rw-r--r--include/hw/virtio/vhost.h346
-rw-r--r--include/hw/virtio/virtio-access.h8
-rw-r--r--include/hw/virtio/virtio-acpi.h15
-rw-r--r--include/hw/virtio/virtio-balloon.h8
-rw-r--r--include/hw/virtio/virtio-blk-common.h20
-rw-r--r--include/hw/virtio/virtio-blk.h40
-rw-r--r--include/hw/virtio/virtio-bus.h19
-rw-r--r--include/hw/virtio/virtio-crypto.h13
-rw-r--r--include/hw/virtio/virtio-dmabuf.h100
-rw-r--r--include/hw/virtio/virtio-gpu-bswap.h37
-rw-r--r--include/hw/virtio/virtio-gpu-pci.h5
-rw-r--r--include/hw/virtio/virtio-gpu.h177
-rw-r--r--include/hw/virtio/virtio-input.h44
-rw-r--r--include/hw/virtio/virtio-iommu.h27
-rw-r--r--include/hw/virtio/virtio-md-pci.h44
-rw-r--r--include/hw/virtio/virtio-mem.h74
-rw-r--r--include/hw/virtio/virtio-mmio.h22
-rw-r--r--include/hw/virtio/virtio-net.h45
-rw-r--r--include/hw/virtio/virtio-pci.h272
-rw-r--r--include/hw/virtio/virtio-pmem.h19
-rw-r--r--include/hw/virtio/virtio-rng.h8
-rw-r--r--include/hw/virtio/virtio-scsi.h93
-rw-r--r--include/hw/virtio/virtio-serial.h22
-rw-r--r--include/hw/virtio/virtio.h158
-rw-r--r--include/hw/vmstate-if.h11
-rw-r--r--include/hw/watchdog/allwinner-wdt.h123
-rw-r--r--include/hw/watchdog/cmsdk-apb-watchdog.h13
-rw-r--r--include/hw/watchdog/sbsa_gwdt.h79
-rw-r--r--include/hw/watchdog/wdt_aspeed.h24
-rw-r--r--include/hw/watchdog/wdt_diag288.h19
-rw-r--r--include/hw/watchdog/wdt_imx2.h13
-rw-r--r--include/hw/xen/arch_hvm.h5
-rw-r--r--include/hw/xen/interface/arch-arm.h509
-rw-r--r--include/hw/xen/interface/arch-x86/cpuid.h113
-rw-r--r--include/hw/xen/interface/arch-x86/xen-x86_32.h177
-rw-r--r--include/hw/xen/interface/arch-x86/xen-x86_64.h224
-rw-r--r--include/hw/xen/interface/arch-x86/xen.h378
-rw-r--r--include/hw/xen/interface/event_channel.h371
-rw-r--r--include/hw/xen/interface/features.h126
-rw-r--r--include/hw/xen/interface/grant_table.h669
-rw-r--r--include/hw/xen/interface/hvm/hvm_op.h378
-rw-r--r--include/hw/xen/interface/hvm/params.h301
-rw-r--r--include/hw/xen/interface/io/blkif.h41
-rw-r--r--include/hw/xen/interface/io/console.h29
-rw-r--r--include/hw/xen/interface/io/fbif.h39
-rw-r--r--include/hw/xen/interface/io/kbdif.h29
-rw-r--r--include/hw/xen/interface/io/netif.h119
-rw-r--r--include/hw/xen/interface/io/protocols.h19
-rw-r--r--include/hw/xen/interface/io/ring.h139
-rw-r--r--include/hw/xen/interface/io/usbif.h396
-rw-r--r--include/hw/xen/interface/io/xenbus.h29
-rw-r--r--include/hw/xen/interface/io/xs_wire.h147
-rw-r--r--include/hw/xen/interface/memory.h746
-rw-r--r--include/hw/xen/interface/physdev.h366
-rw-r--r--include/hw/xen/interface/sched.h185
-rw-r--r--include/hw/xen/interface/trace.h324
-rw-r--r--include/hw/xen/interface/vcpu.h231
-rw-r--r--include/hw/xen/interface/version.h96
-rw-r--r--include/hw/xen/interface/xen-compat.h29
-rw-r--r--include/hw/xen/interface/xen.h1032
-rw-r--r--include/hw/xen/xen-backend.h2
-rw-r--r--include/hw/xen/xen-block.h33
-rw-r--r--include/hw/xen/xen-bus-helper.h36
-rw-r--r--include/hw/xen/xen-bus.h67
-rw-r--r--include/hw/xen/xen-hvm-common.h98
-rw-r--r--include/hw/xen/xen-legacy-backend.h35
-rw-r--r--include/hw/xen/xen-x86.h15
-rw-r--r--include/hw/xen/xen.h35
-rw-r--r--include/hw/xen/xen_backend_ops.h408
-rw-r--r--include/hw/xen/xen_igd.h33
-rw-r--r--include/hw/xen/xen_native.h (renamed from include/hw/xen/xen_common.h)220
-rw-r--r--include/hw/xen/xen_pvdev.h8
738 files changed, 39989 insertions, 9268 deletions
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index 38a42f409a..0e6e82b339 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -41,38 +41,13 @@ enum {
};
typedef struct AcpiRsdpData {
- uint8_t oem_id[6] QEMU_NONSTRING; /* OEM identification */
+ char *oem_id; /* OEM identification */
uint8_t revision; /* Must be 0 for 1.0, 2 for 2.0 */
unsigned *rsdt_tbl_offset;
unsigned *xsdt_tbl_offset;
} AcpiRsdpData;
-/* Table structure from Linux kernel (the ACPI tables are under the
- BSD license) */
-
-
-#define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \
- uint32_t signature; /* ACPI signature (4 ASCII characters) */ \
- uint32_t length; /* Length of table, in bytes, including header */ \
- uint8_t revision; /* ACPI Specification minor version # */ \
- uint8_t checksum; /* To make sum of entire table == 0 */ \
- uint8_t oem_id[6] \
- QEMU_NONSTRING; /* OEM identification */ \
- uint8_t oem_table_id[8] \
- QEMU_NONSTRING; /* OEM table identification */ \
- uint32_t oem_revision; /* OEM revision number */ \
- uint8_t asl_compiler_id[4] \
- QEMU_NONSTRING; /* ASL compiler vendor ID */ \
- uint32_t asl_compiler_revision; /* ASL compiler revision number */
-
-
-/* ACPI common table header */
-struct AcpiTableHeader {
- ACPI_TABLE_HEADER_DEF
-} QEMU_PACKED;
-typedef struct AcpiTableHeader AcpiTableHeader;
-
struct AcpiGenericAddress {
uint8_t space_id; /* Address space where struct or register exists */
uint8_t bit_width; /* Size in bits of given register */
@@ -80,7 +55,7 @@ struct AcpiGenericAddress {
uint8_t access_width; /* ACPI 3.0: Minimum Access size (ACPI 3.0),
ACPI 2.0: Reserved, Table 5-1 */
uint64_t address; /* 64-bit address of struct or register */
-} QEMU_PACKED;
+};
typedef struct AcpiFadtData {
struct AcpiGenericAddress pm1a_cnt; /* PM1a_CNT_BLK */
@@ -102,6 +77,7 @@ typedef struct AcpiFadtData {
uint16_t plvl2_lat; /* P_LVL2_LAT */
uint16_t plvl3_lat; /* P_LVL3_LAT */
uint16_t arm_boot_arch; /* ARM_BOOT_ARCH */
+ uint16_t iapc_boot_arch; /* IAPC_BOOT_ARCH */
uint8_t minor_ver; /* FADT Minor Version */
/*
@@ -114,508 +90,40 @@ typedef struct AcpiFadtData {
unsigned *xdsdt_tbl_offset;
} AcpiFadtData;
-#define ACPI_FADT_ARM_PSCI_COMPLIANT (1 << 0)
-#define ACPI_FADT_ARM_PSCI_USE_HVC (1 << 1)
-
-/*
- * Serial Port Console Redirection Table (SPCR), Rev. 1.02
- *
- * For .interface_type see Debug Port Table 2 (DBG2) serial port
- * subtypes in Table 3, Rev. May 22, 2012
- */
-struct AcpiSerialPortConsoleRedirection {
- ACPI_TABLE_HEADER_DEF
- uint8_t interface_type;
- uint8_t reserved1[3];
- struct AcpiGenericAddress base_address;
- uint8_t interrupt_types;
- uint8_t irq;
- uint32_t gsi;
- uint8_t baud;
- uint8_t parity;
- uint8_t stopbits;
- uint8_t flowctrl;
- uint8_t term_type;
- uint8_t reserved2;
- uint16_t pci_device_id;
- uint16_t pci_vendor_id;
- uint8_t pci_bus;
- uint8_t pci_slot;
- uint8_t pci_func;
+typedef struct AcpiGas {
+ uint8_t id; /* Address space ID */
+ uint8_t width; /* Register bit width */
+ uint8_t offset; /* Register bit offset */
+ uint8_t size; /* Access size */
+ uint64_t addr; /* Address */
+} AcpiGas;
+
+/* SPCR (Serial Port Console Redirection table) */
+typedef struct AcpiSpcrData {
+ uint8_t interface_type;
+ uint8_t reserved[3];
+ struct AcpiGas base_addr;
+ uint8_t interrupt_type;
+ uint8_t pc_interrupt;
+ uint32_t interrupt; /* Global system interrupt */
+ uint8_t baud_rate;
+ uint8_t parity;
+ uint8_t stop_bits;
+ uint8_t flow_control;
+ uint8_t terminal_type;
+ uint8_t language;
+ uint8_t reserved1;
+ uint16_t pci_device_id; /* Must be 0xffff if not PCI device */
+ uint16_t pci_vendor_id; /* Must be 0xffff if not PCI device */
+ uint8_t pci_bus;
+ uint8_t pci_device;
+ uint8_t pci_function;
uint32_t pci_flags;
- uint8_t pci_seg;
- uint32_t reserved3;
-} QEMU_PACKED;
-typedef struct AcpiSerialPortConsoleRedirection
- AcpiSerialPortConsoleRedirection;
-
-/*
- * ACPI 1.0 Root System Description Table (RSDT)
- */
-struct AcpiRsdtDescriptorRev1 {
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- uint32_t table_offset_entry[]; /* Array of pointers to other */
- /* ACPI tables */
-} QEMU_PACKED;
-typedef struct AcpiRsdtDescriptorRev1 AcpiRsdtDescriptorRev1;
-
-/*
- * ACPI 2.0 eXtended System Description Table (XSDT)
- */
-struct AcpiXsdtDescriptorRev2 {
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- uint64_t table_offset_entry[]; /* Array of pointers to other */
- /* ACPI tables */
-} QEMU_PACKED;
-typedef struct AcpiXsdtDescriptorRev2 AcpiXsdtDescriptorRev2;
-
-/*
- * ACPI 1.0 Firmware ACPI Control Structure (FACS)
- */
-struct AcpiFacsDescriptorRev1 {
- uint32_t signature; /* ACPI Signature */
- uint32_t length; /* Length of structure, in bytes */
- uint32_t hardware_signature; /* Hardware configuration signature */
- uint32_t firmware_waking_vector; /* ACPI OS waking vector */
- uint32_t global_lock; /* Global Lock */
- uint32_t flags;
- uint8_t resverved3 [40]; /* Reserved - must be zero */
-} QEMU_PACKED;
-typedef struct AcpiFacsDescriptorRev1 AcpiFacsDescriptorRev1;
-
-/*
- * Differentiated System Description Table (DSDT)
- */
-
-/*
- * MADT values and structures
- */
-
-/* Values for MADT PCATCompat */
-
-#define ACPI_DUAL_PIC 0
-#define ACPI_MULTIPLE_APIC 1
-
-/* Master MADT */
-
-struct AcpiMultipleApicTable {
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- uint32_t local_apic_address; /* Physical address of local APIC */
- uint32_t flags;
-} QEMU_PACKED;
-typedef struct AcpiMultipleApicTable AcpiMultipleApicTable;
-
-/* Values for Type in APIC sub-headers */
-
-#define ACPI_APIC_PROCESSOR 0
-#define ACPI_APIC_IO 1
-#define ACPI_APIC_XRUPT_OVERRIDE 2
-#define ACPI_APIC_NMI 3
-#define ACPI_APIC_LOCAL_NMI 4
-#define ACPI_APIC_ADDRESS_OVERRIDE 5
-#define ACPI_APIC_IO_SAPIC 6
-#define ACPI_APIC_LOCAL_SAPIC 7
-#define ACPI_APIC_XRUPT_SOURCE 8
-#define ACPI_APIC_LOCAL_X2APIC 9
-#define ACPI_APIC_LOCAL_X2APIC_NMI 10
-#define ACPI_APIC_GENERIC_CPU_INTERFACE 11
-#define ACPI_APIC_GENERIC_DISTRIBUTOR 12
-#define ACPI_APIC_GENERIC_MSI_FRAME 13
-#define ACPI_APIC_GENERIC_REDISTRIBUTOR 14
-#define ACPI_APIC_GENERIC_TRANSLATOR 15
-#define ACPI_APIC_RESERVED 16 /* 16 and greater are reserved */
-
-/*
- * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
- */
-#define ACPI_SUB_HEADER_DEF /* Common ACPI sub-structure header */\
- uint8_t type; \
- uint8_t length;
-
-/* Sub-structures for MADT */
-
-struct AcpiMadtProcessorApic {
- ACPI_SUB_HEADER_DEF
- uint8_t processor_id; /* ACPI processor id */
- uint8_t local_apic_id; /* Processor's local APIC id */
- uint32_t flags;
-} QEMU_PACKED;
-typedef struct AcpiMadtProcessorApic AcpiMadtProcessorApic;
-
-struct AcpiMadtIoApic {
- ACPI_SUB_HEADER_DEF
- uint8_t io_apic_id; /* I/O APIC ID */
- uint8_t reserved; /* Reserved - must be zero */
- uint32_t address; /* APIC physical address */
- uint32_t interrupt; /* Global system interrupt where INTI
- * lines start */
-} QEMU_PACKED;
-typedef struct AcpiMadtIoApic AcpiMadtIoApic;
-
-struct AcpiMadtIntsrcovr {
- ACPI_SUB_HEADER_DEF
- uint8_t bus;
- uint8_t source;
- uint32_t gsi;
- uint16_t flags;
-} QEMU_PACKED;
-typedef struct AcpiMadtIntsrcovr AcpiMadtIntsrcovr;
-
-struct AcpiMadtLocalNmi {
- ACPI_SUB_HEADER_DEF
- uint8_t processor_id; /* ACPI processor id */
- uint16_t flags; /* MPS INTI flags */
- uint8_t lint; /* Local APIC LINT# */
-} QEMU_PACKED;
-typedef struct AcpiMadtLocalNmi AcpiMadtLocalNmi;
-
-struct AcpiMadtProcessorX2Apic {
- ACPI_SUB_HEADER_DEF
- uint16_t reserved;
- uint32_t x2apic_id; /* Processor's local x2APIC ID */
- uint32_t flags;
- uint32_t uid; /* Processor object _UID */
-} QEMU_PACKED;
-typedef struct AcpiMadtProcessorX2Apic AcpiMadtProcessorX2Apic;
-
-struct AcpiMadtLocalX2ApicNmi {
- ACPI_SUB_HEADER_DEF
- uint16_t flags; /* MPS INTI flags */
- uint32_t uid; /* Processor object _UID */
- uint8_t lint; /* Local APIC LINT# */
- uint8_t reserved[3]; /* Local APIC LINT# */
-} QEMU_PACKED;
-typedef struct AcpiMadtLocalX2ApicNmi AcpiMadtLocalX2ApicNmi;
-
-struct AcpiMadtGenericCpuInterface {
- ACPI_SUB_HEADER_DEF
- uint16_t reserved;
- uint32_t cpu_interface_number;
- uint32_t uid;
- uint32_t flags;
- uint32_t parking_version;
- uint32_t performance_interrupt;
- uint64_t parked_address;
- uint64_t base_address;
- uint64_t gicv_base_address;
- uint64_t gich_base_address;
- uint32_t vgic_interrupt;
- uint64_t gicr_base_address;
- uint64_t arm_mpidr;
-} QEMU_PACKED;
-
-typedef struct AcpiMadtGenericCpuInterface AcpiMadtGenericCpuInterface;
-
-/* GICC CPU Interface Flags */
-#define ACPI_MADT_GICC_ENABLED 1
-
-struct AcpiMadtGenericDistributor {
- ACPI_SUB_HEADER_DEF
- uint16_t reserved;
- uint32_t gic_id;
- uint64_t base_address;
- uint32_t global_irq_base;
- /* ACPI 5.1 Errata 1228 Present GIC version in MADT table */
- uint8_t version;
- uint8_t reserved2[3];
-} QEMU_PACKED;
-
-typedef struct AcpiMadtGenericDistributor AcpiMadtGenericDistributor;
-
-struct AcpiMadtGenericMsiFrame {
- ACPI_SUB_HEADER_DEF
- uint16_t reserved;
- uint32_t gic_msi_frame_id;
- uint64_t base_address;
- uint32_t flags;
- uint16_t spi_count;
- uint16_t spi_base;
-} QEMU_PACKED;
-
-typedef struct AcpiMadtGenericMsiFrame AcpiMadtGenericMsiFrame;
-
-struct AcpiMadtGenericRedistributor {
- ACPI_SUB_HEADER_DEF
- uint16_t reserved;
- uint64_t base_address;
- uint32_t range_length;
-} QEMU_PACKED;
-
-typedef struct AcpiMadtGenericRedistributor AcpiMadtGenericRedistributor;
-
-struct AcpiMadtGenericTranslator {
- ACPI_SUB_HEADER_DEF
- uint16_t reserved;
- uint32_t translation_id;
- uint64_t base_address;
+ uint8_t pci_segment;
uint32_t reserved2;
-} QEMU_PACKED;
+} AcpiSpcrData;
-typedef struct AcpiMadtGenericTranslator AcpiMadtGenericTranslator;
-
-/*
- * Generic Timer Description Table (GTDT)
- */
-#define ACPI_GTDT_INTERRUPT_MODE_LEVEL (0 << 0)
-#define ACPI_GTDT_INTERRUPT_MODE_EDGE (1 << 0)
-#define ACPI_GTDT_CAP_ALWAYS_ON (1 << 2)
-
-struct AcpiGenericTimerTable {
- ACPI_TABLE_HEADER_DEF
- uint64_t counter_block_addresss;
- uint32_t reserved;
- uint32_t secure_el1_interrupt;
- uint32_t secure_el1_flags;
- uint32_t non_secure_el1_interrupt;
- uint32_t non_secure_el1_flags;
- uint32_t virtual_timer_interrupt;
- uint32_t virtual_timer_flags;
- uint32_t non_secure_el2_interrupt;
- uint32_t non_secure_el2_flags;
- uint64_t counter_read_block_address;
- uint32_t platform_timer_count;
- uint32_t platform_timer_offset;
-} QEMU_PACKED;
-typedef struct AcpiGenericTimerTable AcpiGenericTimerTable;
-
-/*
- * HPET Description Table
- */
-struct Acpi20Hpet {
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- uint32_t timer_block_id;
- struct AcpiGenericAddress addr;
- uint8_t hpet_number;
- uint16_t min_tick;
- uint8_t page_protect;
-} QEMU_PACKED;
-typedef struct Acpi20Hpet Acpi20Hpet;
-
-/*
- * SRAT (NUMA topology description) table
- */
-
-struct AcpiSystemResourceAffinityTable {
- ACPI_TABLE_HEADER_DEF
- uint32_t reserved1;
- uint32_t reserved2[2];
-} QEMU_PACKED;
-typedef struct AcpiSystemResourceAffinityTable AcpiSystemResourceAffinityTable;
-
-#define ACPI_SRAT_PROCESSOR_APIC 0
-#define ACPI_SRAT_MEMORY 1
-#define ACPI_SRAT_PROCESSOR_x2APIC 2
-#define ACPI_SRAT_PROCESSOR_GICC 3
-
-struct AcpiSratProcessorAffinity {
- ACPI_SUB_HEADER_DEF
- uint8_t proximity_lo;
- uint8_t local_apic_id;
- uint32_t flags;
- uint8_t local_sapic_eid;
- uint8_t proximity_hi[3];
- uint32_t reserved;
-} QEMU_PACKED;
-typedef struct AcpiSratProcessorAffinity AcpiSratProcessorAffinity;
-
-struct AcpiSratProcessorX2ApicAffinity {
- ACPI_SUB_HEADER_DEF
- uint16_t reserved;
- uint32_t proximity_domain;
- uint32_t x2apic_id;
- uint32_t flags;
- uint32_t clk_domain;
- uint32_t reserved2;
-} QEMU_PACKED;
-typedef struct AcpiSratProcessorX2ApicAffinity AcpiSratProcessorX2ApicAffinity;
-
-struct AcpiSratMemoryAffinity {
- ACPI_SUB_HEADER_DEF
- uint32_t proximity;
- uint16_t reserved1;
- uint64_t base_addr;
- uint64_t range_length;
- uint32_t reserved2;
- uint32_t flags;
- uint32_t reserved3[2];
-} QEMU_PACKED;
-typedef struct AcpiSratMemoryAffinity AcpiSratMemoryAffinity;
-
-struct AcpiSratProcessorGiccAffinity {
- ACPI_SUB_HEADER_DEF
- uint32_t proximity;
- uint32_t acpi_processor_uid;
- uint32_t flags;
- uint32_t clock_domain;
-} QEMU_PACKED;
-
-typedef struct AcpiSratProcessorGiccAffinity AcpiSratProcessorGiccAffinity;
-
-/*
- * TCPA Description Table
- *
- * Following Level 00, Rev 00.37 of specs:
- * http://www.trustedcomputinggroup.org/resources/tcg_acpi_specification
- */
-struct Acpi20Tcpa {
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- uint16_t platform_class;
- uint32_t log_area_minimum_length;
- uint64_t log_area_start_address;
-} QEMU_PACKED;
-typedef struct Acpi20Tcpa Acpi20Tcpa;
-
-/* DMAR - DMA Remapping table r2.2 */
-struct AcpiTableDmar {
- ACPI_TABLE_HEADER_DEF
- uint8_t host_address_width; /* Maximum DMA physical addressability */
- uint8_t flags;
- uint8_t reserved[10];
-} QEMU_PACKED;
-typedef struct AcpiTableDmar AcpiTableDmar;
-
-/* Masks for Flags field above */
-#define ACPI_DMAR_INTR_REMAP 1
-#define ACPI_DMAR_X2APIC_OPT_OUT (1 << 1)
-
-/* Values for sub-structure type for DMAR */
-enum {
- ACPI_DMAR_TYPE_HARDWARE_UNIT = 0, /* DRHD */
- ACPI_DMAR_TYPE_RESERVED_MEMORY = 1, /* RMRR */
- ACPI_DMAR_TYPE_ATSR = 2, /* ATSR */
- ACPI_DMAR_TYPE_HARDWARE_AFFINITY = 3, /* RHSR */
- ACPI_DMAR_TYPE_ANDD = 4, /* ANDD */
- ACPI_DMAR_TYPE_RESERVED = 5 /* Reserved for furture use */
-};
-
-/*
- * Sub-structures for DMAR
- */
-
-/* Device scope structure for DRHD. */
-struct AcpiDmarDeviceScope {
- uint8_t entry_type;
- uint8_t length;
- uint16_t reserved;
- uint8_t enumeration_id;
- uint8_t bus;
- struct {
- uint8_t device;
- uint8_t function;
- } path[];
-} QEMU_PACKED;
-typedef struct AcpiDmarDeviceScope AcpiDmarDeviceScope;
-
-/* Type 0: Hardware Unit Definition */
-struct AcpiDmarHardwareUnit {
- uint16_t type;
- uint16_t length;
- uint8_t flags;
- uint8_t reserved;
- uint16_t pci_segment; /* The PCI Segment associated with this unit */
- uint64_t address; /* Base address of remapping hardware register-set */
- AcpiDmarDeviceScope scope[];
-} QEMU_PACKED;
-typedef struct AcpiDmarHardwareUnit AcpiDmarHardwareUnit;
-
-/* Type 2: Root Port ATS Capability Reporting Structure */
-struct AcpiDmarRootPortATS {
- uint16_t type;
- uint16_t length;
- uint8_t flags;
- uint8_t reserved;
- uint16_t pci_segment;
- AcpiDmarDeviceScope scope[];
-} QEMU_PACKED;
-typedef struct AcpiDmarRootPortATS AcpiDmarRootPortATS;
-
-/* Masks for Flags field above */
-#define ACPI_DMAR_INCLUDE_PCI_ALL 1
-#define ACPI_DMAR_ATSR_ALL_PORTS 1
-
-/*
- * Input Output Remapping Table (IORT)
- * Conforms to "IO Remapping Table System Software on ARM Platforms",
- * Document number: ARM DEN 0049B, October 2015
- */
-
-struct AcpiIortTable {
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- uint32_t node_count;
- uint32_t node_offset;
- uint32_t reserved;
-} QEMU_PACKED;
-typedef struct AcpiIortTable AcpiIortTable;
-
-/*
- * IORT node types
- */
-
-#define ACPI_IORT_NODE_HEADER_DEF /* Node format common fields */ \
- uint8_t type; \
- uint16_t length; \
- uint8_t revision; \
- uint32_t reserved; \
- uint32_t mapping_count; \
- uint32_t mapping_offset;
-
-/* Values for node Type above */
-enum {
- ACPI_IORT_NODE_ITS_GROUP = 0x00,
- ACPI_IORT_NODE_NAMED_COMPONENT = 0x01,
- ACPI_IORT_NODE_PCI_ROOT_COMPLEX = 0x02,
- ACPI_IORT_NODE_SMMU = 0x03,
- ACPI_IORT_NODE_SMMU_V3 = 0x04
-};
-
-struct AcpiIortIdMapping {
- uint32_t input_base;
- uint32_t id_count;
- uint32_t output_base;
- uint32_t output_reference;
- uint32_t flags;
-} QEMU_PACKED;
-typedef struct AcpiIortIdMapping AcpiIortIdMapping;
-
-struct AcpiIortMemoryAccess {
- uint32_t cache_coherency;
- uint8_t hints;
- uint16_t reserved;
- uint8_t memory_flags;
-} QEMU_PACKED;
-typedef struct AcpiIortMemoryAccess AcpiIortMemoryAccess;
-
-struct AcpiIortItsGroup {
- ACPI_IORT_NODE_HEADER_DEF
- uint32_t its_count;
- uint32_t identifiers[];
-} QEMU_PACKED;
-typedef struct AcpiIortItsGroup AcpiIortItsGroup;
-
-#define ACPI_IORT_SMMU_V3_COHACC_OVERRIDE 1
-
-struct AcpiIortSmmu3 {
- ACPI_IORT_NODE_HEADER_DEF
- uint64_t base_address;
- uint32_t flags;
- uint32_t reserved2;
- uint64_t vatos_address;
- uint32_t model;
- uint32_t event_gsiv;
- uint32_t pri_gsiv;
- uint32_t gerr_gsiv;
- uint32_t sync_gsiv;
- AcpiIortIdMapping id_mapping_array[];
-} QEMU_PACKED;
-typedef struct AcpiIortSmmu3 AcpiIortSmmu3;
-
-struct AcpiIortRC {
- ACPI_IORT_NODE_HEADER_DEF
- AcpiIortMemoryAccess memory_properties;
- uint32_t ats_attribute;
- uint32_t pci_segment_number;
- AcpiIortIdMapping id_mapping_array[];
-} QEMU_PACKED;
-typedef struct AcpiIortRC AcpiIortRC;
+#define ACPI_FADT_ARM_PSCI_COMPLIANT (1 << 0)
+#define ACPI_FADT_ARM_PSCI_USE_HVC (1 << 1)
#endif
diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h
index 4bef575312..e0e51e85b4 100644
--- a/include/hw/acpi/acpi.h
+++ b/include/hw/acpi/acpi.h
@@ -8,7 +8,7 @@
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -47,6 +47,8 @@
#define ACPI_PM_PROP_PM_IO_BASE "pm_io_base"
#define ACPI_PM_PROP_GPE0_BLK "gpe0_blk"
#define ACPI_PM_PROP_GPE0_BLK_LEN "gpe0_blk_len"
+#define ACPI_PM_PROP_ACPI_PCIHP_BRIDGE "acpi-pci-hotplug-with-bridge-support"
+#define ACPI_PM_PROP_ACPI_PCI_ROOTHP "acpi-root-pci-hotplug"
/* PM Timer ticks per second (HZ) */
#define PM_TIMER_FREQUENCY 3579545
@@ -64,7 +66,7 @@
#define ACPI_BITMASK_POWER_BUTTON_STATUS 0x0100
#define ACPI_BITMASK_SLEEP_BUTTON_STATUS 0x0200
#define ACPI_BITMASK_RT_CLOCK_STATUS 0x0400
-#define ACPI_BITMASK_PCIEXP_WAKE_STATUS 0x4000 /* ACPI 3.0 */
+#define ACPI_BITMASK_PCIEXP_WAKE_STATUS 0x4000 /* ACPI 3.0 */
#define ACPI_BITMASK_WAKE_STATUS 0x8000
#define ACPI_BITMASK_ALL_FIXED_STATUS (\
@@ -82,7 +84,7 @@
#define ACPI_BITMASK_POWER_BUTTON_ENABLE 0x0100
#define ACPI_BITMASK_SLEEP_BUTTON_ENABLE 0x0200
#define ACPI_BITMASK_RT_CLOCK_ENABLE 0x0400
-#define ACPI_BITMASK_PCIEXP_WAKE_DISABLE 0x4000 /* ACPI 3.0 */
+#define ACPI_BITMASK_PCIEXP_WAKE_DISABLE 0x4000 /* ACPI 3.0 */
#define ACPI_BITMASK_PM1_COMMON_ENABLED ( \
ACPI_BITMASK_RT_CLOCK_ENABLE | \
@@ -128,6 +130,7 @@ struct ACPIPM1CNT {
MemoryRegion io;
uint16_t cnt;
uint8_t s4_val;
+ bool acpi_only;
};
struct ACPIGPE {
@@ -163,7 +166,8 @@ void acpi_pm1_evt_init(ACPIREGS *ar, acpi_update_sci_fn update_sci,
/* PM1a_CNT: piix and ich9 don't implement PM1b CNT. */
void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent,
- bool disable_s3, bool disable_s4, uint8_t s4_val);
+ bool disable_s3, bool disable_s4, uint8_t s4_val,
+ bool acpi_only);
void acpi_pm1_cnt_update(ACPIREGS *ar,
bool sci_enable, bool sci_disable);
void acpi_pm1_cnt_reset(ACPIREGS *ar);
diff --git a/include/hw/acpi/acpi_aml_interface.h b/include/hw/acpi/acpi_aml_interface.h
new file mode 100644
index 0000000000..11748a8866
--- /dev/null
+++ b/include/hw/acpi/acpi_aml_interface.h
@@ -0,0 +1,52 @@
+#ifndef ACPI_AML_INTERFACE_H
+#define ACPI_AML_INTERFACE_H
+
+#include "qom/object.h"
+#include "hw/acpi/aml-build.h"
+#include "hw/qdev-core.h"
+
+#define TYPE_ACPI_DEV_AML_IF "acpi-dev-aml-interface"
+typedef struct AcpiDevAmlIfClass AcpiDevAmlIfClass;
+DECLARE_CLASS_CHECKERS(AcpiDevAmlIfClass, ACPI_DEV_AML_IF, TYPE_ACPI_DEV_AML_IF)
+#define ACPI_DEV_AML_IF(obj) \
+ INTERFACE_CHECK(AcpiDevAmlIf, (obj), TYPE_ACPI_DEV_AML_IF)
+
+typedef struct AcpiDevAmlIf AcpiDevAmlIf;
+typedef void (*dev_aml_fn)(AcpiDevAmlIf *adev, Aml *scope);
+
+/**
+ * AcpiDevAmlIfClass:
+ *
+ * build_dev_aml: adds device specific AML blob to provided scope
+ *
+ * Interface is designed for providing generic callback that builds device
+ * specific AML blob.
+ */
+struct AcpiDevAmlIfClass {
+ /* <private> */
+ InterfaceClass parent_class;
+
+ /* <public> */
+ dev_aml_fn build_dev_aml;
+};
+
+static inline dev_aml_fn get_dev_aml_func(DeviceState *dev)
+{
+ if (object_dynamic_cast(OBJECT(dev), TYPE_ACPI_DEV_AML_IF)) {
+ AcpiDevAmlIfClass *klass = ACPI_DEV_AML_IF_GET_CLASS(dev);
+ return klass->build_dev_aml;
+ }
+ return NULL;
+}
+
+static inline void call_dev_aml_func(DeviceState *dev, Aml *scope)
+{
+ dev_aml_fn fn = get_dev_aml_func(dev);
+ if (fn) {
+ fn(ACPI_DEV_AML_IF(dev), scope);
+ }
+}
+
+void qbus_build_aml(BusState *bus, Aml *scope);
+
+#endif
diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h
index a2a12af9b9..68d9d15f50 100644
--- a/include/hw/acpi/acpi_dev_interface.h
+++ b/include/hw/acpi/acpi_dev_interface.h
@@ -1,9 +1,8 @@
#ifndef ACPI_DEV_INTERFACE_H
#define ACPI_DEV_INTERFACE_H
-#include "qapi/qapi-types-misc.h"
+#include "qapi/qapi-types-acpi.h"
#include "qom/object.h"
-#include "hw/boards.h"
#include "hw/qdev-core.h"
/* These values are part of guest ABI, and can not be changed */
@@ -18,12 +17,9 @@ typedef enum {
#define TYPE_ACPI_DEVICE_IF "acpi-device-interface"
-#define ACPI_DEVICE_IF_CLASS(klass) \
- OBJECT_CLASS_CHECK(AcpiDeviceIfClass, (klass), \
- TYPE_ACPI_DEVICE_IF)
-#define ACPI_DEVICE_IF_GET_CLASS(obj) \
- OBJECT_GET_CLASS(AcpiDeviceIfClass, (obj), \
- TYPE_ACPI_DEVICE_IF)
+typedef struct AcpiDeviceIfClass AcpiDeviceIfClass;
+DECLARE_CLASS_CHECKERS(AcpiDeviceIfClass, ACPI_DEVICE_IF,
+ TYPE_ACPI_DEVICE_IF)
#define ACPI_DEVICE_IF(obj) \
INTERFACE_CHECK(AcpiDeviceIf, (obj), \
TYPE_ACPI_DEVICE_IF)
@@ -48,14 +44,12 @@ void acpi_send_event(DeviceState *dev, AcpiEventStatusBits event);
* knowledge about internals of actual device that implements
* ACPI interface.
*/
-typedef struct AcpiDeviceIfClass {
+struct AcpiDeviceIfClass {
/* <private> */
InterfaceClass parent_class;
/* <public> */
void (*ospm_status)(AcpiDeviceIf *adev, ACPIOSTInfoList ***list);
void (*send_event)(AcpiDeviceIf *adev, AcpiEventStatusBits ev);
- void (*madt_cpu)(AcpiDeviceIf *adev, int uid,
- const CPUArchIdList *apic_ids, GArray *entry);
-} AcpiDeviceIfClass;
+};
#endif
diff --git a/include/hw/acpi/acpi_generic_initiator.h b/include/hw/acpi/acpi_generic_initiator.h
new file mode 100644
index 0000000000..a304bad73e
--- /dev/null
+++ b/include/hw/acpi/acpi_generic_initiator.h
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved
+ */
+
+#ifndef ACPI_GENERIC_INITIATOR_H
+#define ACPI_GENERIC_INITIATOR_H
+
+#include "qom/object_interfaces.h"
+
+#define TYPE_ACPI_GENERIC_INITIATOR "acpi-generic-initiator"
+
+typedef struct AcpiGenericInitiator {
+ /* private */
+ Object parent;
+
+ /* public */
+ char *pci_dev;
+ uint16_t node;
+} AcpiGenericInitiator;
+
+/*
+ * ACPI 6.3:
+ * Table 5-81 Flags – Generic Initiator Affinity Structure
+ */
+typedef enum {
+ /*
+ * If clear, the OSPM ignores the contents of the Generic
+ * Initiator/Port Affinity Structure. This allows system firmware
+ * to populate the SRAT with a static number of structures, but only
+ * enable them as necessary.
+ */
+ GEN_AFFINITY_ENABLED = (1 << 0),
+} GenericAffinityFlags;
+
+/*
+ * ACPI 6.3:
+ * Table 5-80 Device Handle - PCI
+ */
+typedef struct PCIDeviceHandle {
+ uint16_t segment;
+ uint16_t bdf;
+} PCIDeviceHandle;
+
+void build_srat_generic_pci_initiator(GArray *table_data);
+
+#endif
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index d27da03d64..a3784155cb 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -4,11 +4,8 @@
#include "hw/acpi/acpi-defs.h"
#include "hw/acpi/bios-linker-loader.h"
-/* Reserve RAM space for tables: add another order of magnitude. */
-#define ACPI_BUILD_TABLE_MAX_SIZE 0x200000
-
#define ACPI_BUILD_APPNAME6 "BOCHS "
-#define ACPI_BUILD_APPNAME4 "BXPC"
+#define ACPI_BUILD_APPNAME8 "BXPC "
#define ACPI_BUILD_TABLE_FILE "etc/acpi/tables"
#define ACPI_BUILD_RSDP_FILE "etc/acpi/rsdp"
@@ -224,6 +221,20 @@ struct AcpiBuildTables {
BIOSLinker *linker;
} AcpiBuildTables;
+typedef
+struct CrsRangeEntry {
+ uint64_t base;
+ uint64_t limit;
+} CrsRangeEntry;
+
+typedef
+struct CrsRangeSet {
+ GPtrArray *io_ranges;
+ GPtrArray *mem_ranges;
+ GPtrArray *mem_64bit_ranges;
+} CrsRangeSet;
+
+
/*
* ACPI 5.0: 6.4.3.8.2 Serial Bus Connection Descriptors
* Serial Bus Type
@@ -266,7 +277,7 @@ void free_aml_allocator(void);
* @child: element that is copied into @parent_ctx context
*
* Joins Aml elements together and helps to construct AML tables
- * Examle of usage:
+ * Example of usage:
* Aml *table = aml_def_block("SSDT", ...);
* Aml *sb = aml_scope("\\_SB");
* Aml *dev = aml_device("PCI0");
@@ -278,7 +289,7 @@ void free_aml_allocator(void);
void aml_append(Aml *parent_ctx, Aml *child);
/* non block AML object primitives */
-Aml *aml_name(const char *name_format, ...) GCC_FMT_ATTR(1, 2);
+Aml *aml_name(const char *name_format, ...) G_GNUC_PRINTF(1, 2);
Aml *aml_name_decl(const char *name, Aml *val);
Aml *aml_debug(void);
Aml *aml_return(Aml *val);
@@ -287,9 +298,11 @@ Aml *aml_arg(int pos);
Aml *aml_to_integer(Aml *arg);
Aml *aml_to_hexstring(Aml *src, Aml *dst);
Aml *aml_to_buffer(Aml *src, Aml *dst);
+Aml *aml_to_decimalstring(Aml *src, Aml *dst);
Aml *aml_store(Aml *val, Aml *target);
Aml *aml_and(Aml *arg1, Aml *arg2, Aml *dst);
Aml *aml_or(Aml *arg1, Aml *arg2, Aml *dst);
+Aml *aml_land(Aml *arg1, Aml *arg2);
Aml *aml_lor(Aml *arg1, Aml *arg2);
Aml *aml_shiftleft(Aml *arg1, Aml *count);
Aml *aml_shiftright(Aml *arg1, Aml *count, Aml *dst);
@@ -300,6 +313,7 @@ Aml *aml_increment(Aml *arg);
Aml *aml_decrement(Aml *arg);
Aml *aml_index(Aml *arg1, Aml *idx);
Aml *aml_notify(Aml *arg1, Aml *arg2);
+Aml *aml_break(void);
Aml *aml_call0(const char *method);
Aml *aml_call1(const char *method, Aml *arg1);
Aml *aml_call2(const char *method, Aml *arg1, Aml *arg2);
@@ -307,6 +321,8 @@ Aml *aml_call3(const char *method, Aml *arg1, Aml *arg2, Aml *arg3);
Aml *aml_call4(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4);
Aml *aml_call5(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4,
Aml *arg5);
+Aml *aml_call6(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4,
+ Aml *arg5, Aml *arg6);
Aml *aml_gpio_int(AmlConsumerAndProducer con_and_pro,
AmlLevelAndEdge edge_level,
AmlActiveHighAndLow active_level, AmlShared shared,
@@ -328,13 +344,13 @@ Aml *aml_irq_no_flags(uint8_t irq);
Aml *aml_named_field(const char *name, unsigned length);
Aml *aml_reserved_field(unsigned length);
Aml *aml_local(int num);
-Aml *aml_string(const char *name_format, ...) GCC_FMT_ATTR(1, 2);
+Aml *aml_string(const char *name_format, ...) G_GNUC_PRINTF(1, 2);
Aml *aml_lnot(Aml *arg);
Aml *aml_equal(Aml *arg1, Aml *arg2);
Aml *aml_lgreater(Aml *arg1, Aml *arg2);
Aml *aml_lgreater_equal(Aml *arg1, Aml *arg2);
Aml *aml_processor(uint8_t proc_id, uint32_t pblk_addr, uint8_t pblk_len,
- const char *name_format, ...) GCC_FMT_ATTR(4, 5);
+ const char *name_format, ...) G_GNUC_PRINTF(4, 5);
Aml *aml_eisaid(const char *str);
Aml *aml_word_bus_number(AmlMinFixed min_fixed, AmlMaxFixed max_fixed,
AmlDecode dec, uint16_t addr_gran,
@@ -368,8 +384,8 @@ Aml *aml_sleep(uint64_t msec);
Aml *aml_i2c_serial_bus_device(uint16_t address, const char *resource_source);
/* Block AML object primitives */
-Aml *aml_scope(const char *name_format, ...) GCC_FMT_ATTR(1, 2);
-Aml *aml_device(const char *name_format, ...) GCC_FMT_ATTR(1, 2);
+Aml *aml_scope(const char *name_format, ...) G_GNUC_PRINTF(1, 2);
+Aml *aml_device(const char *name_format, ...) G_GNUC_PRINTF(1, 2);
Aml *aml_method(const char *name, int arg_count, AmlSerializeFlag sflag);
Aml *aml_if(Aml *predicate);
Aml *aml_else(void);
@@ -397,10 +413,37 @@ Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target);
Aml *aml_object_type(Aml *object);
void build_append_int_noprefix(GArray *table, uint64_t value, int size);
-void
-build_header(BIOSLinker *linker, GArray *table_data,
- AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
- const char *oem_id, const char *oem_table_id);
+
+typedef struct AcpiTable {
+ const char *sig;
+ const uint8_t rev;
+ const char *oem_id;
+ const char *oem_table_id;
+ /* private vars tracking table state */
+ GArray *array;
+ unsigned table_offset;
+} AcpiTable;
+
+/**
+ * acpi_table_begin:
+ * initializes table header and keeps track of
+ * table data/offsets
+ * @desc: ACPI table descriptor
+ * @array: blob where the ACPI table will be composed/stored.
+ */
+void acpi_table_begin(AcpiTable *desc, GArray *array);
+
+/**
+ * acpi_table_end:
+ * sets actual table length and tells bios loader
+ * where table is for the later initialization on
+ * guest side.
+ * @linker: reference to BIOSLinker object to use for the table
+ * @table: ACPI table descriptor that was used with @acpi_table_begin
+ * counterpart
+ */
+void acpi_table_end(BIOSLinker *linker, AcpiTable *table);
+
void *acpi_data_push(GArray *table_data, unsigned size);
unsigned acpi_data_len(GArray *table);
void acpi_add_table(GArray *table_offsets, GArray *table_data);
@@ -417,7 +460,7 @@ build_xsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
int
build_append_named_dword(GArray *array, const char *name_format, ...)
-GCC_FMT_ATTR(2, 3);
+G_GNUC_PRINTF(2, 3);
void build_append_gas(GArray *table, AmlAddressSpace as,
uint8_t bit_width, uint8_t bit_offset,
@@ -430,13 +473,32 @@ build_append_gas_from_struct(GArray *table, const struct AcpiGenericAddress *s)
s->access_width, s->address);
}
-void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base,
+void crs_range_insert(GPtrArray *ranges, uint64_t base, uint64_t limit);
+void crs_replace_with_free_ranges(GPtrArray *ranges,
+ uint64_t start, uint64_t end);
+void crs_range_set_init(CrsRangeSet *range_set);
+void crs_range_set_free(CrsRangeSet *range_set);
+
+Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set, uint32_t io_offset,
+ uint32_t mmio32_offset, uint64_t mmio64_offset,
+ uint16_t bus_nr_offset);
+
+void build_srat_memory(GArray *table_data, uint64_t base,
uint64_t len, int node, MemoryAffinityFlags flags);
-void build_slit(GArray *table_data, BIOSLinker *linker, MachineState *ms);
+void build_slit(GArray *table_data, BIOSLinker *linker, MachineState *ms,
+ const char *oem_id, const char *oem_table_id);
+
+void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
+ const char *oem_id, const char *oem_table_id);
void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f,
const char *oem_id, const char *oem_table_id);
-void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog);
+void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
+ const char *oem_id, const char *oem_table_id);
+
+void build_spcr(GArray *table_data, BIOSLinker *linker,
+ const AcpiSpcrData *f, const uint8_t rev,
+ const char *oem_id, const char *oem_table_id);
#endif
diff --git a/include/hw/acpi/cpu.h b/include/hw/acpi/cpu.h
index 62f0278ba2..e6e1a9ef59 100644
--- a/include/hw/acpi/cpu.h
+++ b/include/hw/acpi/cpu.h
@@ -12,16 +12,19 @@
#ifndef ACPI_CPU_H
#define ACPI_CPU_H
+#include "qapi/qapi-types-acpi.h"
#include "hw/qdev-core.h"
#include "hw/acpi/acpi.h"
#include "hw/acpi/aml-build.h"
+#include "hw/boards.h"
#include "hw/hotplug.h"
typedef struct AcpiCpuStatus {
- struct CPUState *cpu;
+ CPUState *cpu;
uint64_t arch_id;
bool is_inserting;
bool is_removing;
+ bool fw_remove;
uint32_t ost_event;
uint32_t ost_status;
} AcpiCpuStatus;
@@ -50,10 +53,15 @@ void cpu_hotplug_hw_init(MemoryRegion *as, Object *owner,
typedef struct CPUHotplugFeatures {
bool acpi_1_compatible;
bool has_legacy_cphp;
+ bool fw_unplugs_cpu;
+ const char *smi_path;
} CPUHotplugFeatures;
+typedef void (*build_madt_cpu_fn)(int uid, const CPUArchIdList *apic_ids,
+ GArray *entry, bool force_enabled);
+
void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
- hwaddr io_base,
+ build_madt_cpu_fn build_madt_cpu, hwaddr io_base,
const char *res_root,
const char *event_handler_method);
diff --git a/include/hw/acpi/cxl.h b/include/hw/acpi/cxl.h
new file mode 100644
index 0000000000..8f22c71530
--- /dev/null
+++ b/include/hw/acpi/cxl.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2020 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_ACPI_CXL_H
+#define HW_ACPI_CXL_H
+
+#include "hw/acpi/bios-linker-loader.h"
+#include "hw/cxl/cxl.h"
+
+void cxl_build_cedt(GArray *table_offsets, GArray *table_data,
+ BIOSLinker *linker, const char *oem_id,
+ const char *oem_table_id, CXLState *cxl_state);
+void build_cxl_osc_method(Aml *dev);
+void build_cxl_dsm_method(Aml *dev);
+
+#endif
diff --git a/include/hw/acpi/erst.h b/include/hw/acpi/erst.h
new file mode 100644
index 0000000000..b2ff663ddc
--- /dev/null
+++ b/include/hw/acpi/erst.h
@@ -0,0 +1,27 @@
+/*
+ * ACPI Error Record Serialization Table, ERST, Implementation
+ *
+ * ACPI ERST introduced in ACPI 4.0, June 16, 2009.
+ * ACPI Platform Error Interfaces : Error Serialization
+ *
+ * Copyright (c) 2021 Oracle and/or its affiliates.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef HW_ACPI_ERST_H
+#define HW_ACPI_ERST_H
+
+#include "hw/acpi/bios-linker-loader.h"
+#include "qom/object.h"
+
+void build_erst(GArray *table_data, BIOSLinker *linker, Object *erst_dev,
+ const char *oem_id, const char *oem_table_id);
+
+#define TYPE_ACPI_ERST "acpi-erst"
+
+/* returns NULL unless there is exactly one device */
+static inline Object *find_erst_dev(void)
+{
+ return object_resolve_path_type("", TYPE_ACPI_ERST, NULL);
+}
+#endif
diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h
index 90a9180db5..ba84ce0214 100644
--- a/include/hw/acpi/generic_event_device.h
+++ b/include/hw/acpi/generic_event_device.h
@@ -56,22 +56,33 @@
*
*/
-#ifndef HW_ACPI_GED_H
-#define HW_ACPI_GED_H
+#ifndef HW_ACPI_GENERIC_EVENT_DEVICE_H
+#define HW_ACPI_GENERIC_EVENT_DEVICE_H
#include "hw/sysbus.h"
#include "hw/acpi/memory_hotplug.h"
#include "hw/acpi/ghes.h"
+#include "qom/object.h"
#define ACPI_POWER_BUTTON_DEVICE "PWRB"
#define TYPE_ACPI_GED "acpi-ged"
-#define ACPI_GED(obj) \
- OBJECT_CHECK(AcpiGedState, (obj), TYPE_ACPI_GED)
+OBJECT_DECLARE_SIMPLE_TYPE(AcpiGedState, ACPI_GED)
#define ACPI_GED_EVT_SEL_OFFSET 0x0
#define ACPI_GED_EVT_SEL_LEN 0x4
+#define ACPI_GED_REG_SLEEP_CTL 0x00
+#define ACPI_GED_REG_SLEEP_STS 0x01
+#define ACPI_GED_REG_RESET 0x02
+#define ACPI_GED_REG_COUNT 0x03
+
+/* ACPI_GED_REG_RESET value for reset*/
+#define ACPI_GED_RESET_VALUE 0x42
+
+/* ACPI_GED_REG_SLEEP_CTL.SLP_TYP value for S5 (aka poweroff) */
+#define ACPI_GED_SLP_TYP_S5 0x05
+
#define GED_DEVICE "GED"
#define AML_GED_EVT_REG "EREG"
#define AML_GED_EVT_SEL "ESEL"
@@ -87,10 +98,11 @@
typedef struct GEDState {
MemoryRegion evt;
+ MemoryRegion regs;
uint32_t sel;
} GEDState;
-typedef struct AcpiGedState {
+struct AcpiGedState {
SysBusDevice parent_obj;
MemHotplugState memhp_state;
MemoryRegion container_memhp;
@@ -98,9 +110,10 @@ typedef struct AcpiGedState {
uint32_t ged_event_bitmap;
qemu_irq irq;
AcpiGhesState ghes_state;
-} AcpiGedState;
+};
void build_ged_aml(Aml *table, const char* name, HotplugHandler *hotplug_dev,
uint32_t ged_irq, AmlRegionSpace rs, hwaddr ged_base);
+void acpi_dsdt_add_power_button(Aml *scope);
#endif
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
index 4ad025e09a..674f6958e9 100644
--- a/include/hw/acpi/ghes.h
+++ b/include/hw/acpi/ghes.h
@@ -64,11 +64,21 @@ enum {
typedef struct AcpiGhesState {
uint64_t ghes_addr_le;
+ bool present; /* True if GHES is present at all on this board */
} AcpiGhesState;
void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker);
-void acpi_build_hest(GArray *table_data, BIOSLinker *linker);
+void acpi_build_hest(GArray *table_data, BIOSLinker *linker,
+ const char *oem_id, const char *oem_table_id);
void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s,
GArray *hardware_errors);
int acpi_ghes_record_errors(uint8_t notify, uint64_t error_physical_addr);
+
+/**
+ * acpi_ghes_present: Report whether ACPI GHES table is present
+ *
+ * Returns: true if the system has an ACPI GHES table and it is
+ * safe to call acpi_ghes_record_errors() to record a memory error.
+ */
+bool acpi_ghes_present(void);
#endif
diff --git a/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h
index 28a53181cb..2faf7f0cae 100644
--- a/include/hw/acpi/ich9.h
+++ b/include/hw/acpi/ich9.h
@@ -7,7 +7,7 @@
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -24,9 +24,12 @@
#include "hw/acpi/acpi.h"
#include "hw/acpi/cpu_hotplug.h"
#include "hw/acpi/cpu.h"
+#include "hw/acpi/pcihp.h"
#include "hw/acpi/memory_hotplug.h"
#include "hw/acpi/acpi_dev_interface.h"
-#include "hw/acpi/tco.h"
+#include "hw/acpi/ich9_tco.h"
+
+#define ACPI_PCIHP_ADDR_ICH9 0x0cc0
typedef struct ICH9LPCPMRegs {
/*
@@ -53,21 +56,23 @@ typedef struct ICH9LPCPMRegs {
AcpiCpuHotplug gpe_cpu;
CPUHotplugState cpuhp_state;
+ bool keep_pci_slot_hpc;
+ bool use_acpi_hotplug_bridge;
+ AcpiPciHpState acpi_pci_hotplug;
MemHotplugState acpi_memory_hotplug;
uint8_t disable_s3;
uint8_t disable_s4;
uint8_t s4_val;
- uint8_t smm_enabled;
+ bool smm_enabled;
+ bool smm_compat;
bool enable_tco;
TCOIORegs tco_regs;
} ICH9LPCPMRegs;
#define ACPI_PM_PROP_TCO_ENABLED "enable_tco"
-void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
- bool smm_enabled,
- qemu_irq sci_irq);
+void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm, qemu_irq sci_irq);
void ich9_pm_iospace_update(ICH9LPCPMRegs *pm, uint32_t pm_io_base);
extern const VMStateDescription vmstate_ich9_pm;
@@ -82,6 +87,7 @@ void ich9_pm_device_unplug_request_cb(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp);
void ich9_pm_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp);
+bool ich9_pm_is_hotpluggable_bus(HotplugHandler *hotplug_dev, BusState *bus);
void ich9_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list);
#endif /* HW_ACPI_ICH9_H */
diff --git a/include/hw/acpi/tco.h b/include/hw/acpi/ich9_tco.h
index a1e0da8213..2562a7cf39 100644
--- a/include/hw/acpi/tco.h
+++ b/include/hw/acpi/ich9_tco.h
@@ -1,5 +1,5 @@
/*
- * QEMU ICH9 TCO emulation
+ * QEMU ICH9 TCO emulation (total cost of ownership)
*
* Copyright (c) 2015 Paulo Alcantara <pcacjr@zytor.com>
*
@@ -11,6 +11,7 @@
#define HW_ACPI_TCO_H
#include "exec/memory.h"
+#include "migration/vmstate.h"
/* As per ICH9 spec, the internal timer has an error of ~0.6s on every tick */
#define TCO_TICK_NSEC 600000000LL
diff --git a/include/hw/acpi/ipmi.h b/include/hw/acpi/ipmi.h
index c14ad682ac..6c8079c97a 100644
--- a/include/hw/acpi/ipmi.h
+++ b/include/hw/acpi/ipmi.h
@@ -9,13 +9,8 @@
#ifndef HW_ACPI_IPMI_H
#define HW_ACPI_IPMI_H
-#include "hw/acpi/aml-build.h"
+#include "hw/acpi/acpi_aml_interface.h"
-/*
- * Add ACPI IPMI entries for all registered IPMI devices whose parent
- * bus matches the given bus. The resource is the ACPI resource that
- * contains the IPMI device, this is required for the I2C CRS.
- */
-void build_acpi_ipmi_devices(Aml *table, BusState *bus, const char *resource);
+void build_ipmi_dev_aml(AcpiDevAmlIf *adev, Aml *scope);
#endif /* HW_ACPI_IPMI_H */
diff --git a/include/hw/acpi/memory_hotplug.h b/include/hw/acpi/memory_hotplug.h
index dfe9cf3fde..38841d7b06 100644
--- a/include/hw/acpi/memory_hotplug.h
+++ b/include/hw/acpi/memory_hotplug.h
@@ -1,6 +1,7 @@
#ifndef QEMU_HW_ACPI_MEMORY_HOTPLUG_H
#define QEMU_HW_ACPI_MEMORY_HOTPLUG_H
+#include "qapi/qapi-types-acpi.h"
#include "hw/qdev-core.h"
#include "hw/acpi/acpi.h"
#include "hw/acpi/aml-build.h"
diff --git a/include/hw/acpi/pc-hotplug.h b/include/hw/acpi/pc-hotplug.h
index 31bc9191c3..8a654248e9 100644
--- a/include/hw/acpi/pc-hotplug.h
+++ b/include/hw/acpi/pc-hotplug.h
@@ -13,7 +13,7 @@
#define PC_HOTPLUG_H
/*
- * ONLY DEFINEs are permited in this file since it's shared
+ * ONLY DEFINEs are permitted in this file since it's shared
* between C and ASL code.
*/
diff --git a/include/hw/acpi/pci.h b/include/hw/acpi/pci.h
index bf2a3ed0ba..467a99461c 100644
--- a/include/hw/acpi/pci.h
+++ b/include/hw/acpi/pci.h
@@ -27,11 +27,17 @@
#define HW_ACPI_PCI_H
#include "hw/acpi/bios-linker-loader.h"
+#include "hw/acpi/acpi_aml_interface.h"
typedef struct AcpiMcfgInfo {
uint64_t base;
uint32_t size;
} AcpiMcfgInfo;
-void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info);
+void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info,
+ const char *oem_id, const char *oem_table_id);
+Aml *aml_pci_device_dsm(void);
+
+void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus);
+void build_pci_bridge_aml(AcpiDevAmlIf *adev, Aml *scope);
#endif
diff --git a/include/hw/acpi/pcihp.h b/include/hw/acpi/pcihp.h
index 8bc4a4c01d..ac21a95913 100644
--- a/include/hw/acpi/pcihp.h
+++ b/include/hw/acpi/pcihp.h
@@ -10,7 +10,7 @@
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
- * License version 2 as published by the Free Software Foundation.
+ * License version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -46,16 +46,19 @@ typedef struct AcpiPciHpPciStatus {
typedef struct AcpiPciHpState {
AcpiPciHpPciStatus acpi_pcihp_pci_status[ACPI_PCIHP_MAX_HOTPLUG_BUS];
uint32_t hotplug_select;
+ uint32_t acpi_index;
PCIBus *root;
MemoryRegion io;
- bool legacy_piix;
uint16_t io_base;
uint16_t io_len;
+ bool use_acpi_hotplug_bridge;
+ bool use_acpi_root_pci_hotplug;
} AcpiPciHpState;
void acpi_pcihp_init(Object *owner, AcpiPciHpState *, PCIBus *root,
- MemoryRegion *address_space_io, bool bridges_enabled);
+ MemoryRegion *io, uint16_t io_base);
+bool acpi_pcihp_is_hotpluggbale_bus(AcpiPciHpState *s, BusState *bus);
void acpi_pcihp_device_pre_plug_cb(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp);
void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
@@ -69,15 +72,19 @@ void acpi_pcihp_device_unplug_request_cb(HotplugHandler *hotplug_dev,
/* Called on reset */
void acpi_pcihp_reset(AcpiPciHpState *s);
+void build_append_pcihp_slots(Aml *parent_scope, PCIBus *bus);
+
extern const VMStateDescription vmstate_acpi_pcihp_pci_status;
-#define VMSTATE_PCI_HOTPLUG(pcihp, state, test_pcihp) \
+#define VMSTATE_PCI_HOTPLUG(pcihp, state, test_pcihp, test_acpi_index) \
VMSTATE_UINT32_TEST(pcihp.hotplug_select, state, \
test_pcihp), \
VMSTATE_STRUCT_ARRAY_TEST(pcihp.acpi_pcihp_pci_status, state, \
ACPI_PCIHP_MAX_HOTPLUG_BUS, \
test_pcihp, 1, \
vmstate_acpi_pcihp_pci_status, \
- AcpiPciHpPciStatus)
+ AcpiPciHpPciStatus), \
+ VMSTATE_UINT32_TEST(pcihp.acpi_index, state, \
+ test_acpi_index)
#endif
diff --git a/include/hw/acpi/piix4.h b/include/hw/acpi/piix4.h
new file mode 100644
index 0000000000..eb1c122d80
--- /dev/null
+++ b/include/hw/acpi/piix4.h
@@ -0,0 +1,73 @@
+/*
+ * ACPI implementation
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#ifndef HW_ACPI_PIIX4_H
+#define HW_ACPI_PIIX4_H
+
+#include "hw/pci/pci_device.h"
+#include "hw/acpi/acpi.h"
+#include "hw/acpi/cpu_hotplug.h"
+#include "hw/acpi/memory_hotplug.h"
+#include "hw/acpi/pcihp.h"
+#include "hw/i2c/pm_smbus.h"
+#include "hw/isa/apm.h"
+
+#define TYPE_PIIX4_PM "PIIX4_PM"
+OBJECT_DECLARE_SIMPLE_TYPE(PIIX4PMState, PIIX4_PM)
+
+struct PIIX4PMState {
+ /*< private >*/
+ PCIDevice parent_obj;
+ /*< public >*/
+
+ MemoryRegion io;
+ uint32_t io_base;
+
+ MemoryRegion io_gpe;
+ ACPIREGS ar;
+
+ APMState apm;
+
+ PMSMBus smb;
+ uint32_t smb_io_base;
+
+ qemu_irq irq;
+ qemu_irq smi_irq;
+ bool smm_enabled;
+ bool smm_compat;
+ Notifier machine_ready;
+ Notifier powerdown_notifier;
+
+ AcpiPciHpState acpi_pci_hotplug;
+ bool not_migrate_acpi_index;
+
+ uint8_t disable_s3;
+ uint8_t disable_s4;
+ uint8_t s4_val;
+
+ bool cpu_hotplug_legacy;
+ AcpiCpuHotplug gpe_cpu;
+ CPUHotplugState cpuhp_state;
+
+ MemHotplugState acpi_memory_hotplug;
+};
+
+#endif
diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
index 1a2a57a21f..579c45f5ba 100644
--- a/include/hw/acpi/tpm.h
+++ b/include/hw/acpi/tpm.h
@@ -21,6 +21,8 @@
#include "hw/acpi/aml-build.h"
#include "sysemu/tpm.h"
+#ifdef CONFIG_TPM
+
#define TPM_TIS_ADDR_BASE 0xFED40000
#define TPM_TIS_ADDR_SIZE 0x5000
@@ -91,6 +93,7 @@
#define TPM_TIS_CAP_DATA_TRANSFER_64B (3 << 9)
#define TPM_TIS_CAP_DATA_TRANSFER_LEGACY (0 << 9)
#define TPM_TIS_CAP_BURST_COUNT_DYNAMIC (0 << 8)
+#define TPM_TIS_CAP_BURST_COUNT_STATIC (1 << 8)
#define TPM_TIS_CAP_INTERRUPT_LOW_LEVEL (1 << 4) /* support is mandatory */
#define TPM_TIS_CAPABILITIES_SUPPORTED1_3 \
(TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \
@@ -207,6 +210,48 @@ REG32(CRB_DATA_BUFFER, 0x80)
#define TPM_PPI_FUNC_ALLOWED_USR_NOT_REQ (4 << 0)
#define TPM_PPI_FUNC_MASK (7 << 0)
+/* TPM TIS I2C registers */
+#define TPM_I2C_REG_LOC_SEL 0x00
+#define TPM_I2C_REG_ACCESS 0x04
+#define TPM_I2C_REG_INT_ENABLE 0x08
+#define TPM_I2C_REG_INT_CAPABILITY 0x14
+#define TPM_I2C_REG_STS 0x18
+#define TPM_I2C_REG_DATA_FIFO 0x24
+#define TPM_I2C_REG_INTF_CAPABILITY 0x30
+#define TPM_I2C_REG_I2C_DEV_ADDRESS 0x38
+#define TPM_I2C_REG_DATA_CSUM_ENABLE 0x40
+#define TPM_I2C_REG_DATA_CSUM_GET 0x44
+#define TPM_I2C_REG_DID_VID 0x48
+#define TPM_I2C_REG_RID 0x4c
+#define TPM_I2C_REG_UNKNOWN 0xff
+
+/* I2C specific interface capabilities */
+#define TPM_I2C_CAP_INTERFACE_TYPE (0x2 << 0) /* FIFO interface */
+#define TPM_I2C_CAP_INTERFACE_VER (0x0 << 4) /* TCG I2C intf 1.0 */
+#define TPM_I2C_CAP_TPM2_FAMILY (0x1 << 7) /* TPM 2.0 family. */
+#define TPM_I2C_CAP_DEV_ADDR_CHANGE (0x0 << 27) /* No dev addr chng */
+#define TPM_I2C_CAP_BURST_COUNT_STATIC (0x1 << 29) /* Burst count static */
+#define TPM_I2C_CAP_LOCALITY_CAP (0x1 << 25) /* 0-5 locality */
+#define TPM_I2C_CAP_BUS_SPEED (3 << 21) /* std and fast mode */
+
+/*
+ * TPM_I2C_STS masks for read/writing bits from/to TIS
+ * TPM_STS mask for read bits 31:26 must be zero
+ */
+#define TPM_I2C_STS_READ_MASK 0x00ffffdd
+#define TPM_I2C_STS_WRITE_MASK 0x03000062
+
+/* Checksum enabled. */
+#define TPM_DATA_CSUM_ENABLED 0x1
+
+/*
+ * TPM_I2C_INT_ENABLE mask. Linux kernel does not support
+ * interrupts hence setting it to 0.
+ */
+#define TPM_I2C_INT_ENABLE_MASK 0x0
+
void tpm_build_ppi_acpi(TPMIf *tpm, Aml *dev);
+#endif /* CONFIG_TPM */
+
#endif /* HW_ACPI_TPM_H */
diff --git a/include/hw/acpi/utils.h b/include/hw/acpi/utils.h
index 140b4de603..0022df027d 100644
--- a/include/hw/acpi/utils.h
+++ b/include/hw/acpi/utils.h
@@ -4,6 +4,5 @@
#include "hw/nvram/fw_cfg.h"
MemoryRegion *acpi_add_rom_blob(FWCfgCallback update, void *opaque,
- GArray *blob, const char *name,
- uint64_t max_size);
+ GArray *blob, const char *name);
#endif
diff --git a/include/hw/acpi/vmgenid.h b/include/hw/acpi/vmgenid.h
index c49d913f3e..fb135d5bcb 100644
--- a/include/hw/acpi/vmgenid.h
+++ b/include/hw/acpi/vmgenid.h
@@ -4,33 +4,34 @@
#include "hw/acpi/bios-linker-loader.h"
#include "hw/qdev-core.h"
#include "qemu/uuid.h"
+#include "qom/object.h"
-#define VMGENID_DEVICE "vmgenid"
+#define TYPE_VMGENID "vmgenid"
#define VMGENID_GUID "guid"
#define VMGENID_GUID_FW_CFG_FILE "etc/vmgenid_guid"
#define VMGENID_ADDR_FW_CFG_FILE "etc/vmgenid_addr"
#define VMGENID_FW_CFG_SIZE 4096 /* Occupy a page of memory */
#define VMGENID_GUID_OFFSET 40 /* allow space for
- * OVMF SDT Header Probe Supressor
+ * OVMF SDT Header Probe Suppressor
*/
-#define VMGENID(obj) OBJECT_CHECK(VmGenIdState, (obj), VMGENID_DEVICE)
+OBJECT_DECLARE_SIMPLE_TYPE(VmGenIdState, VMGENID)
-typedef struct VmGenIdState {
- DeviceClass parent_obj;
+struct VmGenIdState {
+ DeviceState parent_obj;
QemuUUID guid; /* The 128-bit GUID seen by the guest */
uint8_t vmgenid_addr_le[8]; /* Address of the GUID (little-endian) */
-} VmGenIdState;
+};
/* returns NULL unless there is exactly one device */
static inline Object *find_vmgenid_dev(void)
{
- return object_resolve_path_type("", VMGENID_DEVICE, NULL);
+ return object_resolve_path_type("", TYPE_VMGENID, NULL);
}
void vmgenid_build_acpi(VmGenIdState *vms, GArray *table_data, GArray *guid,
- BIOSLinker *linker);
+ BIOSLinker *linker, const char *oem_id);
void vmgenid_add_fw_cfg(VmGenIdState *vms, FWCfgState *s, GArray *guid);
#endif
diff --git a/include/hw/adc/aspeed_adc.h b/include/hw/adc/aspeed_adc.h
new file mode 100644
index 0000000000..ff1d06ea91
--- /dev/null
+++ b/include/hw/adc/aspeed_adc.h
@@ -0,0 +1,56 @@
+/*
+ * Aspeed ADC
+ *
+ * Copyright 2017-2021 IBM Corp.
+ *
+ * Andrew Jeffery <andrew@aj.id.au>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_ADC_ASPEED_ADC_H
+#define HW_ADC_ASPEED_ADC_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_ASPEED_ADC "aspeed.adc"
+#define TYPE_ASPEED_2400_ADC TYPE_ASPEED_ADC "-ast2400"
+#define TYPE_ASPEED_2500_ADC TYPE_ASPEED_ADC "-ast2500"
+#define TYPE_ASPEED_2600_ADC TYPE_ASPEED_ADC "-ast2600"
+#define TYPE_ASPEED_1030_ADC TYPE_ASPEED_ADC "-ast1030"
+OBJECT_DECLARE_TYPE(AspeedADCState, AspeedADCClass, ASPEED_ADC)
+
+#define TYPE_ASPEED_ADC_ENGINE "aspeed.adc.engine"
+OBJECT_DECLARE_SIMPLE_TYPE(AspeedADCEngineState, ASPEED_ADC_ENGINE)
+
+#define ASPEED_ADC_NR_CHANNELS 16
+#define ASPEED_ADC_NR_REGS (0xD0 >> 2)
+
+struct AspeedADCEngineState {
+ /* <private> */
+ SysBusDevice parent;
+
+ MemoryRegion mmio;
+ qemu_irq irq;
+ uint32_t engine_id;
+ uint32_t nr_channels;
+ uint32_t regs[ASPEED_ADC_NR_REGS];
+};
+
+struct AspeedADCState {
+ /* <private> */
+ SysBusDevice parent;
+
+ MemoryRegion mmio;
+ qemu_irq irq;
+
+ AspeedADCEngineState engines[2];
+};
+
+struct AspeedADCClass {
+ SysBusDeviceClass parent_class;
+
+ uint32_t nr_engines;
+};
+
+#endif /* HW_ADC_ASPEED_ADC_H */
diff --git a/include/hw/misc/max111x.h b/include/hw/adc/max111x.h
index af7f1017ef..beff59c815 100644
--- a/include/hw/misc/max111x.h
+++ b/include/hw/adc/max111x.h
@@ -14,6 +14,7 @@
#define HW_MISC_MAX111X_H
#include "hw/ssi/ssi.h"
+#include "qom/object.h"
/*
* This is a model of the Maxim MAX1110/1111 ADC chip, which for QEMU
@@ -31,8 +32,8 @@
* + the interrupt line is not correctly implemented, and will never
* be lowered once it has been asserted.
*/
-typedef struct {
- SSISlave parent_obj;
+struct MAX111xState {
+ SSIPeripheral parent_obj;
qemu_irq interrupt;
/* Values of inputs at system reset (settable by QOM property) */
@@ -43,12 +44,11 @@ typedef struct {
uint8_t input[8];
int inputs, com;
-} MAX111xState;
+};
#define TYPE_MAX_111X "max111x"
-#define MAX_111X(obj) \
- OBJECT_CHECK(MAX111xState, (obj), TYPE_MAX_111X)
+OBJECT_DECLARE_SIMPLE_TYPE(MAX111xState, MAX_111X)
#define TYPE_MAX_1110 "max1110"
#define TYPE_MAX_1111 "max1111"
diff --git a/include/hw/adc/npcm7xx_adc.h b/include/hw/adc/npcm7xx_adc.h
new file mode 100644
index 0000000000..93330a408d
--- /dev/null
+++ b/include/hw/adc/npcm7xx_adc.h
@@ -0,0 +1,68 @@
+/*
+ * Nuvoton NPCM7xx ADC Module
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_ADC_H
+#define NPCM7XX_ADC_H
+
+#include "hw/clock.h"
+#include "hw/irq.h"
+#include "hw/sysbus.h"
+#include "qemu/timer.h"
+
+#define NPCM7XX_ADC_NUM_INPUTS 8
+/**
+ * This value should not be changed unless write_adc_calibration function in
+ * hw/arm/npcm7xx.c is also changed.
+ */
+#define NPCM7XX_ADC_NUM_CALIB 2
+
+/**
+ * struct NPCM7xxADCState - Analog to Digital Converter Module device state.
+ * @parent: System bus device.
+ * @iomem: Memory region through which registers are accessed.
+ * @conv_timer: The timer counts down remaining cycles for the conversion.
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
+ * @con: The Control Register.
+ * @data: The Data Buffer.
+ * @clock: The ADC Clock.
+ * @adci: The input voltage in units of uV. 1uv = 1e-6V.
+ * @vref: The external reference voltage.
+ * @iref: The internal reference voltage, initialized at launch time.
+ * @rv: The calibrated output values of 0.5V and 1.5V for the ADC.
+ */
+struct NPCM7xxADCState {
+ SysBusDevice parent;
+
+ MemoryRegion iomem;
+
+ QEMUTimer conv_timer;
+
+ qemu_irq irq;
+ uint32_t con;
+ uint32_t data;
+ Clock *clock;
+
+ /* Voltages are in unit of uV. 1V = 1000000uV. */
+ uint32_t adci[NPCM7XX_ADC_NUM_INPUTS];
+ uint32_t vref;
+ uint32_t iref;
+
+ uint16_t calibration_r_values[NPCM7XX_ADC_NUM_CALIB];
+};
+
+#define TYPE_NPCM7XX_ADC "npcm7xx-adc"
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxADCState, NPCM7XX_ADC)
+
+#endif /* NPCM7XX_ADC_H */
diff --git a/include/hw/adc/stm32f2xx_adc.h b/include/hw/adc/stm32f2xx_adc.h
index 663b79f4f3..42b48981f2 100644
--- a/include/hw/adc/stm32f2xx_adc.h
+++ b/include/hw/adc/stm32f2xx_adc.h
@@ -26,6 +26,7 @@
#define HW_STM32F2XX_ADC_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define ADC_SR 0x00
#define ADC_CR1 0x04
@@ -58,10 +59,9 @@
#define ADC_COMMON_ADDRESS 0x100
#define TYPE_STM32F2XX_ADC "stm32f2xx-adc"
-#define STM32F2XX_ADC(obj) \
- OBJECT_CHECK(STM32F2XXADCState, (obj), TYPE_STM32F2XX_ADC)
+OBJECT_DECLARE_SIMPLE_TYPE(STM32F2XXADCState, STM32F2XX_ADC)
-typedef struct {
+struct STM32F2XXADCState {
/* <private> */
SysBusDevice parent_obj;
@@ -84,6 +84,6 @@ typedef struct {
uint32_t adc_dr;
qemu_irq irq;
-} STM32F2XXADCState;
+};
#endif /* HW_STM32F2XX_ADC_H */
diff --git a/include/hw/misc/zynq-xadc.h b/include/hw/adc/zynq-xadc.h
index f1a410a376..c10cc4c379 100644
--- a/include/hw/misc/zynq-xadc.h
+++ b/include/hw/adc/zynq-xadc.h
@@ -16,17 +16,17 @@
#define ZYNQ_XADC_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define ZYNQ_XADC_MMIO_SIZE 0x0020
#define ZYNQ_XADC_NUM_IO_REGS (ZYNQ_XADC_MMIO_SIZE / 4)
#define ZYNQ_XADC_NUM_ADC_REGS 128
#define ZYNQ_XADC_FIFO_DEPTH 15
-#define TYPE_ZYNQ_XADC "xlnx,zynq-xadc"
-#define ZYNQ_XADC(obj) \
- OBJECT_CHECK(ZynqXADCState, (obj), TYPE_ZYNQ_XADC)
+#define TYPE_ZYNQ_XADC "xlnx-zynq-xadc"
+OBJECT_DECLARE_SIMPLE_TYPE(ZynqXADCState, ZYNQ_XADC)
-typedef struct ZynqXADCState {
+struct ZynqXADCState {
/*< private >*/
SysBusDevice parent_obj;
@@ -39,8 +39,7 @@ typedef struct ZynqXADCState {
uint16_t xadc_dfifo[ZYNQ_XADC_FIFO_DEPTH];
uint16_t xadc_dfifo_entries;
- struct IRQState *qemu_irq;
-
-} ZynqXADCState;
+ qemu_irq irq;
+};
#endif /* ZYNQ_XADC_H */
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
index 77c82a9982..67a9a17b86 100644
--- a/include/hw/arm/allwinner-a10.h
+++ b/include/hw/arm/allwinner-a10.h
@@ -1,19 +1,22 @@
#ifndef HW_ARM_ALLWINNER_A10_H
#define HW_ARM_ALLWINNER_A10_H
-#include "qemu/error-report.h"
-#include "hw/char/serial.h"
-#include "hw/arm/boot.h"
#include "hw/timer/allwinner-a10-pit.h"
#include "hw/intc/allwinner-a10-pic.h"
#include "hw/net/allwinner_emac.h"
#include "hw/sd/allwinner-sdhost.h"
-#include "hw/ide/ahci.h"
+#include "hw/ide/ahci-sysbus.h"
#include "hw/usb/hcd-ohci.h"
#include "hw/usb/hcd-ehci.h"
#include "hw/rtc/allwinner-rtc.h"
+#include "hw/misc/allwinner-a10-ccm.h"
+#include "hw/misc/allwinner-a10-dramc.h"
+#include "hw/i2c/allwinner-i2c.h"
+#include "hw/watchdog/allwinner-wdt.h"
+#include "sysemu/block-backend.h"
#include "target/arm/cpu.h"
+#include "qom/object.h"
#define AW_A10_SDRAM_BASE 0x40000000
@@ -21,23 +24,47 @@
#define AW_A10_NUM_USB 2
#define TYPE_AW_A10 "allwinner-a10"
-#define AW_A10(obj) OBJECT_CHECK(AwA10State, (obj), TYPE_AW_A10)
+OBJECT_DECLARE_SIMPLE_TYPE(AwA10State, AW_A10)
-typedef struct AwA10State {
+struct AwA10State {
/*< private >*/
DeviceState parent_obj;
/*< public >*/
ARMCPU cpu;
+ AwA10ClockCtlState ccm;
+ AwA10DramControllerState dramc;
AwA10PITState timer;
AwA10PICState intc;
AwEmacState emac;
AllwinnerAHCIState sata;
AwSdHostState mmc0;
+ AWI2CState i2c0;
AwRtcState rtc;
+ AwWdtState wdt;
MemoryRegion sram_a;
EHCISysBusState ehci[AW_A10_NUM_USB];
OHCISysBusState ohci[AW_A10_NUM_USB];
-} AwA10State;
+};
+
+/**
+ * Emulate Boot ROM firmware setup functionality.
+ *
+ * A real Allwinner A10 SoC contains a Boot ROM
+ * which is the first code that runs right after
+ * the SoC is powered on. The Boot ROM is responsible
+ * for loading user code (e.g. a bootloader) from any
+ * of the supported external devices and writing the
+ * downloaded code to internal SRAM. After loading the SoC
+ * begins executing the code written to SRAM.
+ *
+ * This function emulates the Boot ROM by copying 32 KiB
+ * of data at offset 8 KiB from the given block device and writes it to
+ * the start of the first internal SRAM memory.
+ *
+ * @s: Allwinner A10 state object pointer
+ * @blk: Block backend device object pointer
+ */
+void allwinner_a10_bootrom_setup(AwA10State *s, BlockBackend *blk);
#endif
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
index 82e4e59216..24ba4e1bf4 100644
--- a/include/hw/arm/allwinner-h3.h
+++ b/include/hw/arm/allwinner-h3.h
@@ -18,7 +18,7 @@
*/
/*
- * The Allwinner H3 is a System on Chip containing four ARM Cortex A7
+ * The Allwinner H3 is a System on Chip containing four ARM Cortex-A7
* processor cores. Features and specifications include DDR2/DDR3 memory,
* SD/MMC storage cards, 10/100/1000Mbit Ethernet, USB 2.0, HDMI and
* various I/O modules.
@@ -36,7 +36,6 @@
#define HW_ARM_ALLWINNER_H3_H
#include "qom/object.h"
-#include "hw/arm/boot.h"
#include "hw/timer/allwinner-a10-pit.h"
#include "hw/intc/arm_gic.h"
#include "hw/misc/allwinner-h3-ccu.h"
@@ -47,6 +46,8 @@
#include "hw/sd/allwinner-sdhost.h"
#include "hw/net/allwinner-sun8i-emac.h"
#include "hw/rtc/allwinner-rtc.h"
+#include "hw/i2c/allwinner-i2c.h"
+#include "hw/watchdog/allwinner-wdt.h"
#include "target/arm/cpu.h"
#include "sysemu/block-backend.h"
@@ -61,37 +62,42 @@
* @see AwH3State
*/
enum {
- AW_H3_SRAM_A1,
- AW_H3_SRAM_A2,
- AW_H3_SRAM_C,
- AW_H3_SYSCTRL,
- AW_H3_MMC0,
- AW_H3_SID,
- AW_H3_EHCI0,
- AW_H3_OHCI0,
- AW_H3_EHCI1,
- AW_H3_OHCI1,
- AW_H3_EHCI2,
- AW_H3_OHCI2,
- AW_H3_EHCI3,
- AW_H3_OHCI3,
- AW_H3_CCU,
- AW_H3_PIT,
- AW_H3_UART0,
- AW_H3_UART1,
- AW_H3_UART2,
- AW_H3_UART3,
- AW_H3_EMAC,
- AW_H3_DRAMCOM,
- AW_H3_DRAMCTL,
- AW_H3_DRAMPHY,
- AW_H3_GIC_DIST,
- AW_H3_GIC_CPU,
- AW_H3_GIC_HYP,
- AW_H3_GIC_VCPU,
- AW_H3_RTC,
- AW_H3_CPUCFG,
- AW_H3_SDRAM
+ AW_H3_DEV_SRAM_A1,
+ AW_H3_DEV_SRAM_A2,
+ AW_H3_DEV_SRAM_C,
+ AW_H3_DEV_SYSCTRL,
+ AW_H3_DEV_MMC0,
+ AW_H3_DEV_SID,
+ AW_H3_DEV_EHCI0,
+ AW_H3_DEV_OHCI0,
+ AW_H3_DEV_EHCI1,
+ AW_H3_DEV_OHCI1,
+ AW_H3_DEV_EHCI2,
+ AW_H3_DEV_OHCI2,
+ AW_H3_DEV_EHCI3,
+ AW_H3_DEV_OHCI3,
+ AW_H3_DEV_CCU,
+ AW_H3_DEV_PIT,
+ AW_H3_DEV_UART0,
+ AW_H3_DEV_UART1,
+ AW_H3_DEV_UART2,
+ AW_H3_DEV_UART3,
+ AW_H3_DEV_EMAC,
+ AW_H3_DEV_TWI0,
+ AW_H3_DEV_TWI1,
+ AW_H3_DEV_TWI2,
+ AW_H3_DEV_DRAMCOM,
+ AW_H3_DEV_DRAMCTL,
+ AW_H3_DEV_DRAMPHY,
+ AW_H3_DEV_GIC_DIST,
+ AW_H3_DEV_GIC_CPU,
+ AW_H3_DEV_GIC_HYP,
+ AW_H3_DEV_GIC_VCPU,
+ AW_H3_DEV_RTC,
+ AW_H3_DEV_CPUCFG,
+ AW_H3_DEV_R_TWI,
+ AW_H3_DEV_SDRAM,
+ AW_H3_DEV_WDT
};
/** Total number of CPU cores in the H3 SoC */
@@ -106,7 +112,7 @@ enum {
#define TYPE_AW_H3 "allwinner-h3"
/** Convert input object to Allwinner H3 state object */
-#define AW_H3(obj) OBJECT_CHECK(AwH3State, (obj), TYPE_AW_H3)
+OBJECT_DECLARE_SIMPLE_TYPE(AwH3State, AW_H3)
/** @} */
@@ -116,7 +122,7 @@ enum {
* This struct contains the state of all the devices
* which are currently emulated by the H3 SoC code.
*/
-typedef struct AwH3State {
+struct AwH3State {
/*< private >*/
DeviceState parent_obj;
/*< public >*/
@@ -130,13 +136,18 @@ typedef struct AwH3State {
AwH3SysCtrlState sysctrl;
AwSidState sid;
AwSdHostState mmc0;
+ AWI2CState i2c0;
+ AWI2CState i2c1;
+ AWI2CState i2c2;
+ AWI2CState r_twi;
AwSun8iEmacState emac;
AwRtcState rtc;
+ AwWdtState wdt;
GICState gic;
MemoryRegion sram_a1;
MemoryRegion sram_a2;
MemoryRegion sram_c;
-} AwH3State;
+};
/**
* Emulate Boot ROM firmware setup functionality.
diff --git a/include/hw/arm/allwinner-r40.h b/include/hw/arm/allwinner-r40.h
new file mode 100644
index 0000000000..614e74b7ed
--- /dev/null
+++ b/include/hw/arm/allwinner-r40.h
@@ -0,0 +1,157 @@
+/*
+ * Allwinner R40/A40i/T3 System on Chip emulation
+ *
+ * Copyright (C) 2023 qianfan Zhao <qianfanguijin@163.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_ARM_ALLWINNER_R40_H
+#define HW_ARM_ALLWINNER_R40_H
+
+#include "qom/object.h"
+#include "hw/timer/allwinner-a10-pit.h"
+#include "hw/ide/ahci-sysbus.h"
+#include "hw/intc/arm_gic.h"
+#include "hw/sd/allwinner-sdhost.h"
+#include "hw/misc/allwinner-r40-ccu.h"
+#include "hw/misc/allwinner-r40-dramc.h"
+#include "hw/misc/allwinner-sramc.h"
+#include "hw/i2c/allwinner-i2c.h"
+#include "hw/net/allwinner_emac.h"
+#include "hw/net/allwinner-sun8i-emac.h"
+#include "hw/usb/hcd-ohci.h"
+#include "hw/usb/hcd-ehci.h"
+#include "hw/watchdog/allwinner-wdt.h"
+#include "target/arm/cpu.h"
+#include "sysemu/block-backend.h"
+
+enum {
+ AW_R40_DEV_SRAM_A1,
+ AW_R40_DEV_SRAM_A2,
+ AW_R40_DEV_SRAM_A3,
+ AW_R40_DEV_SRAM_A4,
+ AW_R40_DEV_SRAMC,
+ AW_R40_DEV_EMAC,
+ AW_R40_DEV_MMC0,
+ AW_R40_DEV_MMC1,
+ AW_R40_DEV_MMC2,
+ AW_R40_DEV_MMC3,
+ AW_R40_DEV_AHCI,
+ AW_R40_DEV_EHCI1,
+ AW_R40_DEV_OHCI1,
+ AW_R40_DEV_EHCI2,
+ AW_R40_DEV_OHCI2,
+ AW_R40_DEV_CCU,
+ AW_R40_DEV_PIT,
+ AW_R40_DEV_WDT,
+ AW_R40_DEV_UART0,
+ AW_R40_DEV_UART1,
+ AW_R40_DEV_UART2,
+ AW_R40_DEV_UART3,
+ AW_R40_DEV_UART4,
+ AW_R40_DEV_UART5,
+ AW_R40_DEV_UART6,
+ AW_R40_DEV_UART7,
+ AW_R40_DEV_TWI0,
+ AW_R40_DEV_GMAC,
+ AW_R40_DEV_GIC_DIST,
+ AW_R40_DEV_GIC_CPU,
+ AW_R40_DEV_GIC_HYP,
+ AW_R40_DEV_GIC_VCPU,
+ AW_R40_DEV_SDRAM,
+ AW_R40_DEV_DRAMCOM,
+ AW_R40_DEV_DRAMCTL,
+ AW_R40_DEV_DRAMPHY,
+};
+
+#define AW_R40_NUM_CPUS (4)
+
+/**
+ * Allwinner R40 object model
+ * @{
+ */
+
+/** Object type for the Allwinner R40 SoC */
+#define TYPE_AW_R40 "allwinner-r40"
+
+/** Convert input object to Allwinner R40 state object */
+OBJECT_DECLARE_SIMPLE_TYPE(AwR40State, AW_R40)
+
+/** @} */
+
+/**
+ * Allwinner R40 object
+ *
+ * This struct contains the state of all the devices
+ * which are currently emulated by the R40 SoC code.
+ */
+#define AW_R40_NUM_MMCS 4
+#define AW_R40_NUM_USB 2
+#define AW_R40_NUM_UARTS 8
+
+struct AwR40State {
+ /*< private >*/
+ DeviceState parent_obj;
+ /*< public >*/
+
+ /** Physical base address for start of RAM */
+ hwaddr ram_addr;
+
+ /** Total RAM size in megabytes */
+ uint32_t ram_size;
+
+ ARMCPU cpus[AW_R40_NUM_CPUS];
+ const hwaddr *memmap;
+ AwSRAMCState sramc;
+ AwA10PITState timer;
+ AwWdtState wdt;
+ AllwinnerAHCIState sata;
+ AwSdHostState mmc[AW_R40_NUM_MMCS];
+ EHCISysBusState ehci[AW_R40_NUM_USB];
+ OHCISysBusState ohci[AW_R40_NUM_USB];
+ AwR40ClockCtlState ccu;
+ AwR40DramCtlState dramc;
+ AWI2CState i2c0;
+ AwEmacState emac;
+ AwSun8iEmacState gmac;
+ GICState gic;
+ MemoryRegion sram_a1;
+ MemoryRegion sram_a2;
+ MemoryRegion sram_a3;
+ MemoryRegion sram_a4;
+};
+
+/**
+ * Emulate Boot ROM firmware setup functionality.
+ *
+ * A real Allwinner R40 SoC contains a Boot ROM
+ * which is the first code that runs right after
+ * the SoC is powered on. The Boot ROM is responsible
+ * for loading user code (e.g. a bootloader) from any
+ * of the supported external devices and writing the
+ * downloaded code to internal SRAM. After loading the SoC
+ * begins executing the code written to SRAM.
+ *
+ * This function emulates the Boot ROM by copying 32 KiB
+ * of data from the given block device and writes it to
+ * the start of the first internal SRAM memory.
+ *
+ * @s: Allwinner R40 state object pointer
+ * @blk: Block backend device object pointer
+ * @unit: the mmc control's unit
+ */
+bool allwinner_r40_bootrom_setup(AwR40State *s, BlockBackend *blk, int unit);
+
+#endif /* HW_ARM_ALLWINNER_R40_H */
diff --git a/include/hw/arm/armsse-version.h b/include/hw/arm/armsse-version.h
new file mode 100644
index 0000000000..60780fa984
--- /dev/null
+++ b/include/hw/arm/armsse-version.h
@@ -0,0 +1,42 @@
+/*
+ * ARM SSE (Subsystems for Embedded): IoTKit, SSE-200
+ *
+ * Copyright (c) 2020 Linaro Limited
+ * Written by Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or
+ * (at your option) any later version.
+ */
+
+#ifndef ARMSSE_VERSION_H
+#define ARMSSE_VERSION_H
+
+
+/*
+ * Define an enumeration of the possible values of the sse-version
+ * property implemented by various sub-devices of the SSE, and
+ * a validation function that checks that a valid value has been passed.
+ * These are arbitrary QEMU-internal values (nobody should be creating
+ * the sub-devices of the SSE except for the SSE object itself), but
+ * we pick obvious numbers for the benefit of people debugging with gdb.
+ */
+enum {
+ ARMSSE_IOTKIT = 0,
+ ARMSSE_SSE200 = 200,
+ ARMSSE_SSE300 = 300,
+};
+
+static inline bool armsse_version_valid(uint32_t sse_version)
+{
+ switch (sse_version) {
+ case ARMSSE_IOTKIT:
+ case ARMSSE_SSE200:
+ case ARMSSE_SSE300:
+ return true;
+ default:
+ return false;
+ }
+}
+
+#endif
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index 84080c2299..88b3b759c5 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -14,9 +14,9 @@
* hardware, which include the IoT Kit and the SSE-050, SSE-100 and
* SSE-200. Currently we model:
* - the Arm IoT Kit which is documented in
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
+ * https://developer.arm.com/documentation/ecm0601256/latest
* - the SSE-200 which is documented in
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
+ * https://developer.arm.com/documentation/101104/latest/
*
* The IoTKit contains:
* a Cortex-M33
@@ -37,9 +37,10 @@
* per-CPU identity and control register blocks
*
* QEMU interface:
+ * + Clock input "MAINCLK": clock for CPUs and most peripherals
+ * + Clock input "S32KCLK": slow 32KHz clock used for a few peripherals
* + QOM property "memory" is a MemoryRegion containing the devices provided
* by the board model.
- * + QOM property "MAINCLK" is the frequency of the main system clock
* + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts.
* (In hardware, the SSE-200 permits the number of expansion interrupts
* for the two CPUs to be configured separately, but we restrict it to
@@ -55,6 +56,9 @@
* (matching the hardware) is that for CPU0 in an IoTKit and CPU1 in an
* SSE-200 both are present; CPU0 in an SSE-200 has neither.
* Since the IoTKit has only one CPU, it does not have the CPU1_* properties.
+ * + QOM properties "CPU0_MPU_NS", "CPU0_MPU_S", "CPU1_MPU_NS" and "CPU1_MPU_S"
+ * which set the number of MPU regions on the CPUs. If there is only one
+ * CPU the CPU1 properties are not present.
* + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts for CPU 0,
* which are wired to its NVIC lines 32 .. n+32
* + Named GPIO inputs "EXP_CPU1_IRQ" 0..n are the expansion interrupts for
@@ -96,18 +100,24 @@
#include "hw/misc/tz-mpc.h"
#include "hw/timer/cmsdk-apb-timer.h"
#include "hw/timer/cmsdk-apb-dualtimer.h"
+#include "hw/timer/sse-counter.h"
+#include "hw/timer/sse-timer.h"
#include "hw/watchdog/cmsdk-apb-watchdog.h"
#include "hw/misc/iotkit-sysctl.h"
#include "hw/misc/iotkit-sysinfo.h"
#include "hw/misc/armsse-cpuid.h"
#include "hw/misc/armsse-mhu.h"
+#include "hw/misc/armsse-cpu-pwrctrl.h"
#include "hw/misc/unimp.h"
#include "hw/or-irq.h"
+#include "hw/clock.h"
#include "hw/core/split-irq.h"
#include "hw/cpu/cluster.h"
+#include "qom/object.h"
-#define TYPE_ARMSSE "arm-sse"
-#define ARMSSE(obj) OBJECT_CHECK(ARMSSE, (obj), TYPE_ARMSSE)
+#define TYPE_ARM_SSE "arm-sse"
+OBJECT_DECLARE_TYPE(ARMSSE, ARMSSEClass,
+ ARM_SSE)
/*
* These type names are for specific IoTKit subsystems; other than
@@ -116,12 +126,14 @@
*/
#define TYPE_IOTKIT "iotkit"
#define TYPE_SSE200 "sse-200"
+#define TYPE_SSE300 "sse-300"
/* We have an IRQ splitter and an OR gate input for each external PPC
* and the 2 internal PPCs
*/
+#define NUM_INTERNAL_PPCS 2
#define NUM_EXTERNAL_PPCS (IOTS_NUM_AHB_EXP_PPC + IOTS_NUM_APB_EXP_PPC)
-#define NUM_PPCS (NUM_EXTERNAL_PPCS + 2)
+#define NUM_PPCS (NUM_EXTERNAL_PPCS + NUM_INTERNAL_PPCS)
#define MAX_SRAM_BANKS 4
#if MAX_SRAM_BANKS > IOTS_NUM_MPC
@@ -130,17 +142,12 @@
#define SSE_MAX_CPUS 2
-/* These define what each PPU in the ppu[] index is for */
-#define CPU0CORE_PPU 0
-#define CPU1CORE_PPU 1
-#define DBG_PPU 2
-#define RAM0_PPU 3
-#define RAM1_PPU 4
-#define RAM2_PPU 5
-#define RAM3_PPU 6
-#define NUM_PPUS 7
-
-typedef struct ARMSSE {
+#define NUM_PPUS 8
+
+/* Number of CPU IRQs used by the SSE itself */
+#define NUM_SSE_IRQS 32
+
+struct ARMSSE {
/*< private >*/
SysBusDevice parent_obj;
@@ -148,37 +155,37 @@ typedef struct ARMSSE {
ARMv7MState armv7m[SSE_MAX_CPUS];
CPUClusterState cluster[SSE_MAX_CPUS];
IoTKitSecCtl secctl;
- TZPPC apb_ppc0;
- TZPPC apb_ppc1;
+ TZPPC apb_ppc[NUM_INTERNAL_PPCS];
TZMPC mpc[IOTS_NUM_MPC];
- CMSDKAPBTIMER timer0;
- CMSDKAPBTIMER timer1;
- CMSDKAPBTIMER s32ktimer;
- qemu_or_irq ppc_irq_orgate;
+ CMSDKAPBTimer timer[3];
+ OrIRQState ppc_irq_orgate;
SplitIRQ sec_resp_splitter;
SplitIRQ ppc_irq_splitter[NUM_PPCS];
SplitIRQ mpc_irq_splitter[IOTS_NUM_EXP_MPC + IOTS_NUM_MPC];
- qemu_or_irq mpc_irq_orgate;
- qemu_or_irq nmi_orgate;
+ OrIRQState mpc_irq_orgate;
+ OrIRQState nmi_orgate;
- SplitIRQ cpu_irq_splitter[32];
+ SplitIRQ cpu_irq_splitter[NUM_SSE_IRQS];
CMSDKAPBDualTimer dualtimer;
- CMSDKAPBWatchdog s32kwatchdog;
- CMSDKAPBWatchdog nswatchdog;
- CMSDKAPBWatchdog swatchdog;
+ CMSDKAPBWatchdog cmsdk_watchdog[3];
+
+ SSECounter sse_counter;
+ SSETimer sse_timer[4];
IoTKitSysCtl sysctl;
IoTKitSysCtl sysinfo;
ARMSSEMHU mhu[2];
- UnimplementedDeviceState ppu[NUM_PPUS];
+ UnimplementedDeviceState unimp[NUM_PPUS];
UnimplementedDeviceState cachectrl[SSE_MAX_CPUS];
UnimplementedDeviceState cpusecctrl[SSE_MAX_CPUS];
ARMSSECPUID cpuid[SSE_MAX_CPUS];
+ ARMSSECPUPwrCtrl cpu_pwrctrl[SSE_MAX_CPUS];
+
/*
* 'container' holds all devices seen by all CPUs.
* 'cpu_container[i]' is the view that CPU i has: this has the
@@ -194,6 +201,8 @@ typedef struct ARMSSE {
MemoryRegion alias2;
MemoryRegion alias3[SSE_MAX_CPUS];
MemoryRegion sram[MAX_SRAM_BANKS];
+ MemoryRegion itcm;
+ MemoryRegion dtcm;
qemu_irq *exp_irqs[SSE_MAX_CPUS];
qemu_irq ppc0_irq;
@@ -207,26 +216,26 @@ typedef struct ARMSSE {
uint32_t nsccfg;
+ Clock *mainclk;
+ Clock *s32kclk;
+
/* Properties */
MemoryRegion *board_memory;
uint32_t exp_numirq;
- uint32_t mainclk_frq;
uint32_t sram_addr_width;
uint32_t init_svtor;
+ uint32_t cpu_mpu_ns[SSE_MAX_CPUS];
+ uint32_t cpu_mpu_s[SSE_MAX_CPUS];
bool cpu_fpu[SSE_MAX_CPUS];
bool cpu_dsp[SSE_MAX_CPUS];
-} ARMSSE;
+};
typedef struct ARMSSEInfo ARMSSEInfo;
-typedef struct ARMSSEClass {
- DeviceClass parent_class;
+struct ARMSSEClass {
+ SysBusDeviceClass parent_class;
const ARMSSEInfo *info;
-} ARMSSEClass;
+};
-#define ARMSSE_CLASS(klass) \
- OBJECT_CLASS_CHECK(ARMSSEClass, (klass), TYPE_ARMSSE)
-#define ARMSSE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(ARMSSEClass, (obj), TYPE_ARMSSE)
#endif
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
index a30e3c6471..5c057ab2ec 100644
--- a/include/hw/arm/armv7m.h
+++ b/include/hw/arm/armv7m.h
@@ -12,12 +12,15 @@
#include "hw/sysbus.h"
#include "hw/intc/armv7m_nvic.h"
+#include "hw/misc/armv7m_ras.h"
#include "target/arm/idau.h"
+#include "qom/object.h"
+#include "hw/clock.h"
-#define TYPE_BITBAND "ARM,bitband-memory"
-#define BITBAND(obj) OBJECT_CHECK(BitBandState, (obj), TYPE_BITBAND)
+#define TYPE_BITBAND "ARM-bitband-memory"
+OBJECT_DECLARE_SIMPLE_TYPE(BitBandState, BITBAND)
-typedef struct {
+struct BitBandState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -26,10 +29,10 @@ typedef struct {
MemoryRegion iomem;
uint32_t base;
MemoryRegion *source_memory;
-} BitBandState;
+};
#define TYPE_ARMV7M "armv7m"
-#define ARMV7M(obj) OBJECT_CHECK(ARMv7MState, (obj), TYPE_ARMV7M)
+OBJECT_DECLARE_SIMPLE_TYPE(ARMv7MState, ARMV7M)
#define ARMV7M_NUM_BITBANDS 2
@@ -40,27 +43,57 @@ typedef struct {
* a qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET).
* + Property "cpu-type": CPU type to instantiate
* + Property "num-irq": number of external IRQ lines
+ * + Property "num-prio-bits": number of priority bits in the NVIC
* + Property "memory": MemoryRegion defining the physical address space
* that CPU accesses see. (The NVIC, bitbanding and other CPU-internal
* devices will be automatically layered on top of this view.)
* + Property "idau": IDAU interface (forwarded to CPU object)
* + Property "init-svtor": secure VTOR reset value (forwarded to CPU object)
+ * + Property "init-nsvtor": non-secure VTOR reset value (forwarded to CPU object)
* + Property "vfp": enable VFP (forwarded to CPU object)
* + Property "dsp": enable DSP (forwarded to CPU object)
* + Property "enable-bitband": expose bitbanded IO
+ * + Property "mpu-ns-regions": number of Non-Secure MPU regions (forwarded
+ * to CPU object pmsav7-dregion property; default is whatever the default
+ * for the CPU is)
+ * + Property "mpu-s-regions": number of Secure MPU regions (default is
+ * whatever the default for the CPU is; must currently be set to the same
+ * value as mpu-ns-regions if the CPU implements the Security Extension)
+ * + Clock input "refclk" is the external reference clock for the systick timers
+ * + Clock input "cpuclk" is the main CPU clock
*/
-typedef struct ARMv7MState {
+struct ARMv7MState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
NVICState nvic;
BitBandState bitband[ARMV7M_NUM_BITBANDS];
ARMCPU *cpu;
+ ARMv7MRAS ras;
+ SysTickState systick[M_REG_NUM_BANKS];
/* MemoryRegion we pass to the CPU, with our devices layered on
* top of the ones the board provides in board_memory.
*/
MemoryRegion container;
+ /*
+ * MemoryRegion which passes the transaction to either the S or the
+ * NS systick device depending on the transaction attributes
+ */
+ MemoryRegion systickmem;
+ /*
+ * MemoryRegion which enforces the S/NS handling of the systick
+ * device NS alias region and passes the transaction to the
+ * NS systick device if appropriate.
+ */
+ MemoryRegion systick_ns_mem;
+ /* Ditto, for the sysregs region provided by the NVIC */
+ MemoryRegion sysreg_ns_mem;
+ /* MR providing default PPB behaviour */
+ MemoryRegion defaultmem;
+
+ Clock *refclk;
+ Clock *cpuclk;
/* Properties */
char *cpu_type;
@@ -68,10 +101,13 @@ typedef struct ARMv7MState {
MemoryRegion *board_memory;
Object *idau;
uint32_t init_svtor;
+ uint32_t init_nsvtor;
+ uint32_t mpu_ns_regions;
+ uint32_t mpu_s_regions;
bool enable_bitband;
bool start_powered_off;
bool vfp;
bool dsp;
-} ARMv7MState;
+};
#endif
diff --git a/include/hw/arm/aspeed.h b/include/hw/arm/aspeed.h
index 09da9d9acc..cbeacb214c 100644
--- a/include/hw/arm/aspeed.h
+++ b/include/hw/arm/aspeed.h
@@ -10,24 +10,22 @@
#define ARM_ASPEED_H
#include "hw/boards.h"
+#include "qom/object.h"
typedef struct AspeedMachineState AspeedMachineState;
#define TYPE_ASPEED_MACHINE MACHINE_TYPE_NAME("aspeed")
-#define ASPEED_MACHINE(obj) \
- OBJECT_CHECK(AspeedMachineState, (obj), TYPE_ASPEED_MACHINE)
+typedef struct AspeedMachineClass AspeedMachineClass;
+DECLARE_OBJ_CHECKERS(AspeedMachineState, AspeedMachineClass,
+ ASPEED_MACHINE, TYPE_ASPEED_MACHINE)
#define ASPEED_MAC0_ON (1 << 0)
#define ASPEED_MAC1_ON (1 << 1)
#define ASPEED_MAC2_ON (1 << 2)
#define ASPEED_MAC3_ON (1 << 3)
-#define ASPEED_MACHINE_CLASS(klass) \
- OBJECT_CLASS_CHECK(AspeedMachineClass, (klass), TYPE_ASPEED_MACHINE)
-#define ASPEED_MACHINE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(AspeedMachineClass, (obj), TYPE_ASPEED_MACHINE)
-typedef struct AspeedMachineClass {
+struct AspeedMachineClass {
MachineClass parent_obj;
const char *name;
@@ -40,7 +38,8 @@ typedef struct AspeedMachineClass {
uint32_t num_cs;
uint32_t macs_mask;
void (*i2c_init)(AspeedMachineState *bmc);
-} AspeedMachineClass;
+ uint32_t uart_default;
+};
#endif
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index 914115f3ef..c60fac900a 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -13,45 +13,63 @@
#define ASPEED_SOC_H
#include "hw/cpu/a15mpcore.h"
+#include "hw/arm/armv7m.h"
#include "hw/intc/aspeed_vic.h"
#include "hw/misc/aspeed_scu.h"
+#include "hw/adc/aspeed_adc.h"
#include "hw/misc/aspeed_sdmc.h"
#include "hw/misc/aspeed_xdma.h"
#include "hw/timer/aspeed_timer.h"
#include "hw/rtc/aspeed_rtc.h"
#include "hw/i2c/aspeed_i2c.h"
+#include "hw/misc/aspeed_i3c.h"
#include "hw/ssi/aspeed_smc.h"
+#include "hw/misc/aspeed_hace.h"
+#include "hw/misc/aspeed_sbc.h"
#include "hw/watchdog/wdt_aspeed.h"
#include "hw/net/ftgmac100.h"
#include "target/arm/cpu.h"
#include "hw/gpio/aspeed_gpio.h"
#include "hw/sd/aspeed_sdhci.h"
#include "hw/usb/hcd-ehci.h"
+#include "qom/object.h"
+#include "hw/misc/aspeed_lpc.h"
+#include "hw/misc/unimp.h"
+#include "hw/misc/aspeed_peci.h"
+#include "hw/fsi/aspeed_apb2opb.h"
+#include "hw/char/serial.h"
#define ASPEED_SPIS_NUM 2
#define ASPEED_EHCIS_NUM 2
#define ASPEED_WDTS_NUM 4
#define ASPEED_CPUS_NUM 2
#define ASPEED_MACS_NUM 4
+#define ASPEED_UARTS_NUM 13
+#define ASPEED_JTAG_NUM 2
-typedef struct AspeedSoCState {
- /*< private >*/
+struct AspeedSoCState {
DeviceState parent;
- /*< public >*/
- ARMCPU cpu[ASPEED_CPUS_NUM];
- A15MPPrivState a7mpcore;
+ MemoryRegion *memory;
MemoryRegion *dram_mr;
+ MemoryRegion dram_container;
MemoryRegion sram;
- AspeedVICState vic;
+ MemoryRegion spi_boot_container;
+ MemoryRegion spi_boot;
AspeedRtcState rtc;
AspeedTimerCtrlState timerctrl;
AspeedI2CState i2c;
+ AspeedI3CState i3c;
AspeedSCUState scu;
+ AspeedHACEState hace;
AspeedXDMAState xdma;
+ AspeedADCState adc;
AspeedSMCState fmc;
AspeedSMCState spi[ASPEED_SPIS_NUM];
EHCISysBusState ehci[ASPEED_EHCIS_NUM];
+ AspeedSBCState sbc;
+ MemoryRegion secsram;
+ UnimplementedDeviceState sbc_unimplemented;
AspeedSDMCState sdmc;
AspeedWDTState wdt[ASPEED_WDTS_NUM];
FTGMAC100State ftgmac100[ASPEED_MACS_NUM];
@@ -60,79 +78,176 @@ typedef struct AspeedSoCState {
AspeedGPIOState gpio_1_8v;
AspeedSDHCIState sdhci;
AspeedSDHCIState emmc;
-} AspeedSoCState;
+ AspeedLPCState lpc;
+ AspeedPECIState peci;
+ SerialMM uart[ASPEED_UARTS_NUM];
+ Clock *sysclk;
+ UnimplementedDeviceState iomem;
+ UnimplementedDeviceState video;
+ UnimplementedDeviceState emmc_boot_controller;
+ UnimplementedDeviceState dpmcu;
+ UnimplementedDeviceState pwm;
+ UnimplementedDeviceState espi;
+ UnimplementedDeviceState udc;
+ UnimplementedDeviceState sgpiom;
+ UnimplementedDeviceState jtag[ASPEED_JTAG_NUM];
+ AspeedAPB2OPBState fsi[2];
+};
#define TYPE_ASPEED_SOC "aspeed-soc"
-#define ASPEED_SOC(obj) OBJECT_CHECK(AspeedSoCState, (obj), TYPE_ASPEED_SOC)
+OBJECT_DECLARE_TYPE(AspeedSoCState, AspeedSoCClass, ASPEED_SOC)
+
+struct Aspeed2400SoCState {
+ AspeedSoCState parent;
+
+ ARMCPU cpu[ASPEED_CPUS_NUM];
+ AspeedVICState vic;
+};
+
+#define TYPE_ASPEED2400_SOC "aspeed2400-soc"
+OBJECT_DECLARE_SIMPLE_TYPE(Aspeed2400SoCState, ASPEED2400_SOC)
+
+struct Aspeed2600SoCState {
+ AspeedSoCState parent;
+
+ A15MPPrivState a7mpcore;
+ ARMCPU cpu[ASPEED_CPUS_NUM]; /* XXX belong to a7mpcore */
+};
+
+#define TYPE_ASPEED2600_SOC "aspeed2600-soc"
+OBJECT_DECLARE_SIMPLE_TYPE(Aspeed2600SoCState, ASPEED2600_SOC)
+
+struct Aspeed10x0SoCState {
+ AspeedSoCState parent;
+
+ ARMv7MState armv7m;
+};
+
+#define TYPE_ASPEED10X0_SOC "aspeed10x0-soc"
+OBJECT_DECLARE_SIMPLE_TYPE(Aspeed10x0SoCState, ASPEED10X0_SOC)
-typedef struct AspeedSoCClass {
+struct AspeedSoCClass {
DeviceClass parent_class;
const char *name;
- const char *cpu_type;
+ /** valid_cpu_types: NULL terminated array of a single CPU type. */
+ const char * const *valid_cpu_types;
uint32_t silicon_rev;
uint64_t sram_size;
+ uint64_t secsram_size;
int spis_num;
int ehcis_num;
int wdts_num;
int macs_num;
+ int uarts_num;
+ int uarts_base;
const int *irqmap;
const hwaddr *memmap;
uint32_t num_cpus;
-} AspeedSoCClass;
+ qemu_irq (*get_irq)(AspeedSoCState *s, int dev);
+};
-#define ASPEED_SOC_CLASS(klass) \
- OBJECT_CLASS_CHECK(AspeedSoCClass, (klass), TYPE_ASPEED_SOC)
-#define ASPEED_SOC_GET_CLASS(obj) \
- OBJECT_GET_CLASS(AspeedSoCClass, (obj), TYPE_ASPEED_SOC)
+const char *aspeed_soc_cpu_type(AspeedSoCClass *sc);
enum {
- ASPEED_IOMEM,
- ASPEED_UART1,
- ASPEED_UART2,
- ASPEED_UART3,
- ASPEED_UART4,
- ASPEED_UART5,
- ASPEED_VUART,
- ASPEED_FMC,
- ASPEED_SPI1,
- ASPEED_SPI2,
- ASPEED_EHCI1,
- ASPEED_EHCI2,
- ASPEED_VIC,
- ASPEED_SDMC,
- ASPEED_SCU,
- ASPEED_ADC,
- ASPEED_VIDEO,
- ASPEED_SRAM,
- ASPEED_SDHCI,
- ASPEED_GPIO,
- ASPEED_GPIO_1_8V,
- ASPEED_RTC,
- ASPEED_TIMER1,
- ASPEED_TIMER2,
- ASPEED_TIMER3,
- ASPEED_TIMER4,
- ASPEED_TIMER5,
- ASPEED_TIMER6,
- ASPEED_TIMER7,
- ASPEED_TIMER8,
- ASPEED_WDT,
- ASPEED_PWM,
- ASPEED_LPC,
- ASPEED_IBT,
- ASPEED_I2C,
- ASPEED_ETH1,
- ASPEED_ETH2,
- ASPEED_ETH3,
- ASPEED_ETH4,
- ASPEED_MII1,
- ASPEED_MII2,
- ASPEED_MII3,
- ASPEED_MII4,
- ASPEED_SDRAM,
- ASPEED_XDMA,
- ASPEED_EMMC,
+ ASPEED_DEV_SPI_BOOT,
+ ASPEED_DEV_IOMEM,
+ ASPEED_DEV_UART0,
+ ASPEED_DEV_UART1,
+ ASPEED_DEV_UART2,
+ ASPEED_DEV_UART3,
+ ASPEED_DEV_UART4,
+ ASPEED_DEV_UART5,
+ ASPEED_DEV_UART6,
+ ASPEED_DEV_UART7,
+ ASPEED_DEV_UART8,
+ ASPEED_DEV_UART9,
+ ASPEED_DEV_UART10,
+ ASPEED_DEV_UART11,
+ ASPEED_DEV_UART12,
+ ASPEED_DEV_UART13,
+ ASPEED_DEV_VUART,
+ ASPEED_DEV_FMC,
+ ASPEED_DEV_SPI1,
+ ASPEED_DEV_SPI2,
+ ASPEED_DEV_EHCI1,
+ ASPEED_DEV_EHCI2,
+ ASPEED_DEV_VIC,
+ ASPEED_DEV_SDMC,
+ ASPEED_DEV_SCU,
+ ASPEED_DEV_ADC,
+ ASPEED_DEV_SBC,
+ ASPEED_DEV_SECSRAM,
+ ASPEED_DEV_EMMC_BC,
+ ASPEED_DEV_VIDEO,
+ ASPEED_DEV_SRAM,
+ ASPEED_DEV_SDHCI,
+ ASPEED_DEV_GPIO,
+ ASPEED_DEV_GPIO_1_8V,
+ ASPEED_DEV_RTC,
+ ASPEED_DEV_TIMER1,
+ ASPEED_DEV_TIMER2,
+ ASPEED_DEV_TIMER3,
+ ASPEED_DEV_TIMER4,
+ ASPEED_DEV_TIMER5,
+ ASPEED_DEV_TIMER6,
+ ASPEED_DEV_TIMER7,
+ ASPEED_DEV_TIMER8,
+ ASPEED_DEV_WDT,
+ ASPEED_DEV_PWM,
+ ASPEED_DEV_LPC,
+ ASPEED_DEV_IBT,
+ ASPEED_DEV_I2C,
+ ASPEED_DEV_PECI,
+ ASPEED_DEV_ETH1,
+ ASPEED_DEV_ETH2,
+ ASPEED_DEV_ETH3,
+ ASPEED_DEV_ETH4,
+ ASPEED_DEV_MII1,
+ ASPEED_DEV_MII2,
+ ASPEED_DEV_MII3,
+ ASPEED_DEV_MII4,
+ ASPEED_DEV_SDRAM,
+ ASPEED_DEV_XDMA,
+ ASPEED_DEV_EMMC,
+ ASPEED_DEV_KCS,
+ ASPEED_DEV_HACE,
+ ASPEED_DEV_DPMCU,
+ ASPEED_DEV_DP,
+ ASPEED_DEV_I3C,
+ ASPEED_DEV_ESPI,
+ ASPEED_DEV_UDC,
+ ASPEED_DEV_SGPIOM,
+ ASPEED_DEV_JTAG0,
+ ASPEED_DEV_JTAG1,
+ ASPEED_DEV_FSI1,
+ ASPEED_DEV_FSI2,
};
+qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int dev);
+bool aspeed_soc_uart_realize(AspeedSoCState *s, Error **errp);
+void aspeed_soc_uart_set_chr(AspeedSoCState *s, int dev, Chardev *chr);
+bool aspeed_soc_dram_init(AspeedSoCState *s, Error **errp);
+void aspeed_mmio_map(AspeedSoCState *s, SysBusDevice *dev, int n, hwaddr addr);
+void aspeed_mmio_map_unimplemented(AspeedSoCState *s, SysBusDevice *dev,
+ const char *name, hwaddr addr,
+ uint64_t size);
+void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
+ unsigned int count, int unit0);
+
+static inline int aspeed_uart_index(int uart_dev)
+{
+ return uart_dev - ASPEED_DEV_UART0;
+}
+
+static inline int aspeed_uart_first(AspeedSoCClass *sc)
+{
+ return aspeed_uart_index(sc->uarts_base);
+}
+
+static inline int aspeed_uart_last(AspeedSoCClass *sc)
+{
+ return aspeed_uart_first(sc) + sc->uarts_num - 1;
+}
+
#endif /* ASPEED_SOC_H */
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
index 48a0ad1633..636203baa5 100644
--- a/include/hw/arm/bcm2835_peripherals.h
+++ b/include/hw/arm/bcm2835_peripherals.h
@@ -17,24 +17,32 @@
#include "hw/char/bcm2835_aux.h"
#include "hw/display/bcm2835_fb.h"
#include "hw/dma/bcm2835_dma.h"
+#include "hw/or-irq.h"
#include "hw/intc/bcm2835_ic.h"
#include "hw/misc/bcm2835_property.h"
#include "hw/misc/bcm2835_rng.h"
#include "hw/misc/bcm2835_mbox.h"
#include "hw/misc/bcm2835_mphi.h"
#include "hw/misc/bcm2835_thermal.h"
+#include "hw/misc/bcm2835_cprman.h"
+#include "hw/misc/bcm2835_powermgt.h"
#include "hw/sd/sdhci.h"
#include "hw/sd/bcm2835_sdhost.h"
#include "hw/gpio/bcm2835_gpio.h"
#include "hw/timer/bcm2835_systmr.h"
#include "hw/usb/hcd-dwc2.h"
+#include "hw/ssi/bcm2835_spi.h"
+#include "hw/i2c/bcm2835_i2c.h"
#include "hw/misc/unimp.h"
+#include "qom/object.h"
+#define TYPE_BCM_SOC_PERIPHERALS_BASE "bcm-soc-peripherals-base"
+OBJECT_DECLARE_TYPE(BCMSocPeripheralBaseState, BCMSocPeripheralBaseClass,
+ BCM_SOC_PERIPHERALS_BASE)
#define TYPE_BCM2835_PERIPHERALS "bcm2835-peripherals"
-#define BCM2835_PERIPHERALS(obj) \
- OBJECT_CHECK(BCM2835PeripheralState, (obj), TYPE_BCM2835_PERIPHERALS)
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835PeripheralState, BCM2835_PERIPHERALS)
-typedef struct BCM2835PeripheralState {
+struct BCMSocPeripheralBaseState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -45,31 +53,53 @@ typedef struct BCM2835PeripheralState {
BCM2835SystemTimerState systmr;
BCM2835MphiState mphi;
+ UnimplementedDeviceState txp;
UnimplementedDeviceState armtmr;
- UnimplementedDeviceState cprman;
- UnimplementedDeviceState a2w;
+ BCM2835PowerMgtState powermgt;
+ BCM2835CprmanState cprman;
PL011State uart0;
BCM2835AuxState aux;
BCM2835FBState fb;
BCM2835DMAState dma;
+ OrIRQState orgated_dma_irq;
BCM2835ICState ic;
BCM2835PropertyState property;
- BCM2835RngState rng;
BCM2835MboxState mboxes;
SDHCIState sdhci;
BCM2835SDHostState sdhost;
- BCM2835GpioState gpio;
- Bcm2835ThermalState thermal;
UnimplementedDeviceState i2s;
- UnimplementedDeviceState spi[1];
- UnimplementedDeviceState i2c[3];
+ BCM2835SPIState spi[1];
+ BCM2835I2CState i2c[3];
+ OrIRQState orgated_i2c_irq;
UnimplementedDeviceState otp;
UnimplementedDeviceState dbus;
UnimplementedDeviceState ave0;
+ UnimplementedDeviceState v3d;
UnimplementedDeviceState bscsl;
UnimplementedDeviceState smi;
DWC2State dwc2;
UnimplementedDeviceState sdramc;
-} BCM2835PeripheralState;
+};
+
+struct BCMSocPeripheralBaseClass {
+ /*< private >*/
+ SysBusDeviceClass parent_class;
+ /*< public >*/
+ uint64_t peri_size; /* Peripheral range size */
+};
+
+struct BCM2835PeripheralState {
+ /*< private >*/
+ BCMSocPeripheralBaseState parent_obj;
+ /*< public >*/
+ BCM2835RngState rng;
+ Bcm2835ThermalState thermal;
+ BCM2835GpioState gpio;
+};
+
+void create_unimp(BCMSocPeripheralBaseState *ps,
+ UnimplementedDeviceState *uds,
+ const char *name, hwaddr ofs, hwaddr size);
+void bcm_soc_peripherals_common_realize(DeviceState *dev, Error **errp);
#endif /* BCM2835_PERIPHERALS_H */
diff --git a/include/hw/arm/bcm2836.h b/include/hw/arm/bcm2836.h
index 79dfff9d73..918fb3bf14 100644
--- a/include/hw/arm/bcm2836.h
+++ b/include/hw/arm/bcm2836.h
@@ -15,9 +15,12 @@
#include "hw/arm/bcm2835_peripherals.h"
#include "hw/intc/bcm2836_control.h"
#include "target/arm/cpu.h"
+#include "qom/object.h"
+#define TYPE_BCM283X_BASE "bcm283x-base"
+OBJECT_DECLARE_TYPE(BCM283XBaseState, BCM283XBaseClass, BCM283X_BASE)
#define TYPE_BCM283X "bcm283x"
-#define BCM283X(obj) OBJECT_CHECK(BCM283XState, (obj), TYPE_BCM283X)
+OBJECT_DECLARE_SIMPLE_TYPE(BCM283XState, BCM283X)
#define BCM283X_NCPUS 4
@@ -25,10 +28,11 @@
* them, code using these devices should always handle them via the
* BCM283x base class, so they have no BCM2836(obj) etc macros.
*/
+#define TYPE_BCM2835 "bcm2835"
#define TYPE_BCM2836 "bcm2836"
#define TYPE_BCM2837 "bcm2837"
-typedef struct BCM283XState {
+struct BCM283XBaseState {
/*< private >*/
DeviceState parent_obj;
/*< public >*/
@@ -39,19 +43,28 @@ typedef struct BCM283XState {
ARMCPU core;
} cpu[BCM283X_NCPUS];
BCM2836ControlState control;
- BCM2835PeripheralState peripherals;
-} BCM283XState;
-
-typedef struct BCM283XInfo BCM283XInfo;
+};
-typedef struct BCM283XClass {
+struct BCM283XBaseClass {
+ /*< private >*/
DeviceClass parent_class;
- const BCM283XInfo *info;
-} BCM283XClass;
+ /*< public >*/
+ const char *name;
+ const char *cpu_type;
+ unsigned core_count;
+ hwaddr peri_base; /* Peripheral base address seen by the CPU */
+ hwaddr ctrl_base; /* Interrupt controller and mailboxes etc. */
+ int clusterid;
+};
+
+struct BCM283XState {
+ /*< private >*/
+ BCM283XBaseState parent_obj;
+ /*< public >*/
+ BCM2835PeripheralState peripherals;
+};
-#define BCM283X_CLASS(klass) \
- OBJECT_CLASS_CHECK(BCM283XClass, (klass), TYPE_BCM283X)
-#define BCM283X_GET_CLASS(obj) \
- OBJECT_GET_CLASS(BCM283XClass, (obj), TYPE_BCM283X)
+bool bcm283x_common_realize(DeviceState *dev, BCMSocPeripheralBaseState *ps,
+ Error **errp);
#endif /* BCM2836_H */
diff --git a/include/hw/arm/bcm2838.h b/include/hw/arm/bcm2838.h
new file mode 100644
index 0000000000..e53c7bedf9
--- /dev/null
+++ b/include/hw/arm/bcm2838.h
@@ -0,0 +1,31 @@
+/*
+ * BCM2838 SoC emulation
+ *
+ * Copyright (C) 2022 Ovchinnikov Vitalii <vitalii.ovchinnikov@auriga.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef BCM2838_H
+#define BCM2838_H
+
+#include "hw/arm/bcm2836.h"
+#include "hw/intc/arm_gic.h"
+#include "hw/arm/bcm2838_peripherals.h"
+
+#define BCM2838_PERI_LOW_BASE 0xfc000000
+#define BCM2838_GIC_BASE 0x40000
+
+#define TYPE_BCM2838 "bcm2838"
+
+OBJECT_DECLARE_TYPE(BCM2838State, BCM2838Class, BCM2838)
+
+struct BCM2838State {
+ /*< private >*/
+ BCM283XBaseState parent_obj;
+ /*< public >*/
+ BCM2838PeripheralState peripherals;
+ GICState gic;
+};
+
+#endif /* BCM2838_H */
diff --git a/include/hw/arm/bcm2838_peripherals.h b/include/hw/arm/bcm2838_peripherals.h
new file mode 100644
index 0000000000..7ee1bd066f
--- /dev/null
+++ b/include/hw/arm/bcm2838_peripherals.h
@@ -0,0 +1,84 @@
+/*
+ * BCM2838 peripherals emulation
+ *
+ * Copyright (C) 2022 Ovchinnikov Vitalii <vitalii.ovchinnikov@auriga.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef BCM2838_PERIPHERALS_H
+#define BCM2838_PERIPHERALS_H
+
+#include "hw/arm/bcm2835_peripherals.h"
+#include "hw/sd/sdhci.h"
+#include "hw/gpio/bcm2838_gpio.h"
+
+/* SPI */
+#define GIC_SPI_INTERRUPT_MBOX 33
+#define GIC_SPI_INTERRUPT_MPHI 40
+#define GIC_SPI_INTERRUPT_DWC2 73
+#define GIC_SPI_INTERRUPT_DMA_0 80
+#define GIC_SPI_INTERRUPT_DMA_6 86
+#define GIC_SPI_INTERRUPT_DMA_7_8 87
+#define GIC_SPI_INTERRUPT_DMA_9_10 88
+#define GIC_SPI_INTERRUPT_AUX_UART1 93
+#define GIC_SPI_INTERRUPT_SDHOST 120
+#define GIC_SPI_INTERRUPT_UART0 121
+#define GIC_SPI_INTERRUPT_RNG200 125
+#define GIC_SPI_INTERRUPT_EMMC_EMMC2 126
+#define GIC_SPI_INTERRUPT_PCI_INT_A 143
+#define GIC_SPI_INTERRUPT_GENET_A 157
+#define GIC_SPI_INTERRUPT_GENET_B 158
+
+
+/* GPU (legacy) DMA interrupts */
+#define GPU_INTERRUPT_DMA0 16
+#define GPU_INTERRUPT_DMA1 17
+#define GPU_INTERRUPT_DMA2 18
+#define GPU_INTERRUPT_DMA3 19
+#define GPU_INTERRUPT_DMA4 20
+#define GPU_INTERRUPT_DMA5 21
+#define GPU_INTERRUPT_DMA6 22
+#define GPU_INTERRUPT_DMA7_8 23
+#define GPU_INTERRUPT_DMA9_10 24
+#define GPU_INTERRUPT_DMA11 25
+#define GPU_INTERRUPT_DMA12 26
+#define GPU_INTERRUPT_DMA13 27
+#define GPU_INTERRUPT_DMA14 28
+#define GPU_INTERRUPT_DMA15 31
+
+#define BCM2838_MPHI_OFFSET 0xb200
+#define BCM2838_MPHI_SIZE 0x200
+
+#define TYPE_BCM2838_PERIPHERALS "bcm2838-peripherals"
+OBJECT_DECLARE_TYPE(BCM2838PeripheralState, BCM2838PeripheralClass,
+ BCM2838_PERIPHERALS)
+
+struct BCM2838PeripheralState {
+ /*< private >*/
+ BCMSocPeripheralBaseState parent_obj;
+
+ /*< public >*/
+ MemoryRegion peri_low_mr;
+ MemoryRegion peri_low_mr_alias;
+ MemoryRegion mphi_mr_alias;
+
+ SDHCIState emmc2;
+ BCM2838GpioState gpio;
+
+ OrIRQState mmc_irq_orgate;
+ OrIRQState dma_7_8_irq_orgate;
+ OrIRQState dma_9_10_irq_orgate;
+
+ UnimplementedDeviceState asb;
+ UnimplementedDeviceState clkisp;
+};
+
+struct BCM2838PeripheralClass {
+ /*< private >*/
+ BCMSocPeripheralBaseClass parent_class;
+ /*< public >*/
+ uint64_t peri_low_size; /* Peripheral lower range size */
+};
+
+#endif /* BCM2838_PERIPHERALS_H */
diff --git a/include/hw/arm/boot.h b/include/hw/arm/boot.h
index ce2b48b88b..80c492d742 100644
--- a/include/hw/arm/boot.h
+++ b/include/hw/arm/boot.h
@@ -25,13 +25,16 @@ typedef enum {
* armv7m_load_kernel:
* @cpu: CPU
* @kernel_filename: file to load
+ * @mem_base: base address to load image at (should be where the
+ * CPU expects to find its vector table on reset)
* @mem_size: mem_size: maximum image size to load
*
* Load the guest image for an ARMv7M system. This must be called by
* any ARMv7M board. (This is necessary to ensure that the CPU resets
* correctly on system reset, as well as for kernel loading.)
*/
-void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size);
+void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename,
+ hwaddr mem_base, int mem_size);
/* arm_boot.c */
struct arm_boot_info {
@@ -56,7 +59,6 @@ struct arm_boot_info {
hwaddr smp_loader_start;
hwaddr smp_bootreg_addr;
hwaddr gic_cpu_if_addr;
- int nb_cpus;
int board_id;
/* ARM machines that support the ARM Security Extensions use this field to
* control whether Linux is booted as secure(true) or non-secure(false).
@@ -70,6 +72,9 @@ struct arm_boot_info {
* boot loader/boot ROM code, and secondary_cpu_reset_hook() should
* perform any necessary CPU reset handling and set the PC for the
* secondary CPUs to point at this boot blob.
+ *
+ * These hooks won't be called if secondary CPUs are booting via
+ * emulated PSCI (see psci_conduit below).
*/
void (*write_secondary_boot)(ARMCPU *cpu,
const struct arm_boot_info *info);
@@ -86,6 +91,16 @@ struct arm_boot_info {
* the user it should implement this hook.
*/
void (*modify_dtb)(const struct arm_boot_info *info, void *fdt);
+ /*
+ * If a board wants to use the QEMU emulated-firmware PSCI support,
+ * it should set this to QEMU_PSCI_CONDUIT_HVC or QEMU_PSCI_CONDUIT_SMC
+ * as appropriate. arm_load_kernel() will set the psci-conduit and
+ * start-powered-off properties on the CPUs accordingly.
+ * Note that if the guest image is started at the same exception level
+ * as the conduit specifies calls should go to (eg guest firmware booted
+ * to EL3) then PSCI will not be enabled.
+ */
+ int psci_conduit;
/* Used internally by arm_boot.c */
int is_linux;
hwaddr initrd_start;
@@ -168,4 +183,53 @@ void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
const struct arm_boot_info *info,
hwaddr mvbar_addr);
+typedef enum {
+ FIXUP_NONE = 0, /* do nothing */
+ FIXUP_TERMINATOR, /* end of insns */
+ FIXUP_BOARDID, /* overwrite with board ID number */
+ FIXUP_BOARD_SETUP, /* overwrite with board specific setup code address */
+ FIXUP_ARGPTR_LO, /* overwrite with pointer to kernel args */
+ FIXUP_ARGPTR_HI, /* overwrite with pointer to kernel args (high half) */
+ FIXUP_ENTRYPOINT_LO, /* overwrite with kernel entry point */
+ FIXUP_ENTRYPOINT_HI, /* overwrite with kernel entry point (high half) */
+ FIXUP_GIC_CPU_IF, /* overwrite with GIC CPU interface address */
+ FIXUP_BOOTREG, /* overwrite with boot register address */
+ FIXUP_DSB, /* overwrite with correct DSB insn for cpu */
+ FIXUP_MAX,
+} FixupType;
+
+typedef struct ARMInsnFixup {
+ uint32_t insn;
+ FixupType fixup;
+} ARMInsnFixup;
+
+/**
+ * arm_write_bootloader - write a bootloader to guest memory
+ * @name: name of the bootloader blob
+ * @as: AddressSpace to write the bootloader
+ * @addr: guest address to write it
+ * @insns: the blob to be loaded
+ * @fixupcontext: context to be used for any fixups in @insns
+ *
+ * Write a bootloader to guest memory at address @addr in the address
+ * space @as. @name is the name to use for the resulting ROM blob, so
+ * it should be unique in the system and reasonably identifiable for debugging.
+ *
+ * @insns must be an array of ARMInsnFixup structs, each of which has
+ * one 32-bit value to be written to the guest memory, and a fixup to be
+ * applied to the value. FIXUP_NONE (do nothing) is value 0, so effectively
+ * the fixup is optional when writing a struct initializer.
+ * The final entry in the array must be { 0, FIXUP_TERMINATOR }.
+ *
+ * All other supported fixup types have the semantics "ignore insn
+ * and instead use the value from the array element @fixupcontext[fixup]".
+ * The caller should therefore provide @fixupcontext as an array of
+ * size FIXUP_MAX whose elements have been initialized for at least
+ * the entries that @insns refers to.
+ */
+void arm_write_bootloader(const char *name,
+ AddressSpace *as, hwaddr addr,
+ const ARMInsnFixup *insns,
+ const uint32_t *fixupcontext);
+
#endif /* HW_ARM_BOOT_H */
diff --git a/include/hw/arm/bsa.h b/include/hw/arm/bsa.h
new file mode 100644
index 0000000000..8eaab603c0
--- /dev/null
+++ b/include/hw/arm/bsa.h
@@ -0,0 +1,35 @@
+/*
+ * Common definitions for Arm Base System Architecture (BSA) platforms.
+ *
+ * Copyright (c) 2015 Linaro Limited
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef QEMU_ARM_BSA_H
+#define QEMU_ARM_BSA_H
+
+/* These are architectural INTID values */
+#define VIRTUAL_PMU_IRQ 23
+#define ARCH_GIC_MAINT_IRQ 25
+#define ARCH_TIMER_NS_EL2_IRQ 26
+#define ARCH_TIMER_VIRT_IRQ 27
+#define ARCH_TIMER_NS_EL2_VIRT_IRQ 28
+#define ARCH_TIMER_S_EL1_IRQ 29
+#define ARCH_TIMER_NS_EL1_IRQ 30
+
+#define INTID_TO_PPI(irq) ((irq) - 16)
+
+#endif /* QEMU_ARM_BSA_H */
diff --git a/include/hw/arm/digic.h b/include/hw/arm/digic.h
index 63785baaa8..8f2735c284 100644
--- a/include/hw/arm/digic.h
+++ b/include/hw/arm/digic.h
@@ -21,14 +21,15 @@
#include "cpu.h"
#include "hw/timer/digic-timer.h"
#include "hw/char/digic-uart.h"
+#include "qom/object.h"
#define TYPE_DIGIC "digic"
-#define DIGIC(obj) OBJECT_CHECK(DigicState, (obj), TYPE_DIGIC)
+OBJECT_DECLARE_SIMPLE_TYPE(DigicState, DIGIC)
#define DIGIC4_NB_TIMERS 3
-typedef struct DigicState {
+struct DigicState {
/*< private >*/
DeviceState parent_obj;
/*< public >*/
@@ -37,6 +38,6 @@ typedef struct DigicState {
DigicTimerState timer[DIGIC4_NB_TIMERS];
DigicUartState uart;
-} DigicState;
+};
#endif /* HW_ARM_DIGIC_H */
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
index 55260394af..d33fe38586 100644
--- a/include/hw/arm/exynos4210.h
+++ b/include/hw/arm/exynos4210.h
@@ -26,7 +26,12 @@
#include "hw/or-irq.h"
#include "hw/sysbus.h"
-#include "target/arm/cpu-qom.h"
+#include "hw/cpu/a9mpcore.h"
+#include "hw/intc/exynos4210_gic.h"
+#include "hw/intc/exynos4210_combiner.h"
+#include "hw/core/split-irq.h"
+#include "hw/arm/boot.h"
+#include "qom/object.h"
#define EXYNOS4210_NCPUS 2
@@ -64,34 +69,25 @@
#define EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ \
(EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ * 8)
-#define EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit) ((grp)*8 + (bit))
-#define EXYNOS4210_COMBINER_GET_GRP_NUM(irq) ((irq) / 8)
-#define EXYNOS4210_COMBINER_GET_BIT_NUM(irq) \
- ((irq) - 8 * EXYNOS4210_COMBINER_GET_GRP_NUM(irq))
-
-/* IRQs number for external and internal GIC */
-#define EXYNOS4210_EXT_GIC_NIRQ (160-32)
-#define EXYNOS4210_INT_GIC_NIRQ 64
-
#define EXYNOS4210_I2C_NUMBER 9
#define EXYNOS4210_NUM_DMA 3
-typedef struct Exynos4210Irq {
- qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
- qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
- qemu_irq int_gic_irq[EXYNOS4210_INT_GIC_NIRQ];
- qemu_irq ext_gic_irq[EXYNOS4210_EXT_GIC_NIRQ];
- qemu_irq board_irqs[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
-} Exynos4210Irq;
+/*
+ * We need one splitter for every external combiner input, plus
+ * one for every non-zero entry in combiner_grp_to_gic_id[],
+ * minus one for every external combiner ID in second or later
+ * places in a combinermap[] line.
+ * We'll assert in exynos4210_init_board_irqs() if this is wrong.
+ */
+#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 38)
-typedef struct Exynos4210State {
+struct Exynos4210State {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
ARMCPU *cpu[EXYNOS4210_NCPUS];
- Exynos4210Irq irqs;
- qemu_irq *irq_table;
+ qemu_irq irq_table[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
MemoryRegion chipid_mem;
MemoryRegion iram_mem;
@@ -100,23 +96,21 @@ typedef struct Exynos4210State {
MemoryRegion boot_secondary;
MemoryRegion bootreg_mem;
I2CBus *i2c_if[EXYNOS4210_I2C_NUMBER];
- qemu_or_irq pl330_irq_orgate[EXYNOS4210_NUM_DMA];
-} Exynos4210State;
+ OrIRQState pl330_irq_orgate[EXYNOS4210_NUM_DMA];
+ OrIRQState cpu_irq_orgate[EXYNOS4210_NCPUS];
+ A9MPPrivState a9mpcore;
+ Exynos4210GicState ext_gic;
+ Exynos4210CombinerState int_combiner;
+ Exynos4210CombinerState ext_combiner;
+ SplitIRQ splitter[EXYNOS4210_NUM_SPLITTERS];
+};
#define TYPE_EXYNOS4210_SOC "exynos4210"
-#define EXYNOS4210_SOC(obj) \
- OBJECT_CHECK(Exynos4210State, obj, TYPE_EXYNOS4210_SOC)
+OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210State, EXYNOS4210_SOC)
void exynos4210_write_secondary(ARMCPU *cpu,
const struct arm_boot_info *info);
-/* Initialize exynos4210 IRQ subsystem stub */
-qemu_irq *exynos4210_init_irq(Exynos4210Irq *env);
-
-/* Initialize board IRQs.
- * These IRQs contain splitted Int/External Combiner and External Gic IRQs */
-void exynos4210_init_board_irqs(Exynos4210Irq *s);
-
/* Get IRQ number from exynos4210 IRQ subsystem stub.
* To identify IRQ source use internal combiner group and bit number
* grp - group number
@@ -124,12 +118,6 @@ void exynos4210_init_board_irqs(Exynos4210Irq *s);
uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit);
/*
- * Get Combiner input GPIO into irqs structure
- */
-void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs, DeviceState *dev,
- int ext);
-
-/*
* exynos4210 UART
*/
DeviceState *exynos4210_uart_create(hwaddr addr,
diff --git a/include/hw/arm/fsl-imx25.h b/include/hw/arm/fsl-imx25.h
index 54ee1bfd78..df2f83980f 100644
--- a/include/hw/arm/fsl-imx25.h
+++ b/include/hw/arm/fsl-imx25.h
@@ -17,7 +17,6 @@
#ifndef FSL_IMX25_H
#define FSL_IMX25_H
-#include "hw/arm/boot.h"
#include "hw/intc/imx_avic.h"
#include "hw/misc/imx25_ccm.h"
#include "hw/char/imx_serial.h"
@@ -32,9 +31,10 @@
#include "hw/watchdog/wdt_imx2.h"
#include "exec/memory.h"
#include "target/arm/cpu.h"
+#include "qom/object.h"
-#define TYPE_FSL_IMX25 "fsl,imx25"
-#define FSL_IMX25(obj) OBJECT_CHECK(FslIMX25State, (obj), TYPE_FSL_IMX25)
+#define TYPE_FSL_IMX25 "fsl-imx25"
+OBJECT_DECLARE_SIMPLE_TYPE(FslIMX25State, FSL_IMX25)
#define FSL_IMX25_NUM_UARTS 5
#define FSL_IMX25_NUM_GPTS 4
@@ -44,7 +44,7 @@
#define FSL_IMX25_NUM_ESDHCS 2
#define FSL_IMX25_NUM_USBS 2
-typedef struct FslIMX25State {
+struct FslIMX25State {
/*< private >*/
DeviceState parent_obj;
@@ -66,7 +66,7 @@ typedef struct FslIMX25State {
MemoryRegion iram;
MemoryRegion iram_alias;
uint32_t phy_num;
-} FslIMX25State;
+};
/**
* i.MX25 memory map
@@ -178,7 +178,7 @@ typedef struct FslIMX25State {
* 0xBB00_0000 0xBB00_0FFF 4 Kbytes NAND flash main area buffer
* 0xBB00_1000 0xBB00_11FF 512 B NAND flash spare area buffer
* 0xBB00_1200 0xBB00_1DFF 3 Kbytes Reserved
- * 0xBB00_1E00 0xBB00_1FFF 512 B NAND flash control regisers
+ * 0xBB00_1E00 0xBB00_1FFF 512 B NAND flash control registers
* 0xBB01_2000 0xBFFF_FFFF 96 Mbytes (minus 8 Kbytes) Reserved
* 0xC000_0000 0xFFFF_FFFF 1024 Mbytes Reserved
*/
diff --git a/include/hw/arm/fsl-imx31.h b/include/hw/arm/fsl-imx31.h
index dd8561b309..40c593a5cf 100644
--- a/include/hw/arm/fsl-imx31.h
+++ b/include/hw/arm/fsl-imx31.h
@@ -17,7 +17,6 @@
#ifndef FSL_IMX31_H
#define FSL_IMX31_H
-#include "hw/arm/boot.h"
#include "hw/intc/imx_avic.h"
#include "hw/misc/imx31_ccm.h"
#include "hw/char/imx_serial.h"
@@ -28,16 +27,17 @@
#include "hw/watchdog/wdt_imx2.h"
#include "exec/memory.h"
#include "target/arm/cpu.h"
+#include "qom/object.h"
-#define TYPE_FSL_IMX31 "fsl,imx31"
-#define FSL_IMX31(obj) OBJECT_CHECK(FslIMX31State, (obj), TYPE_FSL_IMX31)
+#define TYPE_FSL_IMX31 "fsl-imx31"
+OBJECT_DECLARE_SIMPLE_TYPE(FslIMX31State, FSL_IMX31)
#define FSL_IMX31_NUM_UARTS 2
#define FSL_IMX31_NUM_EPITS 2
#define FSL_IMX31_NUM_I2CS 3
#define FSL_IMX31_NUM_GPIOS 3
-typedef struct FslIMX31State {
+struct FslIMX31State {
/*< private >*/
DeviceState parent_obj;
@@ -55,7 +55,7 @@ typedef struct FslIMX31State {
MemoryRegion rom;
MemoryRegion iram;
MemoryRegion iram_alias;
-} FslIMX31State;
+};
#define FSL_IMX31_SECURE_ROM_ADDR 0x00000000
#define FSL_IMX31_SECURE_ROM_SIZE 0x4000
diff --git a/include/hw/arm/fsl-imx6.h b/include/hw/arm/fsl-imx6.h
index 162fe99375..61c593ffd2 100644
--- a/include/hw/arm/fsl-imx6.h
+++ b/include/hw/arm/fsl-imx6.h
@@ -17,10 +17,10 @@
#ifndef FSL_IMX6_H
#define FSL_IMX6_H
-#include "hw/arm/boot.h"
#include "hw/cpu/a9mpcore.h"
#include "hw/misc/imx6_ccm.h"
#include "hw/misc/imx6_src.h"
+#include "hw/misc/imx7_snvs.h"
#include "hw/watchdog/wdt_imx2.h"
#include "hw/char/imx_serial.h"
#include "hw/timer/imx_gpt.h"
@@ -32,11 +32,13 @@
#include "hw/net/imx_fec.h"
#include "hw/usb/chipidea.h"
#include "hw/usb/imx-usb-phy.h"
+#include "hw/pci-host/designware.h"
#include "exec/memory.h"
#include "cpu.h"
+#include "qom/object.h"
-#define TYPE_FSL_IMX6 "fsl,imx6"
-#define FSL_IMX6(obj) OBJECT_CHECK(FslIMX6State, (obj), TYPE_FSL_IMX6)
+#define TYPE_FSL_IMX6 "fsl-imx6"
+OBJECT_DECLARE_SIMPLE_TYPE(FslIMX6State, FSL_IMX6)
#define FSL_IMX6_NUM_CPUS 4
#define FSL_IMX6_NUM_UARTS 5
@@ -49,32 +51,34 @@
#define FSL_IMX6_NUM_USB_PHYS 2
#define FSL_IMX6_NUM_USBS 4
-typedef struct FslIMX6State {
+struct FslIMX6State {
/*< private >*/
DeviceState parent_obj;
/*< public >*/
- ARMCPU cpu[FSL_IMX6_NUM_CPUS];
- A9MPPrivState a9mpcore;
- IMX6CCMState ccm;
- IMX6SRCState src;
- IMXSerialState uart[FSL_IMX6_NUM_UARTS];
- IMXGPTState gpt;
- IMXEPITState epit[FSL_IMX6_NUM_EPITS];
- IMXI2CState i2c[FSL_IMX6_NUM_I2CS];
- IMXGPIOState gpio[FSL_IMX6_NUM_GPIOS];
- SDHCIState esdhc[FSL_IMX6_NUM_ESDHCS];
- IMXSPIState spi[FSL_IMX6_NUM_ECSPIS];
- IMX2WdtState wdt[FSL_IMX6_NUM_WDTS];
- IMXUSBPHYState usbphy[FSL_IMX6_NUM_USB_PHYS];
- ChipideaState usb[FSL_IMX6_NUM_USBS];
- IMXFECState eth;
- MemoryRegion rom;
- MemoryRegion caam;
- MemoryRegion ocram;
- MemoryRegion ocram_alias;
- uint32_t phy_num;
-} FslIMX6State;
+ ARMCPU cpu[FSL_IMX6_NUM_CPUS];
+ A9MPPrivState a9mpcore;
+ IMX6CCMState ccm;
+ IMX6SRCState src;
+ IMX7SNVSState snvs;
+ IMXSerialState uart[FSL_IMX6_NUM_UARTS];
+ IMXGPTState gpt;
+ IMXEPITState epit[FSL_IMX6_NUM_EPITS];
+ IMXI2CState i2c[FSL_IMX6_NUM_I2CS];
+ IMXGPIOState gpio[FSL_IMX6_NUM_GPIOS];
+ SDHCIState esdhc[FSL_IMX6_NUM_ESDHCS];
+ IMXSPIState spi[FSL_IMX6_NUM_ECSPIS];
+ IMX2WdtState wdt[FSL_IMX6_NUM_WDTS];
+ IMXUSBPHYState usbphy[FSL_IMX6_NUM_USB_PHYS];
+ ChipideaState usb[FSL_IMX6_NUM_USBS];
+ IMXFECState eth;
+ DesignwarePCIEHost pcie;
+ MemoryRegion rom;
+ MemoryRegion caam;
+ MemoryRegion ocram;
+ MemoryRegion ocram_alias;
+ uint32_t phy_num;
+};
#define FSL_IMX6_MMDC_ADDR 0x10000000
diff --git a/include/hw/arm/fsl-imx6ul.h b/include/hw/arm/fsl-imx6ul.h
index fcbaf3dc86..8277b0e8b2 100644
--- a/include/hw/arm/fsl-imx6ul.h
+++ b/include/hw/arm/fsl-imx6ul.h
@@ -17,12 +17,10 @@
#ifndef FSL_IMX6UL_H
#define FSL_IMX6UL_H
-#include "hw/arm/boot.h"
#include "hw/cpu/a15mpcore.h"
#include "hw/misc/imx6ul_ccm.h"
#include "hw/misc/imx6_src.h"
#include "hw/misc/imx7_snvs.h"
-#include "hw/misc/imx7_gpr.h"
#include "hw/intc/imx_gpcv2.h"
#include "hw/watchdog/wdt_imx2.h"
#include "hw/gpio/imx_gpio.h"
@@ -30,7 +28,6 @@
#include "hw/timer/imx_gpt.h"
#include "hw/timer/imx_epit.h"
#include "hw/i2c/imx_i2c.h"
-#include "hw/gpio/imx_gpio.h"
#include "hw/sd/sdhci.h"
#include "hw/ssi/imx_spi.h"
#include "hw/net/imx_fec.h"
@@ -38,9 +35,11 @@
#include "hw/usb/imx-usb-phy.h"
#include "exec/memory.h"
#include "cpu.h"
+#include "qom/object.h"
+#include "qemu/units.h"
-#define TYPE_FSL_IMX6UL "fsl,imx6ul"
-#define FSL_IMX6UL(obj) OBJECT_CHECK(FslIMX6ULState, (obj), TYPE_FSL_IMX6UL)
+#define TYPE_FSL_IMX6UL "fsl-imx6ul"
+OBJECT_DECLARE_SIMPLE_TYPE(FslIMX6ULState, FSL_IMX6UL)
enum FslIMX6ULConfiguration {
FSL_IMX6UL_NUM_CPUS = 1,
@@ -58,9 +57,12 @@ enum FslIMX6ULConfiguration {
FSL_IMX6UL_NUM_ADCS = 2,
FSL_IMX6UL_NUM_USB_PHYS = 2,
FSL_IMX6UL_NUM_USBS = 2,
+ FSL_IMX6UL_NUM_SAIS = 3,
+ FSL_IMX6UL_NUM_CANS = 2,
+ FSL_IMX6UL_NUM_PWMS = 8,
};
-typedef struct FslIMX6ULState {
+struct FslIMX6ULState {
/*< private >*/
DeviceState parent_obj;
@@ -74,7 +76,6 @@ typedef struct FslIMX6ULState {
IMX6SRCState src;
IMX7SNVSState snvs;
IMXGPCv2State gpcv2;
- IMX7GPRState gpr;
IMXSPIState spi[FSL_IMX6UL_NUM_ECSPIS];
IMXI2CState i2c[FSL_IMX6UL_NUM_I2CS];
IMXSerialState uart[FSL_IMX6UL_NUM_UARTS];
@@ -89,123 +90,234 @@ typedef struct FslIMX6ULState {
MemoryRegion ocram_alias;
uint32_t phy_num[FSL_IMX6UL_NUM_ETHS];
-} FslIMX6ULState;
+ bool phy_connected[FSL_IMX6UL_NUM_ETHS];
+};
enum FslIMX6ULMemoryMap {
FSL_IMX6UL_MMDC_ADDR = 0x80000000,
- FSL_IMX6UL_MMDC_SIZE = 2 * 1024 * 1024 * 1024UL,
+ FSL_IMX6UL_MMDC_SIZE = (2 * GiB),
FSL_IMX6UL_QSPI1_MEM_ADDR = 0x60000000,
+ FSL_IMX6UL_QSPI1_MEM_SIZE = (256 * MiB),
+
FSL_IMX6UL_EIM_ALIAS_ADDR = 0x58000000,
+ FSL_IMX6UL_EIM_ALIAS_SIZE = (128 * MiB),
+
FSL_IMX6UL_EIM_CS_ADDR = 0x50000000,
+ FSL_IMX6UL_EIM_CS_SIZE = (128 * MiB),
+
FSL_IMX6UL_AES_ENCRYPT_ADDR = 0x10000000,
+ FSL_IMX6UL_AES_ENCRYPT_SIZE = (1 * MiB),
+
FSL_IMX6UL_QSPI1_RX_ADDR = 0x0C000000,
+ FSL_IMX6UL_QSPI1_RX_SIZE = (32 * MiB),
- /* AIPS-2 */
+ /* AIPS-2 Begin */
FSL_IMX6UL_UART6_ADDR = 0x021FC000,
+
FSL_IMX6UL_I2C4_ADDR = 0x021F8000,
+
FSL_IMX6UL_UART5_ADDR = 0x021F4000,
FSL_IMX6UL_UART4_ADDR = 0x021F0000,
FSL_IMX6UL_UART3_ADDR = 0x021EC000,
FSL_IMX6UL_UART2_ADDR = 0x021E8000,
+
FSL_IMX6UL_WDOG3_ADDR = 0x021E4000,
+
FSL_IMX6UL_QSPI_ADDR = 0x021E0000,
+ FSL_IMX6UL_QSPI_SIZE = 0x500,
+
FSL_IMX6UL_SYS_CNT_CTRL_ADDR = 0x021DC000,
+ FSL_IMX6UL_SYS_CNT_CTRL_SIZE = (16 * KiB),
+
FSL_IMX6UL_SYS_CNT_CMP_ADDR = 0x021D8000,
+ FSL_IMX6UL_SYS_CNT_CMP_SIZE = (16 * KiB),
+
FSL_IMX6UL_SYS_CNT_RD_ADDR = 0x021D4000,
+ FSL_IMX6UL_SYS_CNT_RD_SIZE = (16 * KiB),
+
FSL_IMX6UL_TZASC_ADDR = 0x021D0000,
+ FSL_IMX6UL_TZASC_SIZE = (16 * KiB),
+
FSL_IMX6UL_PXP_ADDR = 0x021CC000,
+ FSL_IMX6UL_PXP_SIZE = (16 * KiB),
+
FSL_IMX6UL_LCDIF_ADDR = 0x021C8000,
+ FSL_IMX6UL_LCDIF_SIZE = 0x100,
+
FSL_IMX6UL_CSI_ADDR = 0x021C4000,
+ FSL_IMX6UL_CSI_SIZE = 0x100,
+
FSL_IMX6UL_CSU_ADDR = 0x021C0000,
+ FSL_IMX6UL_CSU_SIZE = (16 * KiB),
+
FSL_IMX6UL_OCOTP_CTRL_ADDR = 0x021BC000,
+ FSL_IMX6UL_OCOTP_CTRL_SIZE = (4 * KiB),
+
FSL_IMX6UL_EIM_ADDR = 0x021B8000,
+ FSL_IMX6UL_EIM_SIZE = 0x100,
+
FSL_IMX6UL_SIM2_ADDR = 0x021B4000,
+
FSL_IMX6UL_MMDC_CFG_ADDR = 0x021B0000,
+ FSL_IMX6UL_MMDC_CFG_SIZE = (4 * KiB),
+
FSL_IMX6UL_ROMCP_ADDR = 0x021AC000,
+ FSL_IMX6UL_ROMCP_SIZE = 0x300,
+
FSL_IMX6UL_I2C3_ADDR = 0x021A8000,
FSL_IMX6UL_I2C2_ADDR = 0x021A4000,
FSL_IMX6UL_I2C1_ADDR = 0x021A0000,
+
FSL_IMX6UL_ADC2_ADDR = 0x0219C000,
FSL_IMX6UL_ADC1_ADDR = 0x02198000,
+ FSL_IMX6UL_ADCn_SIZE = 0x100,
+
FSL_IMX6UL_USDHC2_ADDR = 0x02194000,
FSL_IMX6UL_USDHC1_ADDR = 0x02190000,
+
FSL_IMX6UL_SIM1_ADDR = 0x0218C000,
+ FSL_IMX6UL_SIMn_SIZE = (16 * KiB),
+
FSL_IMX6UL_ENET1_ADDR = 0x02188000,
+
FSL_IMX6UL_USBO2_USBMISC_ADDR = 0x02184800,
- FSL_IMX6UL_USBO2_USB_ADDR = 0x02184000,
+ FSL_IMX6UL_USBO2_USBMISC_SIZE = 0x200,
+
+ FSL_IMX6UL_USBO2_USB1_ADDR = 0x02184000,
+ FSL_IMX6UL_USBO2_USB2_ADDR = 0x02184200,
+
FSL_IMX6UL_USBO2_PL301_ADDR = 0x02180000,
+ FSL_IMX6UL_USBO2_PL301_SIZE = (16 * KiB),
+
FSL_IMX6UL_AIPS2_CFG_ADDR = 0x0217C000,
+ FSL_IMX6UL_AIPS2_CFG_SIZE = 0x100,
+
FSL_IMX6UL_CAAM_ADDR = 0x02140000,
+ FSL_IMX6UL_CAAM_SIZE = (16 * KiB),
+
FSL_IMX6UL_A7MPCORE_DAP_ADDR = 0x02100000,
+ FSL_IMX6UL_A7MPCORE_DAP_SIZE = (4 * KiB),
+ /* AIPS-2 End */
- /* AIPS-1 */
+ /* AIPS-1 Begin */
FSL_IMX6UL_PWM8_ADDR = 0x020FC000,
FSL_IMX6UL_PWM7_ADDR = 0x020F8000,
FSL_IMX6UL_PWM6_ADDR = 0x020F4000,
FSL_IMX6UL_PWM5_ADDR = 0x020F0000,
+
FSL_IMX6UL_SDMA_ADDR = 0x020EC000,
+ FSL_IMX6UL_SDMA_SIZE = 0x300,
+
FSL_IMX6UL_GPT2_ADDR = 0x020E8000,
+
FSL_IMX6UL_IOMUXC_GPR_ADDR = 0x020E4000,
+ FSL_IMX6UL_IOMUXC_GPR_SIZE = 0x40,
+
FSL_IMX6UL_IOMUXC_ADDR = 0x020E0000,
+ FSL_IMX6UL_IOMUXC_SIZE = 0x700,
+
FSL_IMX6UL_GPC_ADDR = 0x020DC000,
+
FSL_IMX6UL_SRC_ADDR = 0x020D8000,
+
FSL_IMX6UL_EPIT2_ADDR = 0x020D4000,
FSL_IMX6UL_EPIT1_ADDR = 0x020D0000,
+
FSL_IMX6UL_SNVS_HP_ADDR = 0x020CC000,
+
FSL_IMX6UL_USBPHY2_ADDR = 0x020CA000,
- FSL_IMX6UL_USBPHY2_SIZE = (4 * 1024),
FSL_IMX6UL_USBPHY1_ADDR = 0x020C9000,
- FSL_IMX6UL_USBPHY1_SIZE = (4 * 1024),
+
FSL_IMX6UL_ANALOG_ADDR = 0x020C8000,
+ FSL_IMX6UL_ANALOG_SIZE = 0x300,
+
FSL_IMX6UL_CCM_ADDR = 0x020C4000,
+
FSL_IMX6UL_WDOG2_ADDR = 0x020C0000,
FSL_IMX6UL_WDOG1_ADDR = 0x020BC000,
+
FSL_IMX6UL_KPP_ADDR = 0x020B8000,
+ FSL_IMX6UL_KPP_SIZE = 0x10,
+
FSL_IMX6UL_ENET2_ADDR = 0x020B4000,
+
FSL_IMX6UL_SNVS_LP_ADDR = 0x020B0000,
+ FSL_IMX6UL_SNVS_LP_SIZE = (16 * KiB),
+
FSL_IMX6UL_GPIO5_ADDR = 0x020AC000,
FSL_IMX6UL_GPIO4_ADDR = 0x020A8000,
FSL_IMX6UL_GPIO3_ADDR = 0x020A4000,
FSL_IMX6UL_GPIO2_ADDR = 0x020A0000,
FSL_IMX6UL_GPIO1_ADDR = 0x0209C000,
+
FSL_IMX6UL_GPT1_ADDR = 0x02098000,
+
FSL_IMX6UL_CAN2_ADDR = 0x02094000,
FSL_IMX6UL_CAN1_ADDR = 0x02090000,
+ FSL_IMX6UL_CANn_SIZE = (4 * KiB),
+
FSL_IMX6UL_PWM4_ADDR = 0x0208C000,
FSL_IMX6UL_PWM3_ADDR = 0x02088000,
FSL_IMX6UL_PWM2_ADDR = 0x02084000,
FSL_IMX6UL_PWM1_ADDR = 0x02080000,
+ FSL_IMX6UL_PWMn_SIZE = 0x20,
+
FSL_IMX6UL_AIPS1_CFG_ADDR = 0x0207C000,
+ FSL_IMX6UL_AIPS1_CFG_SIZE = (16 * KiB),
+
FSL_IMX6UL_BEE_ADDR = 0x02044000,
+ FSL_IMX6UL_BEE_SIZE = (16 * KiB),
+
FSL_IMX6UL_TOUCH_CTRL_ADDR = 0x02040000,
+ FSL_IMX6UL_TOUCH_CTRL_SIZE = 0x100,
+
FSL_IMX6UL_SPBA_ADDR = 0x0203C000,
+ FSL_IMX6UL_SPBA_SIZE = 0x100,
+
FSL_IMX6UL_ASRC_ADDR = 0x02034000,
+ FSL_IMX6UL_ASRC_SIZE = 0x100,
+
FSL_IMX6UL_SAI3_ADDR = 0x02030000,
FSL_IMX6UL_SAI2_ADDR = 0x0202C000,
FSL_IMX6UL_SAI1_ADDR = 0x02028000,
+ FSL_IMX6UL_SAIn_SIZE = 0x200,
+
FSL_IMX6UL_UART8_ADDR = 0x02024000,
FSL_IMX6UL_UART1_ADDR = 0x02020000,
FSL_IMX6UL_UART7_ADDR = 0x02018000,
+
FSL_IMX6UL_ECSPI4_ADDR = 0x02014000,
FSL_IMX6UL_ECSPI3_ADDR = 0x02010000,
FSL_IMX6UL_ECSPI2_ADDR = 0x0200C000,
FSL_IMX6UL_ECSPI1_ADDR = 0x02008000,
+
FSL_IMX6UL_SPDIF_ADDR = 0x02004000,
+ FSL_IMX6UL_SPDIF_SIZE = 0x100,
+ /* AIPS-1 End */
+
+ FSL_IMX6UL_BCH_ADDR = 0x01808000,
+ FSL_IMX6UL_BCH_SIZE = 0x200,
+
+ FSL_IMX6UL_GPMI_ADDR = 0x01806000,
+ FSL_IMX6UL_GPMI_SIZE = 0x200,
FSL_IMX6UL_APBH_DMA_ADDR = 0x01804000,
- FSL_IMX6UL_APBH_DMA_SIZE = (32 * 1024),
+ FSL_IMX6UL_APBH_DMA_SIZE = (4 * KiB),
FSL_IMX6UL_A7MPCORE_ADDR = 0x00A00000,
FSL_IMX6UL_OCRAM_ALIAS_ADDR = 0x00920000,
- FSL_IMX6UL_OCRAM_ALIAS_SIZE = 0x00060000,
+ FSL_IMX6UL_OCRAM_ALIAS_SIZE = (384 * KiB),
+
FSL_IMX6UL_OCRAM_MEM_ADDR = 0x00900000,
- FSL_IMX6UL_OCRAM_MEM_SIZE = 0x00020000,
+ FSL_IMX6UL_OCRAM_MEM_SIZE = (128 * KiB),
+
FSL_IMX6UL_CAAM_MEM_ADDR = 0x00100000,
- FSL_IMX6UL_CAAM_MEM_SIZE = 0x00008000,
+ FSL_IMX6UL_CAAM_MEM_SIZE = (32 * KiB),
+
FSL_IMX6UL_ROM_ADDR = 0x00000000,
- FSL_IMX6UL_ROM_SIZE = 0x00018000,
+ FSL_IMX6UL_ROM_SIZE = (96 * KiB),
};
enum FslIMX6ULIRQs {
diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h
index ad88923707..411fa1c2e3 100644
--- a/include/hw/arm/fsl-imx7.h
+++ b/include/hw/arm/fsl-imx7.h
@@ -19,29 +19,29 @@
#ifndef FSL_IMX7_H
#define FSL_IMX7_H
-#include "hw/arm/boot.h"
#include "hw/cpu/a15mpcore.h"
#include "hw/intc/imx_gpcv2.h"
#include "hw/misc/imx7_ccm.h"
#include "hw/misc/imx7_snvs.h"
#include "hw/misc/imx7_gpr.h"
-#include "hw/misc/imx6_src.h"
+#include "hw/misc/imx7_src.h"
#include "hw/watchdog/wdt_imx2.h"
#include "hw/gpio/imx_gpio.h"
#include "hw/char/imx_serial.h"
#include "hw/timer/imx_gpt.h"
#include "hw/timer/imx_epit.h"
#include "hw/i2c/imx_i2c.h"
-#include "hw/gpio/imx_gpio.h"
#include "hw/sd/sdhci.h"
#include "hw/ssi/imx_spi.h"
#include "hw/net/imx_fec.h"
#include "hw/pci-host/designware.h"
#include "hw/usb/chipidea.h"
#include "cpu.h"
+#include "qom/object.h"
+#include "qemu/units.h"
-#define TYPE_FSL_IMX7 "fsl,imx7"
-#define FSL_IMX7(obj) OBJECT_CHECK(FslIMX7State, (obj), TYPE_FSL_IMX7)
+#define TYPE_FSL_IMX7 "fsl-imx7"
+OBJECT_DECLARE_SIMPLE_TYPE(FslIMX7State, FSL_IMX7)
enum FslIMX7Configuration {
FSL_IMX7_NUM_CPUS = 2,
@@ -57,9 +57,12 @@ enum FslIMX7Configuration {
FSL_IMX7_NUM_ECSPIS = 4,
FSL_IMX7_NUM_USBS = 3,
FSL_IMX7_NUM_ADCS = 2,
+ FSL_IMX7_NUM_SAIS = 3,
+ FSL_IMX7_NUM_CANS = 2,
+ FSL_IMX7_NUM_PWMS = 4,
};
-typedef struct FslIMX7State {
+struct FslIMX7State {
/*< private >*/
DeviceState parent_obj;
@@ -71,6 +74,7 @@ typedef struct FslIMX7State {
IMX7CCMState ccm;
IMX7AnalogState analog;
IMX7SNVSState snvs;
+ IMX7SRCState src;
IMXGPCv2State gpcv2;
IMXSPIState spi[FSL_IMX7_NUM_ECSPIS];
IMXI2CState i2c[FSL_IMX7_NUM_I2CS];
@@ -81,126 +85,293 @@ typedef struct FslIMX7State {
IMX7GPRState gpr;
ChipideaState usb[FSL_IMX7_NUM_USBS];
DesignwarePCIEHost pcie;
+ MemoryRegion rom;
+ MemoryRegion caam;
+ MemoryRegion ocram;
+ MemoryRegion ocram_epdc;
+ MemoryRegion ocram_pxp;
+ MemoryRegion ocram_s;
+
uint32_t phy_num[FSL_IMX7_NUM_ETHS];
-} FslIMX7State;
+ bool phy_connected[FSL_IMX7_NUM_ETHS];
+};
enum FslIMX7MemoryMap {
FSL_IMX7_MMDC_ADDR = 0x80000000,
- FSL_IMX7_MMDC_SIZE = 2 * 1024 * 1024 * 1024UL,
+ FSL_IMX7_MMDC_SIZE = (2 * GiB),
- FSL_IMX7_GPIO1_ADDR = 0x30200000,
- FSL_IMX7_GPIO2_ADDR = 0x30210000,
- FSL_IMX7_GPIO3_ADDR = 0x30220000,
- FSL_IMX7_GPIO4_ADDR = 0x30230000,
- FSL_IMX7_GPIO5_ADDR = 0x30240000,
- FSL_IMX7_GPIO6_ADDR = 0x30250000,
- FSL_IMX7_GPIO7_ADDR = 0x30260000,
+ FSL_IMX7_QSPI1_MEM_ADDR = 0x60000000,
+ FSL_IMX7_QSPI1_MEM_SIZE = (256 * MiB),
- FSL_IMX7_IOMUXC_LPSR_GPR_ADDR = 0x30270000,
+ FSL_IMX7_PCIE1_MEM_ADDR = 0x40000000,
+ FSL_IMX7_PCIE1_MEM_SIZE = (256 * MiB),
- FSL_IMX7_WDOG1_ADDR = 0x30280000,
- FSL_IMX7_WDOG2_ADDR = 0x30290000,
- FSL_IMX7_WDOG3_ADDR = 0x302A0000,
- FSL_IMX7_WDOG4_ADDR = 0x302B0000,
+ FSL_IMX7_QSPI1_RX_BUF_ADDR = 0x34000000,
+ FSL_IMX7_QSPI1_RX_BUF_SIZE = (32 * MiB),
- FSL_IMX7_IOMUXC_LPSR_ADDR = 0x302C0000,
+ /* PCIe Peripherals */
+ FSL_IMX7_PCIE_REG_ADDR = 0x33800000,
- FSL_IMX7_GPT1_ADDR = 0x302D0000,
- FSL_IMX7_GPT2_ADDR = 0x302E0000,
- FSL_IMX7_GPT3_ADDR = 0x302F0000,
- FSL_IMX7_GPT4_ADDR = 0x30300000,
+ /* MMAP Peripherals */
+ FSL_IMX7_DMA_APBH_ADDR = 0x33000000,
+ FSL_IMX7_DMA_APBH_SIZE = 0x8000,
+
+ /* GPV configuration */
+ FSL_IMX7_GPV6_ADDR = 0x32600000,
+ FSL_IMX7_GPV5_ADDR = 0x32500000,
+ FSL_IMX7_GPV4_ADDR = 0x32400000,
+ FSL_IMX7_GPV3_ADDR = 0x32300000,
+ FSL_IMX7_GPV2_ADDR = 0x32200000,
+ FSL_IMX7_GPV1_ADDR = 0x32100000,
+ FSL_IMX7_GPV0_ADDR = 0x32000000,
+ FSL_IMX7_GPVn_SIZE = (1 * MiB),
+
+ /* Arm Peripherals */
+ FSL_IMX7_A7MPCORE_ADDR = 0x31000000,
- FSL_IMX7_IOMUXC_ADDR = 0x30330000,
- FSL_IMX7_IOMUXC_GPR_ADDR = 0x30340000,
- FSL_IMX7_IOMUXCn_SIZE = 0x1000,
+ /* AIPS-3 Begin */
- FSL_IMX7_OCOTP_ADDR = 0x30350000,
- FSL_IMX7_OCOTP_SIZE = 0x10000,
+ FSL_IMX7_ENET2_ADDR = 0x30BF0000,
+ FSL_IMX7_ENET1_ADDR = 0x30BE0000,
- FSL_IMX7_ANALOG_ADDR = 0x30360000,
- FSL_IMX7_SNVS_ADDR = 0x30370000,
- FSL_IMX7_CCM_ADDR = 0x30380000,
+ FSL_IMX7_SDMA_ADDR = 0x30BD0000,
+ FSL_IMX7_SDMA_SIZE = (4 * KiB),
- FSL_IMX7_SRC_ADDR = 0x30390000,
- FSL_IMX7_SRC_SIZE = 0x1000,
+ FSL_IMX7_EIM_ADDR = 0x30BC0000,
+ FSL_IMX7_EIM_SIZE = (4 * KiB),
- FSL_IMX7_ADC1_ADDR = 0x30610000,
- FSL_IMX7_ADC2_ADDR = 0x30620000,
- FSL_IMX7_ADCn_SIZE = 0x1000,
+ FSL_IMX7_QSPI_ADDR = 0x30BB0000,
+ FSL_IMX7_QSPI_SIZE = 0x8000,
- FSL_IMX7_PWM1_ADDR = 0x30660000,
- FSL_IMX7_PWM2_ADDR = 0x30670000,
- FSL_IMX7_PWM3_ADDR = 0x30680000,
- FSL_IMX7_PWM4_ADDR = 0x30690000,
- FSL_IMX7_PWMn_SIZE = 0x10000,
+ FSL_IMX7_SIM2_ADDR = 0x30BA0000,
+ FSL_IMX7_SIM1_ADDR = 0x30B90000,
+ FSL_IMX7_SIMn_SIZE = (4 * KiB),
- FSL_IMX7_PCIE_PHY_ADDR = 0x306D0000,
- FSL_IMX7_PCIE_PHY_SIZE = 0x10000,
+ FSL_IMX7_USDHC3_ADDR = 0x30B60000,
+ FSL_IMX7_USDHC2_ADDR = 0x30B50000,
+ FSL_IMX7_USDHC1_ADDR = 0x30B40000,
- FSL_IMX7_GPC_ADDR = 0x303A0000,
+ FSL_IMX7_USB3_ADDR = 0x30B30000,
+ FSL_IMX7_USBMISC3_ADDR = 0x30B30200,
+ FSL_IMX7_USB2_ADDR = 0x30B20000,
+ FSL_IMX7_USBMISC2_ADDR = 0x30B20200,
+ FSL_IMX7_USB1_ADDR = 0x30B10000,
+ FSL_IMX7_USBMISC1_ADDR = 0x30B10200,
+ FSL_IMX7_USBMISCn_SIZE = 0x200,
- FSL_IMX7_CAAM_ADDR = 0x30900000,
- FSL_IMX7_CAAM_SIZE = 0x40000,
+ FSL_IMX7_USB_PL301_ADDR = 0x30AD0000,
+ FSL_IMX7_USB_PL301_SIZE = (64 * KiB),
- FSL_IMX7_CAN1_ADDR = 0x30A00000,
- FSL_IMX7_CAN2_ADDR = 0x30A10000,
- FSL_IMX7_CANn_SIZE = 0x10000,
+ FSL_IMX7_SEMAPHORE_HS_ADDR = 0x30AC0000,
+ FSL_IMX7_SEMAPHORE_HS_SIZE = (64 * KiB),
+
+ FSL_IMX7_MUB_ADDR = 0x30AB0000,
+ FSL_IMX7_MUA_ADDR = 0x30AA0000,
+ FSL_IMX7_MUn_SIZE = (KiB),
+
+ FSL_IMX7_UART7_ADDR = 0x30A90000,
+ FSL_IMX7_UART6_ADDR = 0x30A80000,
+ FSL_IMX7_UART5_ADDR = 0x30A70000,
+ FSL_IMX7_UART4_ADDR = 0x30A60000,
- FSL_IMX7_I2C1_ADDR = 0x30A20000,
- FSL_IMX7_I2C2_ADDR = 0x30A30000,
- FSL_IMX7_I2C3_ADDR = 0x30A40000,
FSL_IMX7_I2C4_ADDR = 0x30A50000,
+ FSL_IMX7_I2C3_ADDR = 0x30A40000,
+ FSL_IMX7_I2C2_ADDR = 0x30A30000,
+ FSL_IMX7_I2C1_ADDR = 0x30A20000,
- FSL_IMX7_ECSPI1_ADDR = 0x30820000,
- FSL_IMX7_ECSPI2_ADDR = 0x30830000,
- FSL_IMX7_ECSPI3_ADDR = 0x30840000,
- FSL_IMX7_ECSPI4_ADDR = 0x30630000,
+ FSL_IMX7_CAN2_ADDR = 0x30A10000,
+ FSL_IMX7_CAN1_ADDR = 0x30A00000,
+ FSL_IMX7_CANn_SIZE = (4 * KiB),
- FSL_IMX7_LCDIF_ADDR = 0x30730000,
- FSL_IMX7_LCDIF_SIZE = 0x1000,
+ FSL_IMX7_AIPS3_CONF_ADDR = 0x309F0000,
+ FSL_IMX7_AIPS3_CONF_SIZE = (64 * KiB),
- FSL_IMX7_UART1_ADDR = 0x30860000,
+ FSL_IMX7_CAAM_ADDR = 0x30900000,
+ FSL_IMX7_CAAM_SIZE = (256 * KiB),
+
+ FSL_IMX7_SPBA_ADDR = 0x308F0000,
+ FSL_IMX7_SPBA_SIZE = (4 * KiB),
+
+ FSL_IMX7_SAI3_ADDR = 0x308C0000,
+ FSL_IMX7_SAI2_ADDR = 0x308B0000,
+ FSL_IMX7_SAI1_ADDR = 0x308A0000,
+ FSL_IMX7_SAIn_SIZE = (4 * KiB),
+
+ FSL_IMX7_UART3_ADDR = 0x30880000,
/*
* Some versions of the reference manual claim that UART2 is @
* 0x30870000, but experiments with HW + DT files in upstream
* Linux kernel show that not to be true and that block is
- * acutally located @ 0x30890000
+ * actually located @ 0x30890000
*/
FSL_IMX7_UART2_ADDR = 0x30890000,
- FSL_IMX7_UART3_ADDR = 0x30880000,
- FSL_IMX7_UART4_ADDR = 0x30A60000,
- FSL_IMX7_UART5_ADDR = 0x30A70000,
- FSL_IMX7_UART6_ADDR = 0x30A80000,
- FSL_IMX7_UART7_ADDR = 0x30A90000,
+ FSL_IMX7_UART1_ADDR = 0x30860000,
- FSL_IMX7_ENET1_ADDR = 0x30BE0000,
- FSL_IMX7_ENET2_ADDR = 0x30BF0000,
+ FSL_IMX7_ECSPI3_ADDR = 0x30840000,
+ FSL_IMX7_ECSPI2_ADDR = 0x30830000,
+ FSL_IMX7_ECSPI1_ADDR = 0x30820000,
+ FSL_IMX7_ECSPIn_SIZE = (4 * KiB),
- FSL_IMX7_USB1_ADDR = 0x30B10000,
- FSL_IMX7_USBMISC1_ADDR = 0x30B10200,
- FSL_IMX7_USB2_ADDR = 0x30B20000,
- FSL_IMX7_USBMISC2_ADDR = 0x30B20200,
- FSL_IMX7_USB3_ADDR = 0x30B30000,
- FSL_IMX7_USBMISC3_ADDR = 0x30B30200,
- FSL_IMX7_USBMISCn_SIZE = 0x200,
+ /* AIPS-3 End */
- FSL_IMX7_USDHC1_ADDR = 0x30B40000,
- FSL_IMX7_USDHC2_ADDR = 0x30B50000,
- FSL_IMX7_USDHC3_ADDR = 0x30B60000,
+ /* AIPS-2 Begin */
- FSL_IMX7_SDMA_ADDR = 0x30BD0000,
- FSL_IMX7_SDMA_SIZE = 0x1000,
+ FSL_IMX7_AXI_DEBUG_MON_ADDR = 0x307E0000,
+ FSL_IMX7_AXI_DEBUG_MON_SIZE = (64 * KiB),
+
+ FSL_IMX7_PERFMON2_ADDR = 0x307D0000,
+ FSL_IMX7_PERFMON1_ADDR = 0x307C0000,
+ FSL_IMX7_PERFMONn_SIZE = (64 * KiB),
+
+ FSL_IMX7_DDRC_ADDR = 0x307A0000,
+ FSL_IMX7_DDRC_SIZE = (4 * KiB),
+
+ FSL_IMX7_DDRC_PHY_ADDR = 0x30790000,
+ FSL_IMX7_DDRC_PHY_SIZE = (4 * KiB),
+
+ FSL_IMX7_TZASC_ADDR = 0x30780000,
+ FSL_IMX7_TZASC_SIZE = (64 * KiB),
+
+ FSL_IMX7_MIPI_DSI_ADDR = 0x30760000,
+ FSL_IMX7_MIPI_DSI_SIZE = (4 * KiB),
+
+ FSL_IMX7_MIPI_CSI_ADDR = 0x30750000,
+ FSL_IMX7_MIPI_CSI_SIZE = 0x4000,
+
+ FSL_IMX7_LCDIF_ADDR = 0x30730000,
+ FSL_IMX7_LCDIF_SIZE = 0x8000,
+
+ FSL_IMX7_CSI_ADDR = 0x30710000,
+ FSL_IMX7_CSI_SIZE = (4 * KiB),
+
+ FSL_IMX7_PXP_ADDR = 0x30700000,
+ FSL_IMX7_PXP_SIZE = 0x4000,
+
+ FSL_IMX7_EPDC_ADDR = 0x306F0000,
+ FSL_IMX7_EPDC_SIZE = (4 * KiB),
+
+ FSL_IMX7_PCIE_PHY_ADDR = 0x306D0000,
+ FSL_IMX7_PCIE_PHY_SIZE = (4 * KiB),
+
+ FSL_IMX7_SYSCNT_CTRL_ADDR = 0x306C0000,
+ FSL_IMX7_SYSCNT_CMP_ADDR = 0x306B0000,
+ FSL_IMX7_SYSCNT_RD_ADDR = 0x306A0000,
+
+ FSL_IMX7_PWM4_ADDR = 0x30690000,
+ FSL_IMX7_PWM3_ADDR = 0x30680000,
+ FSL_IMX7_PWM2_ADDR = 0x30670000,
+ FSL_IMX7_PWM1_ADDR = 0x30660000,
+ FSL_IMX7_PWMn_SIZE = (4 * KiB),
+
+ FSL_IMX7_FlEXTIMER2_ADDR = 0x30650000,
+ FSL_IMX7_FlEXTIMER1_ADDR = 0x30640000,
+ FSL_IMX7_FLEXTIMERn_SIZE = (4 * KiB),
+
+ FSL_IMX7_ECSPI4_ADDR = 0x30630000,
+
+ FSL_IMX7_ADC2_ADDR = 0x30620000,
+ FSL_IMX7_ADC1_ADDR = 0x30610000,
+ FSL_IMX7_ADCn_SIZE = (4 * KiB),
+
+ FSL_IMX7_AIPS2_CONF_ADDR = 0x305F0000,
+ FSL_IMX7_AIPS2_CONF_SIZE = (64 * KiB),
+
+ /* AIPS-2 End */
+
+ /* AIPS-1 Begin */
+
+ FSL_IMX7_CSU_ADDR = 0x303E0000,
+ FSL_IMX7_CSU_SIZE = (64 * KiB),
+
+ FSL_IMX7_RDC_ADDR = 0x303D0000,
+ FSL_IMX7_RDC_SIZE = (4 * KiB),
+
+ FSL_IMX7_SEMAPHORE2_ADDR = 0x303C0000,
+ FSL_IMX7_SEMAPHORE1_ADDR = 0x303B0000,
+ FSL_IMX7_SEMAPHOREn_SIZE = (4 * KiB),
+
+ FSL_IMX7_GPC_ADDR = 0x303A0000,
+
+ FSL_IMX7_SRC_ADDR = 0x30390000,
+
+ FSL_IMX7_CCM_ADDR = 0x30380000,
+
+ FSL_IMX7_SNVS_HP_ADDR = 0x30370000,
+
+ FSL_IMX7_ANALOG_ADDR = 0x30360000,
+
+ FSL_IMX7_OCOTP_ADDR = 0x30350000,
+ FSL_IMX7_OCOTP_SIZE = 0x10000,
+
+ FSL_IMX7_IOMUXC_GPR_ADDR = 0x30340000,
+ FSL_IMX7_IOMUXC_GPR_SIZE = (4 * KiB),
+
+ FSL_IMX7_IOMUXC_ADDR = 0x30330000,
+ FSL_IMX7_IOMUXC_SIZE = (4 * KiB),
+
+ FSL_IMX7_KPP_ADDR = 0x30320000,
+ FSL_IMX7_KPP_SIZE = (4 * KiB),
+
+ FSL_IMX7_ROMCP_ADDR = 0x30310000,
+ FSL_IMX7_ROMCP_SIZE = (4 * KiB),
+
+ FSL_IMX7_GPT4_ADDR = 0x30300000,
+ FSL_IMX7_GPT3_ADDR = 0x302F0000,
+ FSL_IMX7_GPT2_ADDR = 0x302E0000,
+ FSL_IMX7_GPT1_ADDR = 0x302D0000,
+
+ FSL_IMX7_IOMUXC_LPSR_ADDR = 0x302C0000,
+ FSL_IMX7_IOMUXC_LPSR_SIZE = (4 * KiB),
+
+ FSL_IMX7_WDOG4_ADDR = 0x302B0000,
+ FSL_IMX7_WDOG3_ADDR = 0x302A0000,
+ FSL_IMX7_WDOG2_ADDR = 0x30290000,
+ FSL_IMX7_WDOG1_ADDR = 0x30280000,
+
+ FSL_IMX7_IOMUXC_LPSR_GPR_ADDR = 0x30270000,
+
+ FSL_IMX7_GPIO7_ADDR = 0x30260000,
+ FSL_IMX7_GPIO6_ADDR = 0x30250000,
+ FSL_IMX7_GPIO5_ADDR = 0x30240000,
+ FSL_IMX7_GPIO4_ADDR = 0x30230000,
+ FSL_IMX7_GPIO3_ADDR = 0x30220000,
+ FSL_IMX7_GPIO2_ADDR = 0x30210000,
+ FSL_IMX7_GPIO1_ADDR = 0x30200000,
+
+ FSL_IMX7_AIPS1_CONF_ADDR = 0x301F0000,
+ FSL_IMX7_AIPS1_CONF_SIZE = (64 * KiB),
- FSL_IMX7_A7MPCORE_ADDR = 0x31000000,
FSL_IMX7_A7MPCORE_DAP_ADDR = 0x30000000,
+ FSL_IMX7_A7MPCORE_DAP_SIZE = (1 * MiB),
- FSL_IMX7_PCIE_REG_ADDR = 0x33800000,
- FSL_IMX7_PCIE_REG_SIZE = 16 * 1024,
+ /* AIPS-1 End */
- FSL_IMX7_GPR_ADDR = 0x30340000,
+ FSL_IMX7_EIM_CS0_ADDR = 0x28000000,
+ FSL_IMX7_EIM_CS0_SIZE = (128 * MiB),
- FSL_IMX7_DMA_APBH_ADDR = 0x33000000,
- FSL_IMX7_DMA_APBH_SIZE = 0x2000,
+ FSL_IMX7_OCRAM_PXP_ADDR = 0x00940000,
+ FSL_IMX7_OCRAM_PXP_SIZE = (32 * KiB),
+
+ FSL_IMX7_OCRAM_EPDC_ADDR = 0x00920000,
+ FSL_IMX7_OCRAM_EPDC_SIZE = (128 * KiB),
+
+ FSL_IMX7_OCRAM_MEM_ADDR = 0x00900000,
+ FSL_IMX7_OCRAM_MEM_SIZE = (128 * KiB),
+
+ FSL_IMX7_TCMU_ADDR = 0x00800000,
+ FSL_IMX7_TCMU_SIZE = (32 * KiB),
+
+ FSL_IMX7_TCML_ADDR = 0x007F8000,
+ FSL_IMX7_TCML_SIZE = (32 * KiB),
+
+ FSL_IMX7_OCRAM_S_ADDR = 0x00180000,
+ FSL_IMX7_OCRAM_S_SIZE = (32 * KiB),
+
+ FSL_IMX7_CAAM_MEM_ADDR = 0x00100000,
+ FSL_IMX7_CAAM_MEM_SIZE = (32 * KiB),
+
+ FSL_IMX7_ROM_ADDR = 0x00000000,
+ FSL_IMX7_ROM_SIZE = (96 * KiB),
};
enum FslIMX7IRQs {
@@ -229,6 +400,26 @@ enum FslIMX7IRQs {
FSL_IMX7_USB2_IRQ = 42,
FSL_IMX7_USB3_IRQ = 40,
+ FSL_IMX7_GPT1_IRQ = 55,
+ FSL_IMX7_GPT2_IRQ = 54,
+ FSL_IMX7_GPT3_IRQ = 53,
+ FSL_IMX7_GPT4_IRQ = 52,
+
+ FSL_IMX7_GPIO1_LOW_IRQ = 64,
+ FSL_IMX7_GPIO1_HIGH_IRQ = 65,
+ FSL_IMX7_GPIO2_LOW_IRQ = 66,
+ FSL_IMX7_GPIO2_HIGH_IRQ = 67,
+ FSL_IMX7_GPIO3_LOW_IRQ = 68,
+ FSL_IMX7_GPIO3_HIGH_IRQ = 69,
+ FSL_IMX7_GPIO4_LOW_IRQ = 70,
+ FSL_IMX7_GPIO4_HIGH_IRQ = 71,
+ FSL_IMX7_GPIO5_LOW_IRQ = 72,
+ FSL_IMX7_GPIO5_HIGH_IRQ = 73,
+ FSL_IMX7_GPIO6_LOW_IRQ = 74,
+ FSL_IMX7_GPIO6_HIGH_IRQ = 75,
+ FSL_IMX7_GPIO7_LOW_IRQ = 76,
+ FSL_IMX7_GPIO7_HIGH_IRQ = 77,
+
FSL_IMX7_WDOG1_IRQ = 78,
FSL_IMX7_WDOG2_IRQ = 79,
FSL_IMX7_WDOG3_IRQ = 10,
diff --git a/include/hw/arm/linux-boot-if.h b/include/hw/arm/linux-boot-if.h
index 7bbdfd1cc6..c85f33b2c5 100644
--- a/include/hw/arm/linux-boot-if.h
+++ b/include/hw/arm/linux-boot-if.h
@@ -9,16 +9,15 @@
#include "qom/object.h"
#define TYPE_ARM_LINUX_BOOT_IF "arm-linux-boot-if"
-#define ARM_LINUX_BOOT_IF_CLASS(klass) \
- OBJECT_CLASS_CHECK(ARMLinuxBootIfClass, (klass), TYPE_ARM_LINUX_BOOT_IF)
-#define ARM_LINUX_BOOT_IF_GET_CLASS(obj) \
- OBJECT_GET_CLASS(ARMLinuxBootIfClass, (obj), TYPE_ARM_LINUX_BOOT_IF)
+typedef struct ARMLinuxBootIfClass ARMLinuxBootIfClass;
+DECLARE_CLASS_CHECKERS(ARMLinuxBootIfClass, ARM_LINUX_BOOT_IF,
+ TYPE_ARM_LINUX_BOOT_IF)
#define ARM_LINUX_BOOT_IF(obj) \
INTERFACE_CHECK(ARMLinuxBootIf, (obj), TYPE_ARM_LINUX_BOOT_IF)
typedef struct ARMLinuxBootIf ARMLinuxBootIf;
-typedef struct ARMLinuxBootIfClass {
+struct ARMLinuxBootIfClass {
/*< private >*/
InterfaceClass parent_class;
@@ -35,6 +34,6 @@ typedef struct ARMLinuxBootIfClass {
* (or for a CPU which doesn't support TrustZone)
*/
void (*arm_linux_init)(ARMLinuxBootIf *obj, bool secure_boot);
-} ARMLinuxBootIfClass;
+};
#endif
diff --git a/include/hw/arm/msf2-soc.h b/include/hw/arm/msf2-soc.h
index c9cb214aa6..9300664e8e 100644
--- a/include/hw/arm/msf2-soc.h
+++ b/include/hw/arm/msf2-soc.h
@@ -30,9 +30,11 @@
#include "hw/misc/msf2-sysreg.h"
#include "hw/ssi/mss-spi.h"
#include "hw/net/msf2-emac.h"
+#include "hw/clock.h"
+#include "qom/object.h"
#define TYPE_MSF2_SOC "msf2-soc"
-#define MSF2_SOC(obj) OBJECT_CHECK(MSF2State, (obj), TYPE_MSF2_SOC)
+OBJECT_DECLARE_SIMPLE_TYPE(MSF2State, MSF2_SOC)
#define MSF2_NUM_SPIS 2
#define MSF2_NUM_UARTS 2
@@ -44,19 +46,17 @@
*/
#define MSF2_NUM_TIMERS 2
-typedef struct MSF2State {
- /*< private >*/
+struct MSF2State {
SysBusDevice parent_obj;
- /*< public >*/
ARMv7MState armv7m;
- char *cpu_type;
char *part_name;
uint64_t envm_size;
uint64_t esram_size;
- uint32_t m3clk;
+ Clock *m3clk;
+ Clock *refclk;
uint8_t apb0div;
uint8_t apb1div;
@@ -64,6 +64,10 @@ typedef struct MSF2State {
MSSTimerState timer;
MSSSpiState spi[MSF2_NUM_SPIS];
MSF2EmacState emac;
-} MSF2State;
+
+ MemoryRegion nvm;
+ MemoryRegion nvm_alias;
+ MemoryRegion sram;
+};
#endif
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
new file mode 100644
index 0000000000..4e0d210188
--- /dev/null
+++ b/include/hw/arm/npcm7xx.h
@@ -0,0 +1,139 @@
+/*
+ * Nuvoton NPCM7xx SoC family.
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_H
+#define NPCM7XX_H
+
+#include "hw/boards.h"
+#include "hw/adc/npcm7xx_adc.h"
+#include "hw/core/split-irq.h"
+#include "hw/cpu/a9mpcore.h"
+#include "hw/gpio/npcm7xx_gpio.h"
+#include "hw/i2c/npcm7xx_smbus.h"
+#include "hw/mem/npcm7xx_mc.h"
+#include "hw/misc/npcm7xx_clk.h"
+#include "hw/misc/npcm7xx_gcr.h"
+#include "hw/misc/npcm7xx_mft.h"
+#include "hw/misc/npcm7xx_pwm.h"
+#include "hw/misc/npcm7xx_rng.h"
+#include "hw/net/npcm7xx_emc.h"
+#include "hw/net/npcm_gmac.h"
+#include "hw/nvram/npcm7xx_otp.h"
+#include "hw/timer/npcm7xx_timer.h"
+#include "hw/ssi/npcm7xx_fiu.h"
+#include "hw/ssi/npcm_pspi.h"
+#include "hw/usb/hcd-ehci.h"
+#include "hw/usb/hcd-ohci.h"
+#include "target/arm/cpu.h"
+#include "hw/sd/npcm7xx_sdhci.h"
+
+#define NPCM7XX_MAX_NUM_CPUS (2)
+
+/* The first half of the address space is reserved for DDR4 DRAM. */
+#define NPCM7XX_DRAM_BA (0x00000000)
+#define NPCM7XX_DRAM_SZ (2 * GiB)
+
+/* Magic addresses for setting up direct kernel booting and SMP boot stubs. */
+#define NPCM7XX_LOADER_START (0x00000000) /* Start of SDRAM */
+#define NPCM7XX_SMP_LOADER_START (0xffff0000) /* Boot ROM */
+#define NPCM7XX_SMP_BOOTREG_ADDR (0xf080013c) /* GCR.SCRPAD */
+#define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100) /* GIC within A9 */
+#define NPCM7XX_BOARD_SETUP_ADDR (0xffff1000) /* Boot ROM */
+
+#define NPCM7XX_NR_PWM_MODULES 2
+
+struct NPCM7xxMachine {
+ MachineState parent;
+ /*
+ * PWM fan splitter. each splitter connects to one PWM output and
+ * multiple MFT inputs.
+ */
+ SplitIRQ fan_splitter[NPCM7XX_NR_PWM_MODULES *
+ NPCM7XX_PWM_PER_MODULE];
+};
+
+#define TYPE_NPCM7XX_MACHINE MACHINE_TYPE_NAME("npcm7xx")
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxMachine, NPCM7XX_MACHINE)
+
+typedef struct NPCM7xxMachineClass {
+ MachineClass parent;
+
+ const char *soc_type;
+} NPCM7xxMachineClass;
+
+#define NPCM7XX_MACHINE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(NPCM7xxMachineClass, (klass), TYPE_NPCM7XX_MACHINE)
+#define NPCM7XX_MACHINE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(NPCM7xxMachineClass, (obj), TYPE_NPCM7XX_MACHINE)
+
+struct NPCM7xxState {
+ DeviceState parent;
+
+ ARMCPU cpu[NPCM7XX_MAX_NUM_CPUS];
+ A9MPPrivState a9mpcore;
+
+ MemoryRegion sram;
+ MemoryRegion irom;
+ MemoryRegion ram3;
+ MemoryRegion *dram;
+
+ NPCM7xxGCRState gcr;
+ NPCM7xxCLKState clk;
+ NPCM7xxTimerCtrlState tim[3];
+ NPCM7xxADCState adc;
+ NPCM7xxPWMState pwm[NPCM7XX_NR_PWM_MODULES];
+ NPCM7xxMFTState mft[8];
+ NPCM7xxOTPState key_storage;
+ NPCM7xxOTPState fuse_array;
+ NPCM7xxMCState mc;
+ NPCM7xxRNGState rng;
+ NPCM7xxGPIOState gpio[8];
+ NPCM7xxSMBusState smbus[16];
+ EHCISysBusState ehci;
+ OHCISysBusState ohci;
+ NPCM7xxFIUState fiu[2];
+ NPCM7xxEMCState emc[2];
+ NPCMGMACState gmac[2];
+ NPCM7xxSDHCIState mmc;
+ NPCMPSPIState pspi[2];
+};
+
+#define TYPE_NPCM7XX "npcm7xx"
+OBJECT_DECLARE_TYPE(NPCM7xxState, NPCM7xxClass, NPCM7XX)
+
+#define TYPE_NPCM730 "npcm730"
+#define TYPE_NPCM750 "npcm750"
+
+typedef struct NPCM7xxClass {
+ DeviceClass parent;
+
+ /* Bitmask of modules that are permanently disabled on this chip. */
+ uint32_t disabled_modules;
+ /* Number of CPU cores enabled in this SoC class (may be 1 or 2). */
+ uint32_t num_cpus;
+} NPCM7xxClass;
+
+/**
+ * npcm7xx_load_kernel - Loads memory with everything needed to boot
+ * @machine - The machine containing the SoC to be booted.
+ * @soc - The SoC containing the CPU to be booted.
+ *
+ * This will set up the ARM boot info structure for the specific NPCM7xx
+ * derivative and call arm_load_kernel() to set up loading of the kernel, etc.
+ * into memory, if requested by the user.
+ */
+void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc);
+
+#endif /* NPCM7XX_H */
diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
index 0cb78aafea..e52a56e75e 100644
--- a/include/hw/arm/nrf51_soc.h
+++ b/include/hw/arm/nrf51_soc.h
@@ -17,14 +17,15 @@
#include "hw/gpio/nrf51_gpio.h"
#include "hw/nvram/nrf51_nvm.h"
#include "hw/timer/nrf51_timer.h"
+#include "hw/clock.h"
+#include "qom/object.h"
#define TYPE_NRF51_SOC "nrf51-soc"
-#define NRF51_SOC(obj) \
- OBJECT_CHECK(NRF51State, (obj), TYPE_NRF51_SOC)
+OBJECT_DECLARE_SIMPLE_TYPE(NRF51State, NRF51_SOC)
#define NRF51_NUM_TIMERS 3
-typedef struct NRF51State {
+struct NRF51State {
/*< private >*/
SysBusDevice parent_obj;
@@ -50,6 +51,7 @@ typedef struct NRF51State {
MemoryRegion container;
-} NRF51State;
+ Clock *sysclk;
+};
#endif
diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h
index 6be386d0e2..40ee8ea9e5 100644
--- a/include/hw/arm/omap.h
+++ b/include/hw/arm/omap.h
@@ -24,6 +24,7 @@
#include "hw/input/tsc2xxx.h"
#include "target/arm/cpu-qom.h"
#include "qemu/log.h"
+#include "qom/object.h"
# define OMAP_EMIFS_BASE 0x00000000
# define OMAP2_Q0_BASE 0x00000000
@@ -69,10 +70,9 @@ void omap_clk_reparent(omap_clk clk, omap_clk parent);
/* omap_intc.c */
#define TYPE_OMAP_INTC "common-omap-intc"
-#define OMAP_INTC(obj) \
- OBJECT_CHECK(omap_intr_handler, (obj), TYPE_OMAP_INTC)
+typedef struct OMAPIntcState OMAPIntcState;
+DECLARE_INSTANCE_CHECKER(OMAPIntcState, OMAP_INTC, TYPE_OMAP_INTC)
-typedef struct omap_intr_handler_s omap_intr_handler;
/*
* TODO: Ideally we should have a clock framework that
@@ -88,14 +88,13 @@ typedef struct omap_intr_handler_s omap_intr_handler;
* (ie the struct omap_mpu_state_s*) to do the clockname to pointer
* translation.)
*/
-void omap_intc_set_iclk(omap_intr_handler *intc, omap_clk clk);
-void omap_intc_set_fclk(omap_intr_handler *intc, omap_clk clk);
+void omap_intc_set_iclk(OMAPIntcState *intc, omap_clk clk);
+void omap_intc_set_fclk(OMAPIntcState *intc, omap_clk clk);
/* omap_i2c.c */
#define TYPE_OMAP_I2C "omap_i2c"
-#define OMAP_I2C(obj) OBJECT_CHECK(OMAPI2CState, (obj), TYPE_OMAP_I2C)
+OBJECT_DECLARE_SIMPLE_TYPE(OMAPI2CState, OMAP_I2C)
-typedef struct OMAPI2CState OMAPI2CState;
/* TODO: clock framework (see above) */
void omap_i2c_set_iclk(OMAPI2CState *i2c, omap_clk clk);
@@ -103,21 +102,20 @@ void omap_i2c_set_fclk(OMAPI2CState *i2c, omap_clk clk);
/* omap_gpio.c */
#define TYPE_OMAP1_GPIO "omap-gpio"
-#define OMAP1_GPIO(obj) \
- OBJECT_CHECK(struct omap_gpif_s, (obj), TYPE_OMAP1_GPIO)
+typedef struct Omap1GpioState Omap1GpioState;
+DECLARE_INSTANCE_CHECKER(Omap1GpioState, OMAP1_GPIO,
+ TYPE_OMAP1_GPIO)
#define TYPE_OMAP2_GPIO "omap2-gpio"
-#define OMAP2_GPIO(obj) \
- OBJECT_CHECK(struct omap2_gpif_s, (obj), TYPE_OMAP2_GPIO)
-
-typedef struct omap_gpif_s omap_gpif;
-typedef struct omap2_gpif_s omap2_gpif;
+typedef struct Omap2GpioState Omap2GpioState;
+DECLARE_INSTANCE_CHECKER(Omap2GpioState, OMAP2_GPIO,
+ TYPE_OMAP2_GPIO)
/* TODO: clock framework (see above) */
-void omap_gpio_set_clk(omap_gpif *gpio, omap_clk clk);
+void omap_gpio_set_clk(Omap1GpioState *gpio, omap_clk clk);
-void omap2_gpio_set_iclk(omap2_gpif *gpio, omap_clk clk);
-void omap2_gpio_set_fclk(omap2_gpif *gpio, uint8_t i, omap_clk clk);
+void omap2_gpio_set_iclk(Omap2GpioState *gpio, omap_clk clk);
+void omap2_gpio_set_fclk(Omap2GpioState *gpio, uint8_t i, omap_clk clk);
/* OMAP2 l4 Interconnect */
struct omap_l4_s;
@@ -726,7 +724,6 @@ struct omap_uart_s *omap2_uart_init(MemoryRegion *sysmem,
qemu_irq txdma, qemu_irq rxdma,
const char *label, Chardev *chr);
void omap_uart_reset(struct omap_uart_s *s);
-void omap_uart_attach(struct omap_uart_s *s, Chardev *chr);
struct omap_mpuio_s;
qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s);
@@ -1011,7 +1008,8 @@ void omap_mpu_wakeup(void *opaque, int irq, int req);
__func__, paddr)
/* OMAP-specific Linux bootloader tags for the ATAG_BOARD area
- (Board-specifc tags are not here) */
+ * (Board-specific tags are not here)
+ */
#define OMAP_TAG_CLOCK 0x4f01
#define OMAP_TAG_MMC 0x4f02
#define OMAP_TAG_SERIAL_CONSOLE 0x4f03
diff --git a/include/hw/arm/pxa.h b/include/hw/arm/pxa.h
index 8843e5f910..4c6caee113 100644
--- a/include/hw/arm/pxa.h
+++ b/include/hw/arm/pxa.h
@@ -13,6 +13,7 @@
#include "exec/memory.h"
#include "target/arm/cpu-qom.h"
#include "hw/pcmcia.h"
+#include "qom/object.h"
/* Interrupt numbers */
# define PXA2XX_PIC_SSP3 0
@@ -86,18 +87,19 @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
void pxa2xx_lcd_vsync_notifier(PXA2xxLCDState *s, qemu_irq handler);
/* pxa2xx_mmci.c */
-typedef struct PXA2xxMMCIState PXA2xxMMCIState;
+#define TYPE_PXA2XX_MMCI "pxa2xx-mmci"
+OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxMMCIState, PXA2XX_MMCI)
+
PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem,
hwaddr base,
- BlockBackend *blk, qemu_irq irq,
- qemu_irq rx_dma, qemu_irq tx_dma);
+ qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma);
void pxa2xx_mmci_handlers(PXA2xxMMCIState *s, qemu_irq readonly,
qemu_irq coverswitch);
/* pxa2xx_pcmcia.c */
-typedef struct PXA2xxPCMCIAState PXA2xxPCMCIAState;
-PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
- hwaddr base);
+#define TYPE_PXA2XX_PCMCIA "pxa2xx-pcmcia"
+OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxPCMCIAState, PXA2XX_PCMCIA)
+
int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card);
int pxa2xx_pcmcia_detach(void *opaque);
void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq);
@@ -115,13 +117,17 @@ void pxa27x_register_keypad(PXA2xxKeyPadState *kp,
const struct keymap *map, int size);
/* pxa2xx.c */
-typedef struct PXA2xxI2CState PXA2xxI2CState;
+#define TYPE_PXA2XX_I2C "pxa2xx_i2c"
+OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxI2CState, PXA2XX_I2C)
+
PXA2xxI2CState *pxa2xx_i2c_init(hwaddr base,
qemu_irq irq, uint32_t page_size);
I2CBus *pxa2xx_i2c_bus(PXA2xxI2CState *s);
typedef struct PXA2xxI2SState PXA2xxI2SState;
-typedef struct PXA2xxFIrState PXA2xxFIrState;
+
+#define TYPE_PXA2XX_FIR "pxa2xx-fir"
+OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxFIrState, PXA2XX_FIR)
typedef struct {
ARMCPU *cpu;
@@ -185,8 +191,7 @@ struct PXA2xxI2SState {
# define PA_FMT "0x%08lx"
-PXA2xxState *pxa270_init(MemoryRegion *address_space, unsigned int sdram_size,
- const char *revision);
-PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size);
+PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision);
+PXA2xxState *pxa255_init(unsigned int sdram_size);
#endif /* PXA_H */
diff --git a/include/hw/arm/raspberrypi-fw-defs.h b/include/hw/arm/raspberrypi-fw-defs.h
new file mode 100644
index 0000000000..8b404e0533
--- /dev/null
+++ b/include/hw/arm/raspberrypi-fw-defs.h
@@ -0,0 +1,173 @@
+/*
+ * Raspberry Pi firmware definitions
+ *
+ * Copyright (C) 2022 Auriga LLC, based on Linux kernel
+ * `include/soc/bcm2835/raspberrypi-firmware.h` (Copyright © 2015 Broadcom)
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef INCLUDE_HW_MISC_RASPBERRYPI_FW_DEFS_H_
+#define INCLUDE_HW_MISC_RASPBERRYPI_FW_DEFS_H_
+
+
+enum rpi_firmware_property_tag {
+ RPI_FWREQ_PROPERTY_END = 0,
+ RPI_FWREQ_GET_FIRMWARE_REVISION = 0x00000001,
+ RPI_FWREQ_GET_FIRMWARE_VARIANT = 0x00000002,
+ RPI_FWREQ_GET_FIRMWARE_HASH = 0x00000003,
+
+ RPI_FWREQ_SET_CURSOR_INFO = 0x00008010,
+ RPI_FWREQ_SET_CURSOR_STATE = 0x00008011,
+
+ RPI_FWREQ_GET_BOARD_MODEL = 0x00010001,
+ RPI_FWREQ_GET_BOARD_REVISION = 0x00010002,
+ RPI_FWREQ_GET_BOARD_MAC_ADDRESS = 0x00010003,
+ RPI_FWREQ_GET_BOARD_SERIAL = 0x00010004,
+ RPI_FWREQ_GET_ARM_MEMORY = 0x00010005,
+ RPI_FWREQ_GET_VC_MEMORY = 0x00010006,
+ RPI_FWREQ_GET_CLOCKS = 0x00010007,
+ RPI_FWREQ_GET_POWER_STATE = 0x00020001,
+ RPI_FWREQ_GET_TIMING = 0x00020002,
+ RPI_FWREQ_SET_POWER_STATE = 0x00028001,
+ RPI_FWREQ_GET_CLOCK_STATE = 0x00030001,
+ RPI_FWREQ_GET_CLOCK_RATE = 0x00030002,
+ RPI_FWREQ_GET_VOLTAGE = 0x00030003,
+ RPI_FWREQ_GET_MAX_CLOCK_RATE = 0x00030004,
+ RPI_FWREQ_GET_MAX_VOLTAGE = 0x00030005,
+ RPI_FWREQ_GET_TEMPERATURE = 0x00030006,
+ RPI_FWREQ_GET_MIN_CLOCK_RATE = 0x00030007,
+ RPI_FWREQ_GET_MIN_VOLTAGE = 0x00030008,
+ RPI_FWREQ_GET_TURBO = 0x00030009,
+ RPI_FWREQ_GET_MAX_TEMPERATURE = 0x0003000a,
+ RPI_FWREQ_GET_STC = 0x0003000b,
+ RPI_FWREQ_ALLOCATE_MEMORY = 0x0003000c,
+ RPI_FWREQ_LOCK_MEMORY = 0x0003000d,
+ RPI_FWREQ_UNLOCK_MEMORY = 0x0003000e,
+ RPI_FWREQ_RELEASE_MEMORY = 0x0003000f,
+ RPI_FWREQ_EXECUTE_CODE = 0x00030010,
+ RPI_FWREQ_EXECUTE_QPU = 0x00030011,
+ RPI_FWREQ_SET_ENABLE_QPU = 0x00030012,
+ RPI_FWREQ_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014,
+ RPI_FWREQ_GET_EDID_BLOCK = 0x00030020,
+ RPI_FWREQ_GET_CUSTOMER_OTP = 0x00030021,
+ RPI_FWREQ_GET_EDID_BLOCK_DISPLAY = 0x00030023,
+ RPI_FWREQ_GET_DOMAIN_STATE = 0x00030030,
+ RPI_FWREQ_GET_THROTTLED = 0x00030046,
+ RPI_FWREQ_GET_CLOCK_MEASURED = 0x00030047,
+ RPI_FWREQ_NOTIFY_REBOOT = 0x00030048,
+ RPI_FWREQ_SET_CLOCK_STATE = 0x00038001,
+ RPI_FWREQ_SET_CLOCK_RATE = 0x00038002,
+ RPI_FWREQ_SET_VOLTAGE = 0x00038003,
+ RPI_FWREQ_SET_MAX_CLOCK_RATE = 0x00038004,
+ RPI_FWREQ_SET_MIN_CLOCK_RATE = 0x00038007,
+ RPI_FWREQ_SET_TURBO = 0x00038009,
+ RPI_FWREQ_SET_CUSTOMER_OTP = 0x00038021,
+ RPI_FWREQ_SET_DOMAIN_STATE = 0x00038030,
+ RPI_FWREQ_GET_GPIO_STATE = 0x00030041,
+ RPI_FWREQ_SET_GPIO_STATE = 0x00038041,
+ RPI_FWREQ_SET_SDHOST_CLOCK = 0x00038042,
+ RPI_FWREQ_GET_GPIO_CONFIG = 0x00030043,
+ RPI_FWREQ_SET_GPIO_CONFIG = 0x00038043,
+ RPI_FWREQ_GET_PERIPH_REG = 0x00030045,
+ RPI_FWREQ_SET_PERIPH_REG = 0x00038045,
+ RPI_FWREQ_GET_POE_HAT_VAL = 0x00030049,
+ RPI_FWREQ_SET_POE_HAT_VAL = 0x00038049,
+ RPI_FWREQ_SET_POE_HAT_VAL_OLD = 0x00030050,
+ RPI_FWREQ_NOTIFY_XHCI_RESET = 0x00030058,
+ RPI_FWREQ_GET_REBOOT_FLAGS = 0x00030064,
+ RPI_FWREQ_SET_REBOOT_FLAGS = 0x00038064,
+ RPI_FWREQ_NOTIFY_DISPLAY_DONE = 0x00030066,
+
+ /* Dispmanx TAGS */
+ RPI_FWREQ_FRAMEBUFFER_ALLOCATE = 0x00040001,
+ RPI_FWREQ_FRAMEBUFFER_BLANK = 0x00040002,
+ RPI_FWREQ_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003,
+ RPI_FWREQ_FRAMEBUFFER_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004,
+ RPI_FWREQ_FRAMEBUFFER_GET_DEPTH = 0x00040005,
+ RPI_FWREQ_FRAMEBUFFER_GET_PIXEL_ORDER = 0x00040006,
+ RPI_FWREQ_FRAMEBUFFER_GET_ALPHA_MODE = 0x00040007,
+ RPI_FWREQ_FRAMEBUFFER_GET_PITCH = 0x00040008,
+ RPI_FWREQ_FRAMEBUFFER_GET_VIRTUAL_OFFSET = 0x00040009,
+ RPI_FWREQ_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a,
+ RPI_FWREQ_FRAMEBUFFER_GET_PALETTE = 0x0004000b,
+ RPI_FWREQ_FRAMEBUFFER_GET_LAYER = 0x0004000c,
+ RPI_FWREQ_FRAMEBUFFER_GET_TRANSFORM = 0x0004000d,
+ RPI_FWREQ_FRAMEBUFFER_GET_VSYNC = 0x0004000e,
+ RPI_FWREQ_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f,
+ RPI_FWREQ_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010,
+ RPI_FWREQ_FRAMEBUFFER_RELEASE = 0x00048001,
+ RPI_FWREQ_FRAMEBUFFER_GET_DISPLAY_ID = 0x00040016,
+ RPI_FWREQ_FRAMEBUFFER_SET_DISPLAY_NUM = 0x00048013,
+ RPI_FWREQ_FRAMEBUFFER_GET_NUM_DISPLAYS = 0x00040013,
+ RPI_FWREQ_FRAMEBUFFER_GET_DISPLAY_SETTINGS = 0x00040014,
+ RPI_FWREQ_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003,
+ RPI_FWREQ_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004,
+ RPI_FWREQ_FRAMEBUFFER_TEST_DEPTH = 0x00044005,
+ RPI_FWREQ_FRAMEBUFFER_TEST_PIXEL_ORDER = 0x00044006,
+ RPI_FWREQ_FRAMEBUFFER_TEST_ALPHA_MODE = 0x00044007,
+ RPI_FWREQ_FRAMEBUFFER_TEST_VIRTUAL_OFFSET = 0x00044009,
+ RPI_FWREQ_FRAMEBUFFER_TEST_OVERSCAN = 0x0004400a,
+ RPI_FWREQ_FRAMEBUFFER_TEST_PALETTE = 0x0004400b,
+ RPI_FWREQ_FRAMEBUFFER_TEST_LAYER = 0x0004400c,
+ RPI_FWREQ_FRAMEBUFFER_TEST_TRANSFORM = 0x0004400d,
+ RPI_FWREQ_FRAMEBUFFER_TEST_VSYNC = 0x0004400e,
+ RPI_FWREQ_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003,
+ RPI_FWREQ_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004,
+ RPI_FWREQ_FRAMEBUFFER_SET_DEPTH = 0x00048005,
+ RPI_FWREQ_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006,
+ RPI_FWREQ_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007,
+ RPI_FWREQ_FRAMEBUFFER_SET_PITCH = 0x00048008,
+ RPI_FWREQ_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009,
+ RPI_FWREQ_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a,
+ RPI_FWREQ_FRAMEBUFFER_SET_PALETTE = 0x0004800b,
+
+ RPI_FWREQ_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f,
+ RPI_FWREQ_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020,
+ RPI_FWREQ_FRAMEBUFFER_SET_VSYNC = 0x0004800e,
+ RPI_FWREQ_FRAMEBUFFER_SET_LAYER = 0x0004800c,
+ RPI_FWREQ_FRAMEBUFFER_SET_TRANSFORM = 0x0004800d,
+ RPI_FWREQ_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f,
+
+ RPI_FWREQ_VCHIQ_INIT = 0x00048010,
+
+ RPI_FWREQ_SET_PLANE = 0x00048015,
+ RPI_FWREQ_GET_DISPLAY_TIMING = 0x00040017,
+ RPI_FWREQ_SET_TIMING = 0x00048017,
+ RPI_FWREQ_GET_DISPLAY_CFG = 0x00040018,
+ RPI_FWREQ_SET_DISPLAY_POWER = 0x00048019,
+ RPI_FWREQ_GET_COMMAND_LINE = 0x00050001,
+ RPI_FWREQ_GET_DMA_CHANNELS = 0x00060001,
+};
+
+enum rpi_firmware_clk_id {
+ RPI_FIRMWARE_EMMC_CLK_ID = 1,
+ RPI_FIRMWARE_UART_CLK_ID,
+ RPI_FIRMWARE_ARM_CLK_ID,
+ RPI_FIRMWARE_CORE_CLK_ID,
+ RPI_FIRMWARE_V3D_CLK_ID,
+ RPI_FIRMWARE_H264_CLK_ID,
+ RPI_FIRMWARE_ISP_CLK_ID,
+ RPI_FIRMWARE_SDRAM_CLK_ID,
+ RPI_FIRMWARE_PIXEL_CLK_ID,
+ RPI_FIRMWARE_PWM_CLK_ID,
+ RPI_FIRMWARE_HEVC_CLK_ID,
+ RPI_FIRMWARE_EMMC2_CLK_ID,
+ RPI_FIRMWARE_M2MC_CLK_ID,
+ RPI_FIRMWARE_PIXEL_BVB_CLK_ID,
+ RPI_FIRMWARE_VEC_CLK_ID,
+ RPI_FIRMWARE_NUM_CLK_ID,
+};
+
+struct rpi_firmware_property_tag_header {
+ uint32_t tag;
+ uint32_t buf_size;
+ uint32_t req_resp_size;
+};
+
+typedef struct rpi_firmware_prop_request {
+ struct rpi_firmware_property_tag_header hdr;
+ uint8_t payload[0];
+} rpi_firmware_prop_request_t;
+
+#endif /* INCLUDE_HW_MISC_RASPBERRYPI_FW_DEFS_H_ */
diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h
index 61b04a1bd4..7bc4807fa5 100644
--- a/include/hw/arm/raspi_platform.h
+++ b/include/hw/arm/raspi_platform.h
@@ -18,48 +18,117 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * Various undocumented addresses and names come from Herman Hermitage's VC4
+ * documentation:
+ * https://github.com/hermanhermitage/videocoreiv/wiki/MMIO-Register-map
*/
#ifndef HW_ARM_RASPI_PLATFORM_H
#define HW_ARM_RASPI_PLATFORM_H
+#include "hw/boards.h"
+#include "hw/arm/boot.h"
+
+/* Registered machine type (matches RPi Foundation bootloader and U-Boot) */
+#define MACH_TYPE_BCM2708 3138
+
+#define TYPE_RASPI_BASE_MACHINE MACHINE_TYPE_NAME("raspi-base")
+OBJECT_DECLARE_TYPE(RaspiBaseMachineState, RaspiBaseMachineClass,
+ RASPI_BASE_MACHINE)
+
+struct RaspiBaseMachineState {
+ /*< private >*/
+ MachineState parent_obj;
+ /*< public >*/
+ struct arm_boot_info binfo;
+};
+
+struct RaspiBaseMachineClass {
+ /*< private >*/
+ MachineClass parent_obj;
+ /*< public >*/
+ uint32_t board_rev;
+};
+
+/* Common functions for raspberry pi machines */
+const char *board_soc_type(uint32_t board_rev);
+void raspi_machine_init(MachineState *machine);
+
+typedef struct BCM283XBaseState BCM283XBaseState;
+void raspi_base_machine_init(MachineState *machine,
+ BCM283XBaseState *soc);
+
+void raspi_machine_class_common_init(MachineClass *mc,
+ uint32_t board_rev);
+uint64_t board_ram_size(uint32_t board_rev);
+
#define MSYNC_OFFSET 0x0000 /* Multicore Sync Block */
-#define IC0_OFFSET 0x2000
+#define CCPT_OFFSET 0x1000 /* Compact Camera Port 2 TX */
+#define INTE_OFFSET 0x2000 /* VC Interrupt controller */
#define ST_OFFSET 0x3000 /* System Timer */
+#define TXP_OFFSET 0x4000 /* Transposer */
+#define JPEG_OFFSET 0x5000
#define MPHI_OFFSET 0x6000 /* Message-based Parallel Host Intf. */
#define DMA_OFFSET 0x7000 /* DMA controller, channels 0-14 */
-#define ARM_OFFSET 0xB000 /* BCM2708 ARM control block */
+#define ARBA_OFFSET 0x9000
+#define BRDG_OFFSET 0xa000 /* RPiVid ASB for BCM2838 (BCM2711) */
+#define ARM_OFFSET 0xB000 /* ARM control block */
#define ARMCTRL_OFFSET (ARM_OFFSET + 0x000)
#define ARMCTRL_IC_OFFSET (ARM_OFFSET + 0x200) /* Interrupt controller */
-#define ARMCTRL_TIMER0_1_OFFSET (ARM_OFFSET + 0x400) /* Timer 0 and 1 */
+#define ARMCTRL_TIMER0_1_OFFSET (ARM_OFFSET + 0x400) /* Timer 0 and 1 (SP804) */
#define ARMCTRL_0_SBM_OFFSET (ARM_OFFSET + 0x800) /* User 0 (ARM) Semaphores
* Doorbells & Mailboxes */
-#define CPRMAN_OFFSET 0x100000 /* Power Management, Watchdog */
-#define CM_OFFSET 0x101000 /* Clock Management */
-#define A2W_OFFSET 0x102000 /* Reset controller */
+#define PM_OFFSET 0x100000 /* Power Management */
+#define CPRMAN_OFFSET 0x101000 /* Clock Management */
#define AVS_OFFSET 0x103000 /* Audio Video Standard */
#define RNG_OFFSET 0x104000
#define GPIO_OFFSET 0x200000
-#define UART0_OFFSET 0x201000
-#define MMCI0_OFFSET 0x202000
-#define I2S_OFFSET 0x203000
-#define SPI0_OFFSET 0x204000
+#define UART0_OFFSET 0x201000 /* PL011 */
+#define MMCI0_OFFSET 0x202000 /* Legacy MMC */
+#define I2S_OFFSET 0x203000 /* PCM */
+#define SPI0_OFFSET 0x204000 /* SPI master */
#define BSC0_OFFSET 0x205000 /* BSC0 I2C/TWI */
+#define PIXV0_OFFSET 0x206000
+#define PIXV1_OFFSET 0x207000
+#define DPI_OFFSET 0x208000
+#define DSI0_OFFSET 0x209000 /* Display Serial Interface */
+#define PWM_OFFSET 0x20c000
+#define PERM_OFFSET 0x20d000
+#define TEC_OFFSET 0x20e000
#define OTP_OFFSET 0x20f000
+#define SLIM_OFFSET 0x210000 /* SLIMbus */
+#define CPG_OFFSET 0x211000
#define THERMAL_OFFSET 0x212000
-#define BSC_SL_OFFSET 0x214000 /* SPI slave */
+#define AVSP_OFFSET 0x213000
+#define BSC_SL_OFFSET 0x214000 /* SPI slave (bootrom) */
#define AUX_OFFSET 0x215000 /* AUX: UART1/SPI1/SPI2 */
#define EMMC1_OFFSET 0x300000
+#define EMMC2_OFFSET 0x340000
+#define HVS_OFFSET 0x400000
#define SMI_OFFSET 0x600000
+#define DSI1_OFFSET 0x700000
+#define UCAM_OFFSET 0x800000
+#define CMI_OFFSET 0x802000
#define BSC1_OFFSET 0x804000 /* BSC1 I2C/TWI */
#define BSC2_OFFSET 0x805000 /* BSC2 I2C/TWI */
+#define VECA_OFFSET 0x806000
+#define PIXV2_OFFSET 0x807000
+#define HDMI_OFFSET 0x808000
+#define HDCP_OFFSET 0x809000
+#define ARBR0_OFFSET 0x80a000
#define DBUS_OFFSET 0x900000
#define AVE0_OFFSET 0x910000
#define USB_OTG_OFFSET 0x980000 /* DTC_OTG USB controller */
+#define V3D_OFFSET 0xc00000
#define SDRAMC_OFFSET 0xe00000
+#define L2CC_OFFSET 0xe01000 /* Level 2 Cache controller */
+#define L1CC_OFFSET 0xe02000 /* Level 1 Cache controller */
+#define ARBR1_OFFSET 0xe04000
#define DMA15_OFFSET 0xE05000 /* DMA controller, channel 15 */
+#define DCRC_OFFSET 0xe07000
+#define AXIP_OFFSET 0xe08000
/* GPU interrupts */
#define INTERRUPT_TIMER0 0
@@ -137,4 +206,14 @@
#define INTERRUPT_ILLEGAL_TYPE0 6
#define INTERRUPT_ILLEGAL_TYPE1 7
+/* Clock rates */
+#define RPI_FIRMWARE_EMMC_CLK_RATE 50000000
+#define RPI_FIRMWARE_UART_CLK_RATE 3000000
+/*
+ * TODO: this is really SoC-specific; we might want to
+ * set it per-SoC if it turns out any guests care.
+ */
+#define RPI_FIRMWARE_CORE_CLK_RATE 350000000
+#define RPI_FIRMWARE_DEFAULT_CLK_RATE 700000000
+
#endif
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
index ca4a4b1ad1..5ec2e6c1a4 100644
--- a/include/hw/arm/smmu-common.h
+++ b/include/hw/arm/smmu-common.h
@@ -21,12 +21,21 @@
#include "hw/sysbus.h"
#include "hw/pci/pci.h"
+#include "qom/object.h"
-#define SMMU_PCI_BUS_MAX 256
-#define SMMU_PCI_DEVFN_MAX 256
-#define SMMU_PCI_DEVFN(sid) (sid & 0xFF)
+#define SMMU_PCI_BUS_MAX 256
+#define SMMU_PCI_DEVFN_MAX 256
+#define SMMU_PCI_DEVFN(sid) (sid & 0xFF)
-#define SMMU_MAX_VA_BITS 48
+/* VMSAv8-64 Translation constants and functions */
+#define VMSA_LEVELS 4
+#define VMSA_MAX_S2_CONCAT 16
+
+#define VMSA_STRIDE(gran) ((gran) - VMSA_LEVELS + 1)
+#define VMSA_BIT_LVL(isz, strd, lvl) ((isz) - (strd) * \
+ (VMSA_LEVELS - (lvl)))
+#define VMSA_IDXMSK(isz, strd, lvl) ((1ULL << \
+ VMSA_BIT_LVL(isz, strd, lvl)) - 1)
/*
* Page table walk error types
@@ -41,6 +50,7 @@ typedef enum {
} SMMUPTWEventType;
typedef struct SMMUPTWEventInfo {
+ int stage;
SMMUPTWEventType type;
dma_addr_t addr; /* fetched address that induced an abort, if any */
} SMMUPTWEventInfo;
@@ -50,26 +60,51 @@ typedef struct SMMUTransTableInfo {
uint64_t ttb; /* TT base address */
uint8_t tsz; /* input range, ie. 2^(64 -tsz)*/
uint8_t granule_sz; /* granule page shift */
+ bool had; /* hierarchical attribute disable */
} SMMUTransTableInfo;
+typedef struct SMMUTLBEntry {
+ IOMMUTLBEntry entry;
+ uint8_t level;
+ uint8_t granule;
+} SMMUTLBEntry;
+
+/* Stage-2 configuration. */
+typedef struct SMMUS2Cfg {
+ uint8_t tsz; /* Size of IPA input region (S2T0SZ) */
+ uint8_t sl0; /* Start level of translation (S2SL0) */
+ bool affd; /* AF Fault Disable (S2AFFD) */
+ bool record_faults; /* Record fault events (S2R) */
+ uint8_t granule_sz; /* Granule page shift (based on S2TG) */
+ uint8_t eff_ps; /* Effective PA output range (based on S2PS) */
+ uint16_t vmid; /* Virtual Machine ID (S2VMID) */
+ uint64_t vttb; /* Address of translation table base (S2TTB) */
+} SMMUS2Cfg;
+
/*
* Generic structure populated by derived SMMU devices
* after decoding the configuration information and used as
* input to the page table walk
*/
typedef struct SMMUTransCfg {
+ /* Shared fields between stage-1 and stage-2. */
int stage; /* translation stage */
- bool aa64; /* arch64 or aarch32 translation table */
bool disabled; /* smmu is disabled */
bool bypassed; /* translation is bypassed */
bool aborted; /* translation is aborted */
+ bool affd; /* AF fault disable */
+ uint32_t iotlb_hits; /* counts IOTLB hits */
+ uint32_t iotlb_misses; /* counts IOTLB misses*/
+ /* Used by stage-1 only. */
+ bool aa64; /* arch64 or aarch32 translation table */
+ bool record_faults; /* record fault events */
uint64_t ttb; /* TT base address */
uint8_t oas; /* output address width */
uint8_t tbi; /* Top Byte Ignore */
uint16_t asid;
SMMUTransTableInfo tt[2];
- uint32_t iotlb_hits; /* counts IOTLB hits for this asid */
- uint32_t iotlb_misses; /* counts IOTLB misses for this asid */
+ /* Used by stage-2 only. */
+ struct SMMUS2Cfg s2cfg;
} SMMUTransCfg;
typedef struct SMMUDevice {
@@ -91,9 +126,12 @@ typedef struct SMMUPciBus {
typedef struct SMMUIOTLBKey {
uint64_t iova;
uint16_t asid;
+ uint16_t vmid;
+ uint8_t tg;
+ uint8_t level;
} SMMUIOTLBKey;
-typedef struct SMMUState {
+struct SMMUState {
/* <private> */
SysBusDevice dev;
const char *mrtypename;
@@ -107,9 +145,9 @@ typedef struct SMMUState {
QLIST_HEAD(, SMMUDevice) devices_with_notifiers;
uint8_t bus_num;
PCIBus *primary_bus;
-} SMMUState;
+};
-typedef struct {
+struct SMMUBaseClass {
/* <private> */
SysBusDeviceClass parent_class;
@@ -117,14 +155,10 @@ typedef struct {
DeviceRealize parent_realize;
-} SMMUBaseClass;
+};
#define TYPE_ARM_SMMU "arm-smmu"
-#define ARM_SMMU(obj) OBJECT_CHECK(SMMUState, (obj), TYPE_ARM_SMMU)
-#define ARM_SMMU_CLASS(klass) \
- OBJECT_CLASS_CHECK(SMMUBaseClass, (klass), TYPE_ARM_SMMU)
-#define ARM_SMMU_GET_CLASS(obj) \
- OBJECT_GET_CLASS(SMMUBaseClass, (obj), TYPE_ARM_SMMU)
+OBJECT_DECLARE_TYPE(SMMUState, SMMUBaseClass, ARM_SMMU)
/* Return the SMMUPciBus handle associated to a PCI bus number */
SMMUPciBus *smmu_find_smmu_pcibus(SMMUState *s, uint8_t bus_num);
@@ -140,7 +174,7 @@ static inline uint16_t smmu_get_sid(SMMUDevice *sdev)
* pair, according to @cfg translation config
*/
int smmu_ptw(SMMUTransCfg *cfg, dma_addr_t iova, IOMMUAccessFlags perm,
- IOMMUTLBEntry *tlbe, SMMUPTWEventInfo *info);
+ SMMUTLBEntry *tlbe, SMMUPTWEventInfo *info);
/**
* select_tt - compute which translation table shall be used according to
@@ -153,14 +187,18 @@ IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid);
#define SMMU_IOTLB_MAX_SIZE 256
+SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg,
+ SMMUTransTableInfo *tt, hwaddr iova);
+void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, SMMUTLBEntry *entry);
+SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint16_t vmid, uint64_t iova,
+ uint8_t tg, uint8_t level);
void smmu_iotlb_inv_all(SMMUState *s);
void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid);
-void smmu_iotlb_inv_iova(SMMUState *s, uint16_t asid, dma_addr_t iova);
+void smmu_iotlb_inv_vmid(SMMUState *s, uint16_t vmid);
+void smmu_iotlb_inv_iova(SMMUState *s, int asid, int vmid, dma_addr_t iova,
+ uint8_t tg, uint64_t num_pages, uint8_t ttl);
/* Unmap the range of all the notifiers registered to any IOMMU mr */
void smmu_inv_notifiers_all(SMMUState *s);
-/* Unmap the range of all the notifiers registered to @mr */
-void smmu_inv_notifiers_mr(IOMMUMemoryRegion *mr);
-
#endif /* HW_ARM_SMMU_COMMON_H */
diff --git a/include/hw/arm/smmuv3.h b/include/hw/arm/smmuv3.h
index 36b2f45253..d183a62766 100644
--- a/include/hw/arm/smmuv3.h
+++ b/include/hw/arm/smmuv3.h
@@ -20,7 +20,7 @@
#define HW_ARM_SMMUV3_H
#include "hw/arm/smmu-common.h"
-#include "hw/registerfields.h"
+#include "qom/object.h"
#define TYPE_SMMUV3_IOMMU_MEMORY_REGION "smmuv3-iommu-memory-region"
@@ -32,7 +32,7 @@ typedef struct SMMUQueue {
uint8_t log2size;
} SMMUQueue;
-typedef struct SMMUv3State {
+struct SMMUv3State {
SMMUState smmu_state;
uint32_t features;
@@ -41,9 +41,11 @@ typedef struct SMMUv3State {
uint32_t idr[6];
uint32_t iidr;
+ uint32_t aidr;
uint32_t cr[3];
uint32_t cr0ack;
uint32_t statusr;
+ uint32_t gbpa;
uint32_t irq_ctrl;
uint32_t gerror;
uint32_t gerrorn;
@@ -60,7 +62,8 @@ typedef struct SMMUv3State {
qemu_irq irq[4];
QemuMutex mutex;
-} SMMUv3State;
+ char *stage;
+};
typedef enum {
SMMU_IRQ_EVTQ,
@@ -69,20 +72,19 @@ typedef enum {
SMMU_IRQ_GERROR,
} SMMUIrq;
-typedef struct {
+struct SMMUv3Class {
/*< private >*/
SMMUBaseClass smmu_base_class;
/*< public >*/
DeviceRealize parent_realize;
- DeviceReset parent_reset;
-} SMMUv3Class;
+ ResettablePhases parent_phases;
+};
#define TYPE_ARM_SMMUV3 "arm-smmuv3"
-#define ARM_SMMUV3(obj) OBJECT_CHECK(SMMUv3State, (obj), TYPE_ARM_SMMUV3)
-#define ARM_SMMUV3_CLASS(klass) \
- OBJECT_CLASS_CHECK(SMMUv3Class, (klass), TYPE_ARM_SMMUV3)
-#define ARM_SMMUV3_GET_CLASS(obj) \
- OBJECT_GET_CLASS(SMMUv3Class, (obj), TYPE_ARM_SMMUV3)
+OBJECT_DECLARE_TYPE(SMMUv3State, SMMUv3Class, ARM_SMMUV3)
+
+#define STAGE1_SUPPORTED(s) FIELD_EX32(s->idr[0], IDR0, S1P)
+#define STAGE2_SUPPORTED(s) FIELD_EX32(s->idr[0], IDR0, S2P)
#endif
diff --git a/include/hw/arm/stm32f100_soc.h b/include/hw/arm/stm32f100_soc.h
new file mode 100644
index 0000000000..a74d7b369c
--- /dev/null
+++ b/include/hw/arm/stm32f100_soc.h
@@ -0,0 +1,61 @@
+/*
+ * STM32F100 SoC
+ *
+ * Copyright (c) 2021 Alexandre Iooss <erdnaxe@crans.org>
+ *
+ * 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.
+ */
+
+#ifndef HW_ARM_STM32F100_SOC_H
+#define HW_ARM_STM32F100_SOC_H
+
+#include "hw/char/stm32f2xx_usart.h"
+#include "hw/ssi/stm32f2xx_spi.h"
+#include "hw/arm/armv7m.h"
+#include "qom/object.h"
+#include "hw/clock.h"
+
+#define TYPE_STM32F100_SOC "stm32f100-soc"
+OBJECT_DECLARE_SIMPLE_TYPE(STM32F100State, STM32F100_SOC)
+
+#define STM_NUM_USARTS 3
+#define STM_NUM_SPIS 2
+
+#define FLASH_BASE_ADDRESS 0x08000000
+#define FLASH_SIZE (128 * 1024)
+#define SRAM_BASE_ADDRESS 0x20000000
+#define SRAM_SIZE (8 * 1024)
+
+struct STM32F100State {
+ SysBusDevice parent_obj;
+
+ ARMv7MState armv7m;
+
+ STM32F2XXUsartState usart[STM_NUM_USARTS];
+ STM32F2XXSPIState spi[STM_NUM_SPIS];
+
+ MemoryRegion sram;
+ MemoryRegion flash;
+ MemoryRegion flash_alias;
+
+ Clock *sysclk;
+ Clock *refclk;
+};
+
+#endif
diff --git a/include/hw/arm/stm32f205_soc.h b/include/hw/arm/stm32f205_soc.h
index 922a733f88..4f4c8bbebc 100644
--- a/include/hw/arm/stm32f205_soc.h
+++ b/include/hw/arm/stm32f205_soc.h
@@ -32,10 +32,11 @@
#include "hw/or-irq.h"
#include "hw/ssi/stm32f2xx_spi.h"
#include "hw/arm/armv7m.h"
+#include "hw/clock.h"
+#include "qom/object.h"
#define TYPE_STM32F205_SOC "stm32f205-soc"
-#define STM32F205_SOC(obj) \
- OBJECT_CHECK(STM32F205State, (obj), TYPE_STM32F205_SOC)
+OBJECT_DECLARE_SIMPLE_TYPE(STM32F205State, STM32F205_SOC)
#define STM_NUM_USARTS 6
#define STM_NUM_TIMERS 4
@@ -47,12 +48,8 @@
#define SRAM_BASE_ADDRESS 0x20000000
#define SRAM_SIZE (128 * 1024)
-typedef struct STM32F205State {
- /*< private >*/
+struct STM32F205State {
SysBusDevice parent_obj;
- /*< public >*/
-
- char *cpu_type;
ARMv7MState armv7m;
@@ -62,7 +59,14 @@ typedef struct STM32F205State {
STM32F2XXADCState adc[STM_NUM_ADCS];
STM32F2XXSPIState spi[STM_NUM_SPIS];
- qemu_or_irq *adc_irqs;
-} STM32F205State;
+ OrIRQState *adc_irqs;
+
+ MemoryRegion sram;
+ MemoryRegion flash;
+ MemoryRegion flash_alias;
+
+ Clock *sysclk;
+ Clock *refclk;
+};
#endif
diff --git a/include/hw/arm/stm32f405_soc.h b/include/hw/arm/stm32f405_soc.h
index 1fe97f8c3a..d15c03c4b5 100644
--- a/include/hw/arm/stm32f405_soc.h
+++ b/include/hw/arm/stm32f405_soc.h
@@ -33,10 +33,10 @@
#include "hw/or-irq.h"
#include "hw/ssi/stm32f2xx_spi.h"
#include "hw/arm/armv7m.h"
+#include "qom/object.h"
#define TYPE_STM32F405_SOC "stm32f405-soc"
-#define STM32F405_SOC(obj) \
- OBJECT_CHECK(STM32F405State, (obj), TYPE_STM32F405_SOC)
+OBJECT_DECLARE_SIMPLE_TYPE(STM32F405State, STM32F405_SOC)
#define STM_NUM_USARTS 7
#define STM_NUM_TIMERS 4
@@ -46,14 +46,12 @@
#define FLASH_BASE_ADDRESS 0x08000000
#define FLASH_SIZE (1024 * 1024)
#define SRAM_BASE_ADDRESS 0x20000000
-#define SRAM_SIZE (192 * 1024)
+#define SRAM_SIZE (128 * 1024)
+#define CCM_BASE_ADDRESS 0x10000000
+#define CCM_SIZE (64 * 1024)
-typedef struct STM32F405State {
- /*< private >*/
+struct STM32F405State {
SysBusDevice parent_obj;
- /*< public >*/
-
- char *cpu_type;
ARMv7MState armv7m;
@@ -61,13 +59,17 @@ typedef struct STM32F405State {
STM32F4xxExtiState exti;
STM32F2XXUsartState usart[STM_NUM_USARTS];
STM32F2XXTimerState timer[STM_NUM_TIMERS];
- qemu_or_irq adc_irqs;
+ OrIRQState adc_irqs;
STM32F2XXADCState adc[STM_NUM_ADCS];
STM32F2XXSPIState spi[STM_NUM_SPIS];
+ MemoryRegion ccm;
MemoryRegion sram;
MemoryRegion flash;
MemoryRegion flash_alias;
-} STM32F405State;
+
+ Clock *sysclk;
+ Clock *refclk;
+};
#endif
diff --git a/include/hw/arm/stm32l4x5_soc.h b/include/hw/arm/stm32l4x5_soc.h
new file mode 100644
index 0000000000..ee5f362405
--- /dev/null
+++ b/include/hw/arm/stm32l4x5_soc.h
@@ -0,0 +1,67 @@
+/*
+ * STM32L4x5 SoC family
+ *
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * This work is heavily inspired by the stm32f405_soc by Alistair Francis.
+ * Original code is licensed under the MIT License:
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ */
+
+/*
+ * The reference used is the STMicroElectronics RM0351 Reference manual
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
+ */
+
+#ifndef HW_ARM_STM32L4x5_SOC_H
+#define HW_ARM_STM32L4x5_SOC_H
+
+#include "exec/memory.h"
+#include "hw/arm/armv7m.h"
+#include "hw/or-irq.h"
+#include "hw/misc/stm32l4x5_syscfg.h"
+#include "hw/misc/stm32l4x5_exti.h"
+#include "hw/misc/stm32l4x5_rcc.h"
+#include "hw/gpio/stm32l4x5_gpio.h"
+#include "qom/object.h"
+
+#define TYPE_STM32L4X5_SOC "stm32l4x5-soc"
+#define TYPE_STM32L4X5XC_SOC "stm32l4x5xc-soc"
+#define TYPE_STM32L4X5XE_SOC "stm32l4x5xe-soc"
+#define TYPE_STM32L4X5XG_SOC "stm32l4x5xg-soc"
+OBJECT_DECLARE_TYPE(Stm32l4x5SocState, Stm32l4x5SocClass, STM32L4X5_SOC)
+
+#define NUM_EXTI_OR_GATES 4
+
+struct Stm32l4x5SocState {
+ SysBusDevice parent_obj;
+
+ ARMv7MState armv7m;
+
+ Stm32l4x5ExtiState exti;
+ OrIRQState exti_or_gates[NUM_EXTI_OR_GATES];
+ Stm32l4x5SyscfgState syscfg;
+ Stm32l4x5RccState rcc;
+ Stm32l4x5GpioState gpio[NUM_GPIOS];
+
+ MemoryRegion sram1;
+ MemoryRegion sram2;
+ MemoryRegion flash;
+ MemoryRegion flash_alias;
+};
+
+struct Stm32l4x5SocClass {
+ SysBusDeviceClass parent_class;
+
+ size_t flash_size;
+};
+
+#endif
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index dff67e1bef..bb486d36b1 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -34,24 +34,18 @@
#include "qemu/notify.h"
#include "hw/boards.h"
#include "hw/arm/boot.h"
+#include "hw/arm/bsa.h"
#include "hw/block/flash.h"
#include "sysemu/kvm.h"
#include "hw/intc/arm_gicv3_common.h"
+#include "qom/object.h"
#define NUM_GICV2M_SPIS 64
#define NUM_VIRTIO_TRANSPORTS 32
#define NUM_SMMU_IRQS 4
-#define ARCH_GIC_MAINT_IRQ 9
-
-#define ARCH_TIMER_VIRT_IRQ 11
-#define ARCH_TIMER_S_EL1_IRQ 13
-#define ARCH_TIMER_NS_EL1_IRQ 14
-#define ARCH_TIMER_NS_EL2_IRQ 10
-
-#define VIRTUAL_PMU_IRQ 7
-
-#define PPI(irq) ((irq) + 16)
+/* See Linux kernel arch/arm64/include/asm/pvclock-abi.h */
+#define PVTIME_SIZE_PER_CPU 64
enum {
VIRT_FLASH,
@@ -77,9 +71,11 @@ enum {
VIRT_GPIO,
VIRT_SECURE_UART,
VIRT_SECURE_MEM,
+ VIRT_SECURE_GPIO,
VIRT_PCDIMM_ACPI,
VIRT_ACPI_GED,
VIRT_NVDIMM_ACPI,
+ VIRT_PVTIME,
VIRT_LOWMEMMAP_LAST,
};
@@ -103,32 +99,41 @@ typedef enum VirtMSIControllerType {
} VirtMSIControllerType;
typedef enum VirtGICType {
- VIRT_GIC_VERSION_MAX,
- VIRT_GIC_VERSION_HOST,
- VIRT_GIC_VERSION_2,
- VIRT_GIC_VERSION_3,
+ VIRT_GIC_VERSION_MAX = 0,
+ VIRT_GIC_VERSION_HOST = 1,
+ /* The concrete GIC values have to match the GIC version number */
+ VIRT_GIC_VERSION_2 = 2,
+ VIRT_GIC_VERSION_3 = 3,
+ VIRT_GIC_VERSION_4 = 4,
VIRT_GIC_VERSION_NOSEL,
} VirtGICType;
-typedef struct MemMapEntry {
- hwaddr base;
- hwaddr size;
-} MemMapEntry;
+#define VIRT_GIC_VERSION_2_MASK BIT(VIRT_GIC_VERSION_2)
+#define VIRT_GIC_VERSION_3_MASK BIT(VIRT_GIC_VERSION_3)
+#define VIRT_GIC_VERSION_4_MASK BIT(VIRT_GIC_VERSION_4)
-typedef struct {
+struct VirtMachineClass {
MachineClass parent;
bool disallow_affinity_adjustment;
bool no_its;
+ bool no_tcg_its;
bool no_pmu;
bool claim_edge_triggered_timers;
bool smbios_old_sys_ver;
+ bool no_highmem_compact;
bool no_highmem_ecam;
- bool no_ged; /* Machines < 4.2 has no support for ACPI GED device */
+ bool no_ged; /* Machines < 4.2 have no support for ACPI GED device */
bool kvm_no_adjvtime;
+ bool no_kvm_steal_time;
bool acpi_expose_flash;
-} VirtMachineClass;
+ bool no_secure_gpio;
+ /* Machines < 6.2 have no support for describing cpu topology to guest */
+ bool no_cpu_topology;
+ bool no_tcg_lpa2;
+ bool no_ns_el2_virt_timer_irq;
+};
-typedef struct {
+struct VirtMachineState {
MachineState parent;
Notifier machine_done;
DeviceState *platform_bus_dev;
@@ -136,22 +141,26 @@ typedef struct {
PFlashCFI01 *flash[2];
bool secure;
bool highmem;
+ bool highmem_compact;
bool highmem_ecam;
+ bool highmem_mmio;
+ bool highmem_redists;
bool its;
+ bool tcg_its;
bool virt;
bool ras;
bool mte;
+ bool dtb_randomness;
OnOffAuto acpi;
VirtGICType gic_version;
VirtIOMMUType iommu;
+ bool default_bus_bypass_iommu;
VirtMSIControllerType msi_controller;
uint16_t virtio_iommu_bdf;
struct arm_boot_info bootinfo;
MemMapEntry *memmap;
char *pciehb_nodename;
const int *irqmap;
- int smp_cpus;
- void *fdt;
int fdt_size;
uint32_t clock_phandle;
uint32_t gic_phandle;
@@ -162,30 +171,42 @@ typedef struct {
DeviceState *gic;
DeviceState *acpi_dev;
Notifier powerdown_notifier;
-} VirtMachineState;
+ PCIBus *bus;
+ char *oem_id;
+ char *oem_table_id;
+ bool ns_el2_virt_timer_irq;
+};
#define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM)
#define TYPE_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
-#define VIRT_MACHINE(obj) \
- OBJECT_CHECK(VirtMachineState, (obj), TYPE_VIRT_MACHINE)
-#define VIRT_MACHINE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(VirtMachineClass, obj, TYPE_VIRT_MACHINE)
-#define VIRT_MACHINE_CLASS(klass) \
- OBJECT_CLASS_CHECK(VirtMachineClass, klass, TYPE_VIRT_MACHINE)
+OBJECT_DECLARE_TYPE(VirtMachineState, VirtMachineClass, VIRT_MACHINE)
void virt_acpi_setup(VirtMachineState *vms);
bool virt_is_acpi_enabled(VirtMachineState *vms);
+/* Return number of redistributors that fit in the specified region */
+static uint32_t virt_redist_capacity(VirtMachineState *vms, int region)
+{
+ uint32_t redist_size;
+
+ if (vms->gic_version == VIRT_GIC_VERSION_3) {
+ redist_size = GICV3_REDIST_SIZE;
+ } else {
+ redist_size = GICV4_REDIST_SIZE;
+ }
+ return vms->memmap[region].size / redist_size;
+}
+
/* Return the number of used redistributor regions */
static inline int virt_gicv3_redist_region_count(VirtMachineState *vms)
{
- uint32_t redist0_capacity =
- vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
+ uint32_t redist0_capacity = virt_redist_capacity(vms, VIRT_GIC_REDIST);
- assert(vms->gic_version == VIRT_GIC_VERSION_3);
+ assert(vms->gic_version != VIRT_GIC_VERSION_2);
- return vms->smp_cpus > redist0_capacity ? 2 : 1;
+ return (MACHINE(vms)->smp.cpus > redist0_capacity &&
+ vms->highmem_redists) ? 2 : 1;
}
#endif /* QEMU_ARM_VIRT_H */
diff --git a/include/hw/arm/xen_arch_hvm.h b/include/hw/arm/xen_arch_hvm.h
new file mode 100644
index 0000000000..8fd645e723
--- /dev/null
+++ b/include/hw/arm/xen_arch_hvm.h
@@ -0,0 +1,9 @@
+#ifndef HW_XEN_ARCH_ARM_HVM_H
+#define HW_XEN_ARCH_ARM_HVM_H
+
+#include <xen/hvm/ioreq.h>
+void arch_handle_ioreq(XenIOState *state, ioreq_t *req);
+void arch_xen_set_memory(XenIOState *state,
+ MemoryRegionSection *section,
+ bool add);
+#endif
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 9c9f47ba9d..025beb5532 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -13,25 +13,45 @@
#define XLNX_VERSAL_H
#include "hw/sysbus.h"
-#include "hw/arm/boot.h"
+#include "hw/cpu/cluster.h"
+#include "hw/or-irq.h"
#include "hw/sd/sdhci.h"
#include "hw/intc/arm_gicv3.h"
#include "hw/char/pl011.h"
#include "hw/dma/xlnx-zdma.h"
#include "hw/net/cadence_gem.h"
#include "hw/rtc/xlnx-zynqmp-rtc.h"
+#include "qom/object.h"
+#include "hw/usb/xlnx-usb-subsystem.h"
+#include "hw/misc/xlnx-versal-xramc.h"
+#include "hw/nvram/xlnx-bbram.h"
+#include "hw/nvram/xlnx-versal-efuse.h"
+#include "hw/ssi/xlnx-versal-ospi.h"
+#include "hw/dma/xlnx_csu_dma.h"
+#include "hw/misc/xlnx-versal-crl.h"
+#include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
+#include "hw/misc/xlnx-versal-trng.h"
+#include "hw/net/xlnx-versal-canfd.h"
+#include "hw/misc/xlnx-versal-cfu.h"
+#include "hw/misc/xlnx-versal-cframe-reg.h"
+#include "target/arm/cpu.h"
#define TYPE_XLNX_VERSAL "xlnx-versal"
-#define XLNX_VERSAL(obj) OBJECT_CHECK(Versal, (obj), TYPE_XLNX_VERSAL)
+OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
#define XLNX_VERSAL_NR_ACPUS 2
+#define XLNX_VERSAL_NR_RCPUS 2
#define XLNX_VERSAL_NR_UARTS 2
#define XLNX_VERSAL_NR_GEMS 2
#define XLNX_VERSAL_NR_ADMAS 8
#define XLNX_VERSAL_NR_SDS 2
+#define XLNX_VERSAL_NR_XRAM 4
#define XLNX_VERSAL_NR_IRQS 192
+#define XLNX_VERSAL_NR_CANFD 2
+#define XLNX_VERSAL_CANFD_REF_CLK (24 * 1000 * 1000)
+#define XLNX_VERSAL_NR_CFRAME 15
-typedef struct Versal {
+struct Versal {
/*< private >*/
SysBusDevice parent_obj;
@@ -39,6 +59,7 @@ typedef struct Versal {
struct {
struct {
MemoryRegion mr;
+ CPUClusterState cluster;
ARMCPU cpu[XLNX_VERSAL_NR_ACPUS];
GICv3State gic;
} apu;
@@ -58,23 +79,62 @@ typedef struct Versal {
PL011State uart[XLNX_VERSAL_NR_UARTS];
CadenceGEMState gem[XLNX_VERSAL_NR_GEMS];
XlnxZDMA adma[XLNX_VERSAL_NR_ADMAS];
+ VersalUsb2 usb;
+ CanBusState *canbus[XLNX_VERSAL_NR_CANFD];
+ XlnxVersalCANFDState canfd[XLNX_VERSAL_NR_CANFD];
} iou;
+
+ /* Real-time Processing Unit. */
+ struct {
+ MemoryRegion mr;
+ MemoryRegion mr_ps_alias;
+
+ CPUClusterState cluster;
+ ARMCPU cpu[XLNX_VERSAL_NR_RCPUS];
+ } rpu;
+
+ struct {
+ OrIRQState irq_orgate;
+ XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM];
+ } xram;
+
+ XlnxVersalCRL crl;
} lpd;
/* The Platform Management Controller subsystem. */
struct {
struct {
SDHCIState sd[XLNX_VERSAL_NR_SDS];
+ XlnxVersalPmcIouSlcr slcr;
+
+ struct {
+ XlnxVersalOspi ospi;
+ XlnxCSUDMA dma_src;
+ XlnxCSUDMA dma_dst;
+ MemoryRegion linear_mr;
+ OrIRQState irq_orgate;
+ } ospi;
} iou;
XlnxZynqMPRTC rtc;
+ XlnxVersalTRng trng;
+ XlnxBBRam bbram;
+ XlnxEFuse efuse;
+ XlnxVersalEFuseCtrl efuse_ctrl;
+ XlnxVersalEFuseCache efuse_cache;
+ XlnxVersalCFUAPB cfu_apb;
+ XlnxVersalCFUFDRO cfu_fdro;
+ XlnxVersalCFUSFR cfu_sfr;
+ XlnxVersalCFrameReg cframe[XLNX_VERSAL_NR_CFRAME];
+ XlnxVersalCFrameBcastReg cframe_bcast;
+
+ OrIRQState apb_irq_orgate;
} pmc;
struct {
MemoryRegion *mr_ddr;
- uint32_t psci_conduit;
} cfg;
-} Versal;
+};
/* Memory-map and IRQ definitions. Copied a subset from
* auto-generated files. */
@@ -85,15 +145,24 @@ typedef struct Versal {
#define VERSAL_TIMER_NS_EL1_IRQ 14
#define VERSAL_TIMER_NS_EL2_IRQ 10
+#define VERSAL_CRL_IRQ 10
#define VERSAL_UART0_IRQ_0 18
#define VERSAL_UART1_IRQ_0 19
+#define VERSAL_CANFD0_IRQ_0 20
+#define VERSAL_CANFD1_IRQ_0 21
+#define VERSAL_USB0_IRQ_0 22
#define VERSAL_GEM0_IRQ_0 56
#define VERSAL_GEM0_WAKE_IRQ_0 57
#define VERSAL_GEM1_IRQ_0 58
#define VERSAL_GEM1_WAKE_IRQ_0 59
#define VERSAL_ADMA_IRQ_0 60
-#define VERSAL_RTC_APB_ERR_IRQ 121
+#define VERSAL_XRAM_IRQ_0 79
+#define VERSAL_CFU_IRQ_0 120
+#define VERSAL_PMC_APB_IRQ 121
+#define VERSAL_OSPI_IRQ 124
#define VERSAL_SD0_IRQ_0 126
+#define VERSAL_EFUSE_IRQ 139
+#define VERSAL_TRNG_IRQ 141
#define VERSAL_RTC_ALARM_IRQ 142
#define VERSAL_RTC_SECONDS_IRQ 143
@@ -113,6 +182,11 @@ typedef struct Versal {
#define MM_UART1 0xff010000U
#define MM_UART1_SIZE 0x10000
+#define MM_CANFD0 0xff060000U
+#define MM_CANFD0_SIZE 0x10000
+#define MM_CANFD1 0xff070000U
+#define MM_CANFD1_SIZE 0x10000
+
#define MM_GEM0 0xff0c0000U
#define MM_GEM0_SIZE 0x10000
#define MM_GEM1 0xff0d0000U
@@ -124,6 +198,16 @@ typedef struct Versal {
#define MM_OCM 0xfffc0000U
#define MM_OCM_SIZE 0x40000
+#define MM_XRAM 0xfe800000
+#define MM_XRAMC 0xff8e0000
+#define MM_XRAMC_SIZE 0x10000
+
+#define MM_USB2_CTRL_REGS 0xFF9D0000
+#define MM_USB2_CTRL_REGS_SIZE 0x10000
+
+#define MM_USB_0 0xFE200000
+#define MM_USB_0_SIZE 0x10000
+
#define MM_TOP_DDR 0x0
#define MM_TOP_DDR_SIZE 0x80000000U
#define MM_TOP_DDR_2 0x800000000ULL
@@ -144,11 +228,110 @@ typedef struct Versal {
#define MM_IOU_SCNTRS_SIZE 0x10000
#define MM_FPD_CRF 0xfd1a0000U
#define MM_FPD_CRF_SIZE 0x140000
+#define MM_FPD_FPD_APU 0xfd5c0000
+#define MM_FPD_FPD_APU_SIZE 0x100
+
+#define MM_PMC_PMC_IOU_SLCR 0xf1060000
+#define MM_PMC_PMC_IOU_SLCR_SIZE 0x10000
+
+#define MM_PMC_OSPI 0xf1010000
+#define MM_PMC_OSPI_SIZE 0x10000
+
+#define MM_PMC_OSPI_DAC 0xc0000000
+#define MM_PMC_OSPI_DAC_SIZE 0x20000000
+
+#define MM_PMC_OSPI_DMA_DST 0xf1011800
+#define MM_PMC_OSPI_DMA_SRC 0xf1011000
#define MM_PMC_SD0 0xf1040000U
#define MM_PMC_SD0_SIZE 0x10000
+#define MM_PMC_BBRAM_CTRL 0xf11f0000
+#define MM_PMC_BBRAM_CTRL_SIZE 0x00050
+#define MM_PMC_EFUSE_CTRL 0xf1240000
+#define MM_PMC_EFUSE_CTRL_SIZE 0x00104
+#define MM_PMC_EFUSE_CACHE 0xf1250000
+#define MM_PMC_EFUSE_CACHE_SIZE 0x00C00
+
+#define MM_PMC_CFU_APB 0xf12b0000
+#define MM_PMC_CFU_APB_SIZE 0x10000
+#define MM_PMC_CFU_STREAM 0xf12c0000
+#define MM_PMC_CFU_STREAM_SIZE 0x1000
+#define MM_PMC_CFU_SFR 0xf12c1000
+#define MM_PMC_CFU_SFR_SIZE 0x1000
+#define MM_PMC_CFU_FDRO 0xf12c2000
+#define MM_PMC_CFU_FDRO_SIZE 0x1000
+#define MM_PMC_CFU_STREAM_2 0xf1f80000
+#define MM_PMC_CFU_STREAM_2_SIZE 0x40000
+
+#define MM_PMC_CFRAME0_REG 0xf12d0000
+#define MM_PMC_CFRAME0_REG_SIZE 0x1000
+#define MM_PMC_CFRAME0_FDRI 0xf12d1000
+#define MM_PMC_CFRAME0_FDRI_SIZE 0x1000
+#define MM_PMC_CFRAME1_REG 0xf12d2000
+#define MM_PMC_CFRAME1_REG_SIZE 0x1000
+#define MM_PMC_CFRAME1_FDRI 0xf12d3000
+#define MM_PMC_CFRAME1_FDRI_SIZE 0x1000
+#define MM_PMC_CFRAME2_REG 0xf12d4000
+#define MM_PMC_CFRAME2_REG_SIZE 0x1000
+#define MM_PMC_CFRAME2_FDRI 0xf12d5000
+#define MM_PMC_CFRAME2_FDRI_SIZE 0x1000
+#define MM_PMC_CFRAME3_REG 0xf12d6000
+#define MM_PMC_CFRAME3_REG_SIZE 0x1000
+#define MM_PMC_CFRAME3_FDRI 0xf12d7000
+#define MM_PMC_CFRAME3_FDRI_SIZE 0x1000
+#define MM_PMC_CFRAME4_REG 0xf12d8000
+#define MM_PMC_CFRAME4_REG_SIZE 0x1000
+#define MM_PMC_CFRAME4_FDRI 0xf12d9000
+#define MM_PMC_CFRAME4_FDRI_SIZE 0x1000
+#define MM_PMC_CFRAME5_REG 0xf12da000
+#define MM_PMC_CFRAME5_REG_SIZE 0x1000
+#define MM_PMC_CFRAME5_FDRI 0xf12db000
+#define MM_PMC_CFRAME5_FDRI_SIZE 0x1000
+#define MM_PMC_CFRAME6_REG 0xf12dc000
+#define MM_PMC_CFRAME6_REG_SIZE 0x1000
+#define MM_PMC_CFRAME6_FDRI 0xf12dd000
+#define MM_PMC_CFRAME6_FDRI_SIZE 0x1000
+#define MM_PMC_CFRAME7_REG 0xf12de000
+#define MM_PMC_CFRAME7_REG_SIZE 0x1000
+#define MM_PMC_CFRAME7_FDRI 0xf12df000
+#define MM_PMC_CFRAME7_FDRI_SIZE 0x1000
+#define MM_PMC_CFRAME8_REG 0xf12e0000
+#define MM_PMC_CFRAME8_REG_SIZE 0x1000
+#define MM_PMC_CFRAME8_FDRI 0xf12e1000
+#define MM_PMC_CFRAME8_FDRI_SIZE 0x1000
+#define MM_PMC_CFRAME9_REG 0xf12e2000
+#define MM_PMC_CFRAME9_REG_SIZE 0x1000
+#define MM_PMC_CFRAME9_FDRI 0xf12e3000
+#define MM_PMC_CFRAME9_FDRI_SIZE 0x1000
+#define MM_PMC_CFRAME10_REG 0xf12e4000
+#define MM_PMC_CFRAME10_REG_SIZE 0x1000
+#define MM_PMC_CFRAME10_FDRI 0xf12e5000
+#define MM_PMC_CFRAME10_FDRI_SIZE 0x1000
+#define MM_PMC_CFRAME11_REG 0xf12e6000
+#define MM_PMC_CFRAME11_REG_SIZE 0x1000
+#define MM_PMC_CFRAME11_FDRI 0xf12e7000
+#define MM_PMC_CFRAME11_FDRI_SIZE 0x1000
+#define MM_PMC_CFRAME12_REG 0xf12e8000
+#define MM_PMC_CFRAME12_REG_SIZE 0x1000
+#define MM_PMC_CFRAME12_FDRI 0xf12e9000
+#define MM_PMC_CFRAME12_FDRI_SIZE 0x1000
+#define MM_PMC_CFRAME13_REG 0xf12ea000
+#define MM_PMC_CFRAME13_REG_SIZE 0x1000
+#define MM_PMC_CFRAME13_FDRI 0xf12eb000
+#define MM_PMC_CFRAME13_FDRI_SIZE 0x1000
+#define MM_PMC_CFRAME14_REG 0xf12ec000
+#define MM_PMC_CFRAME14_REG_SIZE 0x1000
+#define MM_PMC_CFRAME14_FDRI 0xf12ed000
+#define MM_PMC_CFRAME14_FDRI_SIZE 0x1000
+#define MM_PMC_CFRAME_BCAST_REG 0xf12ee000
+#define MM_PMC_CFRAME_BCAST_REG_SIZE 0x1000
+#define MM_PMC_CFRAME_BCAST_FDRI 0xf12ef000
+#define MM_PMC_CFRAME_BCAST_FDRI_SIZE 0x1000
+
#define MM_PMC_CRP 0xf1260000U
#define MM_PMC_CRP_SIZE 0x10000
#define MM_PMC_RTC 0xf12a0000
#define MM_PMC_RTC_SIZE 0x10000
+#define MM_PMC_TRNG 0xf1230000
+#define MM_PMC_TRNG_SIZE 0x10000
#endif
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
index 53076fa29a..48f7948092 100644
--- a/include/hw/arm/xlnx-zynqmp.h
+++ b/include/hw/arm/xlnx-zynqmp.h
@@ -18,11 +18,11 @@
#ifndef XLNX_ZYNQMP_H
#define XLNX_ZYNQMP_H
-#include "hw/arm/boot.h"
#include "hw/intc/arm_gic.h"
#include "hw/net/cadence_gem.h"
#include "hw/char/cadence_uart.h"
-#include "hw/ide/ahci.h"
+#include "hw/net/xlnx-zynqmp-can.h"
+#include "hw/ide/ahci-sysbus.h"
#include "hw/sd/sdhci.h"
#include "hw/ssi/xilinx_spips.h"
#include "hw/dma/xlnx_dpdma.h"
@@ -32,19 +32,31 @@
#include "hw/rtc/xlnx-zynqmp-rtc.h"
#include "hw/cpu/cluster.h"
#include "target/arm/cpu.h"
-
-#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
-#define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \
- TYPE_XLNX_ZYNQMP)
+#include "qom/object.h"
+#include "net/can_emu.h"
+#include "hw/dma/xlnx_csu_dma.h"
+#include "hw/nvram/xlnx-bbram.h"
+#include "hw/nvram/xlnx-zynqmp-efuse.h"
+#include "hw/or-irq.h"
+#include "hw/misc/xlnx-zynqmp-apu-ctrl.h"
+#include "hw/misc/xlnx-zynqmp-crf.h"
+#include "hw/timer/cadence_ttc.h"
+#include "hw/usb/hcd-dwc3.h"
+
+#define TYPE_XLNX_ZYNQMP "xlnx-zynqmp"
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
#define XLNX_ZYNQMP_NUM_APU_CPUS 4
#define XLNX_ZYNQMP_NUM_RPU_CPUS 2
#define XLNX_ZYNQMP_NUM_GEMS 4
#define XLNX_ZYNQMP_NUM_UARTS 2
+#define XLNX_ZYNQMP_NUM_CAN 2
+#define XLNX_ZYNQMP_CAN_REF_CLK (24 * 1000 * 1000)
#define XLNX_ZYNQMP_NUM_SDHCI 2
#define XLNX_ZYNQMP_NUM_SPIS 2
#define XLNX_ZYNQMP_NUM_GDMA_CH 8
#define XLNX_ZYNQMP_NUM_ADMA_CH 8
+#define XLNX_ZYNQMP_NUM_USB 2
#define XLNX_ZYNQMP_NUM_QSPI_BUS 2
#define XLNX_ZYNQMP_NUM_QSPI_BUS_CS 2
@@ -56,7 +68,8 @@
#define XLNX_ZYNQMP_GIC_REGIONS 6
-/* ZynqMP maps the ARM GIC regions (GICC, GICD ...) at consecutive 64k offsets
+/*
+ * ZynqMP maps the ARM GIC regions (GICC, GICD ...) at consecutive 64k offsets
* and under-decodes the 64k region. This mirrors the 4k regions to every 4k
* aligned address in the 64k region. To implement each GIC region needs a
* number of memory region aliases.
@@ -73,7 +86,14 @@
#define XLNX_ZYNQMP_MAX_RAM_SIZE (XLNX_ZYNQMP_MAX_LOW_RAM_SIZE + \
XLNX_ZYNQMP_MAX_HIGH_RAM_SIZE)
-typedef struct XlnxZynqMPState {
+#define XLNX_ZYNQMP_NUM_TTC 4
+
+/*
+ * Unimplemented mmio regions needed to boot some images.
+ */
+#define XLNX_ZYNQMP_NUM_UNIMP_AREAS 1
+
+struct XlnxZynqMPState {
/*< private >*/
DeviceState parent_obj;
@@ -89,9 +109,15 @@ typedef struct XlnxZynqMPState {
MemoryRegion *ddr_ram;
MemoryRegion ddr_ram_low, ddr_ram_high;
+ XlnxBBRam bbram;
+ XlnxEFuse efuse;
+ XlnxZynqMPEFuse efuse_ctrl;
+
+ MemoryRegion mr_unimp[XLNX_ZYNQMP_NUM_UNIMP_AREAS];
CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS];
+ XlnxZynqMPCANState can[XLNX_ZYNQMP_NUM_CAN];
SysbusAHCIState sata;
SDHCIState sdhci[XLNX_ZYNQMP_NUM_SDHCI];
XilinxSPIPS spi[XLNX_ZYNQMP_NUM_SPIS];
@@ -102,6 +128,12 @@ typedef struct XlnxZynqMPState {
XlnxZynqMPRTC rtc;
XlnxZDMA gdma[XLNX_ZYNQMP_NUM_GDMA_CH];
XlnxZDMA adma[XLNX_ZYNQMP_NUM_ADMA_CH];
+ XlnxCSUDMA qspi_dma;
+ OrIRQState qspi_irq_orgate;
+ XlnxZynqMPAPUCtrl apu_ctrl;
+ XlnxZynqMPCRF crf;
+ CadenceTTCState ttc[XLNX_ZYNQMP_NUM_TTC];
+ USBDWC3 usb[XLNX_ZYNQMP_NUM_USB];
char *boot_cpu;
ARMCPU *boot_cpu_ptr;
@@ -110,8 +142,9 @@ typedef struct XlnxZynqMPState {
bool secure;
/* Has the ARM Virtualization extensions? */
bool virt;
- /* Has the RPU subsystem? */
- bool has_rpu;
-} XlnxZynqMPState;
+
+ /* CAN bus. */
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
+};
#endif
diff --git a/include/hw/audio/asc.h b/include/hw/audio/asc.h
new file mode 100644
index 0000000000..04fac270b6
--- /dev/null
+++ b/include/hw/audio/asc.h
@@ -0,0 +1,85 @@
+/*
+ * QEMU Apple Sound Chip emulation
+ *
+ * Apple Sound Chip (ASC) 344S0063
+ * Enhanced Apple Sound Chip (EASC) 343S1063
+ *
+ * Copyright (c) 2012-2018 Laurent Vivier <laurent@vivier.eu>
+ * Copyright (c) 2022 Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_AUDIO_ASC_H
+#define HW_AUDIO_ASC_H
+
+#include "hw/sysbus.h"
+#include "audio/audio.h"
+
+#define ASC_FREQ 22257
+
+enum {
+ ASC_TYPE_ASC = 0, /* original discrete Apple Sound Chip */
+ ASC_TYPE_EASC = 1 /* discrete Enhanced Apple Sound Chip */
+};
+
+#define ASC_FIFO_OFFSET 0x0
+#define ASC_FIFO_SIZE 0x400
+
+#define ASC_REG_OFFSET 0x800
+#define ASC_REG_SIZE 0x60
+
+#define ASC_EXTREG_OFFSET 0xf00
+#define ASC_EXTREG_SIZE 0x20
+
+typedef struct ASCFIFOState {
+ int index;
+
+ MemoryRegion mem_fifo;
+ uint8_t fifo[ASC_FIFO_SIZE];
+ uint8_t int_status;
+
+ int cnt;
+ int wptr;
+ int rptr;
+
+ MemoryRegion mem_extregs;
+ uint8_t extregs[ASC_EXTREG_SIZE];
+
+ int xa_cnt;
+ uint8_t xa_val;
+ uint8_t xa_flags;
+ int16_t xa_last[2];
+} ASCFIFOState;
+
+struct ASCState {
+ SysBusDevice parent_obj;
+
+ uint8_t type;
+ MemoryRegion asc;
+ MemoryRegion mem_fifo;
+ MemoryRegion mem_regs;
+ MemoryRegion mem_extregs;
+
+ QEMUSoundCard card;
+ SWVoiceOut *voice;
+ uint8_t *mixbuf;
+ int samples;
+ int shift;
+
+ uint8_t *silentbuf;
+
+ /* Time when we were last able to generate samples */
+ int64_t fifo_empty_ns;
+
+ qemu_irq irq;
+
+ ASCFIFOState fifos[2];
+
+ uint8_t regs[ASC_REG_SIZE];
+};
+
+#define TYPE_ASC "apple-sound-chip"
+OBJECT_DECLARE_SIMPLE_TYPE(ASCState, ASC)
+
+#endif
diff --git a/include/hw/audio/pcspk.h b/include/hw/audio/pcspk.h
index 9506179587..6be75a6b86 100644
--- a/include/hw/audio/pcspk.h
+++ b/include/hw/audio/pcspk.h
@@ -25,16 +25,6 @@
#ifndef HW_PCSPK_H
#define HW_PCSPK_H
-#include "hw/isa/isa.h"
-#include "hw/qdev-properties.h"
-#include "qapi/error.h"
-
#define TYPE_PC_SPEAKER "isa-pcspk"
-static inline void pcspk_init(ISADevice *isadev, ISABus *bus, ISADevice *pit)
-{
- object_property_set_link(OBJECT(isadev), "pit", OBJECT(pit), NULL);
- isa_realize_and_unref(isadev, bus, &error_fatal);
-}
-
#endif /* HW_PCSPK_H */
diff --git a/include/hw/audio/soundhw.h b/include/hw/audio/soundhw.h
index f09a297854..474c5ff94e 100644
--- a/include/hw/audio/soundhw.h
+++ b/include/hw/audio/soundhw.h
@@ -1,15 +1,13 @@
#ifndef HW_SOUNDHW_H
#define HW_SOUNDHW_H
-void isa_register_soundhw(const char *name, const char *descr,
- int (*init_isa)(ISABus *bus));
-
void pci_register_soundhw(const char *name, const char *descr,
- int (*init_pci)(PCIBus *bus));
+ int (*init_pci)(PCIBus *bus, const char *audiodev));
void deprecated_register_soundhw(const char *name, const char *descr,
int isa, const char *typename);
void soundhw_init(void);
-void select_soundhw(const char *optarg);
+void show_valid_soundhw(void);
+void select_soundhw(const char *name, const char *audiodev);
#endif
diff --git a/include/hw/audio/virtio-snd.h b/include/hw/audio/virtio-snd.h
new file mode 100644
index 0000000000..8dafedb276
--- /dev/null
+++ b/include/hw/audio/virtio-snd.h
@@ -0,0 +1,250 @@
+/*
+ * VIRTIO Sound Device conforming to
+ *
+ * "Virtual I/O Device (VIRTIO) Version 1.2
+ * Committee Specification Draft 01
+ * 09 May 2022"
+ *
+ * Copyright (c) 2023 Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
+ * Copyright (C) 2019 OpenSynergy GmbH
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version. See the COPYING file in the
+ * top-level directory.
+ */
+
+#ifndef QEMU_VIRTIO_SOUND_H
+#define QEMU_VIRTIO_SOUND_H
+
+#include "hw/virtio/virtio.h"
+#include "audio/audio.h"
+#include "standard-headers/linux/virtio_ids.h"
+#include "standard-headers/linux/virtio_snd.h"
+
+#define TYPE_VIRTIO_SND "virtio-sound-device"
+#define VIRTIO_SND(obj) \
+ OBJECT_CHECK(VirtIOSound, (obj), TYPE_VIRTIO_SND)
+
+/* CONFIGURATION SPACE */
+
+typedef struct virtio_snd_config virtio_snd_config;
+
+/* COMMON DEFINITIONS */
+
+/* common header for request/response*/
+typedef struct virtio_snd_hdr virtio_snd_hdr;
+
+/* event notification */
+typedef struct virtio_snd_event virtio_snd_event;
+
+/* common control request to query an item information */
+typedef struct virtio_snd_query_info virtio_snd_query_info;
+
+/* JACK CONTROL MESSAGES */
+
+typedef struct virtio_snd_jack_hdr virtio_snd_jack_hdr;
+
+/* jack information structure */
+typedef struct virtio_snd_jack_info virtio_snd_jack_info;
+
+/* jack remapping control request */
+typedef struct virtio_snd_jack_remap virtio_snd_jack_remap;
+
+/*
+ * PCM CONTROL MESSAGES
+ */
+typedef struct virtio_snd_pcm_hdr virtio_snd_pcm_hdr;
+
+/* PCM stream info structure */
+typedef struct virtio_snd_pcm_info virtio_snd_pcm_info;
+
+/* set PCM stream params */
+typedef struct virtio_snd_pcm_set_params virtio_snd_pcm_set_params;
+
+/* I/O request header */
+typedef struct virtio_snd_pcm_xfer virtio_snd_pcm_xfer;
+
+/* I/O request status */
+typedef struct virtio_snd_pcm_status virtio_snd_pcm_status;
+
+/* device structs */
+
+typedef struct VirtIOSound VirtIOSound;
+
+typedef struct VirtIOSoundPCMStream VirtIOSoundPCMStream;
+
+typedef struct virtio_snd_ctrl_command virtio_snd_ctrl_command;
+
+typedef struct VirtIOSoundPCM VirtIOSoundPCM;
+
+typedef struct VirtIOSoundPCMBuffer VirtIOSoundPCMBuffer;
+
+/*
+ * The VirtIO sound spec reuses layouts and values from the High Definition
+ * Audio spec (virtio/v1.2: 5.14 Sound Device). This struct handles each I/O
+ * message's buffer (virtio/v1.2: 5.14.6.8 PCM I/O Messages).
+ *
+ * In the case of TX (i.e. playback) buffers, we defer reading the raw PCM data
+ * from the virtqueue until QEMU's sound backsystem calls the output callback.
+ * This is tracked by the `bool populated;` field, which is set to true when
+ * data has been read into our own buffer for consumption.
+ *
+ * VirtIOSoundPCMBuffer has a dynamic size since it includes the raw PCM data
+ * in its allocation. It must be initialized and destroyed as follows:
+ *
+ * size_t size = [[derived from owned VQ element descriptor sizes]];
+ * buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer) + size);
+ * buffer->elem = [[owned VQ element]];
+ *
+ * [..]
+ *
+ * g_free(buffer->elem);
+ * g_free(buffer);
+ */
+struct VirtIOSoundPCMBuffer {
+ QSIMPLEQ_ENTRY(VirtIOSoundPCMBuffer) entry;
+ VirtQueueElement *elem;
+ VirtQueue *vq;
+ size_t size;
+ /*
+ * In TX / Plaback, `offset` represents the first unused position inside
+ * `data`. If `offset == size` then there are no unused data left.
+ */
+ uint64_t offset;
+ /* Used for the TX queue for lazy I/O copy from `elem` */
+ bool populated;
+ /*
+ * VirtIOSoundPCMBuffer is an unsized type because it ends with an array of
+ * bytes. The size of `data` is determined from the I/O message's read-only
+ * or write-only size when allocating VirtIOSoundPCMBuffer.
+ */
+ uint8_t data[];
+};
+
+struct VirtIOSoundPCM {
+ VirtIOSound *snd;
+ /*
+ * PCM parameters are a separate field instead of a VirtIOSoundPCMStream
+ * field, because the operation of PCM control requests is first
+ * VIRTIO_SND_R_PCM_SET_PARAMS and then VIRTIO_SND_R_PCM_PREPARE; this
+ * means that some times we get parameters without having an allocated
+ * stream yet.
+ */
+ virtio_snd_pcm_set_params *pcm_params;
+ VirtIOSoundPCMStream **streams;
+};
+
+struct VirtIOSoundPCMStream {
+ VirtIOSoundPCM *pcm;
+ virtio_snd_pcm_info info;
+ virtio_snd_pcm_set_params params;
+ uint32_t id;
+ /* channel position values (VIRTIO_SND_CHMAP_XXX) */
+ uint8_t positions[VIRTIO_SND_CHMAP_MAX_SIZE];
+ VirtIOSound *s;
+ bool flushing;
+ audsettings as;
+ union {
+ SWVoiceIn *in;
+ SWVoiceOut *out;
+ } voice;
+ QemuMutex queue_mutex;
+ bool active;
+ QSIMPLEQ_HEAD(, VirtIOSoundPCMBuffer) queue;
+};
+
+/*
+ * PCM stream state machine.
+ * -------------------------
+ *
+ * 5.14.6.6.1 PCM Command Lifecycle
+ * ================================
+ *
+ * A PCM stream has the following command lifecycle:
+ * - `SET PARAMETERS`
+ * The driver negotiates the stream parameters (format, transport, etc) with
+ * the device.
+ * Possible valid transitions: `SET PARAMETERS`, `PREPARE`.
+ * - `PREPARE`
+ * The device prepares the stream (allocates resources, etc).
+ * Possible valid transitions: `SET PARAMETERS`, `PREPARE`, `START`,
+ * `RELEASE`. Output only: the driver transfers data for pre-buffing.
+ * - `START`
+ * The device starts the stream (unmute, putting into running state, etc).
+ * Possible valid transitions: `STOP`.
+ * The driver transfers data to/from the stream.
+ * - `STOP`
+ * The device stops the stream (mute, putting into non-running state, etc).
+ * Possible valid transitions: `START`, `RELEASE`.
+ * - `RELEASE`
+ * The device releases the stream (frees resources, etc).
+ * Possible valid transitions: `SET PARAMETERS`, `PREPARE`.
+ *
+ * +---------------+ +---------+ +---------+ +-------+ +-------+
+ * | SetParameters | | Prepare | | Release | | Start | | Stop |
+ * +---------------+ +---------+ +---------+ +-------+ +-------+
+ * |- | | | |
+ * || | | | |
+ * |< | | | |
+ * |------------->| | | |
+ * |<-------------| | | |
+ * | |- | | |
+ * | || | | |
+ * | |< | | |
+ * | |--------------------->| |
+ * | |---------->| | |
+ * | | | |-------->|
+ * | | | |<--------|
+ * | | |<-------------------|
+ * |<-------------------------| | |
+ * | |<----------| | |
+ *
+ * CTRL in the VirtIOSound device
+ * ==============================
+ *
+ * The control messages that affect the state of a stream arrive in the
+ * `virtio_snd_handle_ctrl()` queue callback and are of type `struct
+ * virtio_snd_ctrl_command`. They are stored in a queue field in the device
+ * type, `VirtIOSound`. This allows deferring the CTRL request completion if
+ * it's not immediately possible due to locking/state reasons.
+ *
+ * The CTRL message is finally handled in `process_cmd()`.
+ */
+struct VirtIOSound {
+ VirtIODevice parent_obj;
+
+ VirtQueue *queues[VIRTIO_SND_VQ_MAX];
+ uint64_t features;
+ VirtIOSoundPCM *pcm;
+ QEMUSoundCard card;
+ VMChangeStateEntry *vmstate;
+ virtio_snd_config snd_conf;
+ QemuMutex cmdq_mutex;
+ QTAILQ_HEAD(, virtio_snd_ctrl_command) cmdq;
+ bool processing_cmdq;
+ /*
+ * Convenience queue to keep track of invalid tx/rx queue messages inside
+ * the tx/rx callbacks.
+ *
+ * In the callbacks as a first step we are emptying the virtqueue to handle
+ * each message and we cannot add an invalid message back to the queue: we
+ * would re-process it in subsequent loop iterations.
+ *
+ * Instead, we add them to this queue and after finishing examining every
+ * virtqueue element, we inform the guest for each invalid message.
+ *
+ * This queue must be empty at all times except for inside the tx/rx
+ * callbacks.
+ */
+ QSIMPLEQ_HEAD(, VirtIOSoundPCMBuffer) invalid;
+};
+
+struct virtio_snd_ctrl_command {
+ VirtQueueElement *elem;
+ VirtQueue *vq;
+ virtio_snd_hdr ctrl;
+ virtio_snd_hdr resp;
+ size_t payload_size;
+ QTAILQ_ENTRY(virtio_snd_ctrl_command) next;
+};
+#endif
diff --git a/include/hw/block/block.h b/include/hw/block/block.h
index 1e8b6253dd..de3946a5f1 100644
--- a/include/hw/block/block.h
+++ b/include/hw/block/block.h
@@ -13,11 +13,13 @@
#include "exec/hwaddr.h"
#include "qapi/qapi-types-block-core.h"
+#include "hw/qdev-properties-system.h"
/* Configuration */
typedef struct BlockConf {
BlockBackend *blk;
+ OnOffAuto backend_defaults;
uint32_t physical_block_size;
uint32_t logical_block_size;
uint32_t min_io_size;
@@ -29,6 +31,7 @@ typedef struct BlockConf {
uint32_t lcyls, lheads, lsecs;
OnOffAuto wce;
bool share_rw;
+ OnOffAuto account_invalid, account_failed;
BlockdevOnError rerror;
BlockdevOnError werror;
} BlockConf;
@@ -47,6 +50,8 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
}
#define DEFINE_BLOCK_PROPERTIES_BASE(_state, _conf) \
+ DEFINE_PROP_ON_OFF_AUTO("backend_defaults", _state, \
+ _conf.backend_defaults, ON_OFF_AUTO_AUTO), \
DEFINE_PROP_BLOCKSIZE("logical_block_size", _state, \
_conf.logical_block_size), \
DEFINE_PROP_BLOCKSIZE("physical_block_size", _state, \
@@ -57,7 +62,11 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
_conf.discard_granularity, -1), \
DEFINE_PROP_ON_OFF_AUTO("write-cache", _state, _conf.wce, \
ON_OFF_AUTO_AUTO), \
- DEFINE_PROP_BOOL("share-rw", _state, _conf.share_rw, false)
+ DEFINE_PROP_BOOL("share-rw", _state, _conf.share_rw, false), \
+ DEFINE_PROP_ON_OFF_AUTO("account-invalid", _state, \
+ _conf.account_invalid, ON_OFF_AUTO_AUTO), \
+ DEFINE_PROP_ON_OFF_AUTO("account-failed", _state, \
+ _conf.account_failed, ON_OFF_AUTO_AUTO)
#define DEFINE_BLOCK_PROPERTIES(_state, _conf) \
DEFINE_PROP_DRIVE("drive", _state, _conf.blk), \
@@ -79,8 +88,8 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
/* Backend access helpers */
-bool blk_check_size_and_read_all(BlockBackend *blk, void *buf, hwaddr size,
- Error **errp);
+bool blk_check_size_and_read_all(BlockBackend *blk, DeviceState *dev,
+ void *buf, hwaddr size, Error **errp);
/* Configuration helpers */
diff --git a/include/hw/block/fdc.h b/include/hw/block/fdc.h
index 1ecca7cac7..c367c5efea 100644
--- a/include/hw/block/fdc.h
+++ b/include/hw/block/fdc.h
@@ -10,11 +10,13 @@
#define TYPE_ISA_FDC "isa-fdc"
void isa_fdc_init_drives(ISADevice *fdc, DriveInfo **fds);
-void fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
- hwaddr mmio_base, DriveInfo **fds);
+void fdctrl_init_sysbus(qemu_irq irq, hwaddr mmio_base, DriveInfo **fds);
void sun4m_fdctrl_init(qemu_irq irq, hwaddr io_base,
DriveInfo **fds, qemu_irq *fdc_tc);
+void isa_fdc_set_iobase(ISADevice *fdc, hwaddr iobase);
+void isa_fdc_set_enabled(ISADevice *fdc, bool enabled);
+
FloppyDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i);
int cmos_get_fd_drive_type(FloppyDriveType fd0);
diff --git a/include/hw/block/flash.h b/include/hw/block/flash.h
index 2136a2d5e4..2b5ccd92f4 100644
--- a/include/hw/block/flash.h
+++ b/include/hw/block/flash.h
@@ -4,14 +4,13 @@
/* NOR flash devices */
#include "exec/hwaddr.h"
+#include "qom/object.h"
/* pflash_cfi01.c */
#define TYPE_PFLASH_CFI01 "cfi.pflash01"
-#define PFLASH_CFI01(obj) \
- OBJECT_CHECK(PFlashCFI01, (obj), TYPE_PFLASH_CFI01)
+OBJECT_DECLARE_SIMPLE_TYPE(PFlashCFI01, PFLASH_CFI01)
-typedef struct PFlashCFI01 PFlashCFI01;
PFlashCFI01 *pflash_cfi01_register(hwaddr base,
const char *name,
@@ -29,10 +28,8 @@ void pflash_cfi01_legacy_drive(PFlashCFI01 *dev, DriveInfo *dinfo);
/* pflash_cfi02.c */
#define TYPE_PFLASH_CFI02 "cfi.pflash02"
-#define PFLASH_CFI02(obj) \
- OBJECT_CHECK(PFlashCFI02, (obj), TYPE_PFLASH_CFI02)
+OBJECT_DECLARE_SIMPLE_TYPE(PFlashCFI02, PFLASH_CFI02)
-typedef struct PFlashCFI02 PFlashCFI02;
PFlashCFI02 *pflash_cfi02_register(hwaddr base,
const char *name,
@@ -56,27 +53,33 @@ void nand_setio(DeviceState *dev, uint32_t value);
uint32_t nand_getio(DeviceState *dev);
uint32_t nand_getbuswidth(DeviceState *dev);
-#define NAND_MFR_TOSHIBA 0x98
-#define NAND_MFR_SAMSUNG 0xec
-#define NAND_MFR_FUJITSU 0x04
-#define NAND_MFR_NATIONAL 0x8f
-#define NAND_MFR_RENESAS 0x07
-#define NAND_MFR_STMICRO 0x20
-#define NAND_MFR_HYNIX 0xad
-#define NAND_MFR_MICRON 0x2c
+#define NAND_MFR_TOSHIBA 0x98
+#define NAND_MFR_SAMSUNG 0xec
+#define NAND_MFR_FUJITSU 0x04
+#define NAND_MFR_NATIONAL 0x8f
+#define NAND_MFR_RENESAS 0x07
+#define NAND_MFR_STMICRO 0x20
+#define NAND_MFR_HYNIX 0xad
+#define NAND_MFR_MICRON 0x2c
/* onenand.c */
void *onenand_raw_otp(DeviceState *onenand_device);
/* ecc.c */
typedef struct {
- uint8_t cp; /* Column parity */
- uint16_t lp[2]; /* Line parity */
+ uint8_t cp; /* Column parity */
+ uint16_t lp[2]; /* Line parity */
uint16_t count;
} ECCState;
uint8_t ecc_digest(ECCState *s, uint8_t sample);
void ecc_reset(ECCState *s);
-extern VMStateDescription vmstate_ecc_state;
+extern const VMStateDescription vmstate_ecc_state;
+
+/* m25p80.c */
+
+#define TYPE_M25P80 "m25p80-generic"
+
+BlockBackend *m25p80_get_blk(DeviceState *dev);
#endif
diff --git a/include/hw/block/swim.h b/include/hw/block/swim.h
index 6add3499d0..5f567e8d59 100644
--- a/include/hw/block/swim.h
+++ b/include/hw/block/swim.h
@@ -11,17 +11,16 @@
#ifndef SWIM_H
#define SWIM_H
-#include "qemu/osdep.h"
+#include "hw/block/block.h"
#include "hw/sysbus.h"
+#include "qom/object.h"
#define SWIM_MAX_FD 2
-typedef struct SWIMDrive SWIMDrive;
-typedef struct SWIMBus SWIMBus;
typedef struct SWIMCtrl SWIMCtrl;
#define TYPE_SWIM_DRIVE "swim-drive"
-#define SWIM_DRIVE(obj) OBJECT_CHECK(SWIMDrive, (obj), TYPE_SWIM_DRIVE)
+OBJECT_DECLARE_SIMPLE_TYPE(SWIMDrive, SWIM_DRIVE)
struct SWIMDrive {
DeviceState qdev;
@@ -30,7 +29,7 @@ struct SWIMDrive {
};
#define TYPE_SWIM_BUS "swim-bus"
-#define SWIM_BUS(obj) OBJECT_CHECK(SWIMBus, (obj), TYPE_SWIM_BUS)
+OBJECT_DECLARE_SIMPLE_TYPE(SWIMBus, SWIM_BUS)
struct SWIMBus {
BusState bus;
@@ -44,33 +43,30 @@ typedef struct FDrive {
} FDrive;
struct SWIMCtrl {
- MemoryRegion iomem;
+ MemoryRegion swim;
+ MemoryRegion iwm;
+ MemoryRegion ism;
FDrive drives[SWIM_MAX_FD];
int mode;
/* IWM mode */
int iwm_switch;
- uint16_t regs[8];
-#define IWM_PH0 0
-#define IWM_PH1 1
-#define IWM_PH2 2
-#define IWM_PH3 3
-#define IWM_MTR 4
-#define IWM_DRIVE 5
-#define IWM_Q6 6
-#define IWM_Q7 7
- uint8_t iwm_data;
- uint8_t iwm_mode;
+ uint8_t iwm_latches;
+ uint8_t iwmregs[8];
/* SWIM mode */
+ uint8_t ismregs[16];
uint8_t swim_phase;
uint8_t swim_mode;
+ uint8_t swim_status;
+ uint8_t pram[16];
+ uint8_t pram_idx;
SWIMBus bus;
};
#define TYPE_SWIM "swim"
-#define SWIM(obj) OBJECT_CHECK(SWIM, (obj), TYPE_SWIM)
+OBJECT_DECLARE_SIMPLE_TYPE(Swim, SWIM)
-typedef struct SWIM {
+struct Swim {
SysBusDevice parent_obj;
SWIMCtrl ctrl;
-} SWIM;
+};
#endif
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 426ce5f625..69c1ba45cf 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -6,7 +6,6 @@
#include "exec/memory.h"
#include "sysemu/hostmem.h"
#include "sysemu/blockdev.h"
-#include "sysemu/accel.h"
#include "qapi/qapi-types-machine.h"
#include "qemu/module.h"
#include "qom/object.h"
@@ -21,26 +20,88 @@
#define TYPE_MACHINE "machine"
#undef MACHINE /* BSD defines it and QEMU does not use it */
-#define MACHINE(obj) \
- OBJECT_CHECK(MachineState, (obj), TYPE_MACHINE)
-#define MACHINE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(MachineClass, (obj), TYPE_MACHINE)
-#define MACHINE_CLASS(klass) \
- OBJECT_CLASS_CHECK(MachineClass, (klass), TYPE_MACHINE)
+OBJECT_DECLARE_TYPE(MachineState, MachineClass, MACHINE)
extern MachineState *current_machine;
-void machine_run_board_init(MachineState *machine);
+/**
+ * machine_class_default_cpu_type: Return the machine default CPU type.
+ * @mc: Machine class
+ */
+const char *machine_class_default_cpu_type(MachineClass *mc);
+
+void machine_add_audiodev_property(MachineClass *mc);
+void machine_run_board_init(MachineState *machine, const char *mem_path, Error **errp);
bool machine_usb(MachineState *machine);
int machine_phandle_start(MachineState *machine);
bool machine_dump_guest_core(MachineState *machine);
bool machine_mem_merge(MachineState *machine);
+bool machine_require_guest_memfd(MachineState *machine);
HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine);
void machine_set_cpu_numa_node(MachineState *machine,
const CpuInstanceProperties *props,
Error **errp);
+void machine_parse_smp_config(MachineState *ms,
+ const SMPConfiguration *config, Error **errp);
+unsigned int machine_topo_get_cores_per_socket(const MachineState *ms);
+unsigned int machine_topo_get_threads_per_socket(const MachineState *ms);
+void machine_memory_devices_init(MachineState *ms, hwaddr base, uint64_t size);
+/**
+ * machine_class_allow_dynamic_sysbus_dev: Add type to list of valid devices
+ * @mc: Machine class
+ * @type: type to allow (should be a subtype of TYPE_SYS_BUS_DEVICE)
+ *
+ * Add the QOM type @type to the list of devices of which are subtypes
+ * of TYPE_SYS_BUS_DEVICE but which are still permitted to be dynamically
+ * created (eg by the user on the command line with -device).
+ * By default if the user tries to create any devices on the command line
+ * that are subtypes of TYPE_SYS_BUS_DEVICE they will get an error message;
+ * for the special cases which are permitted for this machine model, the
+ * machine model class init code must call this function to add them
+ * to the list of specifically permitted devices.
+ */
void machine_class_allow_dynamic_sysbus_dev(MachineClass *mc, const char *type);
+
+/**
+ * device_type_is_dynamic_sysbus: Check if type is an allowed sysbus device
+ * type for the machine class.
+ * @mc: Machine class
+ * @type: type to check (should be a subtype of TYPE_SYS_BUS_DEVICE)
+ *
+ * Returns: true if @type is a type in the machine's list of
+ * dynamically pluggable sysbus devices; otherwise false.
+ *
+ * Check if the QOM type @type is in the list of allowed sysbus device
+ * types (see machine_class_allowed_dynamic_sysbus_dev()).
+ * Note that if @type has a parent type in the list, it is allowed too.
+ */
+bool device_type_is_dynamic_sysbus(MachineClass *mc, const char *type);
+
+/**
+ * device_is_dynamic_sysbus: test whether device is a dynamic sysbus device
+ * @mc: Machine class
+ * @dev: device to check
+ *
+ * Returns: true if @dev is a sysbus device on the machine's list
+ * of dynamically pluggable sysbus devices; otherwise false.
+ *
+ * This function checks whether @dev is a valid dynamic sysbus device,
+ * by first confirming that it is a sysbus device and then checking it
+ * against the list of permitted dynamic sysbus devices which has been
+ * set up by the machine using machine_class_allow_dynamic_sysbus_dev().
+ *
+ * It is valid to call this with something that is not a subclass of
+ * TYPE_SYS_BUS_DEVICE; the function will return false in this case.
+ * This allows hotplug callback functions to be written as:
+ * if (device_is_dynamic_sysbus(mc, dev)) {
+ * handle dynamic sysbus case;
+ * } else if (some other kind of hotplug) {
+ * handle that;
+ * }
+ */
+bool device_is_dynamic_sysbus(MachineClass *mc, DeviceState *dev);
+
/*
* Checks that backend isn't used, preps it for exclusive usage and
* returns migratable MemoryRegion provided by backend.
@@ -60,7 +121,7 @@ typedef struct CPUArchId {
uint64_t arch_id;
int64_t vcpus_count;
CpuInstanceProperties props;
- Object *cpu;
+ CPUState *cpu;
const char *type;
} CPUArchId;
@@ -75,6 +136,25 @@ typedef struct {
} CPUArchIdList;
/**
+ * SMPCompatProps:
+ * @prefer_sockets - whether sockets are preferred over cores in smp parsing
+ * @dies_supported - whether dies are supported by the machine
+ * @clusters_supported - whether clusters are supported by the machine
+ * @has_clusters - whether clusters are explicitly specified in the user
+ * provided SMP configuration
+ * @books_supported - whether books are supported by the machine
+ * @drawers_supported - whether drawers are supported by the machine
+ */
+typedef struct {
+ bool prefer_sockets;
+ bool dies_supported;
+ bool clusters_supported;
+ bool has_clusters;
+ bool books_supported;
+ bool drawers_supported;
+} SMPCompatProps;
+
+/**
* MachineClass:
* @deprecation_reason: If set, the machine is marked as deprecated. The
* string should provide some clear information about what to use instead.
@@ -90,7 +170,7 @@ typedef struct {
* any actions to be performed by hotplug handler.
* @cpu_index_to_instance_props:
* used to provide @cpu_index to socket/core/thread number mapping, allowing
- * legacy code to perform maping from cpu_index to topology properties
+ * legacy code to perform mapping from cpu_index to topology properties
* Returns: tuple of socket/core/thread ids given cpu_index belongs to.
* used to provide @cpu_index to socket number mapping, allowing
* a machine to group CPU threads belonging to the same socket/package
@@ -132,12 +212,9 @@ typedef struct {
* @kvm_type:
* Return the type of KVM corresponding to the kvm-type string option or
* computed based on other criteria such as the host kernel capabilities.
+ * kvm-type may be NULL if it is not needed.
* @numa_mem_supported:
* true if '--numa node.mem' option is supported and false otherwise
- * @smp_parse:
- * The function pointer to hook different machine specific functions for
- * parsing "smp-opts" from QemuOpts to MachineState::CpuTopology and more
- * machine specific topology fields, such as smp_dies for PCMachine.
* @hotplug_allowed:
* If the hook is provided, then it'll be called for each device
* hotplug to check whether the device hotplug is allowed. Return
@@ -146,10 +223,10 @@ typedef struct {
* the rejection. If the hook is not provided, all hotplug will be
* allowed.
* @default_ram_id:
- * Specifies inital RAM MemoryRegion name to be used for default backend
+ * Specifies initial RAM MemoryRegion name to be used for default backend
* creation if user explicitly hasn't specified backend with "memory-backend"
* property.
- * It also will be used as a way to optin into "-m" option support.
+ * It also will be used as a way to option into "-m" option support.
* If it's not set by board, '-m' will be ignored and generic code will
* not create default RAM MemoryRegion.
* @fixup_ram_size:
@@ -171,11 +248,9 @@ struct MachineClass {
const char *deprecation_reason;
void (*init)(MachineState *state);
- void (*reset)(MachineState *state);
+ void (*reset)(MachineState *state, ShutdownCause reason);
void (*wakeup)(MachineState *state);
- void (*hot_add_cpu)(MachineState *state, const int64_t id, Error **errp);
int (*kvm_type)(MachineState *machine, const char *arg);
- void (*smp_parse)(MachineState *ms, QemuOpts *opts);
BlockInterfaceType block_default_type;
int units_per_default_bus;
@@ -193,6 +268,7 @@ struct MachineClass {
const char *default_machine_opts;
const char *default_boot_order;
const char *default_display;
+ const char *default_nic;
GPtrArray *compat_props;
const char *hw_version;
ram_addr_t default_ram_size;
@@ -204,17 +280,17 @@ struct MachineClass {
bool has_hotpluggable_cpus;
bool ignore_memory_transaction_failures;
int numa_mem_align_shift;
- const char **valid_cpu_types;
+ const char * const *valid_cpu_types;
strList *allowed_dynamic_sysbus_devices;
bool auto_enable_numa_with_memhp;
bool auto_enable_numa_with_memdev;
- void (*numa_auto_assign_ram)(MachineClass *mc, NodeInfo *nodes,
- int nb_nodes, ram_addr_t size);
bool ignore_boot_device_suffixes;
bool smbus_no_migration_support;
bool nvdimm_supported;
bool numa_mem_supported;
bool auto_enable_numa;
+ bool cpu_cluster_has_numa_boundary;
+ SMPCompatProps smp_props;
const char *default_ram_id;
HotplugHandler *(*get_hotplug_handler)(MachineState *machine,
@@ -232,26 +308,50 @@ struct MachineClass {
* DeviceMemoryState:
* @base: address in guest physical address space where the memory
* address space for memory devices starts
- * @mr: address space container for memory devices
+ * @mr: memory region container for memory devices
+ * @as: address space for memory devices
+ * @listener: memory listener used to track used memslots in the address space
+ * @dimm_size: the sum of plugged DIMMs' sizes
+ * @used_region_size: the part of @mr already used by memory devices
+ * @required_memslots: the number of memslots required by memory devices
+ * @used_memslots: the number of memslots currently used by memory devices
+ * @memslot_auto_decision_active: whether any plugged memory device
+ * automatically decided to use more than
+ * one memslot
*/
typedef struct DeviceMemoryState {
hwaddr base;
MemoryRegion mr;
+ AddressSpace as;
+ MemoryListener listener;
+ uint64_t dimm_size;
+ uint64_t used_region_size;
+ unsigned int required_memslots;
+ unsigned int used_memslots;
+ unsigned int memslot_auto_decision_active;
} DeviceMemoryState;
/**
* CpuTopology:
* @cpus: the number of present logical processors on the machine
- * @cores: the number of cores in one package
+ * @drawers: the number of drawers on the machine
+ * @books: the number of books in one drawer
+ * @sockets: the number of sockets in one book
+ * @dies: the number of dies in one socket
+ * @clusters: the number of clusters in one die
+ * @cores: the number of cores in one cluster
* @threads: the number of threads in one core
- * @sockets: the number of sockets on the machine
* @max_cpus: the maximum number of logical processors on the machine
*/
typedef struct CpuTopology {
unsigned int cpus;
+ unsigned int drawers;
+ unsigned int books;
+ unsigned int sockets;
+ unsigned int dies;
+ unsigned int clusters;
unsigned int cores;
unsigned int threads;
- unsigned int sockets;
unsigned int max_cpus;
} CpuTopology;
@@ -261,25 +361,25 @@ typedef struct CpuTopology {
struct MachineState {
/*< private >*/
Object parent_obj;
- Notifier sysbus_notifier;
/*< public >*/
+ void *fdt;
char *dtb;
char *dumpdtb;
int phandle_start;
char *dt_compatible;
bool dump_guest_core;
bool mem_merge;
+ bool require_guest_memfd;
bool usb;
bool usb_disabled;
char *firmware;
bool iommu;
bool suppress_vmdesc;
- bool enforce_config_section;
bool enable_graphics;
- char *memory_encryption;
- char *ram_memdev_id;
+ ConfidentialGuestSupport *cgs;
+ HostMemoryBackend *memdev;
/*
* convenience alias to ram_memdev_id backend memory region
* or to numa container memory region
@@ -287,10 +387,18 @@ struct MachineState {
MemoryRegion *ram;
DeviceMemoryState *device_memory;
+ /*
+ * Included in MachineState for simplicity, but not supported
+ * unless machine_add_audiodev_property is called. Boards
+ * that have embedded audio devices can call it from the
+ * machine init function and forward the property to the device.
+ */
+ char *audiodev;
+
ram_addr_t ram_size;
ram_addr_t maxram_size;
uint64_t ram_slots;
- const char *boot_order;
+ BootConfiguration boot_config;
char *kernel_filename;
char *kernel_cmdline;
char *initrd_filename;
@@ -319,6 +427,42 @@ struct MachineState {
} \
type_init(machine_initfn##_register_types)
+extern GlobalProperty hw_compat_9_0[];
+extern const size_t hw_compat_9_0_len;
+
+extern GlobalProperty hw_compat_8_2[];
+extern const size_t hw_compat_8_2_len;
+
+extern GlobalProperty hw_compat_8_1[];
+extern const size_t hw_compat_8_1_len;
+
+extern GlobalProperty hw_compat_8_0[];
+extern const size_t hw_compat_8_0_len;
+
+extern GlobalProperty hw_compat_7_2[];
+extern const size_t hw_compat_7_2_len;
+
+extern GlobalProperty hw_compat_7_1[];
+extern const size_t hw_compat_7_1_len;
+
+extern GlobalProperty hw_compat_7_0[];
+extern const size_t hw_compat_7_0_len;
+
+extern GlobalProperty hw_compat_6_2[];
+extern const size_t hw_compat_6_2_len;
+
+extern GlobalProperty hw_compat_6_1[];
+extern const size_t hw_compat_6_1_len;
+
+extern GlobalProperty hw_compat_6_0[];
+extern const size_t hw_compat_6_0_len;
+
+extern GlobalProperty hw_compat_5_2[];
+extern const size_t hw_compat_5_2_len;
+
+extern GlobalProperty hw_compat_5_1[];
+extern const size_t hw_compat_5_1_len;
+
extern GlobalProperty hw_compat_5_0[];
extern const size_t hw_compat_5_0_len;
diff --git a/include/hw/char/avr_usart.h b/include/hw/char/avr_usart.h
index 5739aaf26f..0cc599e9b1 100644
--- a/include/hw/char/avr_usart.h
+++ b/include/hw/char/avr_usart.h
@@ -24,7 +24,7 @@
#include "hw/sysbus.h"
#include "chardev/char-fe.h"
-#include "hw/hw.h"
+#include "qom/object.h"
/* Offsets of registers. */
#define USART_DR 0x06
@@ -34,7 +34,7 @@
#define USART_BRRH 0x05
#define USART_BRRL 0x04
-/* Relevant bits in regiters. */
+/* Relevant bits in registers. */
#define USART_CSRA_RXC (1 << 7)
#define USART_CSRA_TXC (1 << 6)
#define USART_CSRA_DRE (1 << 5)
@@ -57,10 +57,9 @@
#define USART_CSRC_CSZ0 (1 << 1)
#define TYPE_AVR_USART "avr-usart"
-#define AVR_USART(obj) \
- OBJECT_CHECK(AVRUsartState, (obj), TYPE_AVR_USART)
+OBJECT_DECLARE_SIMPLE_TYPE(AVRUsartState, AVR_USART)
-typedef struct {
+struct AVRUsartState {
/* <private> */
SysBusDevice parent_obj;
@@ -88,6 +87,6 @@ typedef struct {
qemu_irq txc_irq;
/* Data Register Empty */
qemu_irq dre_irq;
-} AVRUsartState;
+};
#endif /* HW_CHAR_AVR_USART_H */
diff --git a/include/hw/char/bcm2835_aux.h b/include/hw/char/bcm2835_aux.h
index 934acf9c81..9e081793a0 100644
--- a/include/hw/char/bcm2835_aux.h
+++ b/include/hw/char/bcm2835_aux.h
@@ -11,13 +11,14 @@
#include "hw/sysbus.h"
#include "chardev/char-fe.h"
+#include "qom/object.h"
#define TYPE_BCM2835_AUX "bcm2835-aux"
-#define BCM2835_AUX(obj) OBJECT_CHECK(BCM2835AuxState, (obj), TYPE_BCM2835_AUX)
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835AuxState, BCM2835_AUX)
#define BCM2835_AUX_RX_FIFO_LEN 8
-typedef struct {
+struct BCM2835AuxState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -29,6 +30,6 @@ typedef struct {
uint8_t read_fifo[BCM2835_AUX_RX_FIFO_LEN];
uint8_t read_pos, read_count;
uint8_t ier, iir;
-} BCM2835AuxState;
+};
#endif
diff --git a/include/hw/char/cadence_uart.h b/include/hw/char/cadence_uart.h
index ed7b58d31d..e7f7cd8468 100644
--- a/include/hw/char/cadence_uart.h
+++ b/include/hw/char/cadence_uart.h
@@ -24,6 +24,7 @@
#include "chardev/char-fe.h"
#include "qapi/error.h"
#include "qemu/timer.h"
+#include "qom/object.h"
#define CADENCE_UART_RX_FIFO_SIZE 16
#define CADENCE_UART_TX_FIFO_SIZE 16
@@ -31,10 +32,9 @@
#define CADENCE_UART_R_MAX (0x48/4)
#define TYPE_CADENCE_UART "cadence_uart"
-#define CADENCE_UART(obj) OBJECT_CHECK(CadenceUARTState, (obj), \
- TYPE_CADENCE_UART)
+OBJECT_DECLARE_SIMPLE_TYPE(CadenceUARTState, CADENCE_UART)
-typedef struct {
+struct CadenceUARTState {
/*< private >*/
SysBusDevice parent_obj;
@@ -51,23 +51,6 @@ typedef struct {
qemu_irq irq;
QEMUTimer *fifo_trigger_handle;
Clock *refclk;
-} CadenceUARTState;
-
-static inline DeviceState *cadence_uart_create(hwaddr addr,
- qemu_irq irq,
- Chardev *chr)
-{
- DeviceState *dev;
- SysBusDevice *s;
-
- dev = qdev_new(TYPE_CADENCE_UART);
- s = SYS_BUS_DEVICE(dev);
- qdev_prop_set_chr(dev, "chardev", chr);
- sysbus_realize_and_unref(s, &error_fatal);
- sysbus_mmio_map(s, 0, addr);
- sysbus_connect_irq(s, 0, irq);
-
- return dev;
-}
+};
#endif
diff --git a/include/hw/char/cmsdk-apb-uart.h b/include/hw/char/cmsdk-apb-uart.h
index bc9069f9fd..7de8f8d1b9 100644
--- a/include/hw/char/cmsdk-apb-uart.h
+++ b/include/hw/char/cmsdk-apb-uart.h
@@ -12,15 +12,14 @@
#ifndef CMSDK_APB_UART_H
#define CMSDK_APB_UART_H
-#include "hw/qdev-properties.h"
#include "hw/sysbus.h"
#include "chardev/char-fe.h"
+#include "qom/object.h"
#define TYPE_CMSDK_APB_UART "cmsdk-apb-uart"
-#define CMSDK_APB_UART(obj) OBJECT_CHECK(CMSDKAPBUART, (obj), \
- TYPE_CMSDK_APB_UART)
+OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBUART, CMSDK_APB_UART)
-typedef struct {
+struct CMSDKAPBUART {
/*< private >*/
SysBusDevice parent_obj;
@@ -42,38 +41,6 @@ typedef struct {
/* This UART has no FIFO, only a 1-character buffer for each of Tx and Rx */
uint8_t txbuf;
uint8_t rxbuf;
-} CMSDKAPBUART;
-
-/**
- * cmsdk_apb_uart_create - convenience function to create TYPE_CMSDK_APB_UART
- * @addr: location in system memory to map registers
- * @chr: Chardev backend to connect UART to, or NULL if no backend
- * @pclk_frq: frequency in Hz of the PCLK clock (used for calculating baud rate)
- */
-static inline DeviceState *cmsdk_apb_uart_create(hwaddr addr,
- qemu_irq txint,
- qemu_irq rxint,
- qemu_irq txovrint,
- qemu_irq rxovrint,
- qemu_irq uartint,
- Chardev *chr,
- uint32_t pclk_frq)
-{
- DeviceState *dev;
- SysBusDevice *s;
-
- dev = qdev_new(TYPE_CMSDK_APB_UART);
- s = SYS_BUS_DEVICE(dev);
- qdev_prop_set_chr(dev, "chardev", chr);
- qdev_prop_set_uint32(dev, "pclk-frq", pclk_frq);
- sysbus_realize_and_unref(s, &error_fatal);
- sysbus_mmio_map(s, 0, addr);
- sysbus_connect_irq(s, 0, txint);
- sysbus_connect_irq(s, 1, rxint);
- sysbus_connect_irq(s, 2, txovrint);
- sysbus_connect_irq(s, 3, rxovrint);
- sysbus_connect_irq(s, 4, uartint);
- return dev;
-}
+};
#endif
diff --git a/include/hw/char/digic-uart.h b/include/hw/char/digic-uart.h
index de9a3e3551..f710a1a099 100644
--- a/include/hw/char/digic-uart.h
+++ b/include/hw/char/digic-uart.h
@@ -20,10 +20,10 @@
#include "hw/sysbus.h"
#include "chardev/char-fe.h"
+#include "qom/object.h"
#define TYPE_DIGIC_UART "digic-uart"
-#define DIGIC_UART(obj) \
- OBJECT_CHECK(DigicUartState, (obj), TYPE_DIGIC_UART)
+OBJECT_DECLARE_SIMPLE_TYPE(DigicUartState, DIGIC_UART)
enum {
R_TX = 0x00,
@@ -32,7 +32,7 @@ enum {
R_MAX
};
-typedef struct DigicUartState {
+struct DigicUartState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -42,6 +42,6 @@ typedef struct DigicUartState {
uint32_t reg_rx;
uint32_t reg_st;
-} DigicUartState;
+};
#endif /* HW_CHAR_DIGIC_UART_H */
diff --git a/include/hw/char/escc.h b/include/hw/char/escc.h
index 794b653484..5669a5b811 100644
--- a/include/hw/char/escc.h
+++ b/include/hw/char/escc.h
@@ -5,12 +5,13 @@
#include "chardev/char-serial.h"
#include "hw/sysbus.h"
#include "ui/input.h"
+#include "qom/object.h"
/* escc.c */
#define TYPE_ESCC "escc"
#define ESCC_SIZE 4
-#define ESCC(obj) OBJECT_CHECK(ESCCState, (obj), TYPE_ESCC)
+OBJECT_DECLARE_SIMPLE_TYPE(ESCCState, ESCC)
typedef enum {
escc_chn_a, escc_chn_b,
@@ -44,9 +45,10 @@ typedef struct ESCCChannelState {
ESCCChnType type;
uint8_t rx, tx;
QemuInputHandlerState *hs;
+ char *sunkbd_layout;
} ESCCChannelState;
-typedef struct ESCCState {
+struct ESCCState {
SysBusDevice parent_obj;
struct ESCCChannelState chn[2];
@@ -55,6 +57,6 @@ typedef struct ESCCState {
MemoryRegion mmio;
uint32_t disabled;
uint32_t frequency;
-} ESCCState;
+};
#endif
diff --git a/include/hw/char/goldfish_tty.h b/include/hw/char/goldfish_tty.h
new file mode 100644
index 0000000000..d59733e5ae
--- /dev/null
+++ b/include/hw/char/goldfish_tty.h
@@ -0,0 +1,36 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Goldfish TTY
+ *
+ * (c) 2020 Laurent Vivier <laurent@vivier.eu>
+ *
+ */
+
+#ifndef HW_CHAR_GOLDFISH_TTY_H
+#define HW_CHAR_GOLDFISH_TTY_H
+
+#include "qemu/fifo8.h"
+#include "chardev/char-fe.h"
+#include "hw/sysbus.h"
+
+#define TYPE_GOLDFISH_TTY "goldfish_tty"
+OBJECT_DECLARE_SIMPLE_TYPE(GoldfishTTYState, GOLDFISH_TTY)
+
+#define GOLFISH_TTY_BUFFER_SIZE 128
+
+struct GoldfishTTYState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ qemu_irq irq;
+ CharBackend chr;
+
+ uint32_t data_len;
+ uint64_t data_ptr;
+ bool int_enabled;
+
+ Fifo8 rx_fifo;
+};
+
+#endif
diff --git a/include/hw/char/grlib_uart.h b/include/hw/char/grlib_uart.h
new file mode 100644
index 0000000000..7496f8fd5e
--- /dev/null
+++ b/include/hw/char/grlib_uart.h
@@ -0,0 +1,32 @@
+/*
+ * QEMU GRLIB UART
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright (c) 2024 AdaCore
+ *
+ * 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.
+ */
+
+#ifndef GRLIB_UART_H
+#define GRLIB_UART_H
+
+#define TYPE_GRLIB_APB_UART "grlib-apbuart"
+
+#endif
diff --git a/include/hw/char/ibex_uart.h b/include/hw/char/ibex_uart.h
index b6bd5a6700..9deadf223b 100644
--- a/include/hw/char/ibex_uart.h
+++ b/include/hw/char/ibex_uart.h
@@ -26,53 +26,17 @@
#define HW_IBEX_UART_H
#include "hw/sysbus.h"
-#include "hw/registerfields.h"
#include "chardev/char-fe.h"
#include "qemu/timer.h"
-
-REG32(INTR_STATE, 0x00)
- FIELD(INTR_STATE, TX_WATERMARK, 0, 1)
- FIELD(INTR_STATE, RX_WATERMARK, 1, 1)
- FIELD(INTR_STATE, TX_EMPTY, 2, 1)
- FIELD(INTR_STATE, RX_OVERFLOW, 3, 1)
-REG32(INTR_ENABLE, 0x04)
-REG32(INTR_TEST, 0x08)
-REG32(CTRL, 0x0C)
- FIELD(CTRL, TX_ENABLE, 0, 1)
- FIELD(CTRL, RX_ENABLE, 1, 1)
- FIELD(CTRL, NF, 2, 1)
- FIELD(CTRL, SLPBK, 4, 1)
- FIELD(CTRL, LLPBK, 5, 1)
- FIELD(CTRL, PARITY_EN, 6, 1)
- FIELD(CTRL, PARITY_ODD, 7, 1)
- FIELD(CTRL, RXBLVL, 8, 2)
- FIELD(CTRL, NCO, 16, 16)
-REG32(STATUS, 0x10)
- FIELD(STATUS, TXFULL, 0, 1)
- FIELD(STATUS, RXFULL, 1, 1)
- FIELD(STATUS, TXEMPTY, 2, 1)
- FIELD(STATUS, RXIDLE, 4, 1)
- FIELD(STATUS, RXEMPTY, 5, 1)
-REG32(RDATA, 0x14)
-REG32(WDATA, 0x18)
-REG32(FIFO_CTRL, 0x1c)
- FIELD(FIFO_CTRL, RXRST, 0, 1)
- FIELD(FIFO_CTRL, TXRST, 1, 1)
- FIELD(FIFO_CTRL, RXILVL, 2, 3)
- FIELD(FIFO_CTRL, TXILVL, 5, 2)
-REG32(FIFO_STATUS, 0x20)
-REG32(OVRD, 0x24)
-REG32(VAL, 0x28)
-REG32(TIMEOUT_CTRL, 0x2c)
+#include "qom/object.h"
#define IBEX_UART_TX_FIFO_SIZE 16
#define IBEX_UART_CLOCK 50000000 /* 50MHz clock */
#define TYPE_IBEX_UART "ibex-uart"
-#define IBEX_UART(obj) \
- OBJECT_CHECK(IbexUartState, (obj), TYPE_IBEX_UART)
+OBJECT_DECLARE_SIMPLE_TYPE(IbexUartState, IBEX_UART)
-typedef struct {
+struct IbexUartState {
/* <private> */
SysBusDevice parent_obj;
@@ -82,6 +46,8 @@ typedef struct {
uint8_t tx_fifo[IBEX_UART_TX_FIFO_SIZE];
uint32_t tx_level;
+ uint32_t rx_level;
+
QEMUTimer *fifo_trigger_handle;
uint64_t char_tx_time;
@@ -103,5 +69,5 @@ typedef struct {
qemu_irq rx_watermark;
qemu_irq tx_empty;
qemu_irq rx_overflow;
-} IbexUartState;
+};
#endif /* HW_IBEX_UART_H */
diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h
index c8b74284f8..65f0e97c76 100644
--- a/include/hw/char/imx_serial.h
+++ b/include/hw/char/imx_serial.h
@@ -20,12 +20,17 @@
#include "hw/sysbus.h"
#include "chardev/char-fe.h"
+#include "qom/object.h"
+#include "qemu/fifo32.h"
#define TYPE_IMX_SERIAL "imx.serial"
-#define IMX_SERIAL(obj) OBJECT_CHECK(IMXSerialState, (obj), TYPE_IMX_SERIAL)
+OBJECT_DECLARE_SIMPLE_TYPE(IMXSerialState, IMX_SERIAL)
+
+#define FIFO_SIZE 32
#define URXD_CHARRDY (1<<15) /* character read is valid */
#define URXD_ERR (1<<14) /* Character has error */
+#define URXD_OVRRUN (1<<13) /* 32nd character in RX FIFO */
#define URXD_FRMERR (1<<12) /* Character has frame error */
#define URXD_BRK (1<<11) /* Break received */
@@ -64,25 +69,40 @@
#define UCR1_TXMPTYEN (1<<6) /* Tx Empty Interrupt Enable */
#define UCR1_UARTEN (1<<0) /* UART Enable */
+#define UCR2_ATEN (1<<3) /* Ageing Timer Enable */
#define UCR2_TXEN (1<<2) /* Transmitter enable */
#define UCR2_RXEN (1<<1) /* Receiver enable */
#define UCR2_SRST (1<<0) /* Reset complete */
#define UCR4_DREN BIT(0) /* Receive Data Ready interrupt enable */
+#define UCR4_OREN BIT(1) /* Overrun interrupt enable */
#define UCR4_TCEN BIT(3) /* TX complete interrupt enable */
+#define UCR4_WKEN BIT(7) /* WAKE interrupt enable */
#define UTS1_TXEMPTY (1<<6)
#define UTS1_RXEMPTY (1<<5)
#define UTS1_TXFULL (1<<4)
#define UTS1_RXFULL (1<<3)
-typedef struct IMXSerialState {
+#define TL_MASK 0x3f
+
+ /* Bit time in nanoseconds assuming maximum baud rate of 115200 */
+#define BIT_TIME_NS 8681
+
+/* Assume 8 bits per character */
+#define NUM_BITS 8
+
+/* Ageing timer triggers after 8 characters */
+#define AGE_DURATION_NS (8 * NUM_BITS * BIT_TIME_NS)
+
+struct IMXSerialState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
MemoryRegion iomem;
- int32_t readbuff;
+ QEMUTimer ageing_timer;
+ Fifo32 rx_fifo;
uint32_t usr1;
uint32_t usr2;
@@ -103,6 +123,6 @@ typedef struct IMXSerialState {
qemu_irq irq;
CharBackend chr;
-} IMXSerialState;
+};
#endif
diff --git a/include/hw/char/lm32_juart.h b/include/hw/char/lm32_juart.h
deleted file mode 100644
index 6fce278326..0000000000
--- a/include/hw/char/lm32_juart.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef QEMU_HW_CHAR_LM32_JUART_H
-#define QEMU_HW_CHAR_LM32_JUART_H
-
-#include "hw/qdev-core.h"
-
-#define TYPE_LM32_JUART "lm32-juart"
-
-uint32_t lm32_juart_get_jtx(DeviceState *d);
-uint32_t lm32_juart_get_jrx(DeviceState *d);
-void lm32_juart_set_jtx(DeviceState *d, uint32_t jtx);
-void lm32_juart_set_jrx(DeviceState *d, uint32_t jrx);
-
-#endif /* QEMU_HW_CHAR_LM32_JUART_H */
diff --git a/include/hw/char/mchp_pfsoc_mmuart.h b/include/hw/char/mchp_pfsoc_mmuart.h
new file mode 100644
index 0000000000..b0e14ca355
--- /dev/null
+++ b/include/hw/char/mchp_pfsoc_mmuart.h
@@ -0,0 +1,68 @@
+/*
+ * Microchip PolarFire SoC MMUART emulation
+ *
+ * Copyright (c) 2020 Wind River Systems, Inc.
+ *
+ * Author:
+ * Bin Meng <bin.meng@windriver.com>
+ *
+ * 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.
+ */
+
+#ifndef HW_MCHP_PFSOC_MMUART_H
+#define HW_MCHP_PFSOC_MMUART_H
+
+#include "hw/sysbus.h"
+#include "hw/char/serial.h"
+
+#define MCHP_PFSOC_MMUART_REG_COUNT 13
+
+#define TYPE_MCHP_PFSOC_UART "mchp.pfsoc.uart"
+OBJECT_DECLARE_SIMPLE_TYPE(MchpPfSoCMMUartState, MCHP_PFSOC_UART)
+
+typedef struct MchpPfSoCMMUartState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion container;
+ MemoryRegion iomem;
+
+ SerialMM serial_mm;
+
+ uint32_t reg[MCHP_PFSOC_MMUART_REG_COUNT];
+} MchpPfSoCMMUartState;
+
+/**
+ * mchp_pfsoc_mmuart_create - Create a Microchip PolarFire SoC MMUART
+ *
+ * This is a helper routine for board to create a MMUART device that is
+ * compatible with Microchip PolarFire SoC.
+ *
+ * @sysmem: system memory region to map
+ * @base: base address of the MMUART registers
+ * @irq: IRQ number of the MMUART device
+ * @chr: character device to associate to
+ *
+ * @return: a pointer to the device specific control structure
+ */
+MchpPfSoCMMUartState *mchp_pfsoc_mmuart_create(MemoryRegion *sysmem,
+ hwaddr base, qemu_irq irq, Chardev *chr);
+
+#endif /* HW_MCHP_PFSOC_MMUART_H */
diff --git a/include/hw/char/nrf51_uart.h b/include/hw/char/nrf51_uart.h
index eb1c15b490..561b6383c4 100644
--- a/include/hw/char/nrf51_uart.h
+++ b/include/hw/char/nrf51_uart.h
@@ -14,12 +14,13 @@
#include "hw/sysbus.h"
#include "chardev/char-fe.h"
#include "hw/registerfields.h"
+#include "qom/object.h"
#define UART_FIFO_LENGTH 6
#define UART_SIZE 0x1000
#define TYPE_NRF51_UART "nrf51_soc.uart"
-#define NRF51_UART(obj) OBJECT_CHECK(NRF51UARTState, (obj), TYPE_NRF51_UART)
+OBJECT_DECLARE_SIMPLE_TYPE(NRF51UARTState, NRF51_UART)
REG32(UART_STARTRX, 0x000)
REG32(UART_STOPRX, 0x004)
@@ -54,7 +55,7 @@ REG32(UART_TXD, 0x51C)
REG32(UART_BAUDRATE, 0x524)
REG32(UART_CONFIG, 0x56C)
-typedef struct NRF51UARTState {
+struct NRF51UARTState {
SysBusDevice parent_obj;
MemoryRegion iomem;
@@ -72,6 +73,6 @@ typedef struct NRF51UARTState {
bool tx_started;
bool pending_tx_byte;
bool enabled;
-} NRF51UARTState;
+};
#endif
diff --git a/include/hw/char/parallel-isa.h b/include/hw/char/parallel-isa.h
new file mode 100644
index 0000000000..5284b2ffec
--- /dev/null
+++ b/include/hw/char/parallel-isa.h
@@ -0,0 +1,35 @@
+/*
+ * QEMU ISA Parallel PORT emulation
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ * Copyright (c) 2007 Marko Kohtala
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#ifndef HW_PARALLEL_ISA_H
+#define HW_PARALLEL_ISA_H
+
+#include "parallel.h"
+
+#include "exec/ioport.h"
+#include "hw/isa/isa.h"
+#include "qom/object.h"
+
+#define TYPE_ISA_PARALLEL "isa-parallel"
+OBJECT_DECLARE_SIMPLE_TYPE(ISAParallelState, ISA_PARALLEL)
+
+struct ISAParallelState {
+ ISADevice parent_obj;
+
+ uint32_t index;
+ uint32_t iobase;
+ uint32_t isairq;
+ ParallelState state;
+ PortioList portio_list;
+};
+
+void isa_parallel_set_iobase(ISADevice *parallel, hwaddr iobase);
+void isa_parallel_set_enabled(ISADevice *parallel, bool enabled);
+
+#endif /* HW_PARALLEL_ISA_H */
diff --git a/include/hw/char/parallel.h b/include/hw/char/parallel.h
index 0a23c0f57e..cfb97cc7cc 100644
--- a/include/hw/char/parallel.h
+++ b/include/hw/char/parallel.h
@@ -1,9 +1,28 @@
#ifndef HW_PARALLEL_H
#define HW_PARALLEL_H
+#include "exec/memory.h"
#include "hw/isa/isa.h"
+#include "hw/irq.h"
+#include "chardev/char-fe.h"
#include "chardev/char.h"
+typedef struct ParallelState {
+ MemoryRegion iomem;
+ uint8_t dataw;
+ uint8_t datar;
+ uint8_t status;
+ uint8_t control;
+ qemu_irq irq;
+ int irq_pending;
+ CharBackend chr;
+ int hw_driver;
+ int epp_timeout;
+ uint32_t last_read_offset; /* For debugging */
+ /* Memory-mapped interface */
+ int it_shift;
+} ParallelState;
+
void parallel_hds_isa_init(ISABus *bus, int n);
bool parallel_mm_init(MemoryRegion *address_space,
diff --git a/include/hw/char/pl011.h b/include/hw/char/pl011.h
index bed758350f..d853802132 100644
--- a/include/hw/char/pl011.h
+++ b/include/hw/char/pl011.h
@@ -15,18 +15,20 @@
#ifndef HW_PL011_H
#define HW_PL011_H
-#include "hw/qdev-properties.h"
#include "hw/sysbus.h"
#include "chardev/char-fe.h"
-#include "qapi/error.h"
+#include "qom/object.h"
#define TYPE_PL011 "pl011"
-#define PL011(obj) OBJECT_CHECK(PL011State, (obj), TYPE_PL011)
+OBJECT_DECLARE_SIMPLE_TYPE(PL011State, PL011)
/* This shares the same struct (and cast macro) as the base pl011 device */
#define TYPE_PL011_LUMINARY "pl011_luminary"
-typedef struct PL011State {
+/* Depth of UART FIFO in bytes, when FIFO mode is enabled (else depth == 1) */
+#define PL011_FIFO_DEPTH 16
+
+struct PL011State {
SysBusDevice parent_obj;
MemoryRegion iomem;
@@ -38,7 +40,7 @@ typedef struct PL011State {
uint32_t dmacr;
uint32_t int_enabled;
uint32_t int_level;
- uint32_t read_fifo[16];
+ uint32_t read_fifo[PL011_FIFO_DEPTH];
uint32_t ilpr;
uint32_t ibrd;
uint32_t fbrd;
@@ -48,41 +50,11 @@ typedef struct PL011State {
int read_trigger;
CharBackend chr;
qemu_irq irq[6];
+ Clock *clk;
+ bool migrate_clk;
const unsigned char *id;
-} PL011State;
-
-static inline DeviceState *pl011_create(hwaddr addr,
- qemu_irq irq,
- Chardev *chr)
-{
- DeviceState *dev;
- SysBusDevice *s;
-
- dev = qdev_new("pl011");
- s = SYS_BUS_DEVICE(dev);
- qdev_prop_set_chr(dev, "chardev", chr);
- sysbus_realize_and_unref(s, &error_fatal);
- sysbus_mmio_map(s, 0, addr);
- sysbus_connect_irq(s, 0, irq);
-
- return dev;
-}
-
-static inline DeviceState *pl011_luminary_create(hwaddr addr,
- qemu_irq irq,
- Chardev *chr)
-{
- DeviceState *dev;
- SysBusDevice *s;
-
- dev = qdev_new("pl011_luminary");
- s = SYS_BUS_DEVICE(dev);
- qdev_prop_set_chr(dev, "chardev", chr);
- sysbus_realize_and_unref(s, &error_fatal);
- sysbus_mmio_map(s, 0, addr);
- sysbus_connect_irq(s, 0, irq);
+};
- return dev;
-}
+DeviceState *pl011_create(hwaddr addr, qemu_irq irq, Chardev *chr);
#endif
diff --git a/include/hw/char/renesas_sci.h b/include/hw/char/renesas_sci.h
index efdebc620a..a4764e3eee 100644
--- a/include/hw/char/renesas_sci.h
+++ b/include/hw/char/renesas_sci.h
@@ -11,9 +11,12 @@
#include "chardev/char-fe.h"
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_RENESAS_SCI "renesas-sci"
-#define RSCI(obj) OBJECT_CHECK(RSCIState, (obj), TYPE_RENESAS_SCI)
+typedef struct RSCIState RSCIState;
+DECLARE_INSTANCE_CHECKER(RSCIState, RSCI,
+ TYPE_RENESAS_SCI)
enum {
ERI = 0,
@@ -23,7 +26,7 @@ enum {
SCI_NR_IRQ = 4
};
-typedef struct {
+struct RSCIState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -46,6 +49,6 @@ typedef struct {
int64_t trtime;
int64_t rx_next;
uint64_t input_freq;
-} RSCIState;
+};
#endif
diff --git a/include/hw/riscv/riscv_htif.h b/include/hw/char/riscv_htif.h
index fb9452cf51..df493fdf6b 100644
--- a/include/hw/riscv/riscv_htif.h
+++ b/include/hw/char/riscv_htif.h
@@ -23,7 +23,6 @@
#include "chardev/char.h"
#include "chardev/char-fe.h"
#include "exec/memory.h"
-#include "target/riscv/cpu.h"
#define TYPE_HTIF_UART "riscv.htif.uart"
@@ -31,29 +30,25 @@ typedef struct HTIFState {
int allow_tohost;
int fromhost_inprogress;
+ uint64_t tohost;
+ uint64_t fromhost;
hwaddr tohost_offset;
hwaddr fromhost_offset;
- uint64_t tohost_size;
- uint64_t fromhost_size;
MemoryRegion mmio;
- MemoryRegion *address_space;
- MemoryRegion *main_mem;
- void *main_mem_ram_ptr;
- CPURISCVState *env;
CharBackend chr;
uint64_t pending_read;
} HTIFState;
-extern const VMStateDescription vmstate_htif;
-extern const MemoryRegionOps htif_io_ops;
+extern const char *sig_file;
+extern uint8_t line_size;
/* HTIF symbol callback */
void htif_symbol_callback(const char *st_name, int st_info, uint64_t st_value,
uint64_t st_size);
/* legacy pre qom */
-HTIFState *htif_mm_init(MemoryRegion *address_space, MemoryRegion *main_mem,
- CPURISCVState *env, Chardev *chr);
+HTIFState *htif_mm_init(MemoryRegion *address_space, Chardev *chr,
+ uint64_t nonelf_base, bool custom_base);
#endif
diff --git a/include/hw/char/serial.h b/include/hw/char/serial.h
index 535fa23a2b..6e14099ee7 100644
--- a/include/hw/char/serial.h
+++ b/include/hw/char/serial.h
@@ -31,10 +31,11 @@
#include "qemu/fifo8.h"
#include "chardev/char.h"
#include "hw/sysbus.h"
+#include "qom/object.h"
#define UART_FIFO_LENGTH 16 /* 16550A Fifo Length */
-typedef struct SerialState {
+struct SerialState {
DeviceState parent;
uint16_t divider;
@@ -60,7 +61,7 @@ typedef struct SerialState {
uint32_t baudbase;
uint32_t tsr_retry;
guint watch_tag;
- uint32_t wakeup;
+ bool wakeup;
/* Time when the last byte was successfully sent out of the tsr */
uint64_t last_xmit_ts;
@@ -77,22 +78,17 @@ typedef struct SerialState {
QEMUTimer *modem_status_poll;
MemoryRegion io;
-} SerialState;
+};
+typedef struct SerialState SerialState;
-typedef struct SerialMM {
+struct SerialMM {
SysBusDevice parent;
SerialState serial;
uint8_t regshift;
uint8_t endianness;
-} SerialMM;
-
-typedef struct SerialIO {
- SysBusDevice parent;
-
- SerialState serial;
-} SerialIO;
+};
extern const VMStateDescription vmstate_serial;
extern const MemoryRegionOps serial_io_ops;
@@ -100,13 +96,10 @@ extern const MemoryRegionOps serial_io_ops;
void serial_set_frequency(SerialState *s, uint32_t frequency);
#define TYPE_SERIAL "serial"
-#define SERIAL(s) OBJECT_CHECK(SerialState, (s), TYPE_SERIAL)
+OBJECT_DECLARE_SIMPLE_TYPE(SerialState, SERIAL)
#define TYPE_SERIAL_MM "serial-mm"
-#define SERIAL_MM(s) OBJECT_CHECK(SerialMM, (s), TYPE_SERIAL_MM)
-
-#define TYPE_SERIAL_IO "serial-io"
-#define SERIAL_IO(s) OBJECT_CHECK(SerialIO, (s), TYPE_SERIAL_IO)
+OBJECT_DECLARE_SIMPLE_TYPE(SerialMM, SERIAL_MM)
SerialMM *serial_mm_init(MemoryRegion *address_space,
hwaddr base, int regshift,
@@ -119,5 +112,7 @@ SerialMM *serial_mm_init(MemoryRegion *address_space,
#define TYPE_ISA_SERIAL "isa-serial"
void serial_hds_isa_init(ISABus *bus, int from, int to);
+void isa_serial_set_iobase(ISADevice *serial, hwaddr iobase);
+void isa_serial_set_enabled(ISADevice *serial, bool enabled);
#endif
diff --git a/include/hw/char/shakti_uart.h b/include/hw/char/shakti_uart.h
new file mode 100644
index 0000000000..526c408233
--- /dev/null
+++ b/include/hw/char/shakti_uart.h
@@ -0,0 +1,74 @@
+/*
+ * SHAKTI UART
+ *
+ * Copyright (c) 2021 Vijai Kumar K <vijai@behindbytes.com>
+ *
+ * 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.
+ */
+
+#ifndef HW_SHAKTI_UART_H
+#define HW_SHAKTI_UART_H
+
+#include "hw/sysbus.h"
+#include "chardev/char-fe.h"
+
+#define SHAKTI_UART_BAUD 0x00
+#define SHAKTI_UART_TX 0x04
+#define SHAKTI_UART_RX 0x08
+#define SHAKTI_UART_STATUS 0x0C
+#define SHAKTI_UART_DELAY 0x10
+#define SHAKTI_UART_CONTROL 0x14
+#define SHAKTI_UART_INT_EN 0x18
+#define SHAKTI_UART_IQ_CYCLES 0x1C
+#define SHAKTI_UART_RX_THRES 0x20
+
+#define SHAKTI_UART_STATUS_TX_EMPTY (1 << 0)
+#define SHAKTI_UART_STATUS_TX_FULL (1 << 1)
+#define SHAKTI_UART_STATUS_RX_NOT_EMPTY (1 << 2)
+#define SHAKTI_UART_STATUS_RX_FULL (1 << 3)
+/* 9600 8N1 is the default setting */
+/* Reg value = (50000000 Hz)/(16 * 9600)*/
+#define SHAKTI_UART_BAUD_DEFAULT 0x0145
+#define SHAKTI_UART_CONTROL_DEFAULT 0x0100
+
+#define TYPE_SHAKTI_UART "shakti-uart"
+#define SHAKTI_UART(obj) \
+ OBJECT_CHECK(ShaktiUartState, (obj), TYPE_SHAKTI_UART)
+
+typedef struct {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /* <public> */
+ MemoryRegion mmio;
+
+ uint32_t uart_baud;
+ uint32_t uart_tx;
+ uint32_t uart_rx;
+ uint32_t uart_status;
+ uint32_t uart_delay;
+ uint32_t uart_control;
+ uint32_t uart_interrupt;
+ uint32_t uart_iq_cycles;
+ uint32_t uart_rx_threshold;
+
+ CharBackend chr;
+} ShaktiUartState;
+
+#endif /* HW_SHAKTI_UART_H */
diff --git a/include/hw/riscv/sifive_uart.h b/include/hw/char/sifive_uart.h
index 65668825a3..7f6c79f8bd 100644
--- a/include/hw/riscv/sifive_uart.h
+++ b/include/hw/char/sifive_uart.h
@@ -21,7 +21,9 @@
#define HW_SIFIVE_UART_H
#include "chardev/char-fe.h"
+#include "hw/qdev-properties.h"
#include "hw/sysbus.h"
+#include "qom/object.h"
enum {
SIFIVE_UART_TXFIFO = 0,
@@ -48,13 +50,12 @@ enum {
#define SIFIVE_UART_GET_TXCNT(txctrl) ((txctrl >> 16) & 0x7)
#define SIFIVE_UART_GET_RXCNT(rxctrl) ((rxctrl >> 16) & 0x7)
+#define SIFIVE_UART_RX_FIFO_SIZE 8
#define TYPE_SIFIVE_UART "riscv.sifive.uart"
+OBJECT_DECLARE_SIMPLE_TYPE(SiFiveUARTState, SIFIVE_UART)
-#define SIFIVE_UART(obj) \
- OBJECT_CHECK(SiFiveUARTState, (obj), TYPE_SIFIVE_UART)
-
-typedef struct SiFiveUARTState {
+struct SiFiveUARTState {
/*< private >*/
SysBusDevice parent_obj;
@@ -62,14 +63,14 @@ typedef struct SiFiveUARTState {
qemu_irq irq;
MemoryRegion mmio;
CharBackend chr;
- uint8_t rx_fifo[8];
- unsigned int rx_fifo_len;
+ uint8_t rx_fifo[SIFIVE_UART_RX_FIFO_SIZE];
+ uint8_t rx_fifo_len;
uint32_t ie;
uint32_t ip;
uint32_t txctrl;
uint32_t rxctrl;
uint32_t div;
-} SiFiveUARTState;
+};
SiFiveUARTState *sifive_uart_create(MemoryRegion *address_space, hwaddr base,
Chardev *chr, qemu_irq irq);
diff --git a/include/hw/char/stm32f2xx_usart.h b/include/hw/char/stm32f2xx_usart.h
index 8e112671e3..fdfa7424a7 100644
--- a/include/hw/char/stm32f2xx_usart.h
+++ b/include/hw/char/stm32f2xx_usart.h
@@ -27,6 +27,7 @@
#include "hw/sysbus.h"
#include "chardev/char-fe.h"
+#include "qom/object.h"
#define USART_SR 0x00
#define USART_DR 0x04
@@ -47,16 +48,17 @@
#define USART_SR_TC (1 << 6)
#define USART_SR_RXNE (1 << 5)
-#define USART_CR1_UE (1 << 13)
-#define USART_CR1_RXNEIE (1 << 5)
-#define USART_CR1_TE (1 << 3)
-#define USART_CR1_RE (1 << 2)
+#define USART_CR1_UE (1 << 13)
+#define USART_CR1_TXEIE (1 << 7)
+#define USART_CR1_TCEIE (1 << 6)
+#define USART_CR1_RXNEIE (1 << 5)
+#define USART_CR1_TE (1 << 3)
+#define USART_CR1_RE (1 << 2)
#define TYPE_STM32F2XX_USART "stm32f2xx-usart"
-#define STM32F2XX_USART(obj) \
- OBJECT_CHECK(STM32F2XXUsartState, (obj), TYPE_STM32F2XX_USART)
+OBJECT_DECLARE_SIMPLE_TYPE(STM32F2XXUsartState, STM32F2XX_USART)
-typedef struct {
+struct STM32F2XXUsartState {
/* <private> */
SysBusDevice parent_obj;
@@ -73,5 +75,5 @@ typedef struct {
CharBackend chr;
qemu_irq irq;
-} STM32F2XXUsartState;
+};
#endif /* HW_STM32F2XX_USART_H */
diff --git a/include/hw/char/xilinx_uartlite.h b/include/hw/char/xilinx_uartlite.h
index bb32d0fcb3..36d4e8444d 100644
--- a/include/hw/char/xilinx_uartlite.h
+++ b/include/hw/char/xilinx_uartlite.h
@@ -15,24 +15,9 @@
#ifndef XILINX_UARTLITE_H
#define XILINX_UARTLITE_H
-#include "hw/qdev-properties.h"
-#include "hw/sysbus.h"
+#include "qom/object.h"
-static inline DeviceState *xilinx_uartlite_create(hwaddr addr,
- qemu_irq irq,
- Chardev *chr)
-{
- DeviceState *dev;
- SysBusDevice *s;
-
- dev = qdev_new("xlnx.xps-uartlite");
- s = SYS_BUS_DEVICE(dev);
- qdev_prop_set_chr(dev, "chardev", chr);
- sysbus_realize_and_unref(s, &error_fatal);
- sysbus_mmio_map(s, 0, addr);
- sysbus_connect_irq(s, 0, irq);
-
- return dev;
-}
+#define TYPE_XILINX_UARTLITE "xlnx.xps-uartlite"
+OBJECT_DECLARE_SIMPLE_TYPE(XilinxUARTLite, XILINX_UARTLITE)
#endif
diff --git a/include/hw/clock.h b/include/hw/clock.h
index f822a94220..eb58599131 100644
--- a/include/hw/clock.h
+++ b/include/hw/clock.h
@@ -16,11 +16,24 @@
#include "qom/object.h"
#include "qemu/queue.h"
+#include "qemu/host-utils.h"
+#include "qemu/bitops.h"
#define TYPE_CLOCK "clock"
-#define CLOCK(obj) OBJECT_CHECK(Clock, (obj), TYPE_CLOCK)
+OBJECT_DECLARE_SIMPLE_TYPE(Clock, CLOCK)
-typedef void ClockCallback(void *opaque);
+/*
+ * Argument to ClockCallback functions indicating why the callback
+ * has been called. A mask of these values logically ORed together
+ * is used to specify which events are interesting when the callback
+ * is registered, so these values must all be different bit values.
+ */
+typedef enum ClockEvent {
+ ClockUpdate = 1, /* Clock period has just updated */
+ ClockPreUpdate = 2, /* Clock period is about to update */
+} ClockEvent;
+
+typedef void ClockCallback(void *opaque, ClockEvent event);
/*
* clock store a value representing the clock's period in 2^-32ns unit.
@@ -38,7 +51,6 @@ typedef void ClockCallback(void *opaque);
* macro helpers to convert to hertz / nanosecond
*/
#define CLOCK_PERIOD_FROM_NS(ns) ((ns) * (CLOCK_PERIOD_1SEC / 1000000000llu))
-#define CLOCK_PERIOD_TO_NS(per) ((per) / (CLOCK_PERIOD_1SEC / 1000000000llu))
#define CLOCK_PERIOD_FROM_HZ(hz) (((hz) != 0) ? CLOCK_PERIOD_1SEC / (hz) : 0u)
#define CLOCK_PERIOD_TO_HZ(per) (((per) != 0) ? CLOCK_PERIOD_1SEC / (per) : 0u)
@@ -49,12 +61,12 @@ typedef void ClockCallback(void *opaque);
* @canonical_path: clock path string cache (used for trace purpose)
* @callback: called when clock changes
* @callback_opaque: argument for @callback
+ * @callback_events: mask of events when callback should be called
* @source: source (or parent in clock tree) of the clock
* @children: list of clocks connected to this one (it is their source)
* @sibling: structure used to form a clock list
*/
-typedef struct Clock Clock;
struct Clock {
/*< private >*/
@@ -67,6 +79,11 @@ struct Clock {
char *canonical_path;
ClockCallback *callback;
void *callback_opaque;
+ unsigned int callback_events;
+
+ /* Ratio of the parent clock to run the child clocks at */
+ uint32_t multiplier;
+ uint32_t divider;
/* Clocks are organized in a clock tree */
Clock *source;
@@ -82,6 +99,11 @@ extern const VMStateDescription vmstate_clock;
VMSTATE_CLOCK_V(field, state, 0)
#define VMSTATE_CLOCK_V(field, state, version) \
VMSTATE_STRUCT_POINTER_V(field, state, version, vmstate_clock, Clock)
+#define VMSTATE_ARRAY_CLOCK(field, state, num) \
+ VMSTATE_ARRAY_CLOCK_V(field, state, num, 0)
+#define VMSTATE_ARRAY_CLOCK_V(field, state, num, version) \
+ VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(field, state, num, version, \
+ vmstate_clock, Clock)
/**
* clock_setup_canonical_path:
@@ -92,14 +114,32 @@ extern const VMStateDescription vmstate_clock;
void clock_setup_canonical_path(Clock *clk);
/**
+ * clock_new:
+ * @parent: the clock parent
+ * @name: the clock object name
+ *
+ * Helper function to create a new clock and parent it to @parent. There is no
+ * need to call clock_setup_canonical_path on the returned clock as it is done
+ * by this function.
+ *
+ * @return the newly created clock
+ */
+Clock *clock_new(Object *parent, const char *name);
+
+/**
* clock_set_callback:
* @clk: the clock to register the callback into
* @cb: the callback function
* @opaque: the argument to the callback
+ * @events: the events the callback should be called for
+ * (logical OR of ClockEvent enum values)
*
* Register a callback called on every clock update.
+ * Note that a clock has only one callback: you cannot register
+ * different callback functions for different events.
*/
-void clock_set_callback(Clock *clk, ClockCallback *cb, void *opaque);
+void clock_set_callback(Clock *clk, ClockCallback *cb,
+ void *opaque, unsigned int events);
/**
* clock_clear_callback:
@@ -122,22 +162,39 @@ void clock_clear_callback(Clock *clk);
void clock_set_source(Clock *clk, Clock *src);
/**
+ * clock_has_source:
+ * @clk: the clock
+ *
+ * Returns true if the clock has a source clock connected to it.
+ * This is useful for devices which have input clocks which must
+ * be connected by the board/SoC code which creates them. The
+ * device code can use this to check in its realize method that
+ * the clock has been connected.
+ */
+static inline bool clock_has_source(const Clock *clk)
+{
+ return clk->source != NULL;
+}
+
+/**
* clock_set:
* @clk: the clock to initialize.
* @value: the clock's value, 0 means unclocked
*
* Set the local cached period value of @clk to @value.
+ *
+ * @return: true if the clock is changed.
*/
-void clock_set(Clock *clk, uint64_t value);
+bool clock_set(Clock *clk, uint64_t value);
-static inline void clock_set_hz(Clock *clk, unsigned hz)
+static inline bool clock_set_hz(Clock *clk, unsigned hz)
{
- clock_set(clk, CLOCK_PERIOD_FROM_HZ(hz));
+ return clock_set(clk, CLOCK_PERIOD_FROM_HZ(hz));
}
-static inline void clock_set_ns(Clock *clk, unsigned ns)
+static inline bool clock_set_ns(Clock *clk, unsigned ns)
{
- clock_set(clk, CLOCK_PERIOD_FROM_NS(ns));
+ return clock_set(clk, CLOCK_PERIOD_FROM_NS(ns));
}
/**
@@ -147,7 +204,7 @@ static inline void clock_set_ns(Clock *clk, unsigned ns)
* Propagate the clock period that has been previously configured using
* @clock_set(). This will update recursively all connected clocks.
* It is an error to call this function on a clock which has a source.
- * Note: this function must not be called during device inititialization
+ * Note: this function must not be called during device initialization
* or migration.
*/
void clock_propagate(Clock *clk);
@@ -163,8 +220,9 @@ void clock_propagate(Clock *clk);
*/
static inline void clock_update(Clock *clk, uint64_t value)
{
- clock_set(clk, value);
- clock_propagate(clk);
+ if (clock_set(clk, value)) {
+ clock_propagate(clk);
+ }
}
static inline void clock_update_hz(Clock *clk, unsigned hz)
@@ -193,9 +251,81 @@ static inline unsigned clock_get_hz(Clock *clk)
return CLOCK_PERIOD_TO_HZ(clock_get(clk));
}
-static inline unsigned clock_get_ns(Clock *clk)
+/**
+ * clock_ticks_to_ns:
+ * @clk: the clock to query
+ * @ticks: number of ticks
+ *
+ * Returns the length of time in nanoseconds for this clock
+ * to tick @ticks times. Because a clock can have a period
+ * which is not a whole number of nanoseconds, it is important
+ * to use this function when calculating things like timer
+ * expiry deadlines, rather than attempting to obtain a "period
+ * in nanoseconds" value and then multiplying that by a number
+ * of ticks.
+ *
+ * The result could in theory be too large to fit in a 64-bit
+ * value if the number of ticks and the clock period are both
+ * large; to avoid overflow the result will be saturated to INT64_MAX
+ * (because this is the largest valid input to the QEMUTimer APIs).
+ * Since INT64_MAX nanoseconds is almost 300 years, anything with
+ * an expiry later than that is in the "will never happen" category
+ * and callers can reasonably not special-case the saturated result.
+ */
+static inline uint64_t clock_ticks_to_ns(const Clock *clk, uint64_t ticks)
+{
+ uint64_t ns_low, ns_high;
+
+ /*
+ * clk->period is the period in units of 2^-32 ns, so
+ * (clk->period * ticks) is the required length of time in those
+ * units, and we can convert to nanoseconds by multiplying by
+ * 2^32, which is the same as shifting the 128-bit multiplication
+ * result right by 32.
+ */
+ mulu64(&ns_low, &ns_high, clk->period, ticks);
+ if (ns_high & MAKE_64BIT_MASK(31, 33)) {
+ return INT64_MAX;
+ }
+ return ns_low >> 32 | ns_high << 32;
+}
+
+/**
+ * clock_ns_to_ticks:
+ * @clk: the clock to query
+ * @ns: duration in nanoseconds
+ *
+ * Returns the number of ticks this clock would make in the given
+ * number of nanoseconds. Because a clock can have a period which
+ * is not a whole number of nanoseconds, it is important to use this
+ * function rather than attempting to obtain a "period in nanoseconds"
+ * value and then dividing the duration by that value.
+ *
+ * If the clock is stopped (ie it has period zero), returns 0.
+ *
+ * For some inputs the result could overflow a 64-bit value (because
+ * the clock's period is short and the duration is long). In these
+ * cases we truncate the result to a 64-bit value. This is on the
+ * assumption that generally the result is going to be used to report
+ * a 32-bit or 64-bit guest register value, so wrapping either cannot
+ * happen or is the desired behaviour.
+ */
+static inline uint64_t clock_ns_to_ticks(const Clock *clk, uint64_t ns)
{
- return CLOCK_PERIOD_TO_NS(clock_get(clk));
+ /*
+ * ticks = duration_in_ns / period_in_ns
+ * = ns / (period / 2^32)
+ * = (ns * 2^32) / period
+ * The hi, lo inputs to divu128() are (ns << 32) as a 128 bit value.
+ */
+ uint64_t lo = ns << 32;
+ uint64_t hi = ns >> 32;
+ if (clk->period == 0) {
+ return 0;
+ }
+
+ divu128(&lo, &hi, clk->period);
+ return lo;
}
/**
@@ -209,17 +339,43 @@ static inline bool clock_is_enabled(const Clock *clk)
return clock_get(clk) != 0;
}
-static inline void clock_init(Clock *clk, uint64_t value)
-{
- clock_set(clk, value);
-}
-static inline void clock_init_hz(Clock *clk, uint64_t value)
-{
- clock_set_hz(clk, value);
-}
-static inline void clock_init_ns(Clock *clk, uint64_t value)
-{
- clock_set_ns(clk, value);
-}
+/**
+ * clock_display_freq: return human-readable representation of clock frequency
+ * @clk: clock
+ *
+ * Return a string which has a human-readable representation of the
+ * clock's frequency, e.g. "33.3 MHz". This is intended for debug
+ * and display purposes.
+ *
+ * The caller is responsible for freeing the string with g_free().
+ */
+char *clock_display_freq(Clock *clk);
+
+/**
+ * clock_set_mul_div: set multiplier/divider for child clocks
+ * @clk: clock
+ * @multiplier: multiplier value
+ * @divider: divider value
+ *
+ * @return: true if the clock is changed.
+ *
+ * By default, a Clock's children will all run with the same period
+ * as their parent. This function allows you to adjust the multiplier
+ * and divider used to derive the child clock frequency.
+ * For example, setting a multiplier of 2 and a divider of 3
+ * will run child clocks with a period 2/3 of the parent clock,
+ * so if the parent clock is an 8MHz clock the children will
+ * be 12MHz.
+ *
+ * Setting the multiplier to 0 will stop the child clocks.
+ * Setting the divider to 0 is a programming error (diagnosed with
+ * an assertion failure).
+ * Setting a multiplier value that results in the child period
+ * overflowing is not diagnosed.
+ *
+ * Note that this function does not call clock_propagate(); the
+ * caller should do that if necessary.
+ */
+bool clock_set_mul_div(Clock *clk, uint32_t multiplier, uint32_t divider);
#endif /* QEMU_HW_CLOCK_H */
diff --git a/include/hw/core/accel-cpu.h b/include/hw/core/accel-cpu.h
new file mode 100644
index 0000000000..24dad45ab9
--- /dev/null
+++ b/include/hw/core/accel-cpu.h
@@ -0,0 +1,38 @@
+/*
+ * Accelerator interface, specializes CPUClass
+ * This header is used only by target-specific code.
+ *
+ * Copyright 2021 SUSE LLC
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef ACCEL_CPU_H
+#define ACCEL_CPU_H
+
+/*
+ * This header is used to define new accelerator-specific target-specific
+ * accelerator cpu subclasses.
+ * It uses CPU_RESOLVING_TYPE, so this is clearly target-specific.
+ *
+ * Do not try to use for any other purpose than the implementation of new
+ * subclasses in target/, or the accel implementation itself in accel/
+ */
+
+#define TYPE_ACCEL_CPU "accel-" CPU_RESOLVING_TYPE
+#define ACCEL_CPU_NAME(name) (name "-" TYPE_ACCEL_CPU)
+typedef struct AccelCPUClass AccelCPUClass;
+DECLARE_CLASS_CHECKERS(AccelCPUClass, ACCEL_CPU, TYPE_ACCEL_CPU)
+
+typedef struct AccelCPUClass {
+ /*< private >*/
+ ObjectClass parent_class;
+ /*< public >*/
+
+ void (*cpu_class_init)(CPUClass *cc);
+ void (*cpu_instance_init)(CPUState *cpu);
+ bool (*cpu_target_realize)(CPUState *cpu, Error **errp);
+} AccelCPUClass;
+
+#endif /* ACCEL_CPU_H */
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index 8f145733ce..ec14f74ce5 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -23,30 +23,20 @@
#include "hw/qdev-core.h"
#include "disas/dis-asm.h"
#include "exec/hwaddr.h"
+#include "exec/vaddr.h"
#include "exec/memattrs.h"
+#include "exec/tlb-common.h"
#include "qapi/qapi-types-run-state.h"
#include "qemu/bitmap.h"
#include "qemu/rcu_queue.h"
#include "qemu/queue.h"
#include "qemu/thread.h"
-#include "qemu/plugin.h"
+#include "qom/object.h"
typedef int (*WriteCoreDumpFunction)(const void *buf, size_t size,
void *opaque);
/**
- * vaddr:
- * Type wide enough to contain any #target_ulong virtual address.
- */
-typedef uint64_t vaddr;
-#define VADDR_PRId PRId64
-#define VADDR_PRIu PRIu64
-#define VADDR_PRIo PRIo64
-#define VADDR_PRIx PRIx64
-#define VADDR_PRIX PRIX64
-#define VADDR_MAX UINT64_MAX
-
-/**
* SECTION:cpu
* @section_id: QEMU-cpu
* @title: CPU Class
@@ -61,41 +51,65 @@ typedef uint64_t vaddr;
*/
#define CPU(obj) ((CPUState *)(obj))
-#define CPU_CLASS(class) OBJECT_CLASS_CHECK(CPUClass, (class), TYPE_CPU)
-#define CPU_GET_CLASS(obj) OBJECT_GET_CLASS(CPUClass, (obj), TYPE_CPU)
+/*
+ * The class checkers bring in CPU_GET_CLASS() which is potentially
+ * expensive given the eventual call to
+ * object_class_dynamic_cast_assert(). Because of this the CPUState
+ * has a cached value for the class in cs->cc which is set up in
+ * cpu_exec_realizefn() for use in hot code paths.
+ */
+typedef struct CPUClass CPUClass;
+DECLARE_CLASS_CHECKERS(CPUClass, CPU,
+ TYPE_CPU)
+
+/**
+ * OBJECT_DECLARE_CPU_TYPE:
+ * @CpuInstanceType: instance struct name
+ * @CpuClassType: class struct name
+ * @CPU_MODULE_OBJ_NAME: the CPU name in uppercase with underscore separators
+ *
+ * This macro is typically used in "cpu-qom.h" header file, and will:
+ *
+ * - create the typedefs for the CPU object and class structs
+ * - register the type for use with g_autoptr
+ * - provide three standard type cast functions
+ *
+ * The object struct and class struct need to be declared manually.
+ */
+#define OBJECT_DECLARE_CPU_TYPE(CpuInstanceType, CpuClassType, CPU_MODULE_OBJ_NAME) \
+ typedef struct ArchCPU CpuInstanceType; \
+ OBJECT_DECLARE_TYPE(ArchCPU, CpuClassType, CPU_MODULE_OBJ_NAME);
typedef enum MMUAccessType {
MMU_DATA_LOAD = 0,
MMU_DATA_STORE = 1,
MMU_INST_FETCH = 2
+#define MMU_ACCESS_COUNT 3
} MMUAccessType;
typedef struct CPUWatchpoint CPUWatchpoint;
-struct TranslationBlock;
+/* see accel-cpu.h */
+struct AccelCPUClass;
+
+/* see sysemu-cpu-ops.h */
+struct SysemuCPUOps;
/**
* CPUClass:
* @class_by_name: Callback to map -cpu command line model name to an
- * instantiatable CPU type.
+ * instantiatable CPU type.
* @parse_features: Callback to parse command line arguments.
* @reset_dump_flags: #CPUDumpFlags to use for reset logging.
* @has_work: Callback for checking if there is work to do.
- * @do_interrupt: Callback for interrupt handling.
- * @do_unaligned_access: Callback for unaligned access handling, if
- * the target defines #TARGET_ALIGNED_ONLY.
- * @do_transaction_failed: Callback for handling failed memory transactions
- * (ie bus faults or external aborts; not MMU faults)
- * @virtio_is_big_endian: Callback to return %true if a CPU which supports
- * runtime configurable endianness is currently big-endian. Non-configurable
- * CPUs can use the default implementation of this method. This method should
- * not be used by any callers other than the pre-1.0 virtio devices.
+ * @mmu_index: Callback for choosing softmmu mmu index;
+ * may be used internally by memory_rw_debug without TCG.
* @memory_rw_debug: Callback for GDB memory access.
* @dump_state: Callback for dumping state.
- * @dump_statistics: Callback for dumping statistics.
+ * @query_cpu_fast:
+ * Fill in target specific information for the "query-cpus-fast"
+ * QAPI call.
* @get_arch_id: Callback for getting architecture-dependent CPU ID.
- * @get_paging_enabled: Callback for inquiring whether paging is enabled.
- * @get_memory_mapping: Callback for obtaining the memory mappings.
* @set_pc: Callback for setting the Program Counter register. This
* should have the semantics used by the target architecture when
* setting the PC from a source such as an ELF file entry point;
@@ -104,59 +118,29 @@ struct TranslationBlock;
* If the target behaviour here is anything other than "set
* the PC register to the value passed in" then the target must
* also implement the synchronize_from_tb hook.
- * @synchronize_from_tb: Callback for synchronizing state from a TCG
- * #TranslationBlock. This is called when we abandon execution
- * of a TB before starting it, and must set all parts of the CPU
- * state which the previous TB in the chain may not have updated.
- * This always includes at least the program counter; some targets
- * will need to do more. If this hook is not implemented then the
- * default is to call @set_pc(tb->pc).
- * @tlb_fill: Callback for handling a softmmu tlb miss or user-only
- * address fault. For system mode, if the access is valid, call
- * tlb_set_page and return true; if the access is invalid, and
- * probe is true, return false; otherwise raise an exception and
- * do not return. For user-only mode, always raise an exception
- * and do not return.
- * @get_phys_page_debug: Callback for obtaining a physical address.
- * @get_phys_page_attrs_debug: Callback for obtaining a physical address and the
- * associated memory transaction attributes to use for the access.
- * CPUs which use memory transaction attributes should implement this
- * instead of get_phys_page_debug.
- * @asidx_from_attrs: Callback to return the CPU AddressSpace to use for
- * a memory access with the specified memory transaction attributes.
+ * @get_pc: Callback for getting the Program Counter register.
+ * As above, with the semantics of the target architecture.
* @gdb_read_register: Callback for letting GDB read a register.
* @gdb_write_register: Callback for letting GDB write a register.
- * @debug_check_watchpoint: Callback: return true if the architectural
- * watchpoint whose address has matched should really fire.
- * @debug_excp_handler: Callback for handling debug exceptions.
- * @write_elf64_note: Callback for writing a CPU-specific ELF note to a
- * 64-bit VM coredump.
- * @write_elf32_qemunote: Callback for writing a CPU- and QEMU-specific ELF
- * note to a 32-bit VM coredump.
- * @write_elf32_note: Callback for writing a CPU-specific ELF note to a
- * 32-bit VM coredump.
- * @write_elf32_qemunote: Callback for writing a CPU- and QEMU-specific ELF
- * note to a 32-bit VM coredump.
- * @vmsd: State description for migration.
- * @gdb_num_core_regs: Number of core registers accessible to GDB.
+ * @gdb_adjust_breakpoint: Callback for adjusting the address of a
+ * breakpoint. Used by AVR to handle a gdb mis-feature with
+ * its Harvard architecture split code and data.
+ * @gdb_num_core_regs: Number of core registers accessible to GDB or 0 to infer
+ * from @gdb_core_xml_file.
* @gdb_core_xml_file: File name for core registers GDB XML description.
* @gdb_stop_before_watchpoint: Indicates whether GDB expects the CPU to stop
* before the insn which triggers a watchpoint rather than after it.
* @gdb_arch_name: Optional callback that returns the architecture name known
* to GDB. The caller must free the returned string with g_free.
- * @gdb_get_dynamic_xml: Callback to return dynamically generated XML for the
- * gdb stub. Returns a pointer to the XML contents for the specified XML file
- * or NULL if the CPU doesn't have a dynamically generated content for it.
- * @cpu_exec_enter: Callback for cpu_exec preparation.
- * @cpu_exec_exit: Callback for cpu_exec cleanup.
- * @cpu_exec_interrupt: Callback for processing interrupts in cpu_exec.
* @disas_set_info: Setup architecture specific components of disassembly info
* @adjust_watchpoint_address: Perform a target-specific adjustment to an
* address before attempting to match it against watchpoints.
+ * @deprecation_note: If this CPUClass is deprecated, this field provides
+ * related information.
*
* Represents a CPU family or model.
*/
-typedef struct CPUClass {
+struct CPUClass {
/*< private >*/
DeviceClass parent_class;
/*< public >*/
@@ -164,65 +148,180 @@ typedef struct CPUClass {
ObjectClass *(*class_by_name)(const char *cpu_model);
void (*parse_features)(const char *typename, char *str, Error **errp);
- int reset_dump_flags;
bool (*has_work)(CPUState *cpu);
- void (*do_interrupt)(CPUState *cpu);
- void (*do_unaligned_access)(CPUState *cpu, vaddr addr,
- MMUAccessType access_type,
- int mmu_idx, uintptr_t retaddr);
- void (*do_transaction_failed)(CPUState *cpu, hwaddr physaddr, vaddr addr,
- unsigned size, MMUAccessType access_type,
- int mmu_idx, MemTxAttrs attrs,
- MemTxResult response, uintptr_t retaddr);
- bool (*virtio_is_big_endian)(CPUState *cpu);
+ int (*mmu_index)(CPUState *cpu, bool ifetch);
int (*memory_rw_debug)(CPUState *cpu, vaddr addr,
uint8_t *buf, int len, bool is_write);
void (*dump_state)(CPUState *cpu, FILE *, int flags);
- GuestPanicInformation* (*get_crash_info)(CPUState *cpu);
- void (*dump_statistics)(CPUState *cpu, int flags);
+ void (*query_cpu_fast)(CPUState *cpu, CpuInfoFast *value);
int64_t (*get_arch_id)(CPUState *cpu);
- bool (*get_paging_enabled)(const CPUState *cpu);
- void (*get_memory_mapping)(CPUState *cpu, MemoryMappingList *list,
- Error **errp);
void (*set_pc)(CPUState *cpu, vaddr value);
- void (*synchronize_from_tb)(CPUState *cpu, struct TranslationBlock *tb);
- bool (*tlb_fill)(CPUState *cpu, vaddr address, int size,
- MMUAccessType access_type, int mmu_idx,
- bool probe, uintptr_t retaddr);
- hwaddr (*get_phys_page_debug)(CPUState *cpu, vaddr addr);
- hwaddr (*get_phys_page_attrs_debug)(CPUState *cpu, vaddr addr,
- MemTxAttrs *attrs);
- int (*asidx_from_attrs)(CPUState *cpu, MemTxAttrs attrs);
+ vaddr (*get_pc)(CPUState *cpu);
int (*gdb_read_register)(CPUState *cpu, GByteArray *buf, int reg);
int (*gdb_write_register)(CPUState *cpu, uint8_t *buf, int reg);
- bool (*debug_check_watchpoint)(CPUState *cpu, CPUWatchpoint *wp);
- void (*debug_excp_handler)(CPUState *cpu);
-
- int (*write_elf64_note)(WriteCoreDumpFunction f, CPUState *cpu,
- int cpuid, void *opaque);
- int (*write_elf64_qemunote)(WriteCoreDumpFunction f, CPUState *cpu,
- void *opaque);
- int (*write_elf32_note)(WriteCoreDumpFunction f, CPUState *cpu,
- int cpuid, void *opaque);
- int (*write_elf32_qemunote)(WriteCoreDumpFunction f, CPUState *cpu,
- void *opaque);
-
- const VMStateDescription *vmsd;
+ vaddr (*gdb_adjust_breakpoint)(CPUState *cpu, vaddr addr);
+
const char *gdb_core_xml_file;
- gchar * (*gdb_arch_name)(CPUState *cpu);
- const char * (*gdb_get_dynamic_xml)(CPUState *cpu, const char *xmlname);
- void (*cpu_exec_enter)(CPUState *cpu);
- void (*cpu_exec_exit)(CPUState *cpu);
- bool (*cpu_exec_interrupt)(CPUState *cpu, int interrupt_request);
+ const gchar * (*gdb_arch_name)(CPUState *cpu);
void (*disas_set_info)(CPUState *cpu, disassemble_info *info);
- vaddr (*adjust_watchpoint_address)(CPUState *cpu, vaddr addr, int len);
- void (*tcg_initialize)(void);
- /* Keep non-pointer data at the end to minimize holes. */
+ const char *deprecation_note;
+ struct AccelCPUClass *accel_cpu;
+
+ /* when system emulation is not available, this pointer is NULL */
+ const struct SysemuCPUOps *sysemu_ops;
+
+ /* when TCG is not available, this pointer is NULL */
+ const TCGCPUOps *tcg_ops;
+
+ /*
+ * if not NULL, this is called in order for the CPUClass to initialize
+ * class data that depends on the accelerator, see accel/accel-common.c.
+ */
+ void (*init_accel_cpu)(struct AccelCPUClass *accel_cpu, CPUClass *cc);
+
+ /*
+ * Keep non-pointer data at the end to minimize holes.
+ */
+ int reset_dump_flags;
int gdb_num_core_regs;
bool gdb_stop_before_watchpoint;
-} CPUClass;
+};
+
+/*
+ * Fix the number of mmu modes to 16, which is also the maximum
+ * supported by the softmmu tlb api.
+ */
+#define NB_MMU_MODES 16
+
+/* Use a fully associative victim tlb of 8 entries. */
+#define CPU_VTLB_SIZE 8
+
+/*
+ * The full TLB entry, which is not accessed by generated TCG code,
+ * so the layout is not as critical as that of CPUTLBEntry. This is
+ * also why we don't want to combine the two structs.
+ */
+typedef struct CPUTLBEntryFull {
+ /*
+ * @xlat_section contains:
+ * - in the lower TARGET_PAGE_BITS, a physical section number
+ * - with the lower TARGET_PAGE_BITS masked off, an offset which
+ * must be added to the virtual address to obtain:
+ * + the ram_addr_t of the target RAM (if the physical section
+ * number is PHYS_SECTION_NOTDIRTY or PHYS_SECTION_ROM)
+ * + the offset within the target MemoryRegion (otherwise)
+ */
+ hwaddr xlat_section;
+
+ /*
+ * @phys_addr contains the physical address in the address space
+ * given by cpu_asidx_from_attrs(cpu, @attrs).
+ */
+ hwaddr phys_addr;
+
+ /* @attrs contains the memory transaction attributes for the page. */
+ MemTxAttrs attrs;
+
+ /* @prot contains the complete protections for the page. */
+ uint8_t prot;
+
+ /* @lg_page_size contains the log2 of the page size. */
+ uint8_t lg_page_size;
+
+ /* Additional tlb flags requested by tlb_fill. */
+ uint8_t tlb_fill_flags;
+
+ /*
+ * Additional tlb flags for use by the slow path. If non-zero,
+ * the corresponding CPUTLBEntry comparator must have TLB_FORCE_SLOW.
+ */
+ uint8_t slow_flags[MMU_ACCESS_COUNT];
+
+ /*
+ * Allow target-specific additions to this structure.
+ * This may be used to cache items from the guest cpu
+ * page tables for later use by the implementation.
+ */
+ union {
+ /*
+ * Cache the attrs and shareability fields from the page table entry.
+ *
+ * For ARMMMUIdx_Stage2*, pte_attrs is the S2 descriptor bits [5:2].
+ * Otherwise, pte_attrs is the same as the MAIR_EL1 8-bit format.
+ * For shareability and guarded, as in the SH and GP fields respectively
+ * of the VMSAv8-64 PTEs.
+ */
+ struct {
+ uint8_t pte_attrs;
+ uint8_t shareability;
+ bool guarded;
+ } arm;
+ } extra;
+} CPUTLBEntryFull;
+
+/*
+ * Data elements that are per MMU mode, minus the bits accessed by
+ * the TCG fast path.
+ */
+typedef struct CPUTLBDesc {
+ /*
+ * Describe a region covering all of the large pages allocated
+ * into the tlb. When any page within this region is flushed,
+ * we must flush the entire tlb. The region is matched if
+ * (addr & large_page_mask) == large_page_addr.
+ */
+ vaddr large_page_addr;
+ vaddr large_page_mask;
+ /* host time (in ns) at the beginning of the time window */
+ int64_t window_begin_ns;
+ /* maximum number of entries observed in the window */
+ size_t window_max_entries;
+ size_t n_used_entries;
+ /* The next index to use in the tlb victim table. */
+ size_t vindex;
+ /* The tlb victim table, in two parts. */
+ CPUTLBEntry vtable[CPU_VTLB_SIZE];
+ CPUTLBEntryFull vfulltlb[CPU_VTLB_SIZE];
+ CPUTLBEntryFull *fulltlb;
+} CPUTLBDesc;
+
+/*
+ * Data elements that are shared between all MMU modes.
+ */
+typedef struct CPUTLBCommon {
+ /* Serialize updates to f.table and d.vtable, and others as noted. */
+ QemuSpin lock;
+ /*
+ * Within dirty, for each bit N, modifications have been made to
+ * mmu_idx N since the last time that mmu_idx was flushed.
+ * Protected by tlb_c.lock.
+ */
+ uint16_t dirty;
+ /*
+ * Statistics. These are not lock protected, but are read and
+ * written atomically. This allows the monitor to print a snapshot
+ * of the stats without interfering with the cpu.
+ */
+ size_t full_flush_count;
+ size_t part_flush_count;
+ size_t elide_flush_count;
+} CPUTLBCommon;
+
+/*
+ * The entire softmmu tlb, for all MMU modes.
+ * The meaning of each of the MMU modes is defined in the target code.
+ * Since this is placed within CPUNegativeOffsetState, the smallest
+ * negative offsets are at the end of the struct.
+ */
+typedef struct CPUTLB {
+#ifdef CONFIG_TCG
+ CPUTLBCommon c;
+ CPUTLBDesc d[NB_MMU_MODES];
+ CPUTLBDescFast f[NB_MMU_MODES];
+#endif
+} CPUTLB;
/*
* Low 16 bits: number of cycles left, used only in icount mode.
@@ -234,7 +333,7 @@ typedef struct CPUClass {
typedef union IcountDecr {
uint32_t u32;
struct {
-#ifdef HOST_WORDS_BIGENDIAN
+#if HOST_BIG_ENDIAN
uint16_t high;
uint16_t low;
#else
@@ -244,6 +343,16 @@ typedef union IcountDecr {
} u16;
} IcountDecr;
+/*
+ * Elements of CPUState most efficiently accessed from CPUArchState,
+ * via small negative offsets.
+ */
+typedef struct CPUNegativeOffsetState {
+ CPUTLB tlb;
+ IcountDecr icount_decr;
+ bool can_do_io;
+} CPUNegativeOffsetState;
+
typedef struct CPUBreakpoint {
vaddr pc;
int flags; /* BP_* */
@@ -259,26 +368,9 @@ struct CPUWatchpoint {
QTAILQ_ENTRY(CPUWatchpoint) entry;
};
-#ifdef CONFIG_PLUGIN
-/*
- * For plugins we sometime need to save the resolved iotlb data before
- * the memory regions get moved around by io_writex.
- */
-typedef struct SavedIOTLB {
- hwaddr addr;
- MemoryRegionSection *section;
- hwaddr mr_offset;
-} SavedIOTLB;
-#endif
-
struct KVMState;
struct kvm_run;
-struct hax_vcpu_state;
-
-#define TB_JMP_CACHE_BITS 12
-#define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS)
-
/* work queue */
/* The union type allows passing of 64 bit target pointers on 32 bit
@@ -302,7 +394,6 @@ typedef void (*run_on_cpu_func)(CPUState *cpu, run_on_cpu_data data);
struct qemu_work_item;
#define CPU_UNSET_NUMA_NODE_ID -1
-#define CPU_TRACE_DSTATE_MAX_EVENTS 32
/**
* CPUState:
@@ -312,8 +403,11 @@ struct qemu_work_item;
* to a cluster this will be UNASSIGNED_CLUSTER_INDEX; otherwise it will
* be the same as the cluster-id property of the CPU object's TYPE_CPU_CLUSTER
* QOM parent.
+ * Under TCG this value is propagated to @tcg_cflags.
+ * See TranslationBlock::TCG CF_CLUSTER_MASK.
+ * @tcg_cflags: Pre-computed cflags for this cpu.
* @nr_cores: Number of cores within this CPU package.
- * @nr_threads: Number of threads within this CPU.
+ * @nr_threads: Number of threads within this CPU core.
* @running: #true if CPU is currently running (lockless).
* @has_waiter: #true if a CPU is currently waiting for the cpu_exec_end;
* valid under cpu_list_lock.
@@ -326,38 +420,42 @@ struct qemu_work_item;
* @crash_occurred: Indicates the OS reported a crash (panic) for this CPU
* @singlestep_enabled: Flags for single-stepping.
* @icount_extra: Instructions until next timer event.
- * @can_do_io: Nonzero if memory-mapped IO is safe. Deterministic execution
- * requires that IO only be performed on the last instruction of a TB
- * so that interrupts take effect immediately.
+ * @neg.can_do_io: True if memory-mapped IO is allowed.
* @cpu_ases: Pointer to array of CPUAddressSpaces (which define the
* AddressSpaces this CPU has)
* @num_ases: number of CPUAddressSpaces in @cpu_ases
* @as: Pointer to the first AddressSpace, for the convenience of targets which
* only have a single AddressSpace
- * @env_ptr: Pointer to subclass-specific CPUArchState field.
- * @icount_decr_ptr: Pointer to IcountDecr field within subclass.
* @gdb_regs: Additional GDB registers.
* @gdb_num_regs: Number of total registers accessible to GDB.
* @gdb_num_g_regs: Number of registers in GDB 'g' packets.
- * @next_cpu: Next CPU sharing TB cache.
+ * @node: QTAILQ of CPUs sharing TB cache.
* @opaque: User data.
* @mem_io_pc: Host Program Counter at which the memory was accessed.
+ * @accel: Pointer to accelerator specific state.
* @kvm_fd: vCPU file descriptor for KVM.
* @work_mutex: Lock to prevent multiple access to @work_list.
* @work_list: List of pending asynchronous work.
- * @trace_dstate_delayed: Delayed changes to trace_dstate (includes all changes
- * to @trace_dstate).
- * @trace_dstate: Dynamic tracing state of events for this vCPU (bitmask).
- * @plugin_mask: Plugin event bitmap. Modified only via async work.
+ * @plugin_mem_cbs: active plugin memory callbacks
+ * @plugin_state: per-CPU plugin state
* @ignore_memory_transaction_failures: Cached copy of the MachineState
* flag of the same name: allows the board to suppress calling of the
* CPU do_transaction_failed hook function.
+ * @kvm_dirty_gfns: Points to the KVM dirty ring for this CPU when KVM dirty
+ * ring is enabled.
+ * @kvm_fetch_index: Keeps the index that we last fetched from the per-vCPU
+ * dirty ring structure.
*
* State of one CPU core or thread.
+ *
+ * Align, in order to match possible alignment required by CPUArchState,
+ * and eliminate a hole between CPUState and CPUArchState within ArchCPU.
*/
struct CPUState {
/*< private >*/
DeviceState parent_obj;
+ /* cache to avoid expensive CPU_GET_CLASS */
+ CPUClass *cc;
/*< public >*/
int nr_cores;
@@ -365,7 +463,7 @@ struct CPUState {
struct QemuThread *thread;
#ifdef _WIN32
- HANDLE hThread;
+ QemuSemaphore sem;
#endif
int thread_id;
bool running, has_waiter;
@@ -374,10 +472,14 @@ struct CPUState {
bool created;
bool stop;
bool stopped;
+
+ /* Should CPU start in powered-off state? */
+ bool start_powered_off;
+
bool unplug;
bool crash_occurred;
bool exit_request;
- bool in_exclusive_context;
+ int exclusive_context_count;
uint32_t cflags_next_tb;
/* updates protected by BQL */
uint32_t interrupt_request;
@@ -395,13 +497,9 @@ struct CPUState {
AddressSpace *as;
MemoryRegion *memory;
- void *env_ptr; /* CPUArchState */
- IcountDecr *icount_decr_ptr;
+ CPUJumpCache *tb_jmp_cache;
- /* Accessed in parallel; all accesses must be atomic */
- struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE];
-
- struct GDBRegisterState *gdb_regs;
+ GArray *gdb_regs;
int gdb_num_regs;
int gdb_num_g_regs;
QTAILQ_ENTRY(CPUState) node;
@@ -419,30 +517,36 @@ struct CPUState {
*/
uintptr_t mem_io_pc;
+ /* Only used in KVM */
int kvm_fd;
struct KVMState *kvm_state;
struct kvm_run *kvm_run;
+ struct kvm_dirty_gfn *kvm_dirty_gfns;
+ uint32_t kvm_fetch_index;
+ uint64_t dirty_pages;
+ int kvm_vcpu_stats_fd;
- /* Used for events with 'vcpu' and *without* the 'disabled' properties */
- DECLARE_BITMAP(trace_dstate_delayed, CPU_TRACE_DSTATE_MAX_EVENTS);
- DECLARE_BITMAP(trace_dstate, CPU_TRACE_DSTATE_MAX_EVENTS);
-
- DECLARE_BITMAP(plugin_mask, QEMU_PLUGIN_EV_MAX);
+ /* Use by accel-block: CPU is executing an ioctl() */
+ QemuLockCnt in_ioctl_lock;
#ifdef CONFIG_PLUGIN
+ /*
+ * The callback pointer stays in the main CPUState as it is
+ * accessed via TCG (see gen_empty_mem_helper).
+ */
GArray *plugin_mem_cbs;
- /* saved iotlb data from io_writex */
- SavedIOTLB saved_iotlb;
+ CPUPluginState *plugin_state;
#endif
/* TODO Move common fields from CPUArchState here. */
int cpu_index;
int cluster_index;
+ uint32_t tcg_cflags;
uint32_t halted;
- uint32_t can_do_io;
int32_t exception_index;
- /* shared by kvm, hax and hvf */
+ AccelCPUState *accel;
+ /* shared by kvm and hvf */
bool vcpu_dirty;
/* Used to keep track of an outstanding cpu throttle thread for migration
@@ -450,36 +554,48 @@ struct CPUState {
*/
bool throttle_thread_scheduled;
- bool ignore_memory_transaction_failures;
+ /*
+ * Sleep throttle_us_per_full microseconds once dirty ring is full
+ * if dirty page rate limit is enabled.
+ */
+ int64_t throttle_us_per_full;
- struct hax_vcpu_state *hax_vcpu;
+ bool ignore_memory_transaction_failures;
- int hvf_fd;
+ /* Used for user-only emulation of prctl(PR_SET_UNALIGN). */
+ bool prctl_unalign_sigbus;
/* track IOMMUs whose translations we've cached in the TCG TLB */
GArray *iommu_notifiers;
+
+ /*
+ * MUST BE LAST in order to minimize the displacement to CPUArchState.
+ */
+ char neg_align[-sizeof(CPUNegativeOffsetState) % 16] QEMU_ALIGNED(16);
+ CPUNegativeOffsetState neg;
};
+/* Validate placement of CPUNegativeOffsetState. */
+QEMU_BUILD_BUG_ON(offsetof(CPUState, neg) !=
+ sizeof(CPUState) - sizeof(CPUNegativeOffsetState));
+
+static inline CPUArchState *cpu_env(CPUState *cpu)
+{
+ /* We validate that CPUArchState follows CPUState in cpu-all.h. */
+ return (CPUArchState *)(cpu + 1);
+}
+
typedef QTAILQ_HEAD(CPUTailQ, CPUState) CPUTailQ;
-extern CPUTailQ cpus;
+extern CPUTailQ cpus_queue;
-#define first_cpu QTAILQ_FIRST_RCU(&cpus)
+#define first_cpu QTAILQ_FIRST_RCU(&cpus_queue)
#define CPU_NEXT(cpu) QTAILQ_NEXT_RCU(cpu, node)
-#define CPU_FOREACH(cpu) QTAILQ_FOREACH_RCU(cpu, &cpus, node)
+#define CPU_FOREACH(cpu) QTAILQ_FOREACH_RCU(cpu, &cpus_queue, node)
#define CPU_FOREACH_SAFE(cpu, next_cpu) \
- QTAILQ_FOREACH_SAFE_RCU(cpu, &cpus, node, next_cpu)
+ QTAILQ_FOREACH_SAFE_RCU(cpu, &cpus_queue, node, next_cpu)
extern __thread CPUState *current_cpu;
-static inline void cpu_tb_jmp_cache_clear(CPUState *cpu)
-{
- unsigned int i;
-
- for (i = 0; i < TB_JMP_CACHE_SIZE; i++) {
- atomic_set(&cpu->tb_jmp_cache[i], NULL);
- }
-}
-
/**
* qemu_tcg_mttcg_enabled:
* Check whether we are running MultiThread TCG or not.
@@ -502,8 +618,10 @@ bool cpu_paging_enabled(const CPUState *cpu);
* @cpu: The CPU whose memory mappings are to be obtained.
* @list: Where to write the memory mappings to.
* @errp: Pointer for reporting an #Error.
+ *
+ * Returns: %true on success, %false otherwise.
*/
-void cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list,
+bool cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list,
Error **errp);
#if !defined(CONFIG_USER_ONLY)
@@ -564,11 +682,13 @@ GuestPanicInformation *cpu_get_crash_info(CPUState *cpu);
* @CPU_DUMP_CODE:
* @CPU_DUMP_FPU: dump FPU register state, not just integer
* @CPU_DUMP_CCOP: dump info about TCG QEMU's condition code optimization state
+ * @CPU_DUMP_VPU: dump VPU registers
*/
enum CPUDumpFlags {
CPU_DUMP_CODE = 0x00010000,
CPU_DUMP_FPU = 0x00020000,
CPU_DUMP_CCOP = 0x00040000,
+ CPU_DUMP_VPU = 0x00080000,
};
/**
@@ -580,16 +700,6 @@ enum CPUDumpFlags {
*/
void cpu_dump_state(CPUState *cpu, FILE *f, int flags);
-/**
- * cpu_dump_statistics:
- * @cpu: The CPU whose state is to be dumped.
- * @flags: Flags what to dump.
- *
- * Dump CPU statistics to the current monitor if we have one, else to
- * stdout.
- */
-void cpu_dump_statistics(CPUState *cpu, int flags);
-
#ifndef CONFIG_USER_ONLY
/**
* cpu_get_phys_page_attrs_debug:
@@ -604,18 +714,8 @@ void cpu_dump_statistics(CPUState *cpu, int flags);
*
* Returns: Corresponding physical page address or -1 if no page found.
*/
-static inline hwaddr cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr,
- MemTxAttrs *attrs)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
-
- if (cc->get_phys_page_attrs_debug) {
- return cc->get_phys_page_attrs_debug(cpu, addr, attrs);
- }
- /* Fallback for CPUs which don't implement the _attrs_ hook */
- *attrs = MEMTXATTRS_UNSPECIFIED;
- return cc->get_phys_page_debug(cpu, addr);
-}
+hwaddr cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr,
+ MemTxAttrs *attrs);
/**
* cpu_get_phys_page_debug:
@@ -627,12 +727,7 @@ static inline hwaddr cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr,
*
* Returns: Corresponding physical page address or -1 if no page found.
*/
-static inline hwaddr cpu_get_phys_page_debug(CPUState *cpu, vaddr addr)
-{
- MemTxAttrs attrs = {};
-
- return cpu_get_phys_page_attrs_debug(cpu, addr, &attrs);
-}
+hwaddr cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
/** cpu_asidx_from_attrs:
* @cpu: CPU
@@ -641,17 +736,16 @@ static inline hwaddr cpu_get_phys_page_debug(CPUState *cpu, vaddr addr)
* Returns the address space index specifying the CPU AddressSpace
* to use for a memory access with the given transaction attributes.
*/
-static inline int cpu_asidx_from_attrs(CPUState *cpu, MemTxAttrs attrs)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
- int ret = 0;
+int cpu_asidx_from_attrs(CPUState *cpu, MemTxAttrs attrs);
- if (cc->asidx_from_attrs) {
- ret = cc->asidx_from_attrs(cpu, attrs);
- assert(ret < cpu->num_ases && ret >= 0);
- }
- return ret;
-}
+/**
+ * cpu_virtio_is_big_endian:
+ * @cpu: CPU
+
+ * Returns %true if a CPU which supports runtime configurable endianness
+ * is currently big-endian.
+ */
+bool cpu_virtio_is_big_endian(CPUState *cpu);
#endif /* CONFIG_USER_ONLY */
@@ -678,13 +772,27 @@ void cpu_reset(CPUState *cpu);
* @typename: The CPU base type.
* @cpu_model: The model string without any parameters.
*
- * Looks up a CPU #ObjectClass matching name @cpu_model.
+ * Looks up a concrete CPU #ObjectClass matching name @cpu_model.
*
- * Returns: A #CPUClass or %NULL if not matching class is found.
+ * Returns: A concrete #CPUClass or %NULL if no matching class is found
+ * or if the matching class is abstract.
*/
ObjectClass *cpu_class_by_name(const char *typename, const char *cpu_model);
/**
+ * cpu_model_from_type:
+ * @typename: The CPU type name
+ *
+ * Extract the CPU model name from the CPU type name. The
+ * CPU type name is either the combination of the CPU model
+ * name and suffix, or same to the CPU model name.
+ *
+ * Returns: CPU model name or NULL if the CPU class doesn't exist
+ * The user should g_free() the string once no longer needed.
+ */
+char *cpu_model_from_type(const char *typename);
+
+/**
* cpu_create:
* @typename: The CPU type.
*
@@ -805,7 +913,7 @@ void async_safe_run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data
*/
static inline bool cpu_in_exclusive_context(const CPUState *cpu)
{
- return cpu->in_exclusive_context;
+ return cpu->exclusive_context_count;
}
/**
@@ -838,12 +946,6 @@ bool cpu_exists(int64_t id);
*/
CPUState *cpu_by_arch_id(int64_t id);
-#ifndef CONFIG_USER_ONLY
-
-typedef void (*CPUInterruptHandler)(CPUState *, int);
-
-extern CPUInterruptHandler cpu_interrupt_handler;
-
/**
* cpu_interrupt:
* @cpu: The CPU to set an interrupt on.
@@ -851,47 +953,9 @@ extern CPUInterruptHandler cpu_interrupt_handler;
*
* Invokes the interrupt handler.
*/
-static inline void cpu_interrupt(CPUState *cpu, int mask)
-{
- cpu_interrupt_handler(cpu, mask);
-}
-
-#else /* USER_ONLY */
void cpu_interrupt(CPUState *cpu, int mask);
-#endif /* USER_ONLY */
-
-#ifdef NEED_CPU_H
-
-#ifdef CONFIG_SOFTMMU
-static inline void cpu_unaligned_access(CPUState *cpu, vaddr addr,
- MMUAccessType access_type,
- int mmu_idx, uintptr_t retaddr)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
-
- cc->do_unaligned_access(cpu, addr, access_type, mmu_idx, retaddr);
-}
-
-static inline void cpu_transaction_failed(CPUState *cpu, hwaddr physaddr,
- vaddr addr, unsigned size,
- MMUAccessType access_type,
- int mmu_idx, MemTxAttrs attrs,
- MemTxResult response,
- uintptr_t retaddr)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
-
- if (!cpu->ignore_memory_transaction_failures && cc->do_transaction_failed) {
- cc->do_transaction_failed(cpu, physaddr, addr, size, access_type,
- mmu_idx, attrs, response, retaddr);
- }
-}
-#endif
-
-#endif /* NEED_CPU_H */
-
/**
* cpu_set_pc:
* @cpu: The CPU to set the program counter for.
@@ -932,14 +996,6 @@ void cpu_exit(CPUState *cpu);
void cpu_resume(CPUState *cpu);
/**
- * cpu_remove:
- * @cpu: The CPU to remove.
- *
- * Requests the CPU to be removed.
- */
-void cpu_remove(CPUState *cpu);
-
- /**
* cpu_remove_sync:
* @cpu: The CPU to remove.
*
@@ -1020,9 +1076,10 @@ void cpu_single_step(CPUState *cpu, int enabled);
#define BP_GDB 0x10
#define BP_CPU 0x20
#define BP_ANY (BP_GDB | BP_CPU)
-#define BP_WATCHPOINT_HIT_READ 0x40
-#define BP_WATCHPOINT_HIT_WRITE 0x80
-#define BP_WATCHPOINT_HIT (BP_WATCHPOINT_HIT_READ | BP_WATCHPOINT_HIT_WRITE)
+#define BP_HIT_SHIFT 6
+#define BP_WATCHPOINT_HIT_READ (BP_MEM_READ << BP_HIT_SHIFT)
+#define BP_WATCHPOINT_HIT_WRITE (BP_MEM_WRITE << BP_HIT_SHIFT)
+#define BP_WATCHPOINT_HIT (BP_MEM_ACCESS << BP_HIT_SHIFT)
int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags,
CPUBreakpoint **breakpoint);
@@ -1045,7 +1102,7 @@ static inline bool cpu_breakpoint_test(CPUState *cpu, vaddr pc, int mask)
return false;
}
-#ifdef CONFIG_USER_ONLY
+#if defined(CONFIG_USER_ONLY)
static inline int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len,
int flags, CPUWatchpoint **watchpoint)
{
@@ -1066,17 +1123,6 @@ static inline void cpu_watchpoint_remove_by_ref(CPUState *cpu,
static inline void cpu_watchpoint_remove_all(CPUState *cpu, int mask)
{
}
-
-static inline void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len,
- MemTxAttrs atr, int fl, uintptr_t ra)
-{
-}
-
-static inline int cpu_watchpoint_address_matches(CPUState *cpu,
- vaddr addr, vaddr len)
-{
- return 0;
-}
#else
int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len,
int flags, CPUWatchpoint **watchpoint);
@@ -1084,33 +1130,24 @@ int cpu_watchpoint_remove(CPUState *cpu, vaddr addr,
vaddr len, int flags);
void cpu_watchpoint_remove_by_ref(CPUState *cpu, CPUWatchpoint *watchpoint);
void cpu_watchpoint_remove_all(CPUState *cpu, int mask);
+#endif
/**
- * cpu_check_watchpoint:
- * @cpu: cpu context
- * @addr: guest virtual address
- * @len: access length
- * @attrs: memory access attributes
- * @flags: watchpoint access type
- * @ra: unwind return address
- *
- * Check for a watchpoint hit in [addr, addr+len) of the type
- * specified by @flags. Exit via exception with a hit.
- */
-void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len,
- MemTxAttrs attrs, int flags, uintptr_t ra);
-
-/**
- * cpu_watchpoint_address_matches:
- * @cpu: cpu context
- * @addr: guest virtual address
- * @len: access length
+ * cpu_plugin_mem_cbs_enabled() - are plugin memory callbacks enabled?
+ * @cs: CPUState pointer
*
- * Return the watchpoint flags that apply to [addr, addr+len).
- * If no watchpoint is registered for the range, the result is 0.
+ * The memory callbacks are installed if a plugin has instrumented an
+ * instruction for memory. This can be useful to know if you want to
+ * force a slow path for a series of memory accesses.
*/
-int cpu_watchpoint_address_matches(CPUState *cpu, vaddr addr, vaddr len);
+static inline bool cpu_plugin_mem_cbs_enabled(const CPUState *cpu)
+{
+#ifdef CONFIG_PLUGIN
+ return !!cpu->plugin_mem_cbs;
+#else
+ return false;
#endif
+}
/**
* cpu_get_address_space:
@@ -1122,31 +1159,34 @@ int cpu_watchpoint_address_matches(CPUState *cpu, vaddr addr, vaddr len);
*/
AddressSpace *cpu_get_address_space(CPUState *cpu, int asidx);
-void QEMU_NORETURN cpu_abort(CPUState *cpu, const char *fmt, ...)
- GCC_FMT_ATTR(2, 3);
-extern Property cpu_common_props[];
+G_NORETURN void cpu_abort(CPUState *cpu, const char *fmt, ...)
+ G_GNUC_PRINTF(2, 3);
+
+/* $(top_srcdir)/cpu.c */
+void cpu_class_init_props(DeviceClass *dc);
void cpu_exec_initfn(CPUState *cpu);
-void cpu_exec_realizefn(CPUState *cpu, Error **errp);
+bool cpu_exec_realizefn(CPUState *cpu, Error **errp);
void cpu_exec_unrealizefn(CPUState *cpu);
+void cpu_exec_reset_hold(CPUState *cpu);
/**
* target_words_bigendian:
* Returns true if the (default) endianness of the target is big endian,
* false otherwise. Note that in target-specific code, you can use
- * TARGET_WORDS_BIGENDIAN directly instead. On the other hand, common
+ * TARGET_BIG_ENDIAN directly instead. On the other hand, common
* code should normally never need to know about the endianness of the
* target, so please do *not* use this function unless you know very well
* what you are doing!
*/
bool target_words_bigendian(void);
+const char *target_name(void);
+
#ifdef NEED_CPU_H
-#ifdef CONFIG_SOFTMMU
+#ifndef CONFIG_USER_ONLY
+
extern const VMStateDescription vmstate_cpu_common;
-#else
-#define vmstate_cpu_common vmstate_dummy
-#endif
#define VMSTATE_CPU() { \
.name = "parent_obj", \
@@ -1155,6 +1195,7 @@ extern const VMStateDescription vmstate_cpu_common;
.flags = VMS_STRUCT, \
.offset = 0, \
}
+#endif /* !CONFIG_USER_ONLY */
#endif /* NEED_CPU_H */
diff --git a/include/hw/core/generic-loader.h b/include/hw/core/generic-loader.h
index 9ffce1c5a3..19d87b39c8 100644
--- a/include/hw/core/generic-loader.h
+++ b/include/hw/core/generic-loader.h
@@ -20,8 +20,9 @@
#include "elf.h"
#include "hw/qdev-core.h"
+#include "qom/object.h"
-typedef struct GenericLoaderState {
+struct GenericLoaderState {
/* <private> */
DeviceState parent_obj;
@@ -38,10 +39,9 @@ typedef struct GenericLoaderState {
bool force_raw;
bool data_be;
bool set_pc;
-} GenericLoaderState;
+};
#define TYPE_GENERIC_LOADER "loader"
-#define GENERIC_LOADER(obj) OBJECT_CHECK(GenericLoaderState, (obj), \
- TYPE_GENERIC_LOADER)
+OBJECT_DECLARE_SIMPLE_TYPE(GenericLoaderState, GENERIC_LOADER)
#endif
diff --git a/include/hw/core/resetcontainer.h b/include/hw/core/resetcontainer.h
new file mode 100644
index 0000000000..23db0c7a88
--- /dev/null
+++ b/include/hw/core/resetcontainer.h
@@ -0,0 +1,48 @@
+/*
+ * Reset container
+ *
+ * Copyright (c) 2024 Linaro, Ltd
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef HW_RESETCONTAINER_H
+#define HW_RESETCONTAINER_H
+
+/*
+ * The "reset container" is an object which implements the Resettable
+ * interface. It contains a list of arbitrary other objects which also
+ * implement Resettable. Resetting the reset container resets all the
+ * objects in it.
+ */
+
+#include "qom/object.h"
+
+#define TYPE_RESETTABLE_CONTAINER "resettable-container"
+OBJECT_DECLARE_TYPE(ResettableContainer, ResettableContainerClass, RESETTABLE_CONTAINER)
+
+/**
+ * resettable_container_add: Add a resettable object to the container
+ * @rc: container
+ * @obj: object to add to the container
+ *
+ * Add @obj to the ResettableContainer @rc. @obj must implement the
+ * Resettable interface.
+ *
+ * When @rc is reset, it will reset every object that has been added
+ * to it, in the order they were added.
+ */
+void resettable_container_add(ResettableContainer *rc, Object *obj);
+
+/**
+ * resettable_container_remove: Remove an object from the container
+ * @rc: container
+ * @obj: object to remove from the container
+ *
+ * Remove @obj from the ResettableContainer @rc. @obj must have been
+ * previously added to this container.
+ */
+void resettable_container_remove(ResettableContainer *rc, Object *obj);
+
+#endif
diff --git a/include/hw/core/split-irq.h b/include/hw/core/split-irq.h
index 872a39aa4f..ff8852f407 100644
--- a/include/hw/core/split-irq.h
+++ b/include/hw/core/split-irq.h
@@ -42,9 +42,8 @@
#define MAX_SPLIT_LINES 16
-typedef struct SplitIRQ SplitIRQ;
-#define SPLIT_IRQ(obj) OBJECT_CHECK(SplitIRQ, (obj), TYPE_SPLIT_IRQ)
+OBJECT_DECLARE_SIMPLE_TYPE(SplitIRQ, SPLIT_IRQ)
struct SplitIRQ {
DeviceState parent_obj;
diff --git a/include/hw/arm/sysbus-fdt.h b/include/hw/core/sysbus-fdt.h
index 340c382cdd..340c382cdd 100644
--- a/include/hw/arm/sysbus-fdt.h
+++ b/include/hw/core/sysbus-fdt.h
diff --git a/include/hw/core/sysemu-cpu-ops.h b/include/hw/core/sysemu-cpu-ops.h
new file mode 100644
index 0000000000..24d003fe04
--- /dev/null
+++ b/include/hw/core/sysemu-cpu-ops.h
@@ -0,0 +1,92 @@
+/*
+ * CPU operations specific to system emulation
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef SYSEMU_CPU_OPS_H
+#define SYSEMU_CPU_OPS_H
+
+#include "hw/core/cpu.h"
+
+/*
+ * struct SysemuCPUOps: System operations specific to a CPU class
+ */
+typedef struct SysemuCPUOps {
+ /**
+ * @get_memory_mapping: Callback for obtaining the memory mappings.
+ */
+ bool (*get_memory_mapping)(CPUState *cpu, MemoryMappingList *list,
+ Error **errp);
+ /**
+ * @get_paging_enabled: Callback for inquiring whether paging is enabled.
+ */
+ bool (*get_paging_enabled)(const CPUState *cpu);
+ /**
+ * @get_phys_page_debug: Callback for obtaining a physical address.
+ */
+ hwaddr (*get_phys_page_debug)(CPUState *cpu, vaddr addr);
+ /**
+ * @get_phys_page_attrs_debug: Callback for obtaining a physical address
+ * and the associated memory transaction attributes to use for the
+ * access.
+ * CPUs which use memory transaction attributes should implement this
+ * instead of get_phys_page_debug.
+ */
+ hwaddr (*get_phys_page_attrs_debug)(CPUState *cpu, vaddr addr,
+ MemTxAttrs *attrs);
+ /**
+ * @asidx_from_attrs: Callback to return the CPU AddressSpace to use for
+ * a memory access with the specified memory transaction attributes.
+ */
+ int (*asidx_from_attrs)(CPUState *cpu, MemTxAttrs attrs);
+ /**
+ * @get_crash_info: Callback for reporting guest crash information in
+ * GUEST_PANICKED events.
+ */
+ GuestPanicInformation* (*get_crash_info)(CPUState *cpu);
+ /**
+ * @write_elf32_note: Callback for writing a CPU-specific ELF note to a
+ * 32-bit VM coredump.
+ */
+ int (*write_elf32_note)(WriteCoreDumpFunction f, CPUState *cpu,
+ int cpuid, DumpState *s);
+ /**
+ * @write_elf64_note: Callback for writing a CPU-specific ELF note to a
+ * 64-bit VM coredump.
+ */
+ int (*write_elf64_note)(WriteCoreDumpFunction f, CPUState *cpu,
+ int cpuid, DumpState *s);
+ /**
+ * @write_elf32_qemunote: Callback for writing a CPU- and QEMU-specific ELF
+ * note to a 32-bit VM coredump.
+ */
+ int (*write_elf32_qemunote)(WriteCoreDumpFunction f, CPUState *cpu,
+ DumpState *s);
+ /**
+ * @write_elf64_qemunote: Callback for writing a CPU- and QEMU-specific ELF
+ * note to a 64-bit VM coredump.
+ */
+ int (*write_elf64_qemunote)(WriteCoreDumpFunction f, CPUState *cpu,
+ DumpState *s);
+ /**
+ * @virtio_is_big_endian: Callback to return %true if a CPU which supports
+ * runtime configurable endianness is currently big-endian.
+ * Non-configurable CPUs can use the default implementation of this method.
+ * This method should not be used by any callers other than the pre-1.0
+ * virtio devices.
+ */
+ bool (*virtio_is_big_endian)(CPUState *cpu);
+
+ /**
+ * @legacy_vmsd: Legacy state for migration.
+ * Do not use in new targets, use #DeviceClass::vmsd instead.
+ */
+ const VMStateDescription *legacy_vmsd;
+
+} SysemuCPUOps;
+
+#endif /* SYSEMU_CPU_OPS_H */
diff --git a/include/hw/core/tcg-cpu-ops.h b/include/hw/core/tcg-cpu-ops.h
new file mode 100644
index 0000000000..bf8ff8e3ee
--- /dev/null
+++ b/include/hw/core/tcg-cpu-ops.h
@@ -0,0 +1,224 @@
+/*
+ * TCG CPU-specific operations
+ *
+ * Copyright 2021 SUSE LLC
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef TCG_CPU_OPS_H
+#define TCG_CPU_OPS_H
+
+#include "hw/core/cpu.h"
+
+struct TCGCPUOps {
+ /**
+ * @initialize: Initialize TCG state
+ *
+ * Called when the first CPU is realized.
+ */
+ void (*initialize)(void);
+ /**
+ * @synchronize_from_tb: Synchronize state from a TCG #TranslationBlock
+ *
+ * This is called when we abandon execution of a TB before starting it,
+ * and must set all parts of the CPU state which the previous TB in the
+ * chain may not have updated.
+ * By default, when this is NULL, a call is made to @set_pc(tb->pc).
+ *
+ * If more state needs to be restored, the target must implement a
+ * function to restore all the state, and register it here.
+ */
+ void (*synchronize_from_tb)(CPUState *cpu, const TranslationBlock *tb);
+ /**
+ * @restore_state_to_opc: Synchronize state from INDEX_op_start_insn
+ *
+ * This is called when we unwind state in the middle of a TB,
+ * usually before raising an exception. Set all part of the CPU
+ * state which are tracked insn-by-insn in the target-specific
+ * arguments to start_insn, passed as @data.
+ */
+ void (*restore_state_to_opc)(CPUState *cpu, const TranslationBlock *tb,
+ const uint64_t *data);
+
+ /** @cpu_exec_enter: Callback for cpu_exec preparation */
+ void (*cpu_exec_enter)(CPUState *cpu);
+ /** @cpu_exec_exit: Callback for cpu_exec cleanup */
+ void (*cpu_exec_exit)(CPUState *cpu);
+ /** @debug_excp_handler: Callback for handling debug exceptions */
+ void (*debug_excp_handler)(CPUState *cpu);
+
+#ifdef NEED_CPU_H
+#ifdef CONFIG_USER_ONLY
+ /**
+ * @fake_user_interrupt: Callback for 'fake exception' handling.
+ *
+ * Simulate 'fake exception' which will be handled outside the
+ * cpu execution loop (hack for x86 user mode).
+ */
+ void (*fake_user_interrupt)(CPUState *cpu);
+
+ /**
+ * record_sigsegv:
+ * @cpu: cpu context
+ * @addr: faulting guest address
+ * @access_type: access was read/write/execute
+ * @maperr: true for invalid page, false for permission fault
+ * @ra: host pc for unwinding
+ *
+ * We are about to raise SIGSEGV with si_code set for @maperr,
+ * and si_addr set for @addr. Record anything further needed
+ * for the signal ucontext_t.
+ *
+ * If the emulated kernel does not provide anything to the signal
+ * handler with anything besides the user context registers, and
+ * the siginfo_t, then this hook need do nothing and may be omitted.
+ * Otherwise, record the data and return; the caller will raise
+ * the signal, unwind the cpu state, and return to the main loop.
+ *
+ * If it is simpler to re-use the sysemu tlb_fill code, @ra is provided
+ * so that a "normal" cpu exception can be raised. In this case,
+ * the signal must be raised by the architecture cpu_loop.
+ */
+ void (*record_sigsegv)(CPUState *cpu, vaddr addr,
+ MMUAccessType access_type,
+ bool maperr, uintptr_t ra);
+ /**
+ * record_sigbus:
+ * @cpu: cpu context
+ * @addr: misaligned guest address
+ * @access_type: access was read/write/execute
+ * @ra: host pc for unwinding
+ *
+ * We are about to raise SIGBUS with si_code BUS_ADRALN,
+ * and si_addr set for @addr. Record anything further needed
+ * for the signal ucontext_t.
+ *
+ * If the emulated kernel does not provide the signal handler with
+ * anything besides the user context registers, and the siginfo_t,
+ * then this hook need do nothing and may be omitted.
+ * Otherwise, record the data and return; the caller will raise
+ * the signal, unwind the cpu state, and return to the main loop.
+ *
+ * If it is simpler to re-use the sysemu do_unaligned_access code,
+ * @ra is provided so that a "normal" cpu exception can be raised.
+ * In this case, the signal must be raised by the architecture cpu_loop.
+ */
+ void (*record_sigbus)(CPUState *cpu, vaddr addr,
+ MMUAccessType access_type, uintptr_t ra);
+#else
+ /** @do_interrupt: Callback for interrupt handling. */
+ void (*do_interrupt)(CPUState *cpu);
+ /** @cpu_exec_interrupt: Callback for processing interrupts in cpu_exec */
+ bool (*cpu_exec_interrupt)(CPUState *cpu, int interrupt_request);
+ /** @cpu_exec_halt: Callback for handling halt in cpu_exec */
+ void (*cpu_exec_halt)(CPUState *cpu);
+ /**
+ * @tlb_fill: Handle a softmmu tlb miss
+ *
+ * If the access is valid, call tlb_set_page and return true;
+ * if the access is invalid and probe is true, return false;
+ * otherwise raise an exception and do not return.
+ */
+ bool (*tlb_fill)(CPUState *cpu, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr);
+ /**
+ * @do_transaction_failed: Callback for handling failed memory transactions
+ * (ie bus faults or external aborts; not MMU faults)
+ */
+ void (*do_transaction_failed)(CPUState *cpu, hwaddr physaddr, vaddr addr,
+ unsigned size, MMUAccessType access_type,
+ int mmu_idx, MemTxAttrs attrs,
+ MemTxResult response, uintptr_t retaddr);
+ /**
+ * @do_unaligned_access: Callback for unaligned access handling
+ * The callback must exit via raising an exception.
+ */
+ G_NORETURN void (*do_unaligned_access)(CPUState *cpu, vaddr addr,
+ MMUAccessType access_type,
+ int mmu_idx, uintptr_t retaddr);
+
+ /**
+ * @adjust_watchpoint_address: hack for cpu_check_watchpoint used by ARM
+ */
+ vaddr (*adjust_watchpoint_address)(CPUState *cpu, vaddr addr, int len);
+
+ /**
+ * @debug_check_watchpoint: return true if the architectural
+ * watchpoint whose address has matched should really fire, used by ARM
+ * and RISC-V
+ */
+ bool (*debug_check_watchpoint)(CPUState *cpu, CPUWatchpoint *wp);
+
+ /**
+ * @debug_check_breakpoint: return true if the architectural
+ * breakpoint whose PC has matched should really fire.
+ */
+ bool (*debug_check_breakpoint)(CPUState *cpu);
+
+ /**
+ * @io_recompile_replay_branch: Callback for cpu_io_recompile.
+ *
+ * The cpu has been stopped, and cpu_restore_state_from_tb has been
+ * called. If the faulting instruction is in a delay slot, and the
+ * target architecture requires re-execution of the branch, then
+ * adjust the cpu state as required and return true.
+ */
+ bool (*io_recompile_replay_branch)(CPUState *cpu,
+ const TranslationBlock *tb);
+ /**
+ * @need_replay_interrupt: Return %true if @interrupt_request
+ * needs to be recorded for replay purposes.
+ */
+ bool (*need_replay_interrupt)(int interrupt_request);
+#endif /* !CONFIG_USER_ONLY */
+#endif /* NEED_CPU_H */
+
+};
+
+#if defined(CONFIG_USER_ONLY)
+
+static inline void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len,
+ MemTxAttrs atr, int fl, uintptr_t ra)
+{
+}
+
+static inline int cpu_watchpoint_address_matches(CPUState *cpu,
+ vaddr addr, vaddr len)
+{
+ return 0;
+}
+
+#else
+
+/**
+ * cpu_check_watchpoint:
+ * @cpu: cpu context
+ * @addr: guest virtual address
+ * @len: access length
+ * @attrs: memory access attributes
+ * @flags: watchpoint access type
+ * @ra: unwind return address
+ *
+ * Check for a watchpoint hit in [addr, addr+len) of the type
+ * specified by @flags. Exit via exception with a hit.
+ */
+void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len,
+ MemTxAttrs attrs, int flags, uintptr_t ra);
+
+/**
+ * cpu_watchpoint_address_matches:
+ * @cpu: cpu context
+ * @addr: guest virtual address
+ * @len: access length
+ *
+ * Return the watchpoint flags that apply to [addr, addr+len).
+ * If no watchpoint is registered for the range, the result is 0.
+ */
+int cpu_watchpoint_address_matches(CPUState *cpu, vaddr addr, vaddr len);
+
+#endif
+
+#endif /* TCG_CPU_OPS_H */
diff --git a/include/hw/cpu/a15mpcore.h b/include/hw/cpu/a15mpcore.h
index b423533d20..75d39e5458 100644
--- a/include/hw/cpu/a15mpcore.h
+++ b/include/hw/cpu/a15mpcore.h
@@ -22,14 +22,14 @@
#include "hw/sysbus.h"
#include "hw/intc/arm_gic.h"
+#include "qom/object.h"
/* A15MP private memory region. */
#define TYPE_A15MPCORE_PRIV "a15mpcore_priv"
-#define A15MPCORE_PRIV(obj) \
- OBJECT_CHECK(A15MPPrivState, (obj), TYPE_A15MPCORE_PRIV)
+OBJECT_DECLARE_SIMPLE_TYPE(A15MPPrivState, A15MPCORE_PRIV)
-typedef struct A15MPPrivState {
+struct A15MPPrivState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -39,6 +39,6 @@ typedef struct A15MPPrivState {
MemoryRegion container;
GICState gic;
-} A15MPPrivState;
+};
#endif
diff --git a/include/hw/cpu/a9mpcore.h b/include/hw/cpu/a9mpcore.h
index 5d67ca22c4..e0396ab6af 100644
--- a/include/hw/cpu/a9mpcore.h
+++ b/include/hw/cpu/a9mpcore.h
@@ -15,12 +15,12 @@
#include "hw/misc/a9scu.h"
#include "hw/timer/arm_mptimer.h"
#include "hw/timer/a9gtimer.h"
+#include "qom/object.h"
#define TYPE_A9MPCORE_PRIV "a9mpcore_priv"
-#define A9MPCORE_PRIV(obj) \
- OBJECT_CHECK(A9MPPrivState, (obj), TYPE_A9MPCORE_PRIV)
+OBJECT_DECLARE_SIMPLE_TYPE(A9MPPrivState, A9MPCORE_PRIV)
-typedef struct A9MPPrivState {
+struct A9MPPrivState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -34,6 +34,6 @@ typedef struct A9MPPrivState {
A9GTimerState gtimer;
ARMMPTimerState mptimer;
ARMMPTimerState wdt;
-} A9MPPrivState;
+};
#endif
diff --git a/include/hw/cpu/arm11mpcore.h b/include/hw/cpu/arm11mpcore.h
index 6196109ca2..2cac8c1232 100644
--- a/include/hw/cpu/arm11mpcore.h
+++ b/include/hw/cpu/arm11mpcore.h
@@ -14,12 +14,12 @@
#include "hw/misc/arm11scu.h"
#include "hw/intc/arm_gic.h"
#include "hw/timer/arm_mptimer.h"
+#include "qom/object.h"
#define TYPE_ARM11MPCORE_PRIV "arm11mpcore_priv"
-#define ARM11MPCORE_PRIV(obj) \
- OBJECT_CHECK(ARM11MPCorePriveState, (obj), TYPE_ARM11MPCORE_PRIV)
+OBJECT_DECLARE_SIMPLE_TYPE(ARM11MPCorePriveState, ARM11MPCORE_PRIV)
-typedef struct ARM11MPCorePriveState {
+struct ARM11MPCorePriveState {
SysBusDevice parent_obj;
uint32_t num_cpu;
@@ -30,6 +30,6 @@ typedef struct ARM11MPCorePriveState {
GICState gic;
ARMMPTimerState mptimer;
ARMMPTimerState wdtimer;
-} ARM11MPCorePriveState;
+};
#endif
diff --git a/include/hw/cpu/cluster.h b/include/hw/cpu/cluster.h
index a616501a55..53fbf36af5 100644
--- a/include/hw/cpu/cluster.h
+++ b/include/hw/cpu/cluster.h
@@ -21,6 +21,7 @@
#define HW_CPU_CLUSTER_H
#include "hw/qdev-core.h"
+#include "qom/object.h"
/*
* CPU Cluster type
@@ -54,8 +55,7 @@
*/
#define TYPE_CPU_CLUSTER "cpu-cluster"
-#define CPU_CLUSTER(obj) \
- OBJECT_CHECK(CPUClusterState, (obj), TYPE_CPU_CLUSTER)
+OBJECT_DECLARE_SIMPLE_TYPE(CPUClusterState, CPU_CLUSTER)
/*
* This limit is imposed by TCG, which puts the cluster ID into an
@@ -70,12 +70,12 @@
*
* State of a CPU cluster.
*/
-typedef struct CPUClusterState {
+struct CPUClusterState {
/*< private >*/
DeviceState parent_obj;
/*< public >*/
uint32_t cluster_id;
-} CPUClusterState;
+};
#endif
diff --git a/include/hw/cpu/core.h b/include/hw/cpu/core.h
index 555ad831bb..98ab91647e 100644
--- a/include/hw/cpu/core.h
+++ b/include/hw/cpu/core.h
@@ -10,20 +10,20 @@
#define HW_CPU_CORE_H
#include "hw/qdev-core.h"
+#include "qom/object.h"
#define TYPE_CPU_CORE "cpu-core"
-#define CPU_CORE(obj) \
- OBJECT_CHECK(CPUCore, (obj), TYPE_CPU_CORE)
+OBJECT_DECLARE_SIMPLE_TYPE(CPUCore, CPU_CORE)
-typedef struct CPUCore {
+struct CPUCore {
/*< private >*/
DeviceState parent_obj;
/*< public >*/
int core_id;
int nr_threads;
-} CPUCore;
+};
/* Note: topology field names need to be kept in sync with
* 'CpuInstanceProperties' */
diff --git a/include/hw/cris/etraxfs.h b/include/hw/cris/etraxfs.h
index 9e99380e0c..012c4e9974 100644
--- a/include/hw/cris/etraxfs.h
+++ b/include/hw/cris/etraxfs.h
@@ -29,8 +29,9 @@
#include "hw/cris/etraxfs_dma.h"
#include "hw/qdev-properties.h"
#include "hw/sysbus.h"
+#include "qapi/error.h"
-DeviceState *etraxfs_eth_init(NICInfo *nd, hwaddr base, int phyaddr,
+DeviceState *etraxfs_eth_init(hwaddr base, int phyaddr,
struct etraxfs_dma_client *dma_out,
struct etraxfs_dma_client *dma_in);
@@ -41,7 +42,7 @@ static inline DeviceState *etraxfs_ser_create(hwaddr addr,
DeviceState *dev;
SysBusDevice *s;
- dev = qdev_new("etraxfs,serial");
+ dev = qdev_new("etraxfs-serial");
s = SYS_BUS_DEVICE(dev);
qdev_prop_set_chr(dev, "chardev", chr);
sysbus_realize_and_unref(s, &error_fatal);
diff --git a/include/hw/cxl/cxl.h b/include/hw/cxl/cxl.h
new file mode 100644
index 0000000000..75e47b6864
--- /dev/null
+++ b/include/hw/cxl/cxl.h
@@ -0,0 +1,70 @@
+/*
+ * QEMU CXL Support
+ *
+ * Copyright (c) 2020 Intel
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See the
+ * COPYING file in the top-level directory.
+ */
+
+#ifndef CXL_H
+#define CXL_H
+
+
+#include "qapi/qapi-types-machine.h"
+#include "qapi/qapi-visit-machine.h"
+#include "hw/pci/pci_host.h"
+#include "cxl_pci.h"
+#include "cxl_component.h"
+#include "cxl_device.h"
+
+#define CXL_CACHE_LINE_SIZE 64
+#define CXL_COMPONENT_REG_BAR_IDX 0
+#define CXL_DEVICE_REG_BAR_IDX 2
+
+#define CXL_WINDOW_MAX 10
+
+typedef struct PXBCXLDev PXBCXLDev;
+
+typedef struct CXLFixedWindow {
+ uint64_t size;
+ char **targets;
+ PXBCXLDev *target_hbs[16];
+ uint8_t num_targets;
+ uint8_t enc_int_ways;
+ uint8_t enc_int_gran;
+ /* Todo: XOR based interleaving */
+ MemoryRegion mr;
+ hwaddr base;
+} CXLFixedWindow;
+
+typedef struct CXLState {
+ bool is_enabled;
+ MemoryRegion host_mr;
+ unsigned int next_mr_idx;
+ GList *fixed_windows;
+ CXLFixedMemoryWindowOptionsList *cfmw_list;
+} CXLState;
+
+struct CXLHost {
+ PCIHostState parent_obj;
+
+ CXLComponentState cxl_cstate;
+ bool passthrough;
+};
+
+#define TYPE_PXB_CXL_HOST "pxb-cxl-host"
+OBJECT_DECLARE_SIMPLE_TYPE(CXLHost, PXB_CXL_HOST)
+
+#define TYPE_CXL_USP "cxl-upstream"
+
+typedef struct CXLUpstreamPort CXLUpstreamPort;
+DECLARE_INSTANCE_CHECKER(CXLUpstreamPort, CXL_USP, TYPE_CXL_USP)
+CXLComponentState *cxl_usp_to_cstate(CXLUpstreamPort *usp);
+
+#define TYPE_CXL_DSP "cxl-downstream"
+
+typedef struct CXLDownstreamPort CXLDownstreamPort;
+DECLARE_INSTANCE_CHECKER(CXLDownstreamPort, CXL_DSP, TYPE_CXL_DSP)
+
+#endif
diff --git a/include/hw/cxl/cxl_cdat.h b/include/hw/cxl/cxl_cdat.h
new file mode 100644
index 0000000000..17a09066dc
--- /dev/null
+++ b/include/hw/cxl/cxl_cdat.h
@@ -0,0 +1,172 @@
+/*
+ * CXL CDAT Structure
+ *
+ * Copyright (C) 2021 Avery Design Systems, Inc.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef CXL_CDAT_H
+#define CXL_CDAT_H
+
+#include "hw/cxl/cxl_pci.h"
+#include "hw/pci/pcie_doe.h"
+
+/*
+ * Reference:
+ * Coherent Device Attribute Table (CDAT) Specification, Rev. 1.03, July. 2022
+ * Compute Express Link (CXL) Specification, Rev. 3.1, Aug. 2023
+ */
+/* Table Access DOE - CXL r3.1 8.1.11 */
+#define CXL_DOE_TABLE_ACCESS 2
+#define CXL_DOE_PROTOCOL_CDAT ((CXL_DOE_TABLE_ACCESS << 16) | CXL_VENDOR_ID)
+
+/* Read Entry - CXL r3.1 8.1.11.1 */
+#define CXL_DOE_TAB_TYPE_CDAT 0
+#define CXL_DOE_TAB_ENT_MAX 0xFFFF
+
+/* Read Entry Request - CXL r3.1 8.1.11.1 Table 8-13 */
+#define CXL_DOE_TAB_REQ 0
+typedef struct CDATReq {
+ DOEHeader header;
+ uint8_t req_code;
+ uint8_t table_type;
+ uint16_t entry_handle;
+} QEMU_PACKED CDATReq;
+
+/* Read Entry Response - CXL r3.1 8.1.11.1 Table 8-14 */
+#define CXL_DOE_TAB_RSP 0
+typedef struct CDATRsp {
+ DOEHeader header;
+ uint8_t rsp_code;
+ uint8_t table_type;
+ uint16_t entry_handle;
+} QEMU_PACKED CDATRsp;
+
+/* CDAT Table Format - CDAT Table 1 */
+#define CXL_CDAT_REV 2
+typedef struct CDATTableHeader {
+ uint32_t length;
+ uint8_t revision;
+ uint8_t checksum;
+ uint8_t reserved[6];
+ uint32_t sequence;
+} QEMU_PACKED CDATTableHeader;
+
+/* CDAT Structure Types - CDAT Table 2 */
+typedef enum {
+ CDAT_TYPE_DSMAS = 0,
+ CDAT_TYPE_DSLBIS = 1,
+ CDAT_TYPE_DSMSCIS = 2,
+ CDAT_TYPE_DSIS = 3,
+ CDAT_TYPE_DSEMTS = 4,
+ CDAT_TYPE_SSLBIS = 5,
+} CDATType;
+
+typedef struct CDATSubHeader {
+ uint8_t type;
+ uint8_t reserved;
+ uint16_t length;
+} CDATSubHeader;
+
+/* Device Scoped Memory Affinity Structure - CDAT Table 3 */
+typedef struct CDATDsmas {
+ CDATSubHeader header;
+ uint8_t DSMADhandle;
+ uint8_t flags;
+#define CDAT_DSMAS_FLAG_NV (1 << 2)
+#define CDAT_DSMAS_FLAG_SHAREABLE (1 << 3)
+#define CDAT_DSMAS_FLAG_HW_COHERENT (1 << 4)
+#define CDAT_DSMAS_FLAG_DYNAMIC_CAP (1 << 5)
+ uint16_t reserved;
+ uint64_t DPA_base;
+ uint64_t DPA_length;
+} CDATDsmas;
+QEMU_BUILD_BUG_ON(sizeof(CDATDsmas) != 24);
+
+/* Device Scoped Latency and Bandwidth Information Structure - CDAT Table 5 */
+typedef struct CDATDslbis {
+ CDATSubHeader header;
+ uint8_t handle;
+ /* Definitions of these fields refer directly to HMAT fields */
+ uint8_t flags;
+ uint8_t data_type;
+ uint8_t reserved;
+ uint64_t entry_base_unit;
+ uint16_t entry[3];
+ uint16_t reserved2;
+} CDATDslbis;
+QEMU_BUILD_BUG_ON(sizeof(CDATDslbis) != 24);
+
+/* Device Scoped Memory Side Cache Information Structure - CDAT Table 6 */
+typedef struct CDATDsmscis {
+ CDATSubHeader header;
+ uint8_t DSMAS_handle;
+ uint8_t reserved[3];
+ uint64_t memory_side_cache_size;
+ uint32_t cache_attributes;
+} QEMU_PACKED CDATDsmscis;
+
+/* Device Scoped Initiator Structure - CDAT Table 7 */
+typedef struct CDATDsis {
+ CDATSubHeader header;
+ uint8_t flags;
+ uint8_t handle;
+ uint16_t reserved;
+} QEMU_PACKED CDATDsis;
+
+/* Device Scoped EFI Memory Type Structure - CDAT Table 8 */
+typedef struct CDATDsemts {
+ CDATSubHeader header;
+ uint8_t DSMAS_handle;
+ uint8_t EFI_memory_type_attr;
+ uint16_t reserved;
+ uint64_t DPA_offset;
+ uint64_t DPA_length;
+} CDATDsemts;
+QEMU_BUILD_BUG_ON(sizeof(CDATDsemts) != 24);
+
+/* Switch Scoped Latency and Bandwidth Information Structure - CDAT Table 9 */
+typedef struct CDATSslbisHeader {
+ CDATSubHeader header;
+ uint8_t data_type;
+ uint8_t reserved[3];
+ uint64_t entry_base_unit;
+} CDATSslbisHeader;
+QEMU_BUILD_BUG_ON(sizeof(CDATSslbisHeader) != 16);
+
+#define CDAT_PORT_ID_USP 0x100
+/* Switch Scoped Latency and Bandwidth Entry - CDAT Table 10 */
+typedef struct CDATSslbe {
+ uint16_t port_x_id;
+ uint16_t port_y_id;
+ uint16_t latency_bandwidth;
+ uint16_t reserved;
+} CDATSslbe;
+QEMU_BUILD_BUG_ON(sizeof(CDATSslbe) != 8);
+
+typedef struct CDATSslbis {
+ CDATSslbisHeader sslbis_header;
+ CDATSslbe sslbe[];
+} CDATSslbis;
+
+typedef struct CDATEntry {
+ void *base;
+ uint32_t length;
+} CDATEntry;
+
+typedef struct CDATObject {
+ CDATEntry *entry;
+ int entry_len;
+
+ int (*build_cdat_table)(CDATSubHeader ***cdat_table, void *priv);
+ void (*free_cdat_table)(CDATSubHeader **cdat_table, int num, void *priv);
+ bool to_update;
+ void *private;
+ char *filename;
+ uint8_t *buf;
+ struct CDATSubHeader **built_buf;
+ int built_buf_len;
+} CDATObject;
+#endif /* CXL_CDAT_H */
diff --git a/include/hw/cxl/cxl_component.h b/include/hw/cxl/cxl_component.h
new file mode 100644
index 0000000000..5012fab6f7
--- /dev/null
+++ b/include/hw/cxl/cxl_component.h
@@ -0,0 +1,280 @@
+/*
+ * QEMU CXL Component
+ *
+ * Copyright (c) 2020 Intel
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See the
+ * COPYING file in the top-level directory.
+ */
+
+#ifndef CXL_COMPONENT_H
+#define CXL_COMPONENT_H
+
+/* CXL r3.1 Section 8.2.4: CXL.cache and CXL.mem Registers */
+#define CXL2_COMPONENT_IO_REGION_SIZE 0x1000
+#define CXL2_COMPONENT_CM_REGION_SIZE 0x1000
+#define CXL2_COMPONENT_BLOCK_SIZE 0x10000
+
+#include "qemu/range.h"
+#include "hw/cxl/cxl_cdat.h"
+#include "hw/register.h"
+#include "qapi/error.h"
+
+enum reg_type {
+ CXL2_DEVICE,
+ CXL2_TYPE3_DEVICE,
+ CXL2_LOGICAL_DEVICE,
+ CXL2_ROOT_PORT,
+ CXL2_RC,
+ CXL2_UPSTREAM_PORT,
+ CXL2_DOWNSTREAM_PORT,
+ CXL3_SWITCH_MAILBOX_CCI,
+};
+
+/*
+ * Capability registers are defined at the top of the CXL.cache/mem region and
+ * are packed. For our purposes we will always define the caps in the same
+ * order.
+ * CXL r3.1 Table 8-22: CXL_CAPABILITY_ID Assignment for details.
+ */
+
+/* CXL r3.1 Section 8.2.4.1: CXL Capability Header Register */
+#define CXL_CAPABILITY_VERSION 1
+REG32(CXL_CAPABILITY_HEADER, 0)
+ FIELD(CXL_CAPABILITY_HEADER, ID, 0, 16)
+ FIELD(CXL_CAPABILITY_HEADER, VERSION, 16, 4)
+ FIELD(CXL_CAPABILITY_HEADER, CACHE_MEM_VERSION, 20, 4)
+ FIELD(CXL_CAPABILITY_HEADER, ARRAY_SIZE, 24, 8)
+
+#define CXLx_CAPABILITY_HEADER(type, offset) \
+ REG32(CXL_##type##_CAPABILITY_HEADER, offset) \
+ FIELD(CXL_##type##_CAPABILITY_HEADER, ID, 0, 16) \
+ FIELD(CXL_##type##_CAPABILITY_HEADER, VERSION, 16, 4) \
+ FIELD(CXL_##type##_CAPABILITY_HEADER, PTR, 20, 12)
+CXLx_CAPABILITY_HEADER(RAS, 0x4)
+CXLx_CAPABILITY_HEADER(LINK, 0x8)
+CXLx_CAPABILITY_HEADER(HDM, 0xc)
+CXLx_CAPABILITY_HEADER(EXTSEC, 0x10)
+CXLx_CAPABILITY_HEADER(SNOOP, 0x14)
+
+/*
+ * Capability structures contain the actual registers that the CXL component
+ * implements. Some of these are specific to certain types of components, but
+ * this implementation leaves enough space regardless.
+ */
+
+/* CXL r3.1 Section 8.2.4.17: CXL RAS Capability Structure */
+#define CXL_RAS_CAPABILITY_VERSION 3
+/* Give ample space for caps before this */
+#define CXL_RAS_REGISTERS_OFFSET 0x80
+#define CXL_RAS_REGISTERS_SIZE 0x58
+REG32(CXL_RAS_UNC_ERR_STATUS, CXL_RAS_REGISTERS_OFFSET)
+#define CXL_RAS_UNC_ERR_CACHE_DATA_PARITY 0
+#define CXL_RAS_UNC_ERR_CACHE_ADDRESS_PARITY 1
+#define CXL_RAS_UNC_ERR_CACHE_BE_PARITY 2
+#define CXL_RAS_UNC_ERR_CACHE_DATA_ECC 3
+#define CXL_RAS_UNC_ERR_MEM_DATA_PARITY 4
+#define CXL_RAS_UNC_ERR_MEM_ADDRESS_PARITY 5
+#define CXL_RAS_UNC_ERR_MEM_BE_PARITY 6
+#define CXL_RAS_UNC_ERR_MEM_DATA_ECC 7
+#define CXL_RAS_UNC_ERR_REINIT_THRESHOLD 8
+#define CXL_RAS_UNC_ERR_RSVD_ENCODING 9
+#define CXL_RAS_UNC_ERR_POISON_RECEIVED 10
+#define CXL_RAS_UNC_ERR_RECEIVER_OVERFLOW 11
+#define CXL_RAS_UNC_ERR_INTERNAL 14
+#define CXL_RAS_UNC_ERR_CXL_IDE_TX 15
+#define CXL_RAS_UNC_ERR_CXL_IDE_RX 16
+#define CXL_RAS_UNC_ERR_CXL_UNUSED 63 /* Magic value */
+REG32(CXL_RAS_UNC_ERR_MASK, CXL_RAS_REGISTERS_OFFSET + 0x4)
+REG32(CXL_RAS_UNC_ERR_SEVERITY, CXL_RAS_REGISTERS_OFFSET + 0x8)
+REG32(CXL_RAS_COR_ERR_STATUS, CXL_RAS_REGISTERS_OFFSET + 0xc)
+#define CXL_RAS_COR_ERR_CACHE_DATA_ECC 0
+#define CXL_RAS_COR_ERR_MEM_DATA_ECC 1
+#define CXL_RAS_COR_ERR_CRC_THRESHOLD 2
+#define CXL_RAS_COR_ERR_RETRY_THRESHOLD 3
+#define CXL_RAS_COR_ERR_CACHE_POISON_RECEIVED 4
+#define CXL_RAS_COR_ERR_MEM_POISON_RECEIVED 5
+#define CXL_RAS_COR_ERR_PHYSICAL 6
+REG32(CXL_RAS_COR_ERR_MASK, CXL_RAS_REGISTERS_OFFSET + 0x10)
+REG32(CXL_RAS_ERR_CAP_CTRL, CXL_RAS_REGISTERS_OFFSET + 0x14)
+ FIELD(CXL_RAS_ERR_CAP_CTRL, FIRST_ERROR_POINTER, 0, 6)
+ FIELD(CXL_RAS_ERR_CAP_CTRL, MULTIPLE_HEADER_RECORDING_CAP, 9, 1)
+ FIELD(CXL_RAS_ERR_POISON_ENABLED, POISON_ENABLED, 13, 1)
+REG32(CXL_RAS_ERR_HEADER0, CXL_RAS_REGISTERS_OFFSET + 0x18)
+#define CXL_RAS_ERR_HEADER_NUM 32
+/* Offset 0x18 - 0x58 reserved for RAS logs */
+
+/* CXL r3.1 Section 8.2.4.18: CXL Security Capability Structure */
+#define CXL_SEC_REGISTERS_OFFSET \
+ (CXL_RAS_REGISTERS_OFFSET + CXL_RAS_REGISTERS_SIZE)
+#define CXL_SEC_REGISTERS_SIZE 0 /* We don't implement 1.1 downstream ports */
+
+/* CXL r3.1 Section 8.2.4.19: CXL Link Capability Structure */
+#define CXL_LINK_CAPABILITY_VERSION 2
+#define CXL_LINK_REGISTERS_OFFSET \
+ (CXL_SEC_REGISTERS_OFFSET + CXL_SEC_REGISTERS_SIZE)
+#define CXL_LINK_REGISTERS_SIZE 0x50
+
+/* CXL r3.1 Section 8.2.4.20: CXL HDM Decoder Capability Structure */
+#define HDM_DECODE_MAX 10 /* Maximum decoders for Devices */
+#define CXL_HDM_CAPABILITY_VERSION 3
+#define CXL_HDM_REGISTERS_OFFSET \
+ (CXL_LINK_REGISTERS_OFFSET + CXL_LINK_REGISTERS_SIZE)
+#define CXL_HDM_REGISTERS_SIZE (0x10 + 0x20 * HDM_DECODE_MAX)
+#define HDM_DECODER_INIT(n) \
+ REG32(CXL_HDM_DECODER##n##_BASE_LO, \
+ CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x10) \
+ FIELD(CXL_HDM_DECODER##n##_BASE_LO, L, 28, 4) \
+ REG32(CXL_HDM_DECODER##n##_BASE_HI, \
+ CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x14) \
+ REG32(CXL_HDM_DECODER##n##_SIZE_LO, \
+ CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x18) \
+ REG32(CXL_HDM_DECODER##n##_SIZE_HI, \
+ CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x1C) \
+ REG32(CXL_HDM_DECODER##n##_CTRL, \
+ CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x20) \
+ FIELD(CXL_HDM_DECODER##n##_CTRL, IG, 0, 4) \
+ FIELD(CXL_HDM_DECODER##n##_CTRL, IW, 4, 4) \
+ FIELD(CXL_HDM_DECODER##n##_CTRL, LOCK_ON_COMMIT, 8, 1) \
+ FIELD(CXL_HDM_DECODER##n##_CTRL, COMMIT, 9, 1) \
+ FIELD(CXL_HDM_DECODER##n##_CTRL, COMMITTED, 10, 1) \
+ FIELD(CXL_HDM_DECODER##n##_CTRL, ERR, 11, 1) \
+ FIELD(CXL_HDM_DECODER##n##_CTRL, TYPE, 12, 1) \
+ FIELD(CXL_HDM_DECODER##n##_CTRL, BI, 13, 1) \
+ FIELD(CXL_HDM_DECODER##n##_CTRL, UIO, 14, 1) \
+ FIELD(CXL_HDM_DECODER##n##_CTRL, UIG, 16, 4) \
+ FIELD(CXL_HDM_DECODER##n##_CTRL, UIW, 20, 4) \
+ FIELD(CXL_HDM_DECODER##n##_CTRL, ISP, 24, 4) \
+ REG32(CXL_HDM_DECODER##n##_TARGET_LIST_LO, \
+ CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x24) \
+ REG32(CXL_HDM_DECODER##n##_TARGET_LIST_HI, \
+ CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x28) \
+ REG32(CXL_HDM_DECODER##n##_DPA_SKIP_LO, \
+ CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x24) \
+ REG32(CXL_HDM_DECODER##n##_DPA_SKIP_HI, \
+ CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x28)
+
+REG32(CXL_HDM_DECODER_CAPABILITY, CXL_HDM_REGISTERS_OFFSET)
+ FIELD(CXL_HDM_DECODER_CAPABILITY, DECODER_COUNT, 0, 4)
+ FIELD(CXL_HDM_DECODER_CAPABILITY, TARGET_COUNT, 4, 4)
+ FIELD(CXL_HDM_DECODER_CAPABILITY, INTERLEAVE_256B, 8, 1)
+ FIELD(CXL_HDM_DECODER_CAPABILITY, INTERLEAVE_4K, 9, 1)
+ FIELD(CXL_HDM_DECODER_CAPABILITY, POISON_ON_ERR_CAP, 10, 1)
+ FIELD(CXL_HDM_DECODER_CAPABILITY, 3_6_12_WAY, 11, 1)
+ FIELD(CXL_HDM_DECODER_CAPABILITY, 16_WAY, 12, 1)
+ FIELD(CXL_HDM_DECODER_CAPABILITY, UIO, 13, 1)
+ FIELD(CXL_HDM_DECODER_CAPABILITY, UIO_DECODER_COUNT, 16, 4)
+ FIELD(CXL_HDM_DECODER_CAPABILITY, MEMDATA_NXM_CAP, 20, 1)
+ FIELD(CXL_HDM_DECODER_CAPABILITY, SUPPORTED_COHERENCY_MODEL, 21, 2)
+REG32(CXL_HDM_DECODER_GLOBAL_CONTROL, CXL_HDM_REGISTERS_OFFSET + 4)
+ FIELD(CXL_HDM_DECODER_GLOBAL_CONTROL, POISON_ON_ERR_EN, 0, 1)
+ FIELD(CXL_HDM_DECODER_GLOBAL_CONTROL, HDM_DECODER_ENABLE, 1, 1)
+
+/* Support 4 decoders at all levels of topology */
+#define CXL_HDM_DECODER_COUNT 4
+
+HDM_DECODER_INIT(0);
+HDM_DECODER_INIT(1);
+HDM_DECODER_INIT(2);
+HDM_DECODER_INIT(3);
+
+/*
+ * CXL r3.1 Section 8.2.4.21: CXL Extended Security Capability Structure
+ * (Root complex only)
+ */
+#define EXTSEC_ENTRY_MAX 256
+#define CXL_EXTSEC_CAP_VERSION 2
+#define CXL_EXTSEC_REGISTERS_OFFSET \
+ (CXL_HDM_REGISTERS_OFFSET + CXL_HDM_REGISTERS_SIZE)
+#define CXL_EXTSEC_REGISTERS_SIZE (8 * EXTSEC_ENTRY_MAX + 4)
+
+/* CXL r3.1 Section 8.2.4.22: CXL IDE Capability Structure */
+#define CXL_IDE_CAP_VERSION 2
+#define CXL_IDE_REGISTERS_OFFSET \
+ (CXL_EXTSEC_REGISTERS_OFFSET + CXL_EXTSEC_REGISTERS_SIZE)
+#define CXL_IDE_REGISTERS_SIZE 0x24
+
+/* CXL r3.1 Section 8.2.4.23 - CXL Snoop Filter Capability Structure */
+#define CXL_SNOOP_CAP_VERSION 1
+#define CXL_SNOOP_REGISTERS_OFFSET \
+ (CXL_IDE_REGISTERS_OFFSET + CXL_IDE_REGISTERS_SIZE)
+#define CXL_SNOOP_REGISTERS_SIZE 0x8
+
+QEMU_BUILD_BUG_MSG((CXL_SNOOP_REGISTERS_OFFSET +
+ CXL_SNOOP_REGISTERS_SIZE) >= 0x1000,
+ "No space for registers");
+
+typedef struct component_registers {
+ /*
+ * Main memory region to be registered with QEMU core.
+ */
+ MemoryRegion component_registers;
+
+ /*
+ * CXL r3.1 Table 8-21: CXL Subsystem Component Register Ranges
+ * 0x0000 - 0x0fff CXL.io registers
+ * 0x1000 - 0x1fff CXL.cache and CXL.mem
+ * 0x2000 - 0xdfff Implementation specific
+ * 0xe000 - 0xe3ff CXL ARB/MUX registers
+ * 0xe400 - 0xffff RSVD
+ */
+ uint32_t io_registers[CXL2_COMPONENT_IO_REGION_SIZE >> 2];
+ MemoryRegion io;
+
+ uint32_t cache_mem_registers[CXL2_COMPONENT_CM_REGION_SIZE >> 2];
+ uint32_t cache_mem_regs_write_mask[CXL2_COMPONENT_CM_REGION_SIZE >> 2];
+ MemoryRegion cache_mem;
+
+ MemoryRegion impl_specific;
+ MemoryRegion arb_mux;
+ MemoryRegion rsvd;
+
+ /* special_ops is used for any component that needs any specific handling */
+ MemoryRegionOps *special_ops;
+} ComponentRegisters;
+
+/*
+ * A CXL component represents all entities in a CXL hierarchy. This includes,
+ * host bridges, root ports, upstream/downstream switch ports, and devices
+ */
+typedef struct cxl_component {
+ ComponentRegisters crb;
+ union {
+ struct {
+ Range dvsecs[CXL20_MAX_DVSEC];
+ uint16_t dvsec_offset;
+ struct PCIDevice *pdev;
+ };
+ };
+
+ CDATObject cdat;
+} CXLComponentState;
+
+void cxl_component_register_block_init(Object *obj,
+ CXLComponentState *cxl_cstate,
+ const char *type);
+void cxl_component_register_init_common(uint32_t *reg_state,
+ uint32_t *write_msk,
+ enum reg_type type);
+
+void cxl_component_create_dvsec(CXLComponentState *cxl_cstate,
+ enum reg_type cxl_dev_type, uint16_t length,
+ uint16_t type, uint8_t rev, uint8_t *body);
+
+int cxl_decoder_count_enc(int count);
+int cxl_decoder_count_dec(int enc_cnt);
+
+uint8_t cxl_interleave_ways_enc(int iw, Error **errp);
+int cxl_interleave_ways_dec(uint8_t iw_enc, Error **errp);
+uint8_t cxl_interleave_granularity_enc(uint64_t gran, Error **errp);
+
+hwaddr cxl_decode_ig(int ig);
+
+CXLComponentState *cxl_get_hb_cstate(PCIHostState *hb);
+bool cxl_get_hb_passthrough(PCIHostState *hb);
+
+void cxl_doe_cdat_init(CXLComponentState *cxl_cstate, Error **errp);
+void cxl_doe_cdat_release(CXLComponentState *cxl_cstate);
+void cxl_doe_cdat_update(CXLComponentState *cxl_cstate, Error **errp);
+
+#endif
diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
new file mode 100644
index 0000000000..279b276bda
--- /dev/null
+++ b/include/hw/cxl/cxl_device.h
@@ -0,0 +1,506 @@
+/*
+ * QEMU CXL Devices
+ *
+ * Copyright (c) 2020 Intel
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See the
+ * COPYING file in the top-level directory.
+ */
+
+#ifndef CXL_DEVICE_H
+#define CXL_DEVICE_H
+
+#include "hw/cxl/cxl_component.h"
+#include "hw/pci/pci_device.h"
+#include "hw/register.h"
+#include "hw/cxl/cxl_events.h"
+
+/*
+ * The following is how a CXL device's Memory Device registers are laid out.
+ * The only requirement from the spec is that the capabilities array and the
+ * capability headers start at offset 0 and are contiguously packed. The headers
+ * themselves provide offsets to the register fields. For this emulation, the
+ * actual registers * will start at offset 0x80 (m == 0x80). No secondary
+ * mailbox is implemented which means that the offset of the start of the
+ * mailbox payload (n) is given by
+ * n = m + sizeof(mailbox registers) + sizeof(device registers).
+ *
+ * +---------------------------------+
+ * | |
+ * | Memory Device Registers |
+ * | |
+ * n + PAYLOAD_SIZE_MAX -----------------------------------
+ * ^ | |
+ * | | |
+ * | | |
+ * | | |
+ * | | |
+ * | | Mailbox Payload |
+ * | | |
+ * | | |
+ * | | |
+ * n -----------------------------------
+ * ^ | Mailbox Registers |
+ * | | |
+ * | -----------------------------------
+ * | | |
+ * | | Device Registers |
+ * | | |
+ * m ---------------------------------->
+ * ^ | Memory Device Capability Header|
+ * | -----------------------------------
+ * | | Mailbox Capability Header |
+ * | -----------------------------------
+ * | | Device Capability Header |
+ * | -----------------------------------
+ * | | Device Cap Array Register |
+ * 0 +---------------------------------+
+ *
+ */
+
+/* CXL r3.1 Figure 8-12: CXL Device Registers */
+#define CXL_DEVICE_CAP_HDR1_OFFSET 0x10
+/* CXL r3.1 Section 8.2.8.2: CXL Device Capability Header Register */
+#define CXL_DEVICE_CAP_REG_SIZE 0x10
+
+/*
+ * CXL r3.1 Section 8.2.8.2.1: CXL Device Capabilities +
+ * CXL r3.1 Section 8.2.8.5: Memory Device Capabilities
+ */
+#define CXL_DEVICE_CAPS_MAX 4
+#define CXL_CAPS_SIZE \
+ (CXL_DEVICE_CAP_REG_SIZE * (CXL_DEVICE_CAPS_MAX + 1)) /* +1 for header */
+
+#define CXL_DEVICE_STATUS_REGISTERS_OFFSET 0x80 /* Read comment above */
+/*
+ * CXL r3.1 Section 8.2.8.3: Device Status Registers
+ * As it is the only Device Status Register in CXL r3.1
+ */
+#define CXL_DEVICE_STATUS_REGISTERS_LENGTH 0x8
+
+#define CXL_MAILBOX_REGISTERS_OFFSET \
+ (CXL_DEVICE_STATUS_REGISTERS_OFFSET + CXL_DEVICE_STATUS_REGISTERS_LENGTH)
+/* CXL r3.1 Figure 8-13: Mailbox Registers */
+#define CXL_MAILBOX_REGISTERS_SIZE 0x20
+#define CXL_MAILBOX_PAYLOAD_SHIFT 11
+#define CXL_MAILBOX_MAX_PAYLOAD_SIZE (1 << CXL_MAILBOX_PAYLOAD_SHIFT)
+#define CXL_MAILBOX_REGISTERS_LENGTH \
+ (CXL_MAILBOX_REGISTERS_SIZE + CXL_MAILBOX_MAX_PAYLOAD_SIZE)
+
+#define CXL_MEMORY_DEVICE_REGISTERS_OFFSET \
+ (CXL_MAILBOX_REGISTERS_OFFSET + CXL_MAILBOX_REGISTERS_LENGTH)
+#define CXL_MEMORY_DEVICE_REGISTERS_LENGTH 0x8
+
+#define CXL_MMIO_SIZE \
+ (CXL_DEVICE_CAP_REG_SIZE + CXL_DEVICE_STATUS_REGISTERS_LENGTH + \
+ CXL_MAILBOX_REGISTERS_LENGTH + CXL_MEMORY_DEVICE_REGISTERS_LENGTH)
+
+/* CXL r3.1 Table 8-34: Command Return Codes */
+typedef enum {
+ CXL_MBOX_SUCCESS = 0x0,
+ CXL_MBOX_BG_STARTED = 0x1,
+ CXL_MBOX_INVALID_INPUT = 0x2,
+ CXL_MBOX_UNSUPPORTED = 0x3,
+ CXL_MBOX_INTERNAL_ERROR = 0x4,
+ CXL_MBOX_RETRY_REQUIRED = 0x5,
+ CXL_MBOX_BUSY = 0x6,
+ CXL_MBOX_MEDIA_DISABLED = 0x7,
+ CXL_MBOX_FW_XFER_IN_PROGRESS = 0x8,
+ CXL_MBOX_FW_XFER_OUT_OF_ORDER = 0x9,
+ CXL_MBOX_FW_AUTH_FAILED = 0xa,
+ CXL_MBOX_FW_INVALID_SLOT = 0xb,
+ CXL_MBOX_FW_ROLLEDBACK = 0xc,
+ CXL_MBOX_FW_REST_REQD = 0xd,
+ CXL_MBOX_INVALID_HANDLE = 0xe,
+ CXL_MBOX_INVALID_PA = 0xf,
+ CXL_MBOX_INJECT_POISON_LIMIT = 0x10,
+ CXL_MBOX_PERMANENT_MEDIA_FAILURE = 0x11,
+ CXL_MBOX_ABORTED = 0x12,
+ CXL_MBOX_INVALID_SECURITY_STATE = 0x13,
+ CXL_MBOX_INCORRECT_PASSPHRASE = 0x14,
+ CXL_MBOX_UNSUPPORTED_MAILBOX = 0x15,
+ CXL_MBOX_INVALID_PAYLOAD_LENGTH = 0x16,
+ CXL_MBOX_INVALID_LOG = 0x17,
+ CXL_MBOX_INTERRUPTED = 0x18,
+ CXL_MBOX_UNSUPPORTED_FEATURE_VERSION = 0x19,
+ CXL_MBOX_UNSUPPORTED_FEATURE_SELECTION_VALUE = 0x1a,
+ CXL_MBOX_FEATURE_TRANSFER_IN_PROGRESS = 0x1b,
+ CXL_MBOX_FEATURE_TRANSFER_OUT_OF_ORDER = 0x1c,
+ CXL_MBOX_RESOURCES_EXHAUSTED = 0x1d,
+ CXL_MBOX_INVALID_EXTENT_LIST = 0x1e,
+ CXL_MBOX_TRANSFER_OUT_OF_ORDER = 0x1f,
+ CXL_MBOX_REQUEST_ABORT_NOTSUP = 0x20,
+ CXL_MBOX_MAX = 0x20
+} CXLRetCode;
+
+typedef struct CXLCCI CXLCCI;
+typedef struct cxl_device_state CXLDeviceState;
+struct cxl_cmd;
+typedef CXLRetCode (*opcode_handler)(const struct cxl_cmd *cmd,
+ uint8_t *payload_in, size_t len_in,
+ uint8_t *payload_out, size_t *len_out,
+ CXLCCI *cci);
+struct cxl_cmd {
+ const char *name;
+ opcode_handler handler;
+ ssize_t in;
+ uint16_t effect; /* Reported in CEL */
+};
+
+typedef struct CXLEvent {
+ CXLEventRecordRaw data;
+ QSIMPLEQ_ENTRY(CXLEvent) node;
+} CXLEvent;
+
+typedef struct CXLEventLog {
+ uint16_t next_handle;
+ uint16_t overflow_err_count;
+ uint64_t first_overflow_timestamp;
+ uint64_t last_overflow_timestamp;
+ bool irq_enabled;
+ int irq_vec;
+ QemuMutex lock;
+ QSIMPLEQ_HEAD(, CXLEvent) events;
+} CXLEventLog;
+
+typedef struct CXLCCI {
+ const struct cxl_cmd (*cxl_cmd_set)[256];
+ struct cel_log {
+ uint16_t opcode;
+ uint16_t effect;
+ } cel_log[1 << 16];
+ size_t cel_size;
+
+ /* background command handling (times in ms) */
+ struct {
+ uint16_t opcode;
+ uint16_t complete_pct;
+ uint16_t ret_code; /* Current value of retcode */
+ uint64_t starttime;
+ /* set by each bg cmd, cleared by the bg_timer when complete */
+ uint64_t runtime;
+ QEMUTimer *timer;
+ } bg;
+ size_t payload_max;
+ /* Pointer to device hosting the CCI */
+ DeviceState *d;
+ /* Pointer to the device hosting the protocol conversion */
+ DeviceState *intf;
+} CXLCCI;
+
+typedef struct cxl_device_state {
+ MemoryRegion device_registers;
+
+ /* CXL r3.1 Section 8.2.8.3: Device Status Registers */
+ struct {
+ MemoryRegion device;
+ union {
+ uint8_t dev_reg_state[CXL_DEVICE_STATUS_REGISTERS_LENGTH];
+ uint16_t dev_reg_state16[CXL_DEVICE_STATUS_REGISTERS_LENGTH / 2];
+ uint32_t dev_reg_state32[CXL_DEVICE_STATUS_REGISTERS_LENGTH / 4];
+ uint64_t dev_reg_state64[CXL_DEVICE_STATUS_REGISTERS_LENGTH / 8];
+ };
+ uint64_t event_status;
+ };
+ MemoryRegion memory_device;
+ struct {
+ MemoryRegion caps;
+ union {
+ uint32_t caps_reg_state32[CXL_CAPS_SIZE / 4];
+ uint64_t caps_reg_state64[CXL_CAPS_SIZE / 8];
+ };
+ };
+
+ /* CXL r3.1 Section 8.2.8.4: Mailbox Registers */
+ struct {
+ MemoryRegion mailbox;
+ uint16_t payload_size;
+ uint8_t mbox_msi_n;
+ union {
+ uint8_t mbox_reg_state[CXL_MAILBOX_REGISTERS_LENGTH];
+ uint16_t mbox_reg_state16[CXL_MAILBOX_REGISTERS_LENGTH / 2];
+ uint32_t mbox_reg_state32[CXL_MAILBOX_REGISTERS_LENGTH / 4];
+ uint64_t mbox_reg_state64[CXL_MAILBOX_REGISTERS_LENGTH / 8];
+ };
+ };
+
+ /* Stash the memory device status value */
+ uint64_t memdev_status;
+
+ struct {
+ bool set;
+ uint64_t last_set;
+ uint64_t host_set;
+ } timestamp;
+
+ /* memory region size, HDM */
+ uint64_t mem_size;
+ uint64_t pmem_size;
+ uint64_t vmem_size;
+
+ const struct cxl_cmd (*cxl_cmd_set)[256];
+ CXLEventLog event_logs[CXL_EVENT_TYPE_MAX];
+} CXLDeviceState;
+
+/* Initialize the register block for a device */
+void cxl_device_register_block_init(Object *obj, CXLDeviceState *dev,
+ CXLCCI *cci);
+
+typedef struct CXLType3Dev CXLType3Dev;
+typedef struct CSWMBCCIDev CSWMBCCIDev;
+/* Set up default values for the register block */
+void cxl_device_register_init_t3(CXLType3Dev *ct3d);
+void cxl_device_register_init_swcci(CSWMBCCIDev *sw);
+
+/*
+ * CXL r3.1 Section 8.2.8.1: CXL Device Capabilities Array Register
+ * Documented as a 128 bit register, but 64 bit accesses and the second
+ * 64 bits are currently reserved.
+ */
+REG64(CXL_DEV_CAP_ARRAY, 0)
+ FIELD(CXL_DEV_CAP_ARRAY, CAP_ID, 0, 16)
+ FIELD(CXL_DEV_CAP_ARRAY, CAP_VERSION, 16, 8)
+ FIELD(CXL_DEV_CAP_ARRAY, CAP_COUNT, 32, 16)
+
+void cxl_event_set_status(CXLDeviceState *cxl_dstate, CXLEventLogType log_type,
+ bool available);
+
+/*
+ * Helper macro to initialize capability headers for CXL devices.
+ *
+ * In CXL r3.1 Section 8.2.8.2: CXL Device Capability Header Register, this is
+ * listed as a 128b register, but in CXL r3.1 Section 8.2.8: CXL Device Register
+ * Interface, it says:
+ * > No registers defined in Section 8.2.8 are larger than 64-bits wide so that
+ * > is the maximum access size allowed for these registers. If this rule is not
+ * > followed, the behavior is undefined.
+ *
+ * > To illustrate how the fields fit together, the layouts ... are shown as
+ * > wider than a 64 bit register. Implementations are expected to use any size
+ * > accesses for this information up to 64 bits without lost of functionality
+ *
+ * Here we've chosen to make it 4 dwords.
+ */
+#define CXL_DEVICE_CAPABILITY_HEADER_REGISTER(n, offset) \
+ REG32(CXL_DEV_##n##_CAP_HDR0, offset) \
+ FIELD(CXL_DEV_##n##_CAP_HDR0, CAP_ID, 0, 16) \
+ FIELD(CXL_DEV_##n##_CAP_HDR0, CAP_VERSION, 16, 8) \
+ REG32(CXL_DEV_##n##_CAP_HDR1, offset + 4) \
+ FIELD(CXL_DEV_##n##_CAP_HDR1, CAP_OFFSET, 0, 32) \
+ REG32(CXL_DEV_##n##_CAP_HDR2, offset + 8) \
+ FIELD(CXL_DEV_##n##_CAP_HDR2, CAP_LENGTH, 0, 32)
+
+CXL_DEVICE_CAPABILITY_HEADER_REGISTER(DEVICE_STATUS, CXL_DEVICE_CAP_HDR1_OFFSET)
+CXL_DEVICE_CAPABILITY_HEADER_REGISTER(MAILBOX, CXL_DEVICE_CAP_HDR1_OFFSET + \
+ CXL_DEVICE_CAP_REG_SIZE)
+CXL_DEVICE_CAPABILITY_HEADER_REGISTER(MEMORY_DEVICE,
+ CXL_DEVICE_CAP_HDR1_OFFSET +
+ CXL_DEVICE_CAP_REG_SIZE * 2)
+
+void cxl_initialize_mailbox_t3(CXLCCI *cci, DeviceState *d, size_t payload_max);
+void cxl_initialize_mailbox_swcci(CXLCCI *cci, DeviceState *intf,
+ DeviceState *d, size_t payload_max);
+void cxl_init_cci(CXLCCI *cci, size_t payload_max);
+int cxl_process_cci_message(CXLCCI *cci, uint8_t set, uint8_t cmd,
+ size_t len_in, uint8_t *pl_in,
+ size_t *len_out, uint8_t *pl_out,
+ bool *bg_started);
+void cxl_initialize_t3_fm_owned_ld_mctpcci(CXLCCI *cci, DeviceState *d,
+ DeviceState *intf,
+ size_t payload_max);
+
+void cxl_initialize_t3_ld_cci(CXLCCI *cci, DeviceState *d,
+ DeviceState *intf, size_t payload_max);
+
+#define cxl_device_cap_init(dstate, reg, cap_id, ver) \
+ do { \
+ uint32_t *cap_hdrs = dstate->caps_reg_state32; \
+ int which = R_CXL_DEV_##reg##_CAP_HDR0; \
+ cap_hdrs[which] = \
+ FIELD_DP32(cap_hdrs[which], CXL_DEV_##reg##_CAP_HDR0, \
+ CAP_ID, cap_id); \
+ cap_hdrs[which] = FIELD_DP32( \
+ cap_hdrs[which], CXL_DEV_##reg##_CAP_HDR0, CAP_VERSION, ver); \
+ cap_hdrs[which + 1] = \
+ FIELD_DP32(cap_hdrs[which + 1], CXL_DEV_##reg##_CAP_HDR1, \
+ CAP_OFFSET, CXL_##reg##_REGISTERS_OFFSET); \
+ cap_hdrs[which + 2] = \
+ FIELD_DP32(cap_hdrs[which + 2], CXL_DEV_##reg##_CAP_HDR2, \
+ CAP_LENGTH, CXL_##reg##_REGISTERS_LENGTH); \
+ } while (0)
+
+/* CXL r3.2 Section 8.2.8.3.1: Event Status Register */
+#define CXL_DEVICE_STATUS_VERSION 2
+REG64(CXL_DEV_EVENT_STATUS, 0)
+ FIELD(CXL_DEV_EVENT_STATUS, EVENT_STATUS, 0, 32)
+
+#define CXL_DEV_MAILBOX_VERSION 1
+/* CXL r3.1 Section 8.2.8.4.3: Mailbox Capabilities Register */
+REG32(CXL_DEV_MAILBOX_CAP, 0)
+ FIELD(CXL_DEV_MAILBOX_CAP, PAYLOAD_SIZE, 0, 5)
+ FIELD(CXL_DEV_MAILBOX_CAP, INT_CAP, 5, 1)
+ FIELD(CXL_DEV_MAILBOX_CAP, BG_INT_CAP, 6, 1)
+ FIELD(CXL_DEV_MAILBOX_CAP, MSI_N, 7, 4)
+ FIELD(CXL_DEV_MAILBOX_CAP, MBOX_READY_TIME, 11, 8)
+ FIELD(CXL_DEV_MAILBOX_CAP, TYPE, 19, 4)
+
+/* CXL r3.1 Section 8.2.8.4.4: Mailbox Control Register */
+REG32(CXL_DEV_MAILBOX_CTRL, 4)
+ FIELD(CXL_DEV_MAILBOX_CTRL, DOORBELL, 0, 1)
+ FIELD(CXL_DEV_MAILBOX_CTRL, INT_EN, 1, 1)
+ FIELD(CXL_DEV_MAILBOX_CTRL, BG_INT_EN, 2, 1)
+
+/* CXL r3.1 Section 8.2.8.4.5: Command Register */
+REG64(CXL_DEV_MAILBOX_CMD, 8)
+ FIELD(CXL_DEV_MAILBOX_CMD, COMMAND, 0, 8)
+ FIELD(CXL_DEV_MAILBOX_CMD, COMMAND_SET, 8, 8)
+ FIELD(CXL_DEV_MAILBOX_CMD, LENGTH, 16, 20)
+
+/* CXL r3.1 Section 8.2.8.4.6: Mailbox Status Register */
+REG64(CXL_DEV_MAILBOX_STS, 0x10)
+ FIELD(CXL_DEV_MAILBOX_STS, BG_OP, 0, 1)
+ FIELD(CXL_DEV_MAILBOX_STS, ERRNO, 32, 16)
+ FIELD(CXL_DEV_MAILBOX_STS, VENDOR_ERRNO, 48, 16)
+
+/* CXL r3.1 Section 8.2.8.4.7: Background Command Status Register */
+REG64(CXL_DEV_BG_CMD_STS, 0x18)
+ FIELD(CXL_DEV_BG_CMD_STS, OP, 0, 16)
+ FIELD(CXL_DEV_BG_CMD_STS, PERCENTAGE_COMP, 16, 7)
+ FIELD(CXL_DEV_BG_CMD_STS, RET_CODE, 32, 16)
+ FIELD(CXL_DEV_BG_CMD_STS, VENDOR_RET_CODE, 48, 16)
+
+/* CXL r3.1 Section 8.2.8.4.8: Command Payload Registers */
+REG32(CXL_DEV_CMD_PAYLOAD, 0x20)
+
+/* CXL r3.1 Section 8.2.8.4.1: Memory Device Status Registers */
+#define CXL_MEM_DEV_STATUS_VERSION 1
+REG64(CXL_MEM_DEV_STS, 0)
+ FIELD(CXL_MEM_DEV_STS, FATAL, 0, 1)
+ FIELD(CXL_MEM_DEV_STS, FW_HALT, 1, 1)
+ FIELD(CXL_MEM_DEV_STS, MEDIA_STATUS, 2, 2)
+ FIELD(CXL_MEM_DEV_STS, MBOX_READY, 4, 1)
+ FIELD(CXL_MEM_DEV_STS, RESET_NEEDED, 5, 3)
+
+static inline void __toggle_media(CXLDeviceState *cxl_dstate, int val)
+{
+ uint64_t dev_status_reg;
+
+ dev_status_reg = cxl_dstate->memdev_status;
+ dev_status_reg = FIELD_DP64(dev_status_reg, CXL_MEM_DEV_STS, MEDIA_STATUS,
+ val);
+ cxl_dstate->memdev_status = dev_status_reg;
+}
+#define cxl_dev_disable_media(cxlds) \
+ do { __toggle_media((cxlds), 0x3); } while (0)
+#define cxl_dev_enable_media(cxlds) \
+ do { __toggle_media((cxlds), 0x1); } while (0)
+
+static inline bool sanitize_running(CXLCCI *cci)
+{
+ return !!cci->bg.runtime && cci->bg.opcode == 0x4400;
+}
+
+typedef struct CXLError {
+ QTAILQ_ENTRY(CXLError) node;
+ int type; /* Error code as per FE definition */
+ uint32_t header[CXL_RAS_ERR_HEADER_NUM];
+} CXLError;
+
+typedef QTAILQ_HEAD(, CXLError) CXLErrorList;
+
+typedef struct CXLPoison {
+ uint64_t start, length;
+ uint8_t type;
+#define CXL_POISON_TYPE_EXTERNAL 0x1
+#define CXL_POISON_TYPE_INTERNAL 0x2
+#define CXL_POISON_TYPE_INJECTED 0x3
+ QLIST_ENTRY(CXLPoison) node;
+} CXLPoison;
+
+typedef QLIST_HEAD(, CXLPoison) CXLPoisonList;
+#define CXL_POISON_LIST_LIMIT 256
+
+struct CXLType3Dev {
+ /* Private */
+ PCIDevice parent_obj;
+
+ /* Properties */
+ HostMemoryBackend *hostmem; /* deprecated */
+ HostMemoryBackend *hostvmem;
+ HostMemoryBackend *hostpmem;
+ HostMemoryBackend *lsa;
+ uint64_t sn;
+
+ /* State */
+ AddressSpace hostvmem_as;
+ AddressSpace hostpmem_as;
+ CXLComponentState cxl_cstate;
+ CXLDeviceState cxl_dstate;
+ CXLCCI cci; /* Primary PCI mailbox CCI */
+ /* Always initialized as no way to know if a VDM might show up */
+ CXLCCI vdm_fm_owned_ld_mctp_cci;
+ CXLCCI ld0_cci;
+
+ /* DOE */
+ DOECap doe_cdat;
+
+ /* Error injection */
+ CXLErrorList error_list;
+
+ /* Poison Injection - cache */
+ CXLPoisonList poison_list;
+ unsigned int poison_list_cnt;
+ bool poison_list_overflowed;
+ uint64_t poison_list_overflow_ts;
+};
+
+#define TYPE_CXL_TYPE3 "cxl-type3"
+OBJECT_DECLARE_TYPE(CXLType3Dev, CXLType3Class, CXL_TYPE3)
+
+struct CXLType3Class {
+ /* Private */
+ PCIDeviceClass parent_class;
+
+ /* public */
+ uint64_t (*get_lsa_size)(CXLType3Dev *ct3d);
+
+ uint64_t (*get_lsa)(CXLType3Dev *ct3d, void *buf, uint64_t size,
+ uint64_t offset);
+ void (*set_lsa)(CXLType3Dev *ct3d, const void *buf, uint64_t size,
+ uint64_t offset);
+ bool (*set_cacheline)(CXLType3Dev *ct3d, uint64_t dpa_offset,
+ uint8_t *data);
+};
+
+struct CSWMBCCIDev {
+ PCIDevice parent_obj;
+ PCIDevice *target;
+ CXLComponentState cxl_cstate;
+ CXLDeviceState cxl_dstate;
+ CXLCCI *cci;
+};
+
+#define TYPE_CXL_SWITCH_MAILBOX_CCI "cxl-switch-mailbox-cci"
+OBJECT_DECLARE_TYPE(CSWMBCCIDev, CSWMBCCIClass, CXL_SWITCH_MAILBOX_CCI)
+
+MemTxResult cxl_type3_read(PCIDevice *d, hwaddr host_addr, uint64_t *data,
+ unsigned size, MemTxAttrs attrs);
+MemTxResult cxl_type3_write(PCIDevice *d, hwaddr host_addr, uint64_t data,
+ unsigned size, MemTxAttrs attrs);
+
+uint64_t cxl_device_get_timestamp(CXLDeviceState *cxlds);
+
+void cxl_event_init(CXLDeviceState *cxlds, int start_msg_num);
+bool cxl_event_insert(CXLDeviceState *cxlds, CXLEventLogType log_type,
+ CXLEventRecordRaw *event);
+CXLRetCode cxl_event_get_records(CXLDeviceState *cxlds, CXLGetEventPayload *pl,
+ uint8_t log_type, int max_recs,
+ size_t *len);
+CXLRetCode cxl_event_clear_records(CXLDeviceState *cxlds,
+ CXLClearEventPayload *pl);
+
+void cxl_event_irq_assert(CXLType3Dev *ct3d);
+
+void cxl_set_poison_list_overflowed(CXLType3Dev *ct3d);
+
+#endif
diff --git a/include/hw/cxl/cxl_events.h b/include/hw/cxl/cxl_events.h
new file mode 100644
index 0000000000..5170b8dbf8
--- /dev/null
+++ b/include/hw/cxl/cxl_events.h
@@ -0,0 +1,169 @@
+/*
+ * QEMU CXL Events
+ *
+ * Copyright (c) 2022 Intel
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See the
+ * COPYING file in the top-level directory.
+ */
+
+#ifndef CXL_EVENTS_H
+#define CXL_EVENTS_H
+
+#include "qemu/uuid.h"
+
+/*
+ * CXL r3.1 section 8.2.9.2.2: Get Event Records (Opcode 0100h); Table 8-52
+ *
+ * Define these as the bit position for the event status register for ease of
+ * setting the status.
+ */
+typedef enum CXLEventLogType {
+ CXL_EVENT_TYPE_INFO = 0,
+ CXL_EVENT_TYPE_WARN = 1,
+ CXL_EVENT_TYPE_FAIL = 2,
+ CXL_EVENT_TYPE_FATAL = 3,
+ CXL_EVENT_TYPE_DYNAMIC_CAP = 4,
+ CXL_EVENT_TYPE_MAX
+} CXLEventLogType;
+
+/*
+ * Common Event Record Format
+ * CXL r3.1 section 8.2.9.2.1: Event Records; Table 8-43
+ */
+#define CXL_EVENT_REC_HDR_RES_LEN 0xf
+typedef struct CXLEventRecordHdr {
+ QemuUUID id;
+ uint8_t length;
+ uint8_t flags[3];
+ uint16_t handle;
+ uint16_t related_handle;
+ uint64_t timestamp;
+ uint8_t maint_op_class;
+ uint8_t reserved[CXL_EVENT_REC_HDR_RES_LEN];
+} QEMU_PACKED CXLEventRecordHdr;
+
+#define CXL_EVENT_RECORD_DATA_LENGTH 0x50
+typedef struct CXLEventRecordRaw {
+ CXLEventRecordHdr hdr;
+ uint8_t data[CXL_EVENT_RECORD_DATA_LENGTH];
+} QEMU_PACKED CXLEventRecordRaw;
+#define CXL_EVENT_RECORD_SIZE (sizeof(CXLEventRecordRaw))
+
+/*
+ * Get Event Records output payload
+ * CXL r3.1 section 8.2.9.2.2; Table 8-53
+ */
+#define CXL_GET_EVENT_FLAG_OVERFLOW BIT(0)
+#define CXL_GET_EVENT_FLAG_MORE_RECORDS BIT(1)
+typedef struct CXLGetEventPayload {
+ uint8_t flags;
+ uint8_t reserved1;
+ uint16_t overflow_err_count;
+ uint64_t first_overflow_timestamp;
+ uint64_t last_overflow_timestamp;
+ uint16_t record_count;
+ uint8_t reserved2[0xa];
+ CXLEventRecordRaw records[];
+} QEMU_PACKED CXLGetEventPayload;
+#define CXL_EVENT_PAYLOAD_HDR_SIZE (sizeof(CXLGetEventPayload))
+
+/*
+ * Clear Event Records input payload
+ * CXL r3.1 section 8.2.9.2.3; Table 8-54
+ */
+typedef struct CXLClearEventPayload {
+ uint8_t event_log; /* CXLEventLogType */
+ uint8_t clear_flags;
+ uint8_t nr_recs;
+ uint8_t reserved[3];
+ uint16_t handle[];
+} CXLClearEventPayload;
+
+/*
+ * Event Interrupt Policy
+ *
+ * CXL r3.1 section 8.2.9.2.4; Table 8-55
+ */
+typedef enum CXLEventIntMode {
+ CXL_INT_NONE = 0x00,
+ CXL_INT_MSI_MSIX = 0x01,
+ CXL_INT_FW = 0x02,
+ CXL_INT_RES = 0x03,
+} CXLEventIntMode;
+#define CXL_EVENT_INT_MODE_MASK 0x3
+#define CXL_EVENT_INT_SETTING(vector) \
+ ((((uint8_t)vector & 0xf) << 4) | CXL_INT_MSI_MSIX)
+typedef struct CXLEventInterruptPolicy {
+ uint8_t info_settings;
+ uint8_t warn_settings;
+ uint8_t failure_settings;
+ uint8_t fatal_settings;
+ uint8_t dyn_cap_settings;
+} QEMU_PACKED CXLEventInterruptPolicy;
+/* DCD is optional but other fields are not */
+#define CXL_EVENT_INT_SETTING_MIN_LEN 4
+
+/*
+ * General Media Event Record
+ * CXL r3.1 Section 8.2.9.2.1.1; Table 8-45
+ */
+#define CXL_EVENT_GEN_MED_COMP_ID_SIZE 0x10
+#define CXL_EVENT_GEN_MED_RES_SIZE 0x2e
+typedef struct CXLEventGenMedia {
+ CXLEventRecordHdr hdr;
+ uint64_t phys_addr;
+ uint8_t descriptor;
+ uint8_t type;
+ uint8_t transaction_type;
+ uint16_t validity_flags;
+ uint8_t channel;
+ uint8_t rank;
+ uint8_t device[3];
+ uint8_t component_id[CXL_EVENT_GEN_MED_COMP_ID_SIZE];
+ uint8_t reserved[CXL_EVENT_GEN_MED_RES_SIZE];
+} QEMU_PACKED CXLEventGenMedia;
+
+/*
+ * DRAM Event Record
+ * CXL r3.1 Section 8.2.9.2.1.2: Table 8-46
+ * All fields little endian.
+ */
+typedef struct CXLEventDram {
+ CXLEventRecordHdr hdr;
+ uint64_t phys_addr;
+ uint8_t descriptor;
+ uint8_t type;
+ uint8_t transaction_type;
+ uint16_t validity_flags;
+ uint8_t channel;
+ uint8_t rank;
+ uint8_t nibble_mask[3];
+ uint8_t bank_group;
+ uint8_t bank;
+ uint8_t row[3];
+ uint16_t column;
+ uint64_t correction_mask[4];
+ uint8_t reserved[0x17];
+} QEMU_PACKED CXLEventDram;
+
+/*
+ * Memory Module Event Record
+ * CXL r3.1 Section 8.2.9.2.1.3: Table 8-47
+ * All fields little endian.
+ */
+typedef struct CXLEventMemoryModule {
+ CXLEventRecordHdr hdr;
+ uint8_t type;
+ uint8_t health_status;
+ uint8_t media_status;
+ uint8_t additional_status;
+ uint8_t life_used;
+ int16_t temperature;
+ uint32_t dirty_shutdown_count;
+ uint32_t corrected_volatile_error_count;
+ uint32_t corrected_persistent_error_count;
+ uint8_t reserved[0x3d];
+} QEMU_PACKED CXLEventMemoryModule;
+
+#endif /* CXL_EVENTS_H */
diff --git a/include/hw/cxl/cxl_host.h b/include/hw/cxl/cxl_host.h
new file mode 100644
index 0000000000..c9bc9c7c50
--- /dev/null
+++ b/include/hw/cxl/cxl_host.h
@@ -0,0 +1,22 @@
+/*
+ * QEMU CXL Host Setup
+ *
+ * Copyright (c) 2022 Huawei
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See the
+ * COPYING file in the top-level directory.
+ */
+
+#include "hw/cxl/cxl.h"
+#include "hw/boards.h"
+
+#ifndef CXL_HOST_H
+#define CXL_HOST_H
+
+void cxl_machine_init(Object *obj, CXLState *state);
+void cxl_fmws_link_targets(CXLState *stat, Error **errp);
+void cxl_hook_up_pxb_registers(PCIBus *bus, CXLState *state, Error **errp);
+
+extern const MemoryRegionOps cfmws_ops;
+
+#endif
diff --git a/include/hw/cxl/cxl_pci.h b/include/hw/cxl/cxl_pci.h
new file mode 100644
index 0000000000..d0855ed78b
--- /dev/null
+++ b/include/hw/cxl/cxl_pci.h
@@ -0,0 +1,194 @@
+/*
+ * QEMU CXL PCI interfaces
+ *
+ * Copyright (c) 2020 Intel
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See the
+ * COPYING file in the top-level directory.
+ */
+
+#ifndef CXL_PCI_H
+#define CXL_PCI_H
+
+
+#define CXL_VENDOR_ID 0x1e98
+
+#define PCIE_DVSEC_HEADER1_OFFSET 0x4 /* Offset from start of extend cap */
+#define PCIE_DVSEC_ID_OFFSET 0x8
+
+#define PCIE_CXL_DEVICE_DVSEC_LENGTH 0x3C
+#define PCIE_CXL31_DEVICE_DVSEC_REVID 3
+
+#define EXTENSIONS_PORT_DVSEC_LENGTH 0x28
+#define EXTENSIONS_PORT_DVSEC_REVID 0
+
+#define GPF_PORT_DVSEC_LENGTH 0x10
+#define GPF_PORT_DVSEC_REVID 0
+
+#define GPF_DEVICE_DVSEC_LENGTH 0x10
+#define GPF_DEVICE_DVSEC_REVID 0
+
+#define PCIE_CXL3_FLEXBUS_PORT_DVSEC_LENGTH 0x20
+#define PCIE_CXL3_FLEXBUS_PORT_DVSEC_REVID 2
+
+#define REG_LOC_DVSEC_LENGTH 0x24
+#define REG_LOC_DVSEC_REVID 0
+
+enum {
+ PCIE_CXL_DEVICE_DVSEC = 0,
+ NON_CXL_FUNCTION_MAP_DVSEC = 2,
+ EXTENSIONS_PORT_DVSEC = 3,
+ GPF_PORT_DVSEC = 4,
+ GPF_DEVICE_DVSEC = 5,
+ PCIE_FLEXBUS_PORT_DVSEC = 7,
+ REG_LOC_DVSEC = 8,
+ MLD_DVSEC = 9,
+ CXL20_MAX_DVSEC
+};
+
+typedef struct DVSECHeader {
+ uint32_t cap_hdr;
+ uint32_t dv_hdr1;
+ uint16_t dv_hdr2;
+} QEMU_PACKED DVSECHeader;
+QEMU_BUILD_BUG_ON(sizeof(DVSECHeader) != 10);
+
+/*
+ * CXL r3.1 Table 8-2: CXL DVSEC ID Assignment
+ * Devices must implement certain DVSEC IDs, and can [optionally]
+ * implement others.
+ * (x) - IDs in Table 8-2.
+ *
+ * CXL RCD (D1): 0, [2], [5], 7, [8], A - Not emulated yet
+ * CXL RCD USP (UP1): 7, [8] - Not emulated yet
+ * CXL RCH DSP (DP1): 7, [8]
+ * CXL SLD (D2): 0, [2], 5, 7, 8, [A]
+ * CXL LD (LD): 0, [2], 5, 7, 8
+ * CXL RP (R): 3, 4, 7, 8
+ * CXL Switch USP (USP): [2], 7, 8
+ * CXL Switch DSP (DSP): 3, 4, 7, 8
+ * FM-Owned LD (FMLD): 0, [2], 7, 8, 9
+ */
+
+/*
+ * CXL r3.1 Section 8.1.3: PCIe DVSEC for Devices
+ * DVSEC ID: 0, Revision: 3
+ */
+typedef struct CXLDVSECDevice {
+ DVSECHeader hdr;
+ uint16_t cap;
+ uint16_t ctrl;
+ uint16_t status;
+ uint16_t ctrl2;
+ uint16_t status2;
+ uint16_t lock;
+ uint16_t cap2;
+ uint32_t range1_size_hi;
+ uint32_t range1_size_lo;
+ uint32_t range1_base_hi;
+ uint32_t range1_base_lo;
+ uint32_t range2_size_hi;
+ uint32_t range2_size_lo;
+ uint32_t range2_base_hi;
+ uint32_t range2_base_lo;
+ uint16_t cap3;
+ uint16_t resv;
+} QEMU_PACKED CXLDVSECDevice;
+QEMU_BUILD_BUG_ON(sizeof(CXLDVSECDevice) != PCIE_CXL_DEVICE_DVSEC_LENGTH);
+
+/*
+ * CXL r3.1 Section 8.1.5: CXL Extensions DVSEC for Ports
+ * DVSEC ID: 3, Revision: 0
+ */
+typedef struct CXLDVSECPortExt {
+ DVSECHeader hdr;
+ uint16_t status;
+ uint16_t control;
+ uint8_t alt_bus_base;
+ uint8_t alt_bus_limit;
+ uint16_t alt_memory_base;
+ uint16_t alt_memory_limit;
+ uint16_t alt_prefetch_base;
+ uint16_t alt_prefetch_limit;
+ uint32_t alt_prefetch_base_high;
+ uint32_t alt_prefetch_limit_high;
+ uint32_t rcrb_base;
+ uint32_t rcrb_base_high;
+} CXLDVSECPortExt;
+QEMU_BUILD_BUG_ON(sizeof(CXLDVSECPortExt) != 0x28);
+
+#define PORT_CONTROL_OFFSET 0xc
+#define PORT_CONTROL_UNMASK_SBR 1
+#define PORT_CONTROL_ALT_MEMID_EN 4
+
+/*
+ * CXL r3.1 Section 8.1.6: GPF DVSEC for CXL Port
+ * DVSEC ID: 4, Revision: 0
+ */
+typedef struct CXLDVSECPortGPF {
+ DVSECHeader hdr;
+ uint16_t rsvd;
+ uint16_t phase1_ctrl;
+ uint16_t phase2_ctrl;
+} CXLDVSECPortGPF;
+QEMU_BUILD_BUG_ON(sizeof(CXLDVSECPortGPF) != 0x10);
+
+/*
+ * CXL r3.1 Section 8.1.7: GPF DVSEC for CXL Device
+ * DVSEC ID: 5, Revision 0
+ */
+typedef struct CXLDVSECDeviceGPF {
+ DVSECHeader hdr;
+ uint16_t phase2_duration;
+ uint32_t phase2_power;
+} CXLDVSECDeviceGPF;
+QEMU_BUILD_BUG_ON(sizeof(CXLDVSECDeviceGPF) != 0x10);
+
+/*
+ * CXL r3.1 Section 8.1.8: PCIe DVSEC for Flex Bus Port
+ * CXL r3.1 Section 8.2.1.3: Flex Bus Port DVSEC
+ * DVSEC ID: 7, Revision 2
+ */
+typedef struct CXLDVSECPortFlexBus {
+ DVSECHeader hdr;
+ uint16_t cap;
+ uint16_t ctrl;
+ uint16_t status;
+ uint32_t rcvd_mod_ts_data_phase1;
+ uint32_t cap2;
+ uint32_t ctrl2;
+ uint32_t status2;
+} CXLDVSECPortFlexBus;
+QEMU_BUILD_BUG_ON(sizeof(CXLDVSECPortFlexBus) != 0x20);
+
+/*
+ * CXL r3.1 Section 8.1.9: Register Locator DVSEC
+ * DVSEC ID: 8, Revision 0
+ */
+typedef struct CXLDVSECRegisterLocator {
+ DVSECHeader hdr;
+ uint16_t rsvd;
+ uint32_t reg0_base_lo;
+ uint32_t reg0_base_hi;
+ uint32_t reg1_base_lo;
+ uint32_t reg1_base_hi;
+ uint32_t reg2_base_lo;
+ uint32_t reg2_base_hi;
+} CXLDVSECRegisterLocator;
+QEMU_BUILD_BUG_ON(sizeof(CXLDVSECRegisterLocator) != 0x24);
+
+/* BAR Equivalence Indicator */
+#define BEI_BAR_10H 0
+#define BEI_BAR_14H 1
+#define BEI_BAR_18H 2
+#define BEI_BAR_1cH 3
+#define BEI_BAR_20H 4
+#define BEI_BAR_24H 5
+
+/* Register Block Identifier */
+#define RBI_EMPTY 0
+#define RBI_COMPONENT_REG (1 << 8)
+#define RBI_BAR_VIRT_ACL (2 << 8)
+#define RBI_CXL_DEVICE_REG (3 << 8)
+
+#endif
diff --git a/include/hw/display/bcm2835_fb.h b/include/hw/display/bcm2835_fb.h
index 2246be74d8..49541bf08f 100644
--- a/include/hw/display/bcm2835_fb.h
+++ b/include/hw/display/bcm2835_fb.h
@@ -14,9 +14,12 @@
#include "hw/sysbus.h"
#include "ui/console.h"
+#include "qom/object.h"
+
+#define UPPER_RAM_BASE 0x40000000
#define TYPE_BCM2835_FB "bcm2835-fb"
-#define BCM2835_FB(obj) OBJECT_CHECK(BCM2835FBState, (obj), TYPE_BCM2835_FB)
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835FBState, BCM2835_FB)
/*
* Configuration information about the fb which the guest can program
@@ -32,7 +35,7 @@ typedef struct {
uint32_t alpha;
} BCM2835FBConfig;
-typedef struct {
+struct BCM2835FBState {
/*< private >*/
SysBusDevice busdev;
/*< public >*/
@@ -49,7 +52,7 @@ typedef struct {
BCM2835FBConfig config;
BCM2835FBConfig initial_config;
-} BCM2835FBState;
+};
void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig);
diff --git a/include/hw/display/dpcd.h b/include/hw/display/dpcd.h
index 6880ee36a3..a4e37abf6f 100644
--- a/include/hw/display/dpcd.h
+++ b/include/hw/display/dpcd.h
@@ -24,11 +24,11 @@
#ifndef DPCD_H
#define DPCD_H
+#include "qom/object.h"
-typedef struct DPCDState DPCDState;
#define TYPE_DPCD "dpcd"
-#define DPCD(obj) OBJECT_CHECK(DPCDState, (obj), TYPE_DPCD)
+OBJECT_DECLARE_SIMPLE_TYPE(DPCDState, DPCD)
/* DCPD Revision. */
#define DPCD_REVISION 0x00
diff --git a/include/hw/display/edid.h b/include/hw/display/edid.h
index 5b1de57f24..520f8ec202 100644
--- a/include/hw/display/edid.h
+++ b/include/hw/display/edid.h
@@ -5,11 +5,13 @@ typedef struct qemu_edid_info {
const char *vendor; /* http://www.uefi.org/pnp_id_list */
const char *name;
const char *serial;
- uint32_t dpi;
+ uint16_t width_mm;
+ uint16_t height_mm;
uint32_t prefx;
uint32_t prefy;
uint32_t maxx;
uint32_t maxy;
+ uint32_t refresh_rate;
} qemu_edid_info;
void qemu_edid_generate(uint8_t *edid, size_t size,
@@ -18,10 +20,13 @@ size_t qemu_edid_size(uint8_t *edid);
void qemu_edid_region_io(MemoryRegion *region, Object *owner,
uint8_t *edid, size_t size);
-#define DEFINE_EDID_PROPERTIES(_state, _edid_info) \
- DEFINE_PROP_UINT32("xres", _state, _edid_info.prefx, 0), \
- DEFINE_PROP_UINT32("yres", _state, _edid_info.prefy, 0), \
- DEFINE_PROP_UINT32("xmax", _state, _edid_info.maxx, 0), \
- DEFINE_PROP_UINT32("ymax", _state, _edid_info.maxy, 0)
+uint32_t qemu_edid_dpi_to_mm(uint32_t dpi, uint32_t res);
+
+#define DEFINE_EDID_PROPERTIES(_state, _edid_info) \
+ DEFINE_PROP_UINT32("xres", _state, _edid_info.prefx, 0), \
+ DEFINE_PROP_UINT32("yres", _state, _edid_info.prefy, 0), \
+ DEFINE_PROP_UINT32("xmax", _state, _edid_info.maxx, 0), \
+ DEFINE_PROP_UINT32("ymax", _state, _edid_info.maxy, 0), \
+ DEFINE_PROP_UINT32("refresh_rate", _state, _edid_info.refresh_rate, 0)
#endif /* EDID_H */
diff --git a/include/hw/display/i2c-ddc.h b/include/hw/display/i2c-ddc.h
index 1cf53a0c8d..94b5880587 100644
--- a/include/hw/display/i2c-ddc.h
+++ b/include/hw/display/i2c-ddc.h
@@ -21,6 +21,7 @@
#include "hw/display/edid.h"
#include "hw/i2c/i2c.h"
+#include "qom/object.h"
/* A simple I2C slave which just returns the contents of its EDID blob. */
struct I2CDDCState {
@@ -33,9 +34,8 @@ struct I2CDDCState {
uint8_t edid_blob[128];
};
-typedef struct I2CDDCState I2CDDCState;
#define TYPE_I2CDDC "i2c-ddc"
-#define I2CDDC(obj) OBJECT_CHECK(I2CDDCState, (obj), TYPE_I2CDDC)
+OBJECT_DECLARE_SIMPLE_TYPE(I2CDDCState, I2CDDC)
#endif /* I2C_DDC_H */
diff --git a/include/hw/display/macfb.h b/include/hw/display/macfb.h
index 26367ae2c4..27cebefc9e 100644
--- a/include/hw/display/macfb.h
+++ b/include/hw/display/macfb.h
@@ -13,9 +13,44 @@
#ifndef MACFB_H
#define MACFB_H
-#include "qemu/osdep.h"
#include "exec/memory.h"
+#include "hw/irq.h"
+#include "hw/nubus/nubus.h"
+#include "hw/sysbus.h"
#include "ui/console.h"
+#include "qemu/timer.h"
+
+typedef enum {
+ MACFB_DISPLAY_APPLE_21_COLOR = 0,
+ MACFB_DISPLAY_APPLE_PORTRAIT = 1,
+ MACFB_DISPLAY_APPLE_12_RGB = 2,
+ MACFB_DISPLAY_APPLE_2PAGE_MONO = 3,
+ MACFB_DISPLAY_NTSC_UNDERSCAN = 4,
+ MACFB_DISPLAY_NTSC_OVERSCAN = 5,
+ MACFB_DISPLAY_APPLE_12_MONO = 6,
+ MACFB_DISPLAY_APPLE_13_RGB = 7,
+ MACFB_DISPLAY_16_COLOR = 8,
+ MACFB_DISPLAY_PAL1_UNDERSCAN = 9,
+ MACFB_DISPLAY_PAL1_OVERSCAN = 10,
+ MACFB_DISPLAY_PAL2_UNDERSCAN = 11,
+ MACFB_DISPLAY_PAL2_OVERSCAN = 12,
+ MACFB_DISPLAY_VGA = 13,
+ MACFB_DISPLAY_SVGA = 14,
+} MacfbDisplayType;
+
+typedef struct MacFbMode {
+ uint8_t type;
+ uint8_t depth;
+ uint32_t mode_ctrl1;
+ uint32_t mode_ctrl2;
+ uint32_t width;
+ uint32_t height;
+ uint32_t stride;
+ uint32_t offset;
+} MacFbMode;
+
+#define MACFB_CTRL_TOPADDR 0x200
+#define MACFB_NUM_REGS (MACFB_CTRL_TOPADDR / sizeof(uint32_t))
typedef struct MacfbState {
MemoryRegion mem_vram;
@@ -28,37 +63,39 @@ typedef struct MacfbState {
uint8_t color_palette[256 * 3];
uint32_t width, height; /* in pixels */
uint8_t depth;
+ uint8_t type;
+
+ uint32_t regs[MACFB_NUM_REGS];
+ MacFbMode *mode;
+
+ QEMUTimer *vbl_timer;
+ qemu_irq irq;
} MacfbState;
#define TYPE_MACFB "sysbus-macfb"
-#define MACFB(obj) \
- OBJECT_CHECK(MacfbSysBusState, (obj), TYPE_MACFB)
+OBJECT_DECLARE_SIMPLE_TYPE(MacfbSysBusState, MACFB)
-typedef struct {
+struct MacfbSysBusState {
SysBusDevice busdev;
MacfbState macfb;
-} MacfbSysBusState;
+};
-#define MACFB_NUBUS_DEVICE_CLASS(class) \
- OBJECT_CLASS_CHECK(MacfbNubusDeviceClass, (class), TYPE_NUBUS_MACFB)
-#define MACFB_NUBUS_GET_CLASS(obj) \
- OBJECT_GET_CLASS(MacfbNubusDeviceClass, (obj), TYPE_NUBUS_MACFB)
+#define TYPE_NUBUS_MACFB "nubus-macfb"
+OBJECT_DECLARE_TYPE(MacfbNubusState, MacfbNubusDeviceClass, NUBUS_MACFB)
-typedef struct MacfbNubusDeviceClass {
+struct MacfbNubusDeviceClass {
DeviceClass parent_class;
DeviceRealize parent_realize;
-} MacfbNubusDeviceClass;
+ DeviceUnrealize parent_unrealize;
+};
-#define TYPE_NUBUS_MACFB "nubus-macfb"
-#define NUBUS_MACFB(obj) \
- OBJECT_CHECK(MacfbNubusState, (obj), TYPE_NUBUS_MACFB)
-typedef struct {
+struct MacfbNubusState {
NubusDevice busdev;
MacfbState macfb;
-} MacfbNubusState;
+};
#endif
diff --git a/include/hw/display/milkymist_tmu2.h b/include/hw/display/milkymist_tmu2.h
deleted file mode 100644
index e3394ff158..0000000000
--- a/include/hw/display/milkymist_tmu2.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * QEMU model of the Milkymist texture mapping unit.
- *
- * Copyright (c) 2010 Michael Walle <michael@walle.cc>
- * Copyright (c) 2010 Sebastien Bourdeauducq
- * <sebastien.bourdeauducq@lekernel.net>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- *
- *
- * Specification available at:
- * http://milkymist.walle.cc/socdoc/tmu2.pdf
- *
- */
-
-#ifndef HW_DISPLAY_MILKYMIST_TMU2_H
-#define HW_DISPLAY_MILKYMIST_TMU2_H
-
-#include "exec/hwaddr.h"
-#include "hw/qdev-core.h"
-
-#if defined(CONFIG_X11) && defined(CONFIG_OPENGL)
-DeviceState *milkymist_tmu2_create(hwaddr base, qemu_irq irq);
-#else
-static inline DeviceState *milkymist_tmu2_create(hwaddr base, qemu_irq irq)
-{
- return NULL;
-}
-#endif
-
-#endif /* HW_DISPLAY_MILKYMIST_TMU2_H */
diff --git a/include/hw/display/ramfb.h b/include/hw/display/ramfb.h
index b33a2c467b..a7e0019144 100644
--- a/include/hw/display/ramfb.h
+++ b/include/hw/display/ramfb.h
@@ -1,11 +1,15 @@
#ifndef RAMFB_H
#define RAMFB_H
+#include "migration/vmstate.h"
+
/* ramfb.c */
typedef struct RAMFBState RAMFBState;
void ramfb_display_update(QemuConsole *con, RAMFBState *s);
RAMFBState *ramfb_setup(Error **errp);
+extern const VMStateDescription ramfb_vmstate;
+
/* ramfb-standalone.c */
#define TYPE_RAMFB_DEVICE "ramfb"
diff --git a/include/hw/display/vga.h b/include/hw/display/vga.h
index ca0003dbfd..a79aa2909b 100644
--- a/include/hw/display/vga.h
+++ b/include/hw/display/vga.h
@@ -9,7 +9,11 @@
#ifndef QEMU_HW_DISPLAY_VGA_H
#define QEMU_HW_DISPLAY_VGA_H
-#include "exec/hwaddr.h"
+/*
+ * modules can reference this symbol to avoid being loaded
+ * into system emulators without vga support
+ */
+extern bool have_vga;
enum vga_retrace_method {
VGA_RETRACE_DUMB,
@@ -18,8 +22,6 @@ enum vga_retrace_method {
extern enum vga_retrace_method vga_retrace_method;
-int isa_vga_mm_init(hwaddr vram_base,
- hwaddr ctrl_base, int it_shift,
- MemoryRegion *address_space);
+#define TYPE_VGA_MMIO "vga-mmio"
#endif
diff --git a/include/hw/display/xlnx_dp.h b/include/hw/display/xlnx_dp.h
index ab0dd250cc..e86a87f235 100644
--- a/include/hw/display/xlnx_dp.h
+++ b/include/hw/display/xlnx_dp.h
@@ -34,21 +34,28 @@
#include "qemu/units.h"
#include "hw/dma/xlnx_dpdma.h"
#include "audio/audio.h"
+#include "qom/object.h"
+#include "hw/ptimer.h"
#define AUD_CHBUF_MAX_DEPTH (32 * KiB)
#define MAX_QEMU_BUFFER_SIZE (4 * KiB)
-#define DP_CORE_REG_ARRAY_SIZE (0x3AF >> 2)
+#define DP_CORE_REG_OFFSET (0x0000)
+#define DP_CORE_REG_ARRAY_SIZE (0x3B0 >> 2)
+#define DP_AVBUF_REG_OFFSET (0xB000)
#define DP_AVBUF_REG_ARRAY_SIZE (0x238 >> 2)
-#define DP_VBLEND_REG_ARRAY_SIZE (0x1DF >> 2)
+#define DP_VBLEND_REG_OFFSET (0xA000)
+#define DP_VBLEND_REG_ARRAY_SIZE (0x1E0 >> 2)
+#define DP_AUDIO_REG_OFFSET (0xC000)
#define DP_AUDIO_REG_ARRAY_SIZE (0x50 >> 2)
+#define DP_CONTAINER_SIZE (0xC050)
struct PixmanPlane {
pixman_format_code_t format;
DisplaySurface *surface;
};
-typedef struct XlnxDPState {
+struct XlnxDPState {
/*< private >*/
SysBusDevice parent_obj;
@@ -101,9 +108,11 @@ typedef struct XlnxDPState {
*/
DPCDState *dpcd;
I2CDDCState *edid;
-} XlnxDPState;
+
+ ptimer_state *vblank;
+};
#define TYPE_XLNX_DP "xlnx.v-dp"
-#define XLNX_DP(obj) OBJECT_CHECK(XlnxDPState, (obj), TYPE_XLNX_DP)
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxDPState, XLNX_DP)
#endif
diff --git a/include/hw/dma/bcm2835_dma.h b/include/hw/dma/bcm2835_dma.h
index a6747842b7..1d26b1d8d0 100644
--- a/include/hw/dma/bcm2835_dma.h
+++ b/include/hw/dma/bcm2835_dma.h
@@ -9,6 +9,7 @@
#define BCM2835_DMA_H
#include "hw/sysbus.h"
+#include "qom/object.h"
typedef struct {
uint32_t cs;
@@ -25,12 +26,11 @@ typedef struct {
} BCM2835DMAChan;
#define TYPE_BCM2835_DMA "bcm2835-dma"
-#define BCM2835_DMA(obj) \
- OBJECT_CHECK(BCM2835DMAState, (obj), TYPE_BCM2835_DMA)
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835DMAState, BCM2835_DMA)
#define BCM2835_DMA_NCHANS 16
-typedef struct {
+struct BCM2835DMAState {
/*< private >*/
SysBusDevice busdev;
/*< public >*/
@@ -42,6 +42,6 @@ typedef struct {
BCM2835DMAChan chan[BCM2835_DMA_NCHANS];
uint32_t int_status;
uint32_t enable;
-} BCM2835DMAState;
+};
#endif
diff --git a/include/hw/dma/i8257.h b/include/hw/dma/i8257.h
index 03e2c166be..4342e4a91e 100644
--- a/include/hw/dma/i8257.h
+++ b/include/hw/dma/i8257.h
@@ -3,8 +3,10 @@
#include "hw/isa/isa.h"
#include "exec/ioport.h"
+#include "qom/object.h"
#define TYPE_I8257 "i8257"
+OBJECT_DECLARE_SIMPLE_TYPE(I8257State, I8257)
typedef struct I8257Regs {
int now[2];
@@ -18,7 +20,7 @@ typedef struct I8257Regs {
void *opaque;
} I8257Regs;
-typedef struct I8257State {
+struct I8257State {
/* <private> */
ISADevice parent_obj;
@@ -41,8 +43,8 @@ typedef struct I8257State {
int running;
PortioList portio_page;
PortioList portio_pageh;
-} I8257State;
+};
-void i8257_dma_init(ISABus *bus, bool high_page_enable);
+void i8257_dma_init(Object *parent, ISABus *bus, bool high_page_enable);
#endif
diff --git a/include/hw/dma/pl080.h b/include/hw/dma/pl080.h
index 9d4b3df143..3c9659e438 100644
--- a/include/hw/dma/pl080.h
+++ b/include/hw/dma/pl080.h
@@ -10,11 +10,12 @@
* (at your option) any later version.
*/
-/* This is a model of the Arm PrimeCell PL080/PL081 DMA controller:
+/*
+ * This is a model of the Arm PrimeCell PL080/PL081 DMA controller:
* The PL080 TRM is:
- * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0196g/DDI0196.pdf
+ * https://developer.arm.com/documentation/ddi0196/latest
* and the PL081 TRM is:
- * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0218e/DDI0218.pdf
+ * https://developer.arm.com/documentation/ddi0218/latest
*
* QEMU interface:
* + sysbus IRQ 0: DMACINTR combined interrupt line
@@ -29,6 +30,7 @@
#define HW_DMA_PL080_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define PL080_MAX_CHANNELS 8
@@ -42,9 +44,9 @@ typedef struct {
#define TYPE_PL080 "pl080"
#define TYPE_PL081 "pl081"
-#define PL080(obj) OBJECT_CHECK(PL080State, (obj), TYPE_PL080)
+OBJECT_DECLARE_SIMPLE_TYPE(PL080State, PL080)
-typedef struct PL080State {
+struct PL080State {
SysBusDevice parent_obj;
MemoryRegion iomem;
@@ -66,6 +68,6 @@ typedef struct PL080State {
MemoryRegion *downstream;
AddressSpace downstream_as;
-} PL080State;
+};
#endif
diff --git a/include/hw/dma/sifive_pdma.h b/include/hw/dma/sifive_pdma.h
new file mode 100644
index 0000000000..8c6cfa7f32
--- /dev/null
+++ b/include/hw/dma/sifive_pdma.h
@@ -0,0 +1,59 @@
+/*
+ * SiFive Platform DMA emulation
+ *
+ * Copyright (c) 2020 Wind River Systems, Inc.
+ *
+ * Author:
+ * Bin Meng <bin.meng@windriver.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SIFIVE_PDMA_H
+#define SIFIVE_PDMA_H
+
+#include "hw/sysbus.h"
+
+struct sifive_pdma_chan {
+ uint32_t control;
+ uint32_t next_config;
+ uint64_t next_bytes;
+ uint64_t next_dst;
+ uint64_t next_src;
+ uint32_t exec_config;
+ uint64_t exec_bytes;
+ uint64_t exec_dst;
+ uint64_t exec_src;
+ int state;
+};
+
+#define SIFIVE_PDMA_CHANS 4
+#define SIFIVE_PDMA_IRQS (SIFIVE_PDMA_CHANS * 2)
+#define SIFIVE_PDMA_REG_SIZE 0x100000
+#define SIFIVE_PDMA_CHAN_NO(reg) ((reg & (SIFIVE_PDMA_REG_SIZE - 1)) >> 12)
+
+typedef struct SiFivePDMAState {
+ SysBusDevice parent;
+ MemoryRegion iomem;
+ qemu_irq irq[SIFIVE_PDMA_IRQS];
+
+ struct sifive_pdma_chan chan[SIFIVE_PDMA_CHANS];
+} SiFivePDMAState;
+
+#define TYPE_SIFIVE_PDMA "sifive.pdma"
+
+#define SIFIVE_PDMA(obj) \
+ OBJECT_CHECK(SiFivePDMAState, (obj), TYPE_SIFIVE_PDMA)
+
+#endif /* SIFIVE_PDMA_H */
diff --git a/include/hw/dma/xlnx-zdma.h b/include/hw/dma/xlnx-zdma.h
index 0b240b4c3c..efc75217d5 100644
--- a/include/hw/dma/xlnx-zdma.h
+++ b/include/hw/dma/xlnx-zdma.h
@@ -32,6 +32,7 @@
#include "hw/sysbus.h"
#include "hw/register.h"
#include "sysemu/dma.h"
+#include "qom/object.h"
#define ZDMA_R_MAX (0x204 / 4)
@@ -50,12 +51,12 @@ typedef union {
uint32_t words[4];
} XlnxZDMADescr;
-typedef struct XlnxZDMA {
+struct XlnxZDMA {
SysBusDevice parent_obj;
MemoryRegion iomem;
MemTxAttrs attr;
MemoryRegion *dma_mr;
- AddressSpace *dma_as;
+ AddressSpace dma_as;
qemu_irq irq_zdma_ch_imr;
struct {
@@ -74,11 +75,10 @@ typedef struct XlnxZDMA {
/* We don't model the common bufs. Must be at least 16 bytes
to model write only mode. */
uint8_t buf[2048];
-} XlnxZDMA;
+};
#define TYPE_XLNX_ZDMA "xlnx.zdma"
-#define XLNX_ZDMA(obj) \
- OBJECT_CHECK(XlnxZDMA, (obj), TYPE_XLNX_ZDMA)
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxZDMA, XLNX_ZDMA)
#endif /* XLNX_ZDMA_H */
diff --git a/include/hw/dma/xlnx-zynq-devcfg.h b/include/hw/dma/xlnx-zynq-devcfg.h
index 1d3969d91f..e4cf085d70 100644
--- a/include/hw/dma/xlnx-zynq-devcfg.h
+++ b/include/hw/dma/xlnx-zynq-devcfg.h
@@ -29,11 +29,11 @@
#include "hw/register.h"
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_XLNX_ZYNQ_DEVCFG "xlnx.ps7-dev-cfg"
-#define XLNX_ZYNQ_DEVCFG(obj) \
- OBJECT_CHECK(XlnxZynqDevcfg, (obj), TYPE_XLNX_ZYNQ_DEVCFG)
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqDevcfg, XLNX_ZYNQ_DEVCFG)
#define XLNX_ZYNQ_DEVCFG_R_MAX (0x100 / 4)
@@ -46,7 +46,7 @@ typedef struct XlnxZynqDevcfgDMACmd {
uint32_t dest_len;
} XlnxZynqDevcfgDMACmd;
-typedef struct XlnxZynqDevcfg {
+struct XlnxZynqDevcfg {
SysBusDevice parent_obj;
MemoryRegion iomem;
@@ -57,6 +57,6 @@ typedef struct XlnxZynqDevcfg {
uint32_t regs[XLNX_ZYNQ_DEVCFG_R_MAX];
RegisterInfo regs_info[XLNX_ZYNQ_DEVCFG_R_MAX];
-} XlnxZynqDevcfg;
+};
#endif
diff --git a/include/hw/dma/xlnx_csu_dma.h b/include/hw/dma/xlnx_csu_dma.h
new file mode 100644
index 0000000000..922ab80eb6
--- /dev/null
+++ b/include/hw/dma/xlnx_csu_dma.h
@@ -0,0 +1,72 @@
+/*
+ * Xilinx Platform CSU Stream DMA emulation
+ *
+ * This implementation is based on
+ * https://github.com/Xilinx/qemu/blob/master/hw/dma/csu_stream_dma.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef XLNX_CSU_DMA_H
+#define XLNX_CSU_DMA_H
+
+#include "hw/sysbus.h"
+#include "hw/register.h"
+#include "hw/ptimer.h"
+#include "hw/stream.h"
+
+#define TYPE_XLNX_CSU_DMA "xlnx.csu_dma"
+
+#define XLNX_CSU_DMA_R_MAX (0x2c / 4)
+
+typedef struct XlnxCSUDMA {
+ SysBusDevice busdev;
+ MemoryRegion iomem;
+ MemTxAttrs attr;
+ MemoryRegion *dma_mr;
+ AddressSpace dma_as;
+ qemu_irq irq;
+ StreamSink *tx_dev; /* Used as generic StreamSink */
+ ptimer_state *src_timer;
+
+ uint16_t width;
+ bool is_dst;
+ bool r_size_last_word;
+
+ StreamCanPushNotifyFn notify;
+ void *notify_opaque;
+
+ uint32_t regs[XLNX_CSU_DMA_R_MAX];
+ RegisterInfo regs_info[XLNX_CSU_DMA_R_MAX];
+} XlnxCSUDMA;
+
+OBJECT_DECLARE_TYPE(XlnxCSUDMA, XlnxCSUDMAClass, XLNX_CSU_DMA)
+
+struct XlnxCSUDMAClass {
+ SysBusDeviceClass parent_class;
+
+ /*
+ * read: Start a read transfer on a Xilinx CSU DMA engine
+ *
+ * @s: the Xilinx CSU DMA engine to start the transfer on
+ * @addr: the address to read
+ * @len: the number of bytes to read at 'addr'
+ *
+ * @return a MemTxResult indicating whether the operation succeeded ('len'
+ * bytes were read) or failed.
+ */
+ MemTxResult (*read)(XlnxCSUDMA *s, hwaddr addr, uint32_t len);
+};
+
+#endif
diff --git a/include/hw/dma/xlnx_dpdma.h b/include/hw/dma/xlnx_dpdma.h
index 7a304a5bb4..40537a848b 100644
--- a/include/hw/dma/xlnx_dpdma.h
+++ b/include/hw/dma/xlnx_dpdma.h
@@ -28,6 +28,7 @@
#include "hw/sysbus.h"
#include "ui/console.h"
#include "sysemu/dma.h"
+#include "qom/object.h"
#define XLNX_DPDMA_REG_ARRAY_SIZE (0x1000 >> 2)
@@ -42,10 +43,9 @@ struct XlnxDPDMAState {
qemu_irq irq;
};
-typedef struct XlnxDPDMAState XlnxDPDMAState;
#define TYPE_XLNX_DPDMA "xlnx.dpdma"
-#define XLNX_DPDMA(obj) OBJECT_CHECK(XlnxDPDMAState, (obj), TYPE_XLNX_DPDMA)
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxDPDMAState, XLNX_DPDMA)
/*
* xlnx_dpdma_start_operation: Start the operation on the specified channel. The
diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
index 6fdff3dced..9c35d1b9da 100644
--- a/include/hw/elf_ops.h
+++ b/include/hw/elf_ops.h
@@ -1,30 +1,30 @@
static void glue(bswap_ehdr, SZ)(struct elfhdr *ehdr)
{
- bswap16s(&ehdr->e_type); /* Object file type */
- bswap16s(&ehdr->e_machine); /* Architecture */
- bswap32s(&ehdr->e_version); /* Object file version */
- bswapSZs(&ehdr->e_entry); /* Entry point virtual address */
- bswapSZs(&ehdr->e_phoff); /* Program header table file offset */
- bswapSZs(&ehdr->e_shoff); /* Section header table file offset */
- bswap32s(&ehdr->e_flags); /* Processor-specific flags */
- bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
- bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
- bswap16s(&ehdr->e_phnum); /* Program header table entry count */
- bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
- bswap16s(&ehdr->e_shnum); /* Section header table entry count */
- bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
+ bswap16s(&ehdr->e_type); /* Object file type */
+ bswap16s(&ehdr->e_machine); /* Architecture */
+ bswap32s(&ehdr->e_version); /* Object file version */
+ bswapSZs(&ehdr->e_entry); /* Entry point virtual address */
+ bswapSZs(&ehdr->e_phoff); /* Program header table file offset */
+ bswapSZs(&ehdr->e_shoff); /* Section header table file offset */
+ bswap32s(&ehdr->e_flags); /* Processor-specific flags */
+ bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
+ bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
+ bswap16s(&ehdr->e_phnum); /* Program header table entry count */
+ bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
+ bswap16s(&ehdr->e_shnum); /* Section header table entry count */
+ bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
}
static void glue(bswap_phdr, SZ)(struct elf_phdr *phdr)
{
- bswap32s(&phdr->p_type); /* Segment type */
- bswapSZs(&phdr->p_offset); /* Segment file offset */
- bswapSZs(&phdr->p_vaddr); /* Segment virtual address */
- bswapSZs(&phdr->p_paddr); /* Segment physical address */
- bswapSZs(&phdr->p_filesz); /* Segment size in file */
- bswapSZs(&phdr->p_memsz); /* Segment size in memory */
- bswap32s(&phdr->p_flags); /* Segment flags */
- bswapSZs(&phdr->p_align); /* Segment alignment */
+ bswap32s(&phdr->p_type); /* Segment type */
+ bswapSZs(&phdr->p_offset); /* Segment file offset */
+ bswapSZs(&phdr->p_vaddr); /* Segment virtual address */
+ bswapSZs(&phdr->p_paddr); /* Segment physical address */
+ bswapSZs(&phdr->p_filesz); /* Segment size in file */
+ bswapSZs(&phdr->p_memsz); /* Segment size in memory */
+ bswap32s(&phdr->p_flags); /* Segment flags */
+ bswapSZs(&phdr->p_align); /* Segment alignment */
}
static void glue(bswap_shdr, SZ)(struct elf_shdr *shdr)
@@ -117,7 +117,7 @@ static void glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
shdr_table = load_at(fd, ehdr->e_shoff,
sizeof(struct elf_shdr) * ehdr->e_shnum);
if (!shdr_table) {
- return ;
+ return;
}
if (must_swab) {
@@ -312,26 +312,26 @@ static struct elf_note *glue(get_elf_note_type, SZ)(struct elf_note *nhdr,
return nhdr;
}
-static int glue(load_elf, SZ)(const char *name, int fd,
- uint64_t (*elf_note_fn)(void *, void *, bool),
- uint64_t (*translate_fn)(void *, uint64_t),
- void *translate_opaque,
- int must_swab, uint64_t *pentry,
- uint64_t *lowaddr, uint64_t *highaddr,
- uint32_t *pflags, int elf_machine,
- int clear_lsb, int data_swab,
- AddressSpace *as, bool load_rom,
- symbol_fn_t sym_cb)
+static ssize_t glue(load_elf, SZ)(const char *name, int fd,
+ uint64_t (*elf_note_fn)(void *, void *, bool),
+ uint64_t (*translate_fn)(void *, uint64_t),
+ void *translate_opaque,
+ int must_swab, uint64_t *pentry,
+ uint64_t *lowaddr, uint64_t *highaddr,
+ uint32_t *pflags, int elf_machine,
+ int clear_lsb, int data_swab,
+ AddressSpace *as, bool load_rom,
+ symbol_fn_t sym_cb)
{
struct elfhdr ehdr;
struct elf_phdr *phdr = NULL, *ph;
- int size, i, total_size;
+ int size, i;
+ ssize_t total_size;
elf_word mem_size, file_size, data_offset;
uint64_t addr, low = (uint64_t)-1, high = 0;
GMappedFile *mapped_file = NULL;
uint8_t *data = NULL;
- char label[128];
- int ret = ELF_LOAD_FAILED;
+ ssize_t ret = ELF_LOAD_FAILED;
if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
goto fail;
@@ -369,14 +369,6 @@ static int glue(load_elf, SZ)(const char *name, int fd,
}
}
break;
- case EM_MOXIE:
- if (ehdr.e_machine != EM_MOXIE) {
- if (ehdr.e_machine != EM_MOXIE_OLD) {
- ret = ELF_LOAD_WRONG_ARCH;
- goto fail;
- }
- }
- break;
case EM_MIPS:
case EM_NANOMIPS:
if ((ehdr.e_machine != EM_MIPS) &&
@@ -393,10 +385,11 @@ static int glue(load_elf, SZ)(const char *name, int fd,
}
if (pflags) {
- *pflags = (elf_word)ehdr.e_flags;
+ *pflags = ehdr.e_flags;
+ }
+ if (pentry) {
+ *pentry = ehdr.e_entry;
}
- if (pentry)
- *pentry = (uint64_t)(elf_sword)ehdr.e_entry;
glue(load_symbols, SZ)(&ehdr, fd, must_swab, clear_lsb, sym_cb);
@@ -418,7 +411,7 @@ static int glue(load_elf, SZ)(const char *name, int fd,
/*
* Since we want to be able to modify the mapped buffer, we set the
- * 'writeble' parameter to 'true'. Modifications to the buffer are not
+ * 'writable' parameter to 'true'. Modifications to the buffer are not
* written back to the file.
*/
mapped_file = g_mapped_file_new_from_fd(fd, true, NULL);
@@ -491,7 +484,7 @@ static int glue(load_elf, SZ)(const char *name, int fd,
}
}
- if (mem_size > INT_MAX - total_size) {
+ if (mem_size > SSIZE_MAX - total_size) {
ret = ELF_LOAD_TOO_BIG;
goto fail;
}
@@ -507,7 +500,7 @@ static int glue(load_elf, SZ)(const char *name, int fd,
}
if (data_swab) {
- int j;
+ elf_word j;
for (j = 0; j < file_size; j += (1 << data_swab)) {
uint8_t *dp = data + j;
switch (data_swab) {
@@ -544,7 +537,9 @@ static int glue(load_elf, SZ)(const char *name, int fd,
*/
if (mem_size != 0) {
if (load_rom) {
- snprintf(label, sizeof(label), "phdr #%d: %s", i, name);
+ g_autofree char *label =
+ g_strdup_printf("%s ELF program header segment %d",
+ name, i);
/*
* rom_add_elf_program() takes its own reference to
@@ -561,6 +556,19 @@ static int glue(load_elf, SZ)(const char *name, int fd,
if (res != MEMTX_OK) {
goto fail;
}
+ /*
+ * We need to zero'ify the space that is not copied
+ * from file
+ */
+ if (file_size < mem_size) {
+ res = address_space_set(as ? as : &address_space_memory,
+ addr + file_size, 0,
+ mem_size - file_size,
+ MEMTXATTRS_UNSPECIFIED);
+ if (res != MEMTX_OK) {
+ goto fail;
+ }
+ }
}
}
@@ -597,18 +605,18 @@ static int glue(load_elf, SZ)(const char *name, int fd,
nhdr = glue(get_elf_note_type, SZ)(nhdr, file_size, ph->p_align,
*(uint64_t *)translate_opaque);
if (nhdr != NULL) {
- bool is64 =
- sizeof(struct elf_note) == sizeof(struct elf64_note);
- elf_note_fn((void *)nhdr, (void *)&ph->p_align, is64);
+ elf_note_fn((void *)nhdr, (void *)&ph->p_align, SZ == 64);
}
data = NULL;
}
}
- if (lowaddr)
- *lowaddr = (uint64_t)(elf_sword)low;
- if (highaddr)
- *highaddr = (uint64_t)(elf_sword)high;
+ if (lowaddr) {
+ *lowaddr = low;
+ }
+ if (highaddr) {
+ *highaddr = high;
+ }
ret = total_size;
fail:
if (mapped_file) {
diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h
index 02a0ced0a0..8d3fb2fb3b 100644
--- a/include/hw/firmware/smbios.h
+++ b/include/hw/firmware/smbios.h
@@ -1,6 +1,9 @@
#ifndef QEMU_SMBIOS_H
#define QEMU_SMBIOS_H
+#include "qapi/qapi-types-machine.h"
+#include "qemu/bitmap.h"
+
/*
* SMBIOS Support
*
@@ -14,8 +17,28 @@
*
*/
+extern uint8_t *usr_blobs;
+extern GArray *usr_blobs_sizes;
+
+typedef struct {
+ const char *vendor, *version, *date;
+ bool have_major_minor, uefi;
+ uint8_t major, minor;
+} smbios_type0_t;
+extern smbios_type0_t smbios_type0;
+
+typedef struct {
+ const char *manufacturer, *product, *version, *serial, *sku, *family;
+ /* uuid is in qemu_uuid */
+} smbios_type1_t;
+extern smbios_type1_t smbios_type1;
#define SMBIOS_MAX_TYPE 127
+extern DECLARE_BITMAP(smbios_have_binfile_bitmap, SMBIOS_MAX_TYPE + 1);
+extern DECLARE_BITMAP(smbios_have_fields_bitmap, SMBIOS_MAX_TYPE + 1);
+
+#define offsetofend(TYPE, MEMBER) \
+ (offsetof(TYPE, MEMBER) + sizeof_field(TYPE, MEMBER))
/* memory area description, used by type 19 table */
struct smbios_phys_mem_area {
@@ -23,14 +46,6 @@ struct smbios_phys_mem_area {
uint64_t length;
};
-/*
- * SMBIOS spec defined tables
- */
-typedef enum SmbiosEntryPointType {
- SMBIOS_ENTRY_POINT_21,
- SMBIOS_ENTRY_POINT_30,
-} SmbiosEntryPointType;
-
/* SMBIOS Entry Point
* There are two types of entry points defined in the SMBIOS specification
* (see below). BIOS must place the entry point(s) at a 16-byte-aligned
@@ -193,6 +208,43 @@ struct smbios_type_4 {
uint8_t thread_count;
uint16_t processor_characteristics;
uint16_t processor_family2;
+ /* SMBIOS spec 3.0.0, Table 21 */
+ uint16_t core_count2;
+ uint16_t core_enabled2;
+ uint16_t thread_count2;
+} QEMU_PACKED;
+
+typedef enum smbios_type_4_len_ver {
+ SMBIOS_TYPE_4_LEN_V28 = offsetofend(struct smbios_type_4,
+ processor_family2),
+ SMBIOS_TYPE_4_LEN_V30 = offsetofend(struct smbios_type_4, thread_count2),
+} smbios_type_4_len_ver;
+
+/* SMBIOS type 8 - Port Connector Information */
+struct smbios_type_8 {
+ struct smbios_structure_header header;
+ uint8_t internal_reference_str;
+ uint8_t internal_connector_type;
+ uint8_t external_reference_str;
+ uint8_t external_connector_type;
+ uint8_t port_type;
+} QEMU_PACKED;
+
+/* SMBIOS type 9 - System Slots (v2.1+) */
+struct smbios_type_9 {
+ struct smbios_structure_header header;
+ uint8_t slot_designation;
+ uint8_t slot_type;
+ uint8_t slot_data_bus_width;
+ uint8_t current_usage;
+ uint8_t slot_length;
+ uint16_t slot_id;
+ uint8_t slot_characteristics1;
+ uint8_t slot_characteristics2;
+ /* SMBIOS spec v2.6+ */
+ uint16_t segment_group_number;
+ uint8_t bus_number;
+ uint8_t device_number;
} QEMU_PACKED;
/* SMBIOS type 11 - OEM strings */
@@ -258,20 +310,36 @@ struct smbios_type_32 {
uint8_t boot_status;
} QEMU_PACKED;
+/* SMBIOS type 41 - Onboard Devices Extended Information */
+struct smbios_type_41 {
+ struct smbios_structure_header header;
+ uint8_t reference_designation_str;
+ uint8_t device_type;
+ uint8_t device_type_instance;
+ uint16_t segment_group_number;
+ uint8_t bus_number;
+ uint8_t device_number;
+} QEMU_PACKED;
+
/* SMBIOS type 127 -- End-of-table */
struct smbios_type_127 {
struct smbios_structure_header header;
} QEMU_PACKED;
+bool smbios_validate_table(SmbiosEntryPointType ep_type, Error **errp);
+void smbios_add_usr_blob_size(size_t size);
void smbios_entry_add(QemuOpts *opts, Error **errp);
void smbios_set_cpuid(uint32_t version, uint32_t features);
void smbios_set_defaults(const char *manufacturer, const char *product,
- const char *version, bool legacy_mode,
- bool uuid_encoded, SmbiosEntryPointType ep_type);
-uint8_t *smbios_get_table_legacy(MachineState *ms, size_t *length);
+ const char *version,
+ bool uuid_encoded);
+void smbios_set_default_processor_family(uint16_t processor_family);
+uint8_t *smbios_get_table_legacy(size_t *length, Error **errp);
void smbios_get_tables(MachineState *ms,
+ SmbiosEntryPointType ep_type,
const struct smbios_phys_mem_area *mem_array,
const unsigned int mem_array_size,
uint8_t **tables, size_t *tables_len,
- uint8_t **anchor, size_t *anchor_len);
+ uint8_t **anchor, size_t *anchor_len,
+ Error **errp);
#endif /* QEMU_SMBIOS_H */
diff --git a/include/hw/fsi/aspeed_apb2opb.h b/include/hw/fsi/aspeed_apb2opb.h
new file mode 100644
index 0000000000..f6a2387abf
--- /dev/null
+++ b/include/hw/fsi/aspeed_apb2opb.h
@@ -0,0 +1,46 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * ASPEED APB2OPB Bridge
+ * IBM On-Chip Peripheral Bus
+ */
+#ifndef FSI_ASPEED_APB2OPB_H
+#define FSI_ASPEED_APB2OPB_H
+
+#include "exec/memory.h"
+#include "hw/fsi/fsi-master.h"
+#include "hw/sysbus.h"
+
+#define TYPE_FSI_OPB "fsi.opb"
+
+#define TYPE_OP_BUS "opb"
+OBJECT_DECLARE_SIMPLE_TYPE(OPBus, OP_BUS)
+
+typedef struct OPBus {
+ BusState bus;
+
+ MemoryRegion mr;
+ AddressSpace as;
+} OPBus;
+
+#define TYPE_ASPEED_APB2OPB "aspeed.apb2opb"
+OBJECT_DECLARE_SIMPLE_TYPE(AspeedAPB2OPBState, ASPEED_APB2OPB)
+
+#define ASPEED_APB2OPB_NR_REGS ((0xe8 >> 2) + 1)
+
+#define ASPEED_FSI_NUM 2
+
+typedef struct AspeedAPB2OPBState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+
+ uint32_t regs[ASPEED_APB2OPB_NR_REGS];
+ qemu_irq irq;
+
+ OPBus opb[ASPEED_FSI_NUM];
+ FSIMasterState fsi[ASPEED_FSI_NUM];
+} AspeedAPB2OPBState;
+
+#endif /* FSI_ASPEED_APB2OPB_H */
diff --git a/include/hw/fsi/cfam.h b/include/hw/fsi/cfam.h
new file mode 100644
index 0000000000..7abc3b287b
--- /dev/null
+++ b/include/hw/fsi/cfam.h
@@ -0,0 +1,34 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * IBM Common FRU Access Macro
+ */
+#ifndef FSI_CFAM_H
+#define FSI_CFAM_H
+
+#include "exec/memory.h"
+
+#include "hw/fsi/fsi.h"
+#include "hw/fsi/lbus.h"
+
+#define TYPE_FSI_CFAM "cfam"
+#define FSI_CFAM(obj) OBJECT_CHECK(FSICFAMState, (obj), TYPE_FSI_CFAM)
+
+/* P9-ism */
+#define CFAM_CONFIG_NR_REGS 0x28
+
+typedef struct FSICFAMState {
+ /* < private > */
+ FSISlaveState parent;
+
+ /* CFAM config address space */
+ MemoryRegion config_iomem;
+
+ MemoryRegion mr;
+
+ FSILBus lbus;
+ FSIScratchPad scratchpad;
+} FSICFAMState;
+
+#endif /* FSI_CFAM_H */
diff --git a/include/hw/fsi/fsi-master.h b/include/hw/fsi/fsi-master.h
new file mode 100644
index 0000000000..68e5f56db2
--- /dev/null
+++ b/include/hw/fsi/fsi-master.h
@@ -0,0 +1,32 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * IBM Flexible Service Interface Master
+ */
+#ifndef FSI_FSI_MASTER_H
+#define FSI_FSI_MASTER_H
+
+#include "exec/memory.h"
+#include "hw/qdev-core.h"
+#include "hw/fsi/fsi.h"
+#include "hw/fsi/cfam.h"
+
+#define TYPE_FSI_MASTER "fsi.master"
+OBJECT_DECLARE_SIMPLE_TYPE(FSIMasterState, FSI_MASTER)
+
+#define FSI_MASTER_NR_REGS ((0x2e0 >> 2) + 1)
+
+typedef struct FSIMasterState {
+ DeviceState parent;
+ MemoryRegion iomem;
+ MemoryRegion opb2fsi;
+
+ FSIBus bus;
+
+ uint32_t regs[FSI_MASTER_NR_REGS];
+ FSICFAMState cfam;
+} FSIMasterState;
+
+
+#endif /* FSI_FSI_H */
diff --git a/include/hw/fsi/fsi.h b/include/hw/fsi/fsi.h
new file mode 100644
index 0000000000..e00f6ef078
--- /dev/null
+++ b/include/hw/fsi/fsi.h
@@ -0,0 +1,37 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * IBM Flexible Service Interface
+ */
+#ifndef FSI_FSI_H
+#define FSI_FSI_H
+
+#include "exec/memory.h"
+#include "hw/qdev-core.h"
+#include "hw/fsi/lbus.h"
+#include "qemu/bitops.h"
+
+/* Bitwise operations at the word level. */
+#define BE_GENMASK(hb, lb) MAKE_64BIT_MASK((lb), ((hb) - (lb) + 1))
+
+#define TYPE_FSI_BUS "fsi.bus"
+OBJECT_DECLARE_SIMPLE_TYPE(FSIBus, FSI_BUS)
+
+typedef struct FSIBus {
+ BusState bus;
+} FSIBus;
+
+#define TYPE_FSI_SLAVE "fsi.slave"
+OBJECT_DECLARE_SIMPLE_TYPE(FSISlaveState, FSI_SLAVE)
+
+#define FSI_SLAVE_CONTROL_NR_REGS ((0x40 >> 2) + 1)
+
+typedef struct FSISlaveState {
+ DeviceState parent;
+
+ MemoryRegion iomem;
+ uint32_t regs[FSI_SLAVE_CONTROL_NR_REGS];
+} FSISlaveState;
+
+#endif /* FSI_FSI_H */
diff --git a/include/hw/fsi/lbus.h b/include/hw/fsi/lbus.h
new file mode 100644
index 0000000000..558268c013
--- /dev/null
+++ b/include/hw/fsi/lbus.h
@@ -0,0 +1,43 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2024 IBM Corp.
+ *
+ * IBM Local bus and connected device structures.
+ */
+#ifndef FSI_LBUS_H
+#define FSI_LBUS_H
+
+#include "hw/qdev-core.h"
+#include "qemu/units.h"
+#include "exec/memory.h"
+
+#define TYPE_FSI_LBUS_DEVICE "fsi.lbus.device"
+OBJECT_DECLARE_SIMPLE_TYPE(FSILBusDevice, FSI_LBUS_DEVICE)
+
+typedef struct FSILBusDevice {
+ DeviceState parent;
+
+ MemoryRegion iomem;
+} FSILBusDevice;
+
+#define TYPE_FSI_LBUS "fsi.lbus"
+OBJECT_DECLARE_SIMPLE_TYPE(FSILBus, FSI_LBUS)
+
+typedef struct FSILBus {
+ BusState bus;
+
+ MemoryRegion mr;
+} FSILBus;
+
+#define TYPE_FSI_SCRATCHPAD "fsi.scratchpad"
+#define SCRATCHPAD(obj) OBJECT_CHECK(FSIScratchPad, (obj), TYPE_FSI_SCRATCHPAD)
+
+#define FSI_SCRATCHPAD_NR_REGS 4
+
+typedef struct FSIScratchPad {
+ FSILBusDevice parent;
+
+ uint32_t regs[FSI_SCRATCHPAD_NR_REGS];
+} FSIScratchPad;
+
+#endif /* FSI_LBUS_H */
diff --git a/include/hw/fw-path-provider.h b/include/hw/fw-path-provider.h
index 10d1bd4959..8e1d45651c 100644
--- a/include/hw/fw-path-provider.h
+++ b/include/hw/fw-path-provider.h
@@ -22,20 +22,19 @@
#define TYPE_FW_PATH_PROVIDER "fw-path-provider"
-#define FW_PATH_PROVIDER_CLASS(klass) \
- OBJECT_CLASS_CHECK(FWPathProviderClass, (klass), TYPE_FW_PATH_PROVIDER)
-#define FW_PATH_PROVIDER_GET_CLASS(obj) \
- OBJECT_GET_CLASS(FWPathProviderClass, (obj), TYPE_FW_PATH_PROVIDER)
+typedef struct FWPathProviderClass FWPathProviderClass;
+DECLARE_CLASS_CHECKERS(FWPathProviderClass, FW_PATH_PROVIDER,
+ TYPE_FW_PATH_PROVIDER)
#define FW_PATH_PROVIDER(obj) \
INTERFACE_CHECK(FWPathProvider, (obj), TYPE_FW_PATH_PROVIDER)
typedef struct FWPathProvider FWPathProvider;
-typedef struct FWPathProviderClass {
+struct FWPathProviderClass {
InterfaceClass parent_class;
char *(*get_dev_path)(FWPathProvider *p, BusState *bus, DeviceState *dev);
-} FWPathProviderClass;
+};
char *fw_path_provider_get_dev_path(FWPathProvider *p, BusState *bus,
DeviceState *dev);
diff --git a/include/hw/gpio/aspeed_gpio.h b/include/hw/gpio/aspeed_gpio.h
index a2deac046a..904eecf62c 100644
--- a/include/hw/gpio/aspeed_gpio.h
+++ b/include/hw/gpio/aspeed_gpio.h
@@ -11,18 +11,15 @@
#define ASPEED_GPIO_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_ASPEED_GPIO "aspeed.gpio"
-#define ASPEED_GPIO(obj) OBJECT_CHECK(AspeedGPIOState, (obj), TYPE_ASPEED_GPIO)
-#define ASPEED_GPIO_CLASS(klass) \
- OBJECT_CLASS_CHECK(AspeedGPIOClass, (klass), TYPE_ASPEED_GPIO)
-#define ASPEED_GPIO_GET_CLASS(obj) \
- OBJECT_GET_CLASS(AspeedGPIOClass, (obj), TYPE_ASPEED_GPIO)
+OBJECT_DECLARE_TYPE(AspeedGPIOState, AspeedGPIOClass, ASPEED_GPIO)
#define ASPEED_GPIO_MAX_NR_SETS 8
+#define ASPEED_GPIOS_PER_SET 32
#define ASPEED_REGS_PER_BANK 14
#define ASPEED_GPIO_MAX_NR_REGS (ASPEED_REGS_PER_BANK * ASPEED_GPIO_MAX_NR_SETS)
-#define ASPEED_GPIO_NR_PINS 228
#define ASPEED_GROUPS_PER_SET 4
#define ASPEED_GPIO_NR_DEBOUNCE_REGS 3
#define ASPEED_CHARS_PER_GROUP_LABEL 4
@@ -53,21 +50,34 @@ enum GPIORegType {
gpio_reg_input_mask,
};
+/* GPIO index mode */
+enum GPIORegIndexType {
+ gpio_reg_idx_data = 0,
+ gpio_reg_idx_direction,
+ gpio_reg_idx_interrupt,
+ gpio_reg_idx_debounce,
+ gpio_reg_idx_tolerance,
+ gpio_reg_idx_cmd_src,
+ gpio_reg_idx_input_mask,
+ gpio_reg_idx_reserved,
+ gpio_reg_idx_new_w_cmd_src,
+ gpio_reg_idx_new_r_cmd_src,
+};
+
typedef struct AspeedGPIOReg {
uint16_t set_idx;
enum GPIORegType type;
- } AspeedGPIOReg;
+} AspeedGPIOReg;
-typedef struct AspeedGPIOClass {
+struct AspeedGPIOClass {
SysBusDevice parent_obj;
const GPIOSetProperties *props;
uint32_t nr_gpio_pins;
uint32_t nr_gpio_sets;
- uint32_t gap;
const AspeedGPIOReg *reg_table;
-} AspeedGPIOClass;
+};
-typedef struct AspeedGPIOState {
+struct AspeedGPIOState {
/* <private> */
SysBusDevice parent;
@@ -75,7 +85,7 @@ typedef struct AspeedGPIOState {
MemoryRegion iomem;
int pending;
qemu_irq irq;
- qemu_irq gpios[ASPEED_GPIO_NR_PINS];
+ qemu_irq gpios[ASPEED_GPIO_MAX_NR_SETS][ASPEED_GPIOS_PER_SET];
/* Parallel GPIO Registers */
uint32_t debounce_regs[ASPEED_GPIO_NR_DEBOUNCE_REGS];
@@ -95,6 +105,6 @@ typedef struct AspeedGPIOState {
uint32_t debounce_2;
uint32_t input_mask;
} sets[ASPEED_GPIO_MAX_NR_SETS];
-} AspeedGPIOState;
+};
-#endif /* _ASPEED_GPIO_H_ */
+#endif /* ASPEED_GPIO_H */
diff --git a/include/hw/gpio/bcm2835_gpio.h b/include/hw/gpio/bcm2835_gpio.h
index b0de0a3c74..1c53a05090 100644
--- a/include/hw/gpio/bcm2835_gpio.h
+++ b/include/hw/gpio/bcm2835_gpio.h
@@ -16,8 +16,9 @@
#include "hw/sd/sd.h"
#include "hw/sysbus.h"
+#include "qom/object.h"
-typedef struct BCM2835GpioState {
+struct BCM2835GpioState {
SysBusDevice parent_obj;
MemoryRegion iomem;
@@ -31,10 +32,9 @@ typedef struct BCM2835GpioState {
uint32_t lev0, lev1;
uint8_t sd_fsel;
qemu_irq out[54];
-} BCM2835GpioState;
+};
#define TYPE_BCM2835_GPIO "bcm2835_gpio"
-#define BCM2835_GPIO(obj) \
- OBJECT_CHECK(BCM2835GpioState, (obj), TYPE_BCM2835_GPIO)
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835GpioState, BCM2835_GPIO)
#endif
diff --git a/include/hw/gpio/bcm2838_gpio.h b/include/hw/gpio/bcm2838_gpio.h
new file mode 100644
index 0000000000..f2a57a697f
--- /dev/null
+++ b/include/hw/gpio/bcm2838_gpio.h
@@ -0,0 +1,45 @@
+/*
+ * Raspberry Pi (BCM2838) GPIO Controller
+ * This implementation is based on bcm2835_gpio (hw/gpio/bcm2835_gpio.c)
+ *
+ * Copyright (c) 2022 Auriga LLC
+ *
+ * Authors:
+ * Lotosh, Aleksey <aleksey.lotosh@auriga.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef BCM2838_GPIO_H
+#define BCM2838_GPIO_H
+
+#include "hw/sd/sd.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_BCM2838_GPIO "bcm2838-gpio"
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2838GpioState, BCM2838_GPIO)
+
+#define BCM2838_GPIO_REGS_SIZE 0x1000
+#define BCM2838_GPIO_NUM 58
+#define GPIO_PUP_PDN_CNTRL_NUM 4
+
+struct BCM2838GpioState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+
+ /* SDBus selector */
+ SDBus sdbus;
+ SDBus *sdbus_sdhci;
+ SDBus *sdbus_sdhost;
+
+ uint8_t fsel[BCM2838_GPIO_NUM];
+ uint32_t lev0, lev1;
+ uint8_t sd_fsel;
+ qemu_irq out[BCM2838_GPIO_NUM];
+ uint32_t pup_cntrl_reg[GPIO_PUP_PDN_CNTRL_NUM];
+};
+
+#endif
diff --git a/include/hw/gpio/imx_gpio.h b/include/hw/gpio/imx_gpio.h
index ffab437f23..227860b9f0 100644
--- a/include/hw/gpio/imx_gpio.h
+++ b/include/hw/gpio/imx_gpio.h
@@ -21,9 +21,10 @@
#define IMX_GPIO_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_IMX_GPIO "imx.gpio"
-#define IMX_GPIO(obj) OBJECT_CHECK(IMXGPIOState, (obj), TYPE_IMX_GPIO)
+OBJECT_DECLARE_SIMPLE_TYPE(IMXGPIOState, IMX_GPIO)
#define IMX_GPIO_MEM_SIZE 0x20
@@ -39,7 +40,7 @@
#define IMX_GPIO_PIN_COUNT 32
-typedef struct IMXGPIOState {
+struct IMXGPIOState {
/*< private >*/
SysBusDevice parent_obj;
@@ -58,6 +59,6 @@ typedef struct IMXGPIOState {
qemu_irq irq[2];
qemu_irq output[IMX_GPIO_PIN_COUNT];
-} IMXGPIOState;
+};
#endif /* IMX_GPIO_H */
diff --git a/include/hw/gpio/npcm7xx_gpio.h b/include/hw/gpio/npcm7xx_gpio.h
new file mode 100644
index 0000000000..b1d771bd77
--- /dev/null
+++ b/include/hw/gpio/npcm7xx_gpio.h
@@ -0,0 +1,55 @@
+/*
+ * Nuvoton NPCM7xx General Purpose Input / Output (GPIO)
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef NPCM7XX_GPIO_H
+#define NPCM7XX_GPIO_H
+
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+
+/* Number of pins managed by each controller. */
+#define NPCM7XX_GPIO_NR_PINS (32)
+
+/*
+ * Number of registers in our device state structure. Don't change this without
+ * incrementing the version_id in the vmstate.
+ */
+#define NPCM7XX_GPIO_NR_REGS (0x80 / sizeof(uint32_t))
+
+typedef struct NPCM7xxGPIOState {
+ SysBusDevice parent;
+
+ /* Properties to be defined by the SoC */
+ uint32_t reset_pu;
+ uint32_t reset_pd;
+ uint32_t reset_osrc;
+ uint32_t reset_odsc;
+
+ MemoryRegion mmio;
+
+ qemu_irq irq;
+ qemu_irq output[NPCM7XX_GPIO_NR_PINS];
+
+ uint32_t pin_level;
+ uint32_t ext_level;
+ uint32_t ext_driven;
+
+ uint32_t regs[NPCM7XX_GPIO_NR_REGS];
+} NPCM7xxGPIOState;
+
+#define TYPE_NPCM7XX_GPIO "npcm7xx-gpio"
+#define NPCM7XX_GPIO(obj) \
+ OBJECT_CHECK(NPCM7xxGPIOState, (obj), TYPE_NPCM7XX_GPIO)
+
+#endif /* NPCM7XX_GPIO_H */
diff --git a/include/hw/gpio/nrf51_gpio.h b/include/hw/gpio/nrf51_gpio.h
index 1d62bbc928..fcfa2bac17 100644
--- a/include/hw/gpio/nrf51_gpio.h
+++ b/include/hw/gpio/nrf51_gpio.h
@@ -27,8 +27,9 @@
#define NRF51_GPIO_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_NRF51_GPIO "nrf51_soc.gpio"
-#define NRF51_GPIO(obj) OBJECT_CHECK(NRF51GPIOState, (obj), TYPE_NRF51_GPIO)
+OBJECT_DECLARE_SIMPLE_TYPE(NRF51GPIOState, NRF51_GPIO)
#define NRF51_GPIO_PINS 32
@@ -47,7 +48,7 @@
#define NRF51_GPIO_PULLDOWN 1
#define NRF51_GPIO_PULLUP 3
-typedef struct NRF51GPIOState {
+struct NRF51GPIOState {
SysBusDevice parent_obj;
MemoryRegion mmio;
@@ -63,7 +64,8 @@ typedef struct NRF51GPIOState {
uint32_t old_out_connected;
qemu_irq output[NRF51_GPIO_PINS];
-} NRF51GPIOState;
+ qemu_irq detect;
+};
#endif
diff --git a/include/hw/misc/pca9552.h b/include/hw/gpio/pca9552.h
index 600356fbf9..c36525f0c3 100644
--- a/include/hw/misc/pca9552.h
+++ b/include/hw/gpio/pca9552.h
@@ -10,15 +10,18 @@
#define PCA9552_H
#include "hw/i2c/i2c.h"
+#include "qom/object.h"
#define TYPE_PCA9552 "pca9552"
#define TYPE_PCA955X "pca955x"
-#define PCA955X(obj) OBJECT_CHECK(PCA955xState, (obj), TYPE_PCA955X)
+typedef struct PCA955xState PCA955xState;
+DECLARE_INSTANCE_CHECKER(PCA955xState, PCA955X,
+ TYPE_PCA955X)
#define PCA955X_NR_REGS 10
#define PCA955X_PIN_COUNT_MAX 16
-typedef struct PCA955xState {
+struct PCA955xState {
/*< private >*/
I2CSlave i2c;
/*< public >*/
@@ -27,8 +30,9 @@ typedef struct PCA955xState {
uint8_t pointer;
uint8_t regs[PCA955X_NR_REGS];
- qemu_irq gpio[PCA955X_PIN_COUNT_MAX];
+ qemu_irq gpio_out[PCA955X_PIN_COUNT_MAX];
+ uint8_t ext_state[PCA955X_PIN_COUNT_MAX];
char *description; /* For debugging purpose only */
-} PCA955xState;
+};
#endif
diff --git a/include/hw/misc/pca9552_regs.h b/include/hw/gpio/pca9552_regs.h
index d8051cfbd6..d8051cfbd6 100644
--- a/include/hw/misc/pca9552_regs.h
+++ b/include/hw/gpio/pca9552_regs.h
diff --git a/include/hw/gpio/pca9554.h b/include/hw/gpio/pca9554.h
new file mode 100644
index 0000000000..54bfc4c4c7
--- /dev/null
+++ b/include/hw/gpio/pca9554.h
@@ -0,0 +1,36 @@
+/*
+ * PCA9554 I/O port
+ *
+ * Copyright (c) 2023, IBM Corporation.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef PCA9554_H
+#define PCA9554_H
+
+#include "hw/i2c/i2c.h"
+#include "qom/object.h"
+
+#define TYPE_PCA9554 "pca9554"
+typedef struct PCA9554State PCA9554State;
+DECLARE_INSTANCE_CHECKER(PCA9554State, PCA9554,
+ TYPE_PCA9554)
+
+#define PCA9554_NR_REGS 4
+#define PCA9554_PIN_COUNT 8
+
+struct PCA9554State {
+ /*< private >*/
+ I2CSlave i2c;
+ /*< public >*/
+
+ uint8_t len;
+ uint8_t pointer;
+
+ uint8_t regs[PCA9554_NR_REGS];
+ qemu_irq gpio_out[PCA9554_PIN_COUNT];
+ uint8_t ext_state[PCA9554_PIN_COUNT];
+ char *description; /* For debugging purpose only */
+};
+
+#endif
diff --git a/include/hw/gpio/pca9554_regs.h b/include/hw/gpio/pca9554_regs.h
new file mode 100644
index 0000000000..602c4a90e0
--- /dev/null
+++ b/include/hw/gpio/pca9554_regs.h
@@ -0,0 +1,19 @@
+/*
+ * PCA9554 I/O port registers
+ *
+ * Copyright (c) 2023, IBM Corporation.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef PCA9554_REGS_H
+#define PCA9554_REGS_H
+
+/*
+ * Bits [0:1] are used to address a specific register.
+ */
+#define PCA9554_INPUT 0 /* read only input register */
+#define PCA9554_OUTPUT 1 /* read/write pin output state */
+#define PCA9554_POLARITY 2 /* Set polarity of input register */
+#define PCA9554_CONFIG 3 /* Set pins as inputs our ouputs */
+
+#endif
diff --git a/include/hw/gpio/pcf8574.h b/include/hw/gpio/pcf8574.h
new file mode 100644
index 0000000000..3291d7dbbc
--- /dev/null
+++ b/include/hw/gpio/pcf8574.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * NXP PCF8574 8-port I2C GPIO expansion chip.
+ *
+ * Copyright (c) 2024 KNS Group (YADRO).
+ * Written by Dmitrii Sharikhin <d.sharikhin@yadro.com>
+ */
+
+#ifndef _HW_GPIO_PCF8574
+#define _HW_GPIO_PCF8574
+
+#define TYPE_PCF8574 "pcf8574"
+
+#endif /* _HW_GPIO_PCF8574 */
diff --git a/include/hw/riscv/sifive_gpio.h b/include/hw/gpio/sifive_gpio.h
index cf12fcfd62..fc53785c9d 100644
--- a/include/hw/riscv/sifive_gpio.h
+++ b/include/hw/gpio/sifive_gpio.h
@@ -15,9 +15,12 @@
#define SIFIVE_GPIO_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_SIFIVE_GPIO "sifive_soc.gpio"
-#define SIFIVE_GPIO(obj) OBJECT_CHECK(SIFIVEGPIOState, (obj), TYPE_SIFIVE_GPIO)
+typedef struct SIFIVEGPIOState SIFIVEGPIOState;
+DECLARE_INSTANCE_CHECKER(SIFIVEGPIOState, SIFIVE_GPIO,
+ TYPE_SIFIVE_GPIO)
#define SIFIVE_GPIO_PINS 32
@@ -41,7 +44,7 @@
#define SIFIVE_GPIO_REG_IOF_SEL 0x03C
#define SIFIVE_GPIO_REG_OUT_XOR 0x040
-typedef struct SIFIVEGPIOState {
+struct SIFIVEGPIOState {
SysBusDevice parent_obj;
MemoryRegion mmio;
@@ -71,6 +74,6 @@ typedef struct SIFIVEGPIOState {
/* config */
uint32_t ngpio;
-} SIFIVEGPIOState;
+};
#endif /* SIFIVE_GPIO_H */
diff --git a/include/hw/gpio/stm32l4x5_gpio.h b/include/hw/gpio/stm32l4x5_gpio.h
new file mode 100644
index 0000000000..878bd19fc9
--- /dev/null
+++ b/include/hw/gpio/stm32l4x5_gpio.h
@@ -0,0 +1,71 @@
+/*
+ * STM32L4x5 GPIO (General Purpose Input/Ouput)
+ *
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+/*
+ * The reference used is the STMicroElectronics RM0351 Reference manual
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
+ */
+
+#ifndef HW_STM32L4X5_GPIO_H
+#define HW_STM32L4X5_GPIO_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_STM32L4X5_GPIO "stm32l4x5-gpio"
+OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5GpioState, STM32L4X5_GPIO)
+
+#define NUM_GPIOS 8
+#define GPIO_NUM_PINS 16
+
+struct Stm32l4x5GpioState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion mmio;
+
+ /* GPIO registers */
+ uint32_t moder;
+ uint32_t otyper;
+ uint32_t ospeedr;
+ uint32_t pupdr;
+ uint32_t idr;
+ uint32_t odr;
+ uint32_t lckr;
+ uint32_t afrl;
+ uint32_t afrh;
+ uint32_t ascr;
+
+ /* GPIO registers reset values */
+ uint32_t moder_reset;
+ uint32_t ospeedr_reset;
+ uint32_t pupdr_reset;
+
+ /*
+ * External driving of pins.
+ * The pins can be set externally through the device
+ * anonymous input GPIOs lines under certain conditions.
+ * The pin must not be in push-pull output mode,
+ * and can't be set high in open-drain mode.
+ * Pins driven externally and configured to
+ * output mode will in general be "disconnected"
+ * (see `get_gpio_pinmask_to_disconnect()`)
+ */
+ uint16_t disconnected_pins;
+ uint16_t pins_connected_high;
+
+ char *name;
+ Clock *clk;
+ qemu_irq pin[GPIO_NUM_PINS];
+};
+
+#endif
diff --git a/include/hw/hotplug.h b/include/hw/hotplug.h
index 6321e292fd..a9840ed485 100644
--- a/include/hw/hotplug.h
+++ b/include/hw/hotplug.h
@@ -16,10 +16,9 @@
#define TYPE_HOTPLUG_HANDLER "hotplug-handler"
-#define HOTPLUG_HANDLER_CLASS(klass) \
- OBJECT_CLASS_CHECK(HotplugHandlerClass, (klass), TYPE_HOTPLUG_HANDLER)
-#define HOTPLUG_HANDLER_GET_CLASS(obj) \
- OBJECT_GET_CLASS(HotplugHandlerClass, (obj), TYPE_HOTPLUG_HANDLER)
+typedef struct HotplugHandlerClass HotplugHandlerClass;
+DECLARE_CLASS_CHECKERS(HotplugHandlerClass, HOTPLUG_HANDLER,
+ TYPE_HOTPLUG_HANDLER)
#define HOTPLUG_HANDLER(obj) \
INTERFACE_CHECK(HotplugHandler, (obj), TYPE_HOTPLUG_HANDLER)
@@ -49,8 +48,9 @@ typedef void (*hotplug_fn)(HotplugHandler *plug_handler,
* @unplug: unplug callback.
* Used for device removal with devices that implement
* asynchronous and synchronous (surprise) removal.
+ * @is_hotpluggable_bus: called to check if bus/its parent allow hotplug on bus
*/
-typedef struct HotplugHandlerClass {
+struct HotplugHandlerClass {
/* <private> */
InterfaceClass parent;
@@ -59,7 +59,8 @@ typedef struct HotplugHandlerClass {
hotplug_fn plug;
hotplug_fn unplug_request;
hotplug_fn unplug;
-} HotplugHandlerClass;
+ bool (*is_hotpluggable_bus)(HotplugHandler *plug_handler, BusState *bus);
+};
/**
* hotplug_handler_plug:
diff --git a/include/hw/hw.h b/include/hw/hw.h
index fc5301f293..045c1c8b09 100644
--- a/include/hw/hw.h
+++ b/include/hw/hw.h
@@ -5,6 +5,6 @@
#error Cannot include hw/hw.h from user emulation
#endif
-void QEMU_NORETURN hw_error(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
+G_NORETURN void hw_error(const char *fmt, ...) G_GNUC_PRINTF(1, 2);
#endif
diff --git a/include/hw/hyperv/dynmem-proto.h b/include/hw/hyperv/dynmem-proto.h
new file mode 100644
index 0000000000..68b8b606f2
--- /dev/null
+++ b/include/hw/hyperv/dynmem-proto.h
@@ -0,0 +1,430 @@
+#ifndef HW_HYPERV_DYNMEM_PROTO_H
+#define HW_HYPERV_DYNMEM_PROTO_H
+
+/*
+ * Hyper-V Dynamic Memory Protocol definitions
+ *
+ * Copyright (C) 2020-2023 Oracle and/or its affiliates.
+ *
+ * Based on drivers/hv/hv_balloon.c from Linux kernel:
+ * Copyright (c) 2012, Microsoft Corporation.
+ *
+ * Author: K. Y. Srinivasan <kys@microsoft.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ * See the COPYING file in the top-level directory.
+ */
+
+/*
+ * Protocol versions. The low word is the minor version, the high word the major
+ * version.
+ *
+ * History:
+ * Initial version 1.0
+ * Changed to 0.1 on 2009/03/25
+ * Changes to 0.2 on 2009/05/14
+ * Changes to 0.3 on 2009/12/03
+ * Changed to 1.0 on 2011/04/05
+ * Changed to 2.0 on 2019/12/10
+ */
+
+#define DYNMEM_MAKE_VERSION(Major, Minor) ((uint32_t)(((Major) << 16) | (Minor)))
+#define DYNMEM_MAJOR_VERSION(Version) ((uint32_t)(Version) >> 16)
+#define DYNMEM_MINOR_VERSION(Version) ((uint32_t)(Version) & 0xff)
+
+enum {
+ DYNMEM_PROTOCOL_VERSION_1 = DYNMEM_MAKE_VERSION(0, 3),
+ DYNMEM_PROTOCOL_VERSION_2 = DYNMEM_MAKE_VERSION(1, 0),
+ DYNMEM_PROTOCOL_VERSION_3 = DYNMEM_MAKE_VERSION(2, 0),
+
+ DYNMEM_PROTOCOL_VERSION_WIN7 = DYNMEM_PROTOCOL_VERSION_1,
+ DYNMEM_PROTOCOL_VERSION_WIN8 = DYNMEM_PROTOCOL_VERSION_2,
+ DYNMEM_PROTOCOL_VERSION_WIN10 = DYNMEM_PROTOCOL_VERSION_3,
+
+ DYNMEM_PROTOCOL_VERSION_CURRENT = DYNMEM_PROTOCOL_VERSION_WIN10
+};
+
+
+
+/*
+ * Message Types
+ */
+
+enum dm_message_type {
+ /*
+ * Version 0.3
+ */
+ DM_ERROR = 0,
+ DM_VERSION_REQUEST = 1,
+ DM_VERSION_RESPONSE = 2,
+ DM_CAPABILITIES_REPORT = 3,
+ DM_CAPABILITIES_RESPONSE = 4,
+ DM_STATUS_REPORT = 5,
+ DM_BALLOON_REQUEST = 6,
+ DM_BALLOON_RESPONSE = 7,
+ DM_UNBALLOON_REQUEST = 8,
+ DM_UNBALLOON_RESPONSE = 9,
+ DM_MEM_HOT_ADD_REQUEST = 10,
+ DM_MEM_HOT_ADD_RESPONSE = 11,
+ DM_VERSION_03_MAX = 11,
+ /*
+ * Version 1.0.
+ */
+ DM_INFO_MESSAGE = 12,
+ DM_VERSION_1_MAX = 12,
+
+ /*
+ * Version 2.0
+ */
+ DM_MEM_HOT_REMOVE_REQUEST = 13,
+ DM_MEM_HOT_REMOVE_RESPONSE = 14
+};
+
+
+/*
+ * Structures defining the dynamic memory management
+ * protocol.
+ */
+
+union dm_version {
+ struct {
+ uint16_t minor_version;
+ uint16_t major_version;
+ };
+ uint32_t version;
+} QEMU_PACKED;
+
+
+union dm_caps {
+ struct {
+ uint64_t balloon:1;
+ uint64_t hot_add:1;
+ /*
+ * To support guests that may have alignment
+ * limitations on hot-add, the guest can specify
+ * its alignment requirements; a value of n
+ * represents an alignment of 2^n in mega bytes.
+ */
+ uint64_t hot_add_alignment:4;
+ uint64_t hot_remove:1;
+ uint64_t reservedz:57;
+ } cap_bits;
+ uint64_t caps;
+} QEMU_PACKED;
+
+union dm_mem_page_range {
+ struct {
+ /*
+ * The PFN number of the first page in the range.
+ * 40 bits is the architectural limit of a PFN
+ * number for AMD64.
+ */
+ uint64_t start_page:40;
+ /*
+ * The number of pages in the range.
+ */
+ uint64_t page_cnt:24;
+ } finfo;
+ uint64_t page_range;
+} QEMU_PACKED;
+
+
+
+/*
+ * The header for all dynamic memory messages:
+ *
+ * type: Type of the message.
+ * size: Size of the message in bytes; including the header.
+ * trans_id: The guest is responsible for manufacturing this ID.
+ */
+
+struct dm_header {
+ uint16_t type;
+ uint16_t size;
+ uint32_t trans_id;
+} QEMU_PACKED;
+
+/*
+ * A generic message format for dynamic memory.
+ * Specific message formats are defined later in the file.
+ */
+
+struct dm_message {
+ struct dm_header hdr;
+ uint8_t data[]; /* enclosed message */
+} QEMU_PACKED;
+
+
+/*
+ * Specific message types supporting the dynamic memory protocol.
+ */
+
+/*
+ * Version negotiation message. Sent from the guest to the host.
+ * The guest is free to try different versions until the host
+ * accepts the version.
+ *
+ * dm_version: The protocol version requested.
+ * is_last_attempt: If TRUE, this is the last version guest will request.
+ * reservedz: Reserved field, set to zero.
+ */
+
+struct dm_version_request {
+ struct dm_header hdr;
+ union dm_version version;
+ uint32_t is_last_attempt:1;
+ uint32_t reservedz:31;
+} QEMU_PACKED;
+
+/*
+ * Version response message; Host to Guest and indicates
+ * if the host has accepted the version sent by the guest.
+ *
+ * is_accepted: If TRUE, host has accepted the version and the guest
+ * should proceed to the next stage of the protocol. FALSE indicates that
+ * guest should re-try with a different version.
+ *
+ * reservedz: Reserved field, set to zero.
+ */
+
+struct dm_version_response {
+ struct dm_header hdr;
+ uint64_t is_accepted:1;
+ uint64_t reservedz:63;
+} QEMU_PACKED;
+
+/*
+ * Message reporting capabilities. This is sent from the guest to the
+ * host.
+ */
+
+struct dm_capabilities {
+ struct dm_header hdr;
+ union dm_caps caps;
+ uint64_t min_page_cnt;
+ uint64_t max_page_number;
+} QEMU_PACKED;
+
+/*
+ * Response to the capabilities message. This is sent from the host to the
+ * guest. This message notifies if the host has accepted the guest's
+ * capabilities. If the host has not accepted, the guest must shutdown
+ * the service.
+ *
+ * is_accepted: Indicates if the host has accepted guest's capabilities.
+ * reservedz: Must be 0.
+ */
+
+struct dm_capabilities_resp_msg {
+ struct dm_header hdr;
+ uint64_t is_accepted:1;
+ uint64_t hot_remove:1;
+ uint64_t suppress_pressure_reports:1;
+ uint64_t reservedz:61;
+} QEMU_PACKED;
+
+/*
+ * This message is used to report memory pressure from the guest.
+ * This message is not part of any transaction and there is no
+ * response to this message.
+ *
+ * num_avail: Available memory in pages.
+ * num_committed: Committed memory in pages.
+ * page_file_size: The accumulated size of all page files
+ * in the system in pages.
+ * zero_free: The number of zero and free pages.
+ * page_file_writes: The writes to the page file in pages.
+ * io_diff: An indicator of file cache efficiency or page file activity,
+ * calculated as File Cache Page Fault Count - Page Read Count.
+ * This value is in pages.
+ *
+ * Some of these metrics are Windows specific and fortunately
+ * the algorithm on the host side that computes the guest memory
+ * pressure only uses num_committed value.
+ */
+
+struct dm_status {
+ struct dm_header hdr;
+ uint64_t num_avail;
+ uint64_t num_committed;
+ uint64_t page_file_size;
+ uint64_t zero_free;
+ uint32_t page_file_writes;
+ uint32_t io_diff;
+} QEMU_PACKED;
+
+
+/*
+ * Message to ask the guest to allocate memory - balloon up message.
+ * This message is sent from the host to the guest. The guest may not be
+ * able to allocate as much memory as requested.
+ *
+ * num_pages: number of pages to allocate.
+ */
+
+struct dm_balloon {
+ struct dm_header hdr;
+ uint32_t num_pages;
+ uint32_t reservedz;
+} QEMU_PACKED;
+
+
+/*
+ * Balloon response message; this message is sent from the guest
+ * to the host in response to the balloon message.
+ *
+ * reservedz: Reserved; must be set to zero.
+ * more_pages: If FALSE, this is the last message of the transaction.
+ * if TRUE there will be at least one more message from the guest.
+ *
+ * range_count: The number of ranges in the range array.
+ *
+ * range_array: An array of page ranges returned to the host.
+ *
+ */
+
+struct dm_balloon_response {
+ struct dm_header hdr;
+ uint32_t reservedz;
+ uint32_t more_pages:1;
+ uint32_t range_count:31;
+ union dm_mem_page_range range_array[];
+} QEMU_PACKED;
+
+/*
+ * Un-balloon message; this message is sent from the host
+ * to the guest to give guest more memory.
+ *
+ * more_pages: If FALSE, this is the last message of the transaction.
+ * if TRUE there will be at least one more message from the guest.
+ *
+ * reservedz: Reserved; must be set to zero.
+ *
+ * range_count: The number of ranges in the range array.
+ *
+ * range_array: An array of page ranges returned to the host.
+ *
+ */
+
+struct dm_unballoon_request {
+ struct dm_header hdr;
+ uint32_t more_pages:1;
+ uint32_t reservedz:31;
+ uint32_t range_count;
+ union dm_mem_page_range range_array[];
+} QEMU_PACKED;
+
+/*
+ * Un-balloon response message; this message is sent from the guest
+ * to the host in response to an unballoon request.
+ *
+ */
+
+struct dm_unballoon_response {
+ struct dm_header hdr;
+} QEMU_PACKED;
+
+
+/*
+ * Hot add request message. Message sent from the host to the guest.
+ *
+ * range: Memory range to hot add.
+ * region: Explicit hot add memory region for guest to use. Optional.
+ *
+ */
+
+struct dm_hot_add {
+ struct dm_header hdr;
+ union dm_mem_page_range range;
+} QEMU_PACKED;
+
+struct dm_hot_add_with_region {
+ struct dm_header hdr;
+ union dm_mem_page_range range;
+ union dm_mem_page_range region;
+} QEMU_PACKED;
+
+/*
+ * Hot add response message.
+ * This message is sent by the guest to report the status of a hot add request.
+ * If page_count is less than the requested page count, then the host should
+ * assume all further hot add requests will fail, since this indicates that
+ * the guest has hit an upper physical memory barrier.
+ *
+ * Hot adds may also fail due to low resources; in this case, the guest must
+ * not complete this message until the hot add can succeed, and the host must
+ * not send a new hot add request until the response is sent.
+ * If VSC fails to hot add memory DYNMEM_NUMBER_OF_UNSUCCESSFUL_HOTADD_ATTEMPTS
+ * times it fails the request.
+ *
+ *
+ * page_count: number of pages that were successfully hot added.
+ *
+ * result: result of the operation 1: success, 0: failure.
+ *
+ */
+
+struct dm_hot_add_response {
+ struct dm_header hdr;
+ uint32_t page_count;
+ uint32_t result;
+} QEMU_PACKED;
+
+struct dm_hot_remove {
+ struct dm_header hdr;
+ uint32_t virtual_node;
+ uint32_t page_count;
+ uint32_t qos_flags;
+ uint32_t reservedZ;
+} QEMU_PACKED;
+
+struct dm_hot_remove_response {
+ struct dm_header hdr;
+ uint32_t result;
+ uint32_t range_count;
+ uint64_t more_pages:1;
+ uint64_t reservedz:63;
+ union dm_mem_page_range range_array[];
+} QEMU_PACKED;
+
+#define DM_REMOVE_QOS_LARGE (1 << 0)
+#define DM_REMOVE_QOS_LOCAL (1 << 1)
+#define DM_REMOVE_QOS_MASK (0x3)
+
+/*
+ * Types of information sent from host to the guest.
+ */
+
+enum dm_info_type {
+ INFO_TYPE_MAX_PAGE_CNT = 0,
+ MAX_INFO_TYPE
+};
+
+
+/*
+ * Header for the information message.
+ */
+
+struct dm_info_header {
+ enum dm_info_type type;
+ uint32_t data_size;
+ uint8_t data[];
+} QEMU_PACKED;
+
+/*
+ * This message is sent from the host to the guest to pass
+ * some relevant information (win8 addition).
+ *
+ * reserved: no used.
+ * info_size: size of the information blob.
+ * info: information blob.
+ */
+
+struct dm_info_msg {
+ struct dm_header hdr;
+ uint32_t reserved;
+ uint32_t info_size;
+ uint8_t info[];
+};
+
+#endif
diff --git a/include/hw/hyperv/hv-balloon.h b/include/hw/hyperv/hv-balloon.h
new file mode 100644
index 0000000000..c1efe70fc2
--- /dev/null
+++ b/include/hw/hyperv/hv-balloon.h
@@ -0,0 +1,18 @@
+/*
+ * QEMU Hyper-V Dynamic Memory Protocol driver
+ *
+ * Copyright (C) 2020-2023 Oracle and/or its affiliates.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef HW_HV_BALLOON_H
+#define HW_HV_BALLOON_H
+
+#include "qom/object.h"
+
+#define TYPE_HV_BALLOON "hv-balloon"
+OBJECT_DECLARE_SIMPLE_TYPE(HvBalloon, HV_BALLOON)
+
+#endif
diff --git a/include/hw/hyperv/hyperv-proto.h b/include/hw/hyperv/hyperv-proto.h
index 21dc28aee9..4a2297307b 100644
--- a/include/hw/hyperv/hyperv-proto.h
+++ b/include/hw/hyperv/hyperv-proto.h
@@ -24,12 +24,17 @@
#define HV_STATUS_INVALID_PORT_ID 17
#define HV_STATUS_INVALID_CONNECTION_ID 18
#define HV_STATUS_INSUFFICIENT_BUFFERS 19
+#define HV_STATUS_NOT_ACKNOWLEDGED 20
+#define HV_STATUS_NO_DATA 27
/*
* Hypercall numbers
*/
#define HV_POST_MESSAGE 0x005c
#define HV_SIGNAL_EVENT 0x005d
+#define HV_POST_DEBUG_DATA 0x0069
+#define HV_RETRIEVE_DEBUG_DATA 0x006a
+#define HV_RESET_DEBUG_SESSION 0x006b
#define HV_HYPERCALL_FAST (1u << 16)
/*
@@ -127,4 +132,51 @@ struct hyperv_event_flags_page {
struct hyperv_event_flags slot[HV_SINT_COUNT];
};
+/*
+ * Kernel debugger structures
+ */
+
+/* Options flags for hyperv_reset_debug_session */
+#define HV_DEBUG_PURGE_INCOMING_DATA 0x00000001
+#define HV_DEBUG_PURGE_OUTGOING_DATA 0x00000002
+struct hyperv_reset_debug_session_input {
+ uint32_t options;
+} __attribute__ ((__packed__));
+
+struct hyperv_reset_debug_session_output {
+ uint32_t host_ip;
+ uint32_t target_ip;
+ uint16_t host_port;
+ uint16_t target_port;
+ uint8_t host_mac[6];
+ uint8_t target_mac[6];
+} __attribute__ ((__packed__));
+
+/* Options for hyperv_post_debug_data */
+#define HV_DEBUG_POST_LOOP 0x00000001
+
+struct hyperv_post_debug_data_input {
+ uint32_t count;
+ uint32_t options;
+ /*uint8_t data[HV_HYP_PAGE_SIZE - 2 * sizeof(uint32_t)];*/
+} __attribute__ ((__packed__));
+
+struct hyperv_post_debug_data_output {
+ uint32_t pending_count;
+} __attribute__ ((__packed__));
+
+/* Options for hyperv_retrieve_debug_data */
+#define HV_DEBUG_RETRIEVE_LOOP 0x00000001
+#define HV_DEBUG_RETRIEVE_TEST_ACTIVITY 0x00000002
+
+struct hyperv_retrieve_debug_data_input {
+ uint32_t count;
+ uint32_t options;
+ uint64_t timeout;
+} __attribute__ ((__packed__));
+
+struct hyperv_retrieve_debug_data_output {
+ uint32_t retrieved_count;
+ uint32_t remaining_count;
+} __attribute__ ((__packed__));
#endif
diff --git a/include/hw/hyperv/hyperv.h b/include/hw/hyperv/hyperv.h
index a63ee0003c..d717b4e13d 100644
--- a/include/hw/hyperv/hyperv.h
+++ b/include/hw/hyperv/hyperv.h
@@ -81,4 +81,66 @@ void hyperv_synic_update(CPUState *cs, bool enable,
hwaddr msg_page_addr, hwaddr event_page_addr);
bool hyperv_is_synic_enabled(void);
+/*
+ * Process HVCALL_RESET_DEBUG_SESSION hypercall.
+ */
+uint16_t hyperv_hcall_reset_dbg_session(uint64_t outgpa);
+/*
+ * Process HVCALL_RETREIVE_DEBUG_DATA hypercall.
+ */
+uint16_t hyperv_hcall_retreive_dbg_data(uint64_t ingpa, uint64_t outgpa,
+ bool fast);
+/*
+ * Process HVCALL_POST_DEBUG_DATA hypercall.
+ */
+uint16_t hyperv_hcall_post_dbg_data(uint64_t ingpa, uint64_t outgpa, bool fast);
+
+uint32_t hyperv_syndbg_send(uint64_t ingpa, uint32_t count);
+uint32_t hyperv_syndbg_recv(uint64_t ingpa, uint32_t count);
+void hyperv_syndbg_set_pending_page(uint64_t ingpa);
+uint64_t hyperv_syndbg_query_options(void);
+
+typedef enum HvSynthDbgMsgType {
+ HV_SYNDBG_MSG_CONNECTION_INFO,
+ HV_SYNDBG_MSG_SEND,
+ HV_SYNDBG_MSG_RECV,
+ HV_SYNDBG_MSG_SET_PENDING_PAGE,
+ HV_SYNDBG_MSG_QUERY_OPTIONS
+} HvDbgSynthMsgType;
+
+typedef struct HvSynDbgMsg {
+ HvDbgSynthMsgType type;
+ union {
+ struct {
+ uint32_t host_ip;
+ uint16_t host_port;
+ } connection_info;
+ struct {
+ uint64_t buf_gpa;
+ uint32_t count;
+ uint32_t pending_count;
+ bool is_raw;
+ } send;
+ struct {
+ uint64_t buf_gpa;
+ uint32_t count;
+ uint32_t options;
+ uint64_t timeout;
+ uint32_t retrieved_count;
+ bool is_raw;
+ } recv;
+ struct {
+ uint64_t buf_gpa;
+ } pending_page;
+ struct {
+ uint64_t options;
+ } query_options;
+ } u;
+} HvSynDbgMsg;
+typedef uint16_t (*HvSynDbgHandler)(void *context, HvSynDbgMsg *msg);
+void hyperv_set_syndbg_handler(HvSynDbgHandler handler, void *context);
+
+bool hyperv_are_vmbus_recommended_features_enabled(void);
+void hyperv_set_vmbus_recommended_features_enabled(void);
+
#endif
diff --git a/include/hw/hyperv/vmbus-bridge.h b/include/hw/hyperv/vmbus-bridge.h
index 33f93de64d..1e5419574e 100644
--- a/include/hw/hyperv/vmbus-bridge.h
+++ b/include/hw/hyperv/vmbus-bridge.h
@@ -11,20 +11,20 @@
#define HW_HYPERV_VMBUS_BRIDGE_H
#include "hw/sysbus.h"
+#include "hw/hyperv/vmbus.h"
+#include "qom/object.h"
#define TYPE_VMBUS_BRIDGE "vmbus-bridge"
-typedef struct VMBus VMBus;
-
-typedef struct VMBusBridge {
+struct VMBusBridge {
SysBusDevice parent_obj;
uint8_t irq;
VMBus *bus;
-} VMBusBridge;
+};
-#define VMBUS_BRIDGE(obj) OBJECT_CHECK(VMBusBridge, (obj), TYPE_VMBUS_BRIDGE)
+OBJECT_DECLARE_SIMPLE_TYPE(VMBusBridge, VMBUS_BRIDGE)
static inline VMBusBridge *vmbus_bridge_find(void)
{
diff --git a/include/hw/hyperv/vmbus.h b/include/hw/hyperv/vmbus.h
index 40e8417eec..5c505852f2 100644
--- a/include/hw/hyperv/vmbus.h
+++ b/include/hw/hyperv/vmbus.h
@@ -16,15 +16,15 @@
#include "migration/vmstate.h"
#include "hw/hyperv/vmbus-proto.h"
#include "qemu/uuid.h"
+#include "qom/object.h"
#define TYPE_VMBUS_DEVICE "vmbus-dev"
-#define VMBUS_DEVICE(obj) \
- OBJECT_CHECK(VMBusDevice, (obj), TYPE_VMBUS_DEVICE)
-#define VMBUS_DEVICE_CLASS(klass) \
- OBJECT_CLASS_CHECK(VMBusDeviceClass, (klass), TYPE_VMBUS_DEVICE)
-#define VMBUS_DEVICE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(VMBusDeviceClass, (obj), TYPE_VMBUS_DEVICE)
+OBJECT_DECLARE_TYPE(VMBusDevice, VMBusDeviceClass,
+ VMBUS_DEVICE)
+
+#define TYPE_VMBUS "vmbus"
+OBJECT_DECLARE_SIMPLE_TYPE(VMBus, VMBUS)
/*
* Object wrapping a GPADL -- GPA Descriptor List -- an array of guest physical
@@ -40,11 +40,10 @@ typedef struct VMBusChannel VMBusChannel;
* Base class for VMBus devices. Includes one or more channels. Identified by
* class GUID and instance GUID.
*/
-typedef struct VMBusDevice VMBusDevice;
typedef void(*VMBusChannelNotifyCb)(struct VMBusChannel *chan);
-typedef struct VMBusDeviceClass {
+struct VMBusDeviceClass {
DeviceClass parent;
QemuUUID classid;
@@ -52,7 +51,7 @@ typedef struct VMBusDeviceClass {
uint16_t channel_flags;
uint16_t mmio_size_mb;
- /* Extentions to standard device callbacks */
+ /* Extensions to standard device callbacks */
void (*vmdev_realize)(VMBusDevice *vdev, Error **errp);
void (*vmdev_unrealize)(VMBusDevice *vdev);
void (*vmdev_reset)(VMBusDevice *vdev);
@@ -76,7 +75,7 @@ typedef struct VMBusDeviceClass {
* side, when there's work to do with the data in the channel ring buffers.
*/
VMBusChannelNotifyCb chan_notify_cb;
-} VMBusDeviceClass;
+};
struct VMBusDevice {
DeviceState parent;
@@ -224,7 +223,4 @@ int vmbus_map_sgl(VMBusChanReq *req, DMADirection dir, struct iovec *iov,
void vmbus_unmap_sgl(VMBusChanReq *req, DMADirection dir, struct iovec *iov,
unsigned iov_cnt, size_t accessed);
-void vmbus_save_req(QEMUFile *f, VMBusChanReq *req);
-void *vmbus_load_req(QEMUFile *f, VMBusDevice *dev, uint32_t size);
-
#endif
diff --git a/include/hw/i2c/allwinner-i2c.h b/include/hw/i2c/allwinner-i2c.h
new file mode 100644
index 0000000000..0e325d265e
--- /dev/null
+++ b/include/hw/i2c/allwinner-i2c.h
@@ -0,0 +1,61 @@
+/*
+ * Allwinner I2C Bus Serial Interface registers definition
+ *
+ * Copyright (C) 2022 Strahinja Jankovic. <strahinja.p.jankovic@gmail.com>
+ *
+ * This file is derived from IMX I2C controller,
+ * by Jean-Christophe DUBOIS .
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef ALLWINNER_I2C_H
+#define ALLWINNER_I2C_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_AW_I2C "allwinner.i2c"
+
+/** Allwinner I2C sun6i family and newer (A31, H2+, H3, etc) */
+#define TYPE_AW_I2C_SUN6I TYPE_AW_I2C "-sun6i"
+
+OBJECT_DECLARE_SIMPLE_TYPE(AWI2CState, AW_I2C)
+
+#define AW_I2C_MEM_SIZE 0x24
+
+struct AWI2CState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+ I2CBus *bus;
+ qemu_irq irq;
+
+ uint8_t addr;
+ uint8_t xaddr;
+ uint8_t data;
+ uint8_t cntr;
+ uint8_t stat;
+ uint8_t ccr;
+ uint8_t srst;
+ uint8_t efr;
+ uint8_t lcr;
+
+ bool irq_clear_inverted;
+};
+
+#endif /* ALLWINNER_I2C_H */
diff --git a/include/hw/i2c/arm_sbcon_i2c.h b/include/hw/i2c/arm_sbcon_i2c.h
index 5d96507ab6..da9b5e8f83 100644
--- a/include/hw/i2c/arm_sbcon_i2c.h
+++ b/include/hw/i2c/arm_sbcon_i2c.h
@@ -9,19 +9,20 @@
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
-#ifndef HW_I2C_ARM_SBCON_H
-#define HW_I2C_ARM_SBCON_H
+
+#ifndef HW_I2C_ARM_SBCON_I2C_H
+#define HW_I2C_ARM_SBCON_I2C_H
#include "hw/sysbus.h"
#include "hw/i2c/bitbang_i2c.h"
+#include "qom/object.h"
-#define TYPE_VERSATILE_I2C "versatile_i2c"
-#define TYPE_ARM_SBCON_I2C TYPE_VERSATILE_I2C
+#define TYPE_ARM_SBCON_I2C "versatile_i2c"
-#define ARM_SBCON_I2C(obj) \
- OBJECT_CHECK(ArmSbconI2CState, (obj), TYPE_ARM_SBCON_I2C)
+typedef struct ArmSbconI2CState ArmSbconI2CState;
+DECLARE_INSTANCE_CHECKER(ArmSbconI2CState, ARM_SBCON_I2C, TYPE_ARM_SBCON_I2C)
-typedef struct ArmSbconI2CState {
+struct ArmSbconI2CState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -30,6 +31,6 @@ typedef struct ArmSbconI2CState {
bitbang_i2c_interface bitbang;
int out;
int in;
-} ArmSbconI2CState;
+};
-#endif /* HW_I2C_ARM_SBCON_H */
+#endif /* HW_I2C_ARM_SBCON_I2C_H */
diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h
index 243789ae5d..a064479e59 100644
--- a/include/hw/i2c/aspeed_i2c.h
+++ b/include/hw/i2c/aspeed_i2c.h
@@ -23,40 +23,231 @@
#include "hw/i2c/i2c.h"
#include "hw/sysbus.h"
+#include "hw/registerfields.h"
+#include "qom/object.h"
#define TYPE_ASPEED_I2C "aspeed.i2c"
#define TYPE_ASPEED_2400_I2C TYPE_ASPEED_I2C "-ast2400"
#define TYPE_ASPEED_2500_I2C TYPE_ASPEED_I2C "-ast2500"
#define TYPE_ASPEED_2600_I2C TYPE_ASPEED_I2C "-ast2600"
-#define ASPEED_I2C(obj) \
- OBJECT_CHECK(AspeedI2CState, (obj), TYPE_ASPEED_I2C)
+#define TYPE_ASPEED_1030_I2C TYPE_ASPEED_I2C "-ast1030"
+OBJECT_DECLARE_TYPE(AspeedI2CState, AspeedI2CClass, ASPEED_I2C)
#define ASPEED_I2C_NR_BUSSES 16
#define ASPEED_I2C_MAX_POOL_SIZE 0x800
+#define ASPEED_I2C_OLD_NUM_REG 11
+#define ASPEED_I2C_NEW_NUM_REG 22
+
+#define A_I2CD_M_STOP_CMD BIT(5)
+#define A_I2CD_M_RX_CMD BIT(3)
+#define A_I2CD_M_TX_CMD BIT(1)
+#define A_I2CD_M_START_CMD BIT(0)
+
+#define A_I2CD_MASTER_EN BIT(0)
+
+/* Tx State Machine */
+#define I2CD_TX_STATE_MASK 0xf
+#define I2CD_IDLE 0x0
+#define I2CD_MACTIVE 0x8
+#define I2CD_MSTART 0x9
+#define I2CD_MSTARTR 0xa
+#define I2CD_MSTOP 0xb
+#define I2CD_MTXD 0xc
+#define I2CD_MRXACK 0xd
+#define I2CD_MRXD 0xe
+#define I2CD_MTXACK 0xf
+#define I2CD_SWAIT 0x1
+#define I2CD_SRXD 0x4
+#define I2CD_STXACK 0x5
+#define I2CD_STXD 0x6
+#define I2CD_SRXACK 0x7
+#define I2CD_RECOVER 0x3
+
+/* I2C Global Register */
+REG32(I2C_CTRL_STATUS, 0x0) /* Device Interrupt Status */
+REG32(I2C_CTRL_ASSIGN, 0x8) /* Device Interrupt Target Assignment */
+REG32(I2C_CTRL_GLOBAL, 0xC) /* Global Control Register */
+ FIELD(I2C_CTRL_GLOBAL, REG_MODE, 2, 1)
+ FIELD(I2C_CTRL_GLOBAL, SRAM_EN, 0, 1)
+REG32(I2C_CTRL_NEW_CLK_DIVIDER, 0x10) /* New mode clock divider */
+
+/* I2C Old Mode Device (Bus) Register */
+REG32(I2CD_FUN_CTRL, 0x0) /* I2CD Function Control */
+ FIELD(I2CD_FUN_CTRL, POOL_PAGE_SEL, 20, 3) /* AST2400 */
+ SHARED_FIELD(M_SDA_LOCK_EN, 16, 1)
+ SHARED_FIELD(MULTI_MASTER_DIS, 15, 1)
+ SHARED_FIELD(M_SCL_DRIVE_EN, 14, 1)
+ SHARED_FIELD(MSB_STS, 9, 1)
+ SHARED_FIELD(SDA_DRIVE_IT_EN, 8, 1)
+ SHARED_FIELD(M_SDA_DRIVE_IT_EN, 7, 1)
+ SHARED_FIELD(M_HIGH_SPEED_EN, 6, 1)
+ SHARED_FIELD(DEF_ADDR_EN, 5, 1)
+ SHARED_FIELD(DEF_ALERT_EN, 4, 1)
+ SHARED_FIELD(DEF_ARP_EN, 3, 1)
+ SHARED_FIELD(DEF_GCALL_EN, 2, 1)
+ SHARED_FIELD(SLAVE_EN, 1, 1)
+ SHARED_FIELD(MASTER_EN, 0, 1)
+REG32(I2CD_AC_TIMING1, 0x04) /* Clock and AC Timing Control #1 */
+REG32(I2CD_AC_TIMING2, 0x08) /* Clock and AC Timing Control #2 */
+REG32(I2CD_INTR_CTRL, 0x0C) /* I2CD Interrupt Control */
+REG32(I2CD_INTR_STS, 0x10) /* I2CD Interrupt Status */
+ SHARED_FIELD(SLAVE_ADDR_MATCH, 31, 1) /* 0: addr1 1: addr2 */
+ SHARED_FIELD(SLAVE_ADDR_RX_PENDING, 29, 1)
+ SHARED_FIELD(SLAVE_INACTIVE_TIMEOUT, 15, 1)
+ SHARED_FIELD(SDA_DL_TIMEOUT, 14, 1)
+ SHARED_FIELD(BUS_RECOVER_DONE, 13, 1)
+ SHARED_FIELD(SMBUS_ALERT, 12, 1) /* Bus [0-3] only */
+ FIELD(I2CD_INTR_STS, SMBUS_ARP_ADDR, 11, 1) /* Removed */
+ FIELD(I2CD_INTR_STS, SMBUS_DEV_ALERT_ADDR, 10, 1) /* Removed */
+ FIELD(I2CD_INTR_STS, SMBUS_DEF_ADDR, 9, 1) /* Removed */
+ FIELD(I2CD_INTR_STS, GCALL_ADDR, 8, 1) /* Removed */
+ FIELD(I2CD_INTR_STS, SLAVE_ADDR_RX_MATCH, 7, 1) /* use RX_DONE */
+ SHARED_FIELD(SCL_TIMEOUT, 6, 1)
+ SHARED_FIELD(ABNORMAL, 5, 1)
+ SHARED_FIELD(NORMAL_STOP, 4, 1)
+ SHARED_FIELD(ARBIT_LOSS, 3, 1)
+ SHARED_FIELD(RX_DONE, 2, 1)
+ SHARED_FIELD(TX_NAK, 1, 1)
+ SHARED_FIELD(TX_ACK, 0, 1)
+REG32(I2CD_CMD, 0x14) /* I2CD Command/Status */
+ SHARED_FIELD(SDA_OE, 28, 1)
+ SHARED_FIELD(SDA_O, 27, 1)
+ SHARED_FIELD(SCL_OE, 26, 1)
+ SHARED_FIELD(SCL_O, 25, 1)
+ SHARED_FIELD(TX_TIMING, 23, 2)
+ SHARED_FIELD(TX_STATE, 19, 4)
+ SHARED_FIELD(SCL_LINE_STS, 18, 1)
+ SHARED_FIELD(SDA_LINE_STS, 17, 1)
+ SHARED_FIELD(BUS_BUSY_STS, 16, 1)
+ SHARED_FIELD(SDA_OE_OUT_DIR, 15, 1)
+ SHARED_FIELD(SDA_O_OUT_DIR, 14, 1)
+ SHARED_FIELD(SCL_OE_OUT_DIR, 13, 1)
+ SHARED_FIELD(SCL_O_OUT_DIR, 12, 1)
+ SHARED_FIELD(BUS_RECOVER_CMD_EN, 11, 1)
+ SHARED_FIELD(S_ALT_EN, 10, 1)
+ /* Command Bits */
+ SHARED_FIELD(RX_DMA_EN, 9, 1)
+ SHARED_FIELD(TX_DMA_EN, 8, 1)
+ SHARED_FIELD(RX_BUFF_EN, 7, 1)
+ SHARED_FIELD(TX_BUFF_EN, 6, 1)
+ SHARED_FIELD(M_STOP_CMD, 5, 1)
+ SHARED_FIELD(M_S_RX_CMD_LAST, 4, 1)
+ SHARED_FIELD(M_RX_CMD, 3, 1)
+ SHARED_FIELD(S_TX_CMD, 2, 1)
+ SHARED_FIELD(M_TX_CMD, 1, 1)
+ SHARED_FIELD(M_START_CMD, 0, 1)
+REG32(I2CD_DEV_ADDR, 0x18) /* Slave Device Address */
+ SHARED_FIELD(SLAVE_DEV_ADDR1, 0, 7)
+REG32(I2CD_POOL_CTRL, 0x1C) /* Pool Buffer Control */
+ SHARED_FIELD(RX_COUNT, 24, 6)
+ SHARED_FIELD(RX_SIZE, 16, 5)
+ SHARED_FIELD(TX_COUNT, 8, 5)
+ FIELD(I2CD_POOL_CTRL, OFFSET, 2, 6) /* AST2400 */
+ SHARED_FIELD(BUF_ORGANIZATION, 0, 1) /* AST2600 */
+REG32(I2CD_BYTE_BUF, 0x20) /* Transmit/Receive Byte Buffer */
+ SHARED_FIELD(RX_BUF, 8, 8)
+ SHARED_FIELD(TX_BUF, 0, 8)
+REG32(I2CD_DMA_ADDR, 0x24) /* DMA Buffer Address */
+REG32(I2CD_DMA_LEN, 0x28) /* DMA Transfer Length < 4KB */
+
+/* I2C New Mode Device (Bus) Register */
+REG32(I2CC_FUN_CTRL, 0x0)
+ FIELD(I2CC_FUN_CTRL, RB_EARLY_DONE_EN, 22, 1)
+ FIELD(I2CC_FUN_CTRL, DMA_DIS_AUTO_RECOVER, 21, 1)
+ FIELD(I2CC_FUN_CTRL, S_SAVE_ADDR, 20, 1)
+ FIELD(I2CC_FUN_CTRL, M_PKT_RETRY_CNT, 18, 2)
+ /* 17:0 shared with I2CD_FUN_CTRL[17:0] */
+REG32(I2CC_AC_TIMING, 0x04)
+REG32(I2CC_MS_TXRX_BYTE_BUF, 0x08)
+ /* 31:16 shared with I2CD_CMD[31:16] */
+ /* 15:0 shared with I2CD_BYTE_BUF[15:0] */
+REG32(I2CC_POOL_CTRL, 0x0c)
+ /* 31:0 shared with I2CD_POOL_CTRL[31:0] */
+REG32(I2CM_INTR_CTRL, 0x10)
+REG32(I2CM_INTR_STS, 0x14)
+ FIELD(I2CM_INTR_STS, PKT_STATE, 28, 4)
+ FIELD(I2CM_INTR_STS, PKT_CMD_TIMEOUT, 18, 1)
+ FIELD(I2CM_INTR_STS, PKT_CMD_FAIL, 17, 1)
+ FIELD(I2CM_INTR_STS, PKT_CMD_DONE, 16, 1)
+ FIELD(I2CM_INTR_STS, BUS_RECOVER_FAIL, 15, 1)
+ /* 14:0 shared with I2CD_INTR_STS[14:0] */
+REG32(I2CM_CMD, 0x18)
+ FIELD(I2CM_CMD, W1_CTRL, 31, 1)
+ FIELD(I2CM_CMD, PKT_DEV_ADDR, 24, 7)
+ FIELD(I2CM_CMD, HS_MASTER_MODE_LSB, 17, 3)
+ FIELD(I2CM_CMD, PKT_OP_EN, 16, 1)
+ /* 15:0 shared with I2CD_CMD[15:0] */
+REG32(I2CM_DMA_LEN, 0x1c)
+ FIELD(I2CM_DMA_LEN, RX_BUF_LEN_W1T, 31, 1)
+ FIELD(I2CM_DMA_LEN, RX_BUF_LEN, 16, 11)
+ FIELD(I2CM_DMA_LEN, TX_BUF_LEN_W1T, 15, 1)
+ FIELD(I2CM_DMA_LEN, TX_BUF_LEN, 0, 11)
+REG32(I2CS_INTR_CTRL, 0x20)
+ FIELD(I2CS_INTR_CTRL, PKT_CMD_FAIL, 17, 1)
+ FIELD(I2CS_INTR_CTRL, PKT_CMD_DONE, 16, 1)
+REG32(I2CS_INTR_STS, 0x24)
+ /* 31:29 shared with I2CD_INTR_STS[31:29] */
+ FIELD(I2CS_INTR_STS, SLAVE_PARKING_STS, 24, 2)
+ FIELD(I2CS_INTR_STS, SLAVE_ADDR3_NAK, 22, 1)
+ FIELD(I2CS_INTR_STS, SLAVE_ADDR2_NAK, 21, 1)
+ FIELD(I2CS_INTR_STS, SLAVE_ADDR1_NAK, 20, 1)
+ FIELD(I2CS_INTR_STS, SLAVE_ADDR_INDICATOR, 18, 2)
+ FIELD(I2CS_INTR_STS, PKT_CMD_FAIL, 17, 1)
+ FIELD(I2CS_INTR_STS, PKT_CMD_DONE, 16, 1)
+ /* 14:0 shared with I2CD_INTR_STS[14:0] */
+ FIELD(I2CS_INTR_STS, SLAVE_ADDR_RX_MATCH, 7, 1)
+REG32(I2CS_CMD, 0x28)
+ FIELD(I2CS_CMD, W1_CTRL, 31, 1)
+ FIELD(I2CS_CMD, PKT_MODE_ACTIVE_ADDR, 17, 2)
+ FIELD(I2CS_CMD, PKT_MODE_EN, 16, 1)
+ FIELD(I2CS_CMD, AUTO_NAK_INACTIVE_ADDR, 15, 1)
+ FIELD(I2CS_CMD, AUTO_NAK_ACTIVE_ADDR, 14, 1)
+ /* 13:0 shared with I2CD_CMD[13:0] */
+REG32(I2CS_DMA_LEN, 0x2c)
+ FIELD(I2CS_DMA_LEN, RX_BUF_LEN_W1T, 31, 1)
+ FIELD(I2CS_DMA_LEN, RX_BUF_LEN, 16, 11)
+ FIELD(I2CS_DMA_LEN, TX_BUF_LEN_W1T, 15, 1)
+ FIELD(I2CS_DMA_LEN, TX_BUF_LEN, 0, 11)
+REG32(I2CM_DMA_TX_ADDR, 0x30)
+ FIELD(I2CM_DMA_TX_ADDR, ADDR, 0, 31)
+REG32(I2CM_DMA_RX_ADDR, 0x34)
+ FIELD(I2CM_DMA_RX_ADDR, ADDR, 0, 31)
+REG32(I2CS_DMA_TX_ADDR, 0x38)
+ FIELD(I2CS_DMA_TX_ADDR, ADDR, 0, 31)
+REG32(I2CS_DMA_RX_ADDR, 0x3c)
+ FIELD(I2CS_DMA_RX_ADDR, ADDR, 0, 31)
+REG32(I2CS_DEV_ADDR, 0x40)
+REG32(I2CM_DMA_LEN_STS, 0x48)
+ FIELD(I2CM_DMA_LEN_STS, RX_LEN, 16, 13)
+ FIELD(I2CM_DMA_LEN_STS, TX_LEN, 0, 13)
+REG32(I2CS_DMA_LEN_STS, 0x4c)
+ FIELD(I2CS_DMA_LEN_STS, RX_LEN, 16, 13)
+ FIELD(I2CS_DMA_LEN_STS, TX_LEN, 0, 13)
+REG32(I2CC_DMA_ADDR, 0x50)
+REG32(I2CC_DMA_LEN, 0x54)
struct AspeedI2CState;
-typedef struct AspeedI2CBus {
+#define TYPE_ASPEED_I2C_BUS "aspeed.i2c.bus"
+OBJECT_DECLARE_SIMPLE_TYPE(AspeedI2CBus, ASPEED_I2C_BUS)
+struct AspeedI2CBus {
+ SysBusDevice parent_obj;
+
struct AspeedI2CState *controller;
+ /* slave mode */
+ I2CSlave *slave;
+
MemoryRegion mr;
I2CBus *bus;
uint8_t id;
qemu_irq irq;
- uint32_t ctrl;
- uint32_t timing[2];
- uint32_t intr_ctrl;
- uint32_t intr_status;
- uint32_t cmd;
- uint32_t buf;
- uint32_t pool_ctrl;
- uint32_t dma_addr;
- uint32_t dma_len;
-} AspeedI2CBus;
-
-typedef struct AspeedI2CState {
+ uint32_t regs[ASPEED_I2C_NEW_NUM_REG];
+};
+
+struct AspeedI2CState {
SysBusDevice parent_obj;
MemoryRegion iomem;
@@ -64,20 +255,22 @@ typedef struct AspeedI2CState {
uint32_t intr_status;
uint32_t ctrl_global;
+ uint32_t new_clk_divider;
MemoryRegion pool_iomem;
uint8_t pool[ASPEED_I2C_MAX_POOL_SIZE];
AspeedI2CBus busses[ASPEED_I2C_NR_BUSSES];
MemoryRegion *dram_mr;
AddressSpace dram_as;
-} AspeedI2CState;
+};
-#define ASPEED_I2C_CLASS(klass) \
- OBJECT_CLASS_CHECK(AspeedI2CClass, (klass), TYPE_ASPEED_I2C)
-#define ASPEED_I2C_GET_CLASS(obj) \
- OBJECT_GET_CLASS(AspeedI2CClass, (obj), TYPE_ASPEED_I2C)
+#define TYPE_ASPEED_I2C_BUS_SLAVE "aspeed.i2c.slave"
+OBJECT_DECLARE_SIMPLE_TYPE(AspeedI2CBusSlave, ASPEED_I2C_BUS_SLAVE)
+struct AspeedI2CBusSlave {
+ I2CSlave i2c;
+};
-typedef struct AspeedI2CClass {
+struct AspeedI2CClass {
SysBusDeviceClass parent_class;
uint8_t num_busses;
@@ -91,7 +284,105 @@ typedef struct AspeedI2CClass {
bool check_sram;
bool has_dma;
-} AspeedI2CClass;
+};
+
+static inline bool aspeed_i2c_is_new_mode(AspeedI2CState *s)
+{
+ return FIELD_EX32(s->ctrl_global, I2C_CTRL_GLOBAL, REG_MODE);
+}
+
+static inline bool aspeed_i2c_bus_pkt_mode_en(AspeedI2CBus *bus)
+{
+ if (aspeed_i2c_is_new_mode(bus->controller)) {
+ return ARRAY_FIELD_EX32(bus->regs, I2CM_CMD, PKT_OP_EN);
+ }
+ return false;
+}
+
+static inline uint32_t aspeed_i2c_bus_ctrl_offset(AspeedI2CBus *bus)
+{
+ if (aspeed_i2c_is_new_mode(bus->controller)) {
+ return R_I2CC_FUN_CTRL;
+ }
+ return R_I2CD_FUN_CTRL;
+}
+
+static inline uint32_t aspeed_i2c_bus_cmd_offset(AspeedI2CBus *bus)
+{
+ if (aspeed_i2c_is_new_mode(bus->controller)) {
+ return R_I2CM_CMD;
+ }
+ return R_I2CD_CMD;
+}
+
+static inline uint32_t aspeed_i2c_bus_dev_addr_offset(AspeedI2CBus *bus)
+{
+ if (aspeed_i2c_is_new_mode(bus->controller)) {
+ return R_I2CS_DEV_ADDR;
+ }
+ return R_I2CD_DEV_ADDR;
+}
+
+static inline uint32_t aspeed_i2c_bus_intr_ctrl_offset(AspeedI2CBus *bus)
+{
+ if (aspeed_i2c_is_new_mode(bus->controller)) {
+ return R_I2CM_INTR_CTRL;
+ }
+ return R_I2CD_INTR_CTRL;
+}
+
+static inline uint32_t aspeed_i2c_bus_intr_sts_offset(AspeedI2CBus *bus)
+{
+ if (aspeed_i2c_is_new_mode(bus->controller)) {
+ return R_I2CM_INTR_STS;
+ }
+ return R_I2CD_INTR_STS;
+}
+
+static inline uint32_t aspeed_i2c_bus_pool_ctrl_offset(AspeedI2CBus *bus)
+{
+ if (aspeed_i2c_is_new_mode(bus->controller)) {
+ return R_I2CC_POOL_CTRL;
+ }
+ return R_I2CD_POOL_CTRL;
+}
+
+static inline uint32_t aspeed_i2c_bus_byte_buf_offset(AspeedI2CBus *bus)
+{
+ if (aspeed_i2c_is_new_mode(bus->controller)) {
+ return R_I2CC_MS_TXRX_BYTE_BUF;
+ }
+ return R_I2CD_BYTE_BUF;
+}
+
+static inline uint32_t aspeed_i2c_bus_dma_len_offset(AspeedI2CBus *bus)
+{
+ if (aspeed_i2c_is_new_mode(bus->controller)) {
+ return R_I2CC_DMA_LEN;
+ }
+ return R_I2CD_DMA_LEN;
+}
+
+static inline uint32_t aspeed_i2c_bus_dma_addr_offset(AspeedI2CBus *bus)
+{
+ if (aspeed_i2c_is_new_mode(bus->controller)) {
+ return R_I2CC_DMA_ADDR;
+ }
+ return R_I2CD_DMA_ADDR;
+}
+
+static inline bool aspeed_i2c_bus_is_master(AspeedI2CBus *bus)
+{
+ return SHARED_ARRAY_FIELD_EX32(bus->regs, aspeed_i2c_bus_ctrl_offset(bus),
+ MASTER_EN);
+}
+
+static inline bool aspeed_i2c_bus_is_enabled(AspeedI2CBus *bus)
+{
+ uint32_t ctrl_reg = aspeed_i2c_bus_ctrl_offset(bus);
+ return SHARED_ARRAY_FIELD_EX32(bus->regs, ctrl_reg, MASTER_EN) ||
+ SHARED_ARRAY_FIELD_EX32(bus->regs, ctrl_reg, SLAVE_EN);
+}
I2CBus *aspeed_i2c_get_bus(AspeedI2CState *s, int busnr);
diff --git a/include/hw/i2c/bcm2835_i2c.h b/include/hw/i2c/bcm2835_i2c.h
new file mode 100644
index 0000000000..0a56df4720
--- /dev/null
+++ b/include/hw/i2c/bcm2835_i2c.h
@@ -0,0 +1,80 @@
+/*
+ * Broadcom Serial Controller (BSC)
+ *
+ * Copyright (c) 2024 Rayhan Faizel <rayhan.faizel@gmail.com>
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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 "hw/sysbus.h"
+#include "hw/i2c/i2c.h"
+#include "qom/object.h"
+
+#define TYPE_BCM2835_I2C "bcm2835-i2c"
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835I2CState, BCM2835_I2C)
+
+#define BCM2835_I2C_C 0x0 /* Control */
+#define BCM2835_I2C_S 0x4 /* Status */
+#define BCM2835_I2C_DLEN 0x8 /* Data Length */
+#define BCM2835_I2C_A 0xc /* Slave Address */
+#define BCM2835_I2C_FIFO 0x10 /* FIFO */
+#define BCM2835_I2C_DIV 0x14 /* Clock Divider */
+#define BCM2835_I2C_DEL 0x18 /* Data Delay */
+#define BCM2835_I2C_CLKT 0x20 /* Clock Stretch Timeout */
+
+#define BCM2835_I2C_C_I2CEN BIT(15) /* I2C enable */
+#define BCM2835_I2C_C_INTR BIT(10) /* Interrupt on RXR */
+#define BCM2835_I2C_C_INTT BIT(9) /* Interrupt on TXW */
+#define BCM2835_I2C_C_INTD BIT(8) /* Interrupt on DONE */
+#define BCM2835_I2C_C_ST BIT(7) /* Start transfer */
+#define BCM2835_I2C_C_CLEAR (BIT(5) | BIT(4)) /* Clear FIFO */
+#define BCM2835_I2C_C_READ BIT(0) /* I2C read mode */
+
+#define BCM2835_I2C_S_CLKT BIT(9) /* Clock stretch timeout */
+#define BCM2835_I2C_S_ERR BIT(8) /* Slave error */
+#define BCM2835_I2C_S_RXF BIT(7) /* RX FIFO full */
+#define BCM2835_I2C_S_TXE BIT(6) /* TX FIFO empty */
+#define BCM2835_I2C_S_RXD BIT(5) /* RX bytes available */
+#define BCM2835_I2C_S_TXD BIT(4) /* TX space available */
+#define BCM2835_I2C_S_RXR BIT(3) /* RX FIFO needs reading */
+#define BCM2835_I2C_S_TXW BIT(2) /* TX FIFO needs writing */
+#define BCM2835_I2C_S_DONE BIT(1) /* I2C Transfer complete */
+#define BCM2835_I2C_S_TA BIT(0) /* I2C Transfer active */
+
+struct BCM2835I2CState {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /* <public> */
+ MemoryRegion iomem;
+ I2CBus *bus;
+ qemu_irq irq;
+
+ uint32_t c;
+ uint32_t s;
+ uint32_t dlen;
+ uint32_t a;
+ uint32_t div;
+ uint32_t del;
+ uint32_t clkt;
+
+ uint32_t last_dlen;
+};
diff --git a/include/hw/i2c/bitbang_i2c.h b/include/hw/i2c/bitbang_i2c.h
index 92334e9016..a079e6d70f 100644
--- a/include/hw/i2c/bitbang_i2c.h
+++ b/include/hw/i2c/bitbang_i2c.h
@@ -3,6 +3,8 @@
#include "hw/i2c/i2c.h"
+#define TYPE_GPIO_I2C "gpio_i2c"
+
typedef struct bitbang_i2c_interface bitbang_i2c_interface;
#define BITBANG_I2C_SDA 0
diff --git a/include/hw/i2c/i2c.h b/include/hw/i2c/i2c.h
index a9c030a512..2a3abacd1b 100644
--- a/include/hw/i2c/i2c.h
+++ b/include/hw/i2c/i2c.h
@@ -2,6 +2,7 @@
#define QEMU_I2C_H
#include "hw/qdev-core.h"
+#include "qom/object.h"
/* The QEMU I2C implementation only supports simple transfers that complete
immediately. It does not support slave devices that need to be able to
@@ -11,26 +12,26 @@
enum i2c_event {
I2C_START_RECV,
I2C_START_SEND,
+ I2C_START_SEND_ASYNC,
I2C_FINISH,
I2C_NACK /* Masker NACKed a receive byte. */
};
-typedef struct I2CSlave I2CSlave;
+typedef struct I2CNodeList I2CNodeList;
#define TYPE_I2C_SLAVE "i2c-slave"
-#define I2C_SLAVE(obj) \
- OBJECT_CHECK(I2CSlave, (obj), TYPE_I2C_SLAVE)
-#define I2C_SLAVE_CLASS(klass) \
- OBJECT_CLASS_CHECK(I2CSlaveClass, (klass), TYPE_I2C_SLAVE)
-#define I2C_SLAVE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(I2CSlaveClass, (obj), TYPE_I2C_SLAVE)
-
-typedef struct I2CSlaveClass {
+OBJECT_DECLARE_TYPE(I2CSlave, I2CSlaveClass,
+ I2C_SLAVE)
+
+struct I2CSlaveClass {
DeviceClass parent_class;
/* Master to slave. Returns non-zero for a NAK, 0 for success. */
int (*send)(I2CSlave *s, uint8_t data);
+ /* Master to slave (asynchronous). Receiving slave must call i2c_ack(). */
+ void (*send_async)(I2CSlave *s, uint8_t data);
+
/*
* Slave to master. This cannot fail, the device should always
* return something here.
@@ -43,7 +44,17 @@ typedef struct I2CSlaveClass {
* return code is not used and should be zero.
*/
int (*event)(I2CSlave *s, enum i2c_event event);
-} I2CSlaveClass;
+
+ /*
+ * Check if this device matches the address provided. Returns bool of
+ * true if it matches (or broadcast), and updates the device list, false
+ * otherwise.
+ *
+ * If broadcast is true, match should add the device and return true.
+ */
+ bool (*match_and_add)(I2CSlave *candidate, uint8_t address, bool broadcast,
+ I2CNodeList *current_devs);
+};
struct I2CSlave {
DeviceState qdev;
@@ -53,7 +64,7 @@ struct I2CSlave {
};
#define TYPE_I2C_BUS "i2c-bus"
-#define I2C_BUS(obj) OBJECT_CHECK(I2CBus, (obj), TYPE_I2C_BUS)
+OBJECT_DECLARE_SIMPLE_TYPE(I2CBus, I2C_BUS)
typedef struct I2CNode I2CNode;
@@ -62,22 +73,86 @@ struct I2CNode {
QLIST_ENTRY(I2CNode) next;
};
+typedef struct I2CPendingMaster I2CPendingMaster;
+
+struct I2CPendingMaster {
+ QEMUBH *bh;
+ QSIMPLEQ_ENTRY(I2CPendingMaster) entry;
+};
+
+typedef QLIST_HEAD(I2CNodeList, I2CNode) I2CNodeList;
+typedef QSIMPLEQ_HEAD(I2CPendingMasters, I2CPendingMaster) I2CPendingMasters;
+
struct I2CBus {
BusState qbus;
- QLIST_HEAD(, I2CNode) current_devs;
+ I2CNodeList current_devs;
+ I2CPendingMasters pending_masters;
uint8_t saved_address;
bool broadcast;
+
+ /* Set from slave currently mastering the bus. */
+ QEMUBH *bh;
};
I2CBus *i2c_init_bus(DeviceState *parent, const char *name);
-void i2c_set_slave_address(I2CSlave *dev, uint8_t address);
int i2c_bus_busy(I2CBus *bus);
-int i2c_start_transfer(I2CBus *bus, uint8_t address, int recv);
+
+/**
+ * i2c_start_transfer: start a transfer on an I2C bus.
+ *
+ * @bus: #I2CBus to be used
+ * @address: address of the slave
+ * @is_recv: indicates the transfer direction
+ *
+ * When @is_recv is a known boolean constant, use the
+ * i2c_start_recv() or i2c_start_send() helper instead.
+ *
+ * Returns: 0 on success, -1 on error
+ */
+int i2c_start_transfer(I2CBus *bus, uint8_t address, bool is_recv);
+
+/**
+ * i2c_start_recv: start a 'receive' transfer on an I2C bus.
+ *
+ * @bus: #I2CBus to be used
+ * @address: address of the slave
+ *
+ * Returns: 0 on success, -1 on error
+ */
+int i2c_start_recv(I2CBus *bus, uint8_t address);
+
+/**
+ * i2c_start_send: start a 'send' transfer on an I2C bus.
+ *
+ * @bus: #I2CBus to be used
+ * @address: address of the slave
+ *
+ * Returns: 0 on success, -1 on error
+ */
+int i2c_start_send(I2CBus *bus, uint8_t address);
+
+/**
+ * i2c_start_send_async: start an asynchronous 'send' transfer on an I2C bus.
+ *
+ * @bus: #I2CBus to be used
+ * @address: address of the slave
+ *
+ * Return: 0 on success, -1 on error
+ */
+int i2c_start_send_async(I2CBus *bus, uint8_t address);
+
+void i2c_schedule_pending_master(I2CBus *bus);
+
void i2c_end_transfer(I2CBus *bus);
void i2c_nack(I2CBus *bus);
-int i2c_send_recv(I2CBus *bus, uint8_t *data, bool send);
+void i2c_ack(I2CBus *bus);
+void i2c_bus_master(I2CBus *bus, QEMUBH *bh);
+void i2c_bus_release(I2CBus *bus);
int i2c_send(I2CBus *bus, uint8_t data);
+int i2c_send_async(I2CBus *bus, uint8_t data);
uint8_t i2c_recv(I2CBus *bus);
+bool i2c_scan_bus(I2CBus *bus, uint8_t address, bool broadcast,
+ I2CNodeList *current_devs);
/**
* Create an I2C slave device on the heap.
@@ -102,7 +177,7 @@ I2CSlave *i2c_slave_new(const char *name, uint8_t addr);
I2CSlave *i2c_slave_create_simple(I2CBus *bus, const char *name, uint8_t addr);
/**
- * Realize and and drop a reference an I2C slave device
+ * Realize and drop a reference an I2C slave device
* @dev: I2C slave device to realize
* @bus: I2C bus to put it on
* @addr: I2C address of the slave on the bus
@@ -131,8 +206,12 @@ I2CSlave *i2c_slave_create_simple(I2CBus *bus, const char *name, uint8_t addr);
*/
bool i2c_slave_realize_and_unref(I2CSlave *dev, I2CBus *bus, Error **errp);
-/* lm832x.c */
-void lm832x_key_event(DeviceState *dev, int key, int state);
+/**
+ * Set the I2C bus address of a slave device
+ * @dev: I2C slave device
+ * @address: I2C address of the slave when put on a bus
+ */
+void i2c_slave_set_address(I2CSlave *dev, uint8_t address);
extern const VMStateDescription vmstate_i2c_slave;
diff --git a/include/hw/i2c/i2c_mux_pca954x.h b/include/hw/i2c/i2c_mux_pca954x.h
new file mode 100644
index 0000000000..3dd25ec983
--- /dev/null
+++ b/include/hw/i2c/i2c_mux_pca954x.h
@@ -0,0 +1,19 @@
+#ifndef QEMU_I2C_MUX_PCA954X_H
+#define QEMU_I2C_MUX_PCA954X_H
+
+#include "hw/i2c/i2c.h"
+
+#define TYPE_PCA9546 "pca9546"
+#define TYPE_PCA9548 "pca9548"
+
+/**
+ * Retrieves the i2c bus associated with the specified channel on this i2c
+ * mux.
+ * @mux: an i2c mux device.
+ * @channel: the i2c channel requested
+ *
+ * Returns: a pointer to the associated i2c bus.
+ */
+I2CBus *pca954x_i2c_get_bus(I2CSlave *mux, uint8_t channel);
+
+#endif
diff --git a/include/hw/i2c/imx_i2c.h b/include/hw/i2c/imx_i2c.h
index 7c73a1fa28..e4f91339f5 100644
--- a/include/hw/i2c/imx_i2c.h
+++ b/include/hw/i2c/imx_i2c.h
@@ -22,9 +22,10 @@
#define IMX_I2C_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_IMX_I2C "imx.i2c"
-#define IMX_I2C(obj) OBJECT_CHECK(IMXI2CState, (obj), TYPE_IMX_I2C)
+OBJECT_DECLARE_SIMPLE_TYPE(IMXI2CState, IMX_I2C)
#define IMX_I2C_MEM_SIZE 0x14
@@ -65,7 +66,7 @@
#define ADDR_RESET 0xFF00
-typedef struct IMXI2CState {
+struct IMXI2CState {
/*< private >*/
SysBusDevice parent_obj;
@@ -82,6 +83,6 @@ typedef struct IMXI2CState {
uint16_t i2sr;
uint16_t i2dr_read;
uint16_t i2dr_write;
-} IMXI2CState;
+};
#endif /* IMX_I2C_H */
diff --git a/include/hw/i2c/microbit_i2c.h b/include/hw/i2c/microbit_i2c.h
index 2bff36680c..3c29e09bf3 100644
--- a/include/hw/i2c/microbit_i2c.h
+++ b/include/hw/i2c/microbit_i2c.h
@@ -13,6 +13,7 @@
#include "hw/sysbus.h"
#include "hw/arm/nrf51.h"
+#include "qom/object.h"
#define NRF51_TWI_TASK_STARTRX 0x000
#define NRF51_TWI_TASK_STARTTX 0x008
@@ -26,17 +27,16 @@
#define NRF51_TWI_REG_ADDRESS 0x588
#define TYPE_MICROBIT_I2C "microbit.i2c"
-#define MICROBIT_I2C(obj) \
- OBJECT_CHECK(MicrobitI2CState, (obj), TYPE_MICROBIT_I2C)
+OBJECT_DECLARE_SIMPLE_TYPE(MicrobitI2CState, MICROBIT_I2C)
#define MICROBIT_I2C_NREGS (NRF51_PERIPHERAL_SIZE / sizeof(uint32_t))
-typedef struct {
+struct MicrobitI2CState {
SysBusDevice parent_obj;
MemoryRegion iomem;
uint32_t regs[MICROBIT_I2C_NREGS];
uint32_t read_idx;
-} MicrobitI2CState;
+};
#endif /* MICROBIT_I2C_H */
diff --git a/include/hw/i2c/npcm7xx_smbus.h b/include/hw/i2c/npcm7xx_smbus.h
new file mode 100644
index 0000000000..dc45963c0e
--- /dev/null
+++ b/include/hw/i2c/npcm7xx_smbus.h
@@ -0,0 +1,112 @@
+/*
+ * Nuvoton NPCM7xx SMBus Module.
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_SMBUS_H
+#define NPCM7XX_SMBUS_H
+
+#include "exec/memory.h"
+#include "hw/i2c/i2c.h"
+#include "hw/irq.h"
+#include "hw/sysbus.h"
+
+/*
+ * Number of addresses this module contains. Do not change this without
+ * incrementing the version_id in the vmstate.
+ */
+#define NPCM7XX_SMBUS_NR_ADDRS 10
+
+/* Size of the FIFO buffer. */
+#define NPCM7XX_SMBUS_FIFO_SIZE 16
+
+typedef enum NPCM7xxSMBusStatus {
+ NPCM7XX_SMBUS_STATUS_IDLE,
+ NPCM7XX_SMBUS_STATUS_SENDING,
+ NPCM7XX_SMBUS_STATUS_RECEIVING,
+ NPCM7XX_SMBUS_STATUS_NEGACK,
+ NPCM7XX_SMBUS_STATUS_STOPPING_LAST_RECEIVE,
+ NPCM7XX_SMBUS_STATUS_STOPPING_NEGACK,
+} NPCM7xxSMBusStatus;
+
+/*
+ * struct NPCM7xxSMBusState - System Management Bus device state.
+ * @bus: The underlying I2C Bus.
+ * @irq: GIC interrupt line to fire on events (if enabled).
+ * @sda: The serial data register.
+ * @st: The status register.
+ * @cst: The control status register.
+ * @cst2: The control status register 2.
+ * @cst3: The control status register 3.
+ * @ctl1: The control register 1.
+ * @ctl2: The control register 2.
+ * @ctl3: The control register 3.
+ * @ctl4: The control register 4.
+ * @ctl5: The control register 5.
+ * @addr: The SMBus module's own addresses on the I2C bus.
+ * @scllt: The SCL low time register.
+ * @sclht: The SCL high time register.
+ * @fif_ctl: The FIFO control register.
+ * @fif_cts: The FIFO control status register.
+ * @fair_per: The fair period register.
+ * @txf_ctl: The transmit FIFO control register.
+ * @t_out: The SMBus timeout register.
+ * @txf_sts: The transmit FIFO status register.
+ * @rxf_sts: The receive FIFO status register.
+ * @rxf_ctl: The receive FIFO control register.
+ * @rx_fifo: The FIFO buffer for receiving in FIFO mode.
+ * @rx_cur: The current position of rx_fifo.
+ * @status: The current status of the SMBus.
+ */
+struct NPCM7xxSMBusState {
+ SysBusDevice parent;
+
+ MemoryRegion iomem;
+
+ I2CBus *bus;
+ qemu_irq irq;
+
+ uint8_t sda;
+ uint8_t st;
+ uint8_t cst;
+ uint8_t cst2;
+ uint8_t cst3;
+ uint8_t ctl1;
+ uint8_t ctl2;
+ uint8_t ctl3;
+ uint8_t ctl4;
+ uint8_t ctl5;
+ uint8_t addr[NPCM7XX_SMBUS_NR_ADDRS];
+
+ uint8_t scllt;
+ uint8_t sclht;
+
+ uint8_t fif_ctl;
+ uint8_t fif_cts;
+ uint8_t fair_per;
+ uint8_t txf_ctl;
+ uint8_t t_out;
+ uint8_t txf_sts;
+ uint8_t rxf_sts;
+ uint8_t rxf_ctl;
+
+ uint8_t rx_fifo[NPCM7XX_SMBUS_FIFO_SIZE];
+ uint8_t rx_cur;
+
+ NPCM7xxSMBusStatus status;
+};
+
+#define TYPE_NPCM7XX_SMBUS "npcm7xx-smbus"
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxSMBusState, NPCM7XX_SMBUS)
+
+#endif /* NPCM7XX_SMBUS_H */
diff --git a/include/hw/i2c/pmbus_device.h b/include/hw/i2c/pmbus_device.h
new file mode 100644
index 0000000000..f195c11384
--- /dev/null
+++ b/include/hw/i2c/pmbus_device.h
@@ -0,0 +1,564 @@
+/*
+ * QEMU PMBus device emulation
+ *
+ * Copyright 2021 Google LLC
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_PMBUS_DEVICE_H
+#define HW_PMBUS_DEVICE_H
+
+#include "qemu/bitops.h"
+#include "hw/i2c/smbus_slave.h"
+
+enum pmbus_registers {
+ PMBUS_PAGE = 0x00, /* R/W byte */
+ PMBUS_OPERATION = 0x01, /* R/W byte */
+ PMBUS_ON_OFF_CONFIG = 0x02, /* R/W byte */
+ PMBUS_CLEAR_FAULTS = 0x03, /* Send Byte */
+ PMBUS_PHASE = 0x04, /* R/W byte */
+ PMBUS_PAGE_PLUS_WRITE = 0x05, /* Block Write-only */
+ PMBUS_PAGE_PLUS_READ = 0x06, /* Block Read-only */
+ PMBUS_WRITE_PROTECT = 0x10, /* R/W byte */
+ PMBUS_STORE_DEFAULT_ALL = 0x11, /* Send Byte */
+ PMBUS_RESTORE_DEFAULT_ALL = 0x12, /* Send Byte */
+ PMBUS_STORE_DEFAULT_CODE = 0x13, /* Write-only Byte */
+ PMBUS_RESTORE_DEFAULT_CODE = 0x14, /* Write-only Byte */
+ PMBUS_STORE_USER_ALL = 0x15, /* Send Byte */
+ PMBUS_RESTORE_USER_ALL = 0x16, /* Send Byte */
+ PMBUS_STORE_USER_CODE = 0x17, /* Write-only Byte */
+ PMBUS_RESTORE_USER_CODE = 0x18, /* Write-only Byte */
+ PMBUS_CAPABILITY = 0x19, /* Read-Only byte */
+ PMBUS_QUERY = 0x1A, /* Write-Only */
+ PMBUS_SMBALERT_MASK = 0x1B, /* Block read, Word write */
+ PMBUS_VOUT_MODE = 0x20, /* R/W byte */
+ PMBUS_VOUT_COMMAND = 0x21, /* R/W word */
+ PMBUS_VOUT_TRIM = 0x22, /* R/W word */
+ PMBUS_VOUT_CAL_OFFSET = 0x23, /* R/W word */
+ PMBUS_VOUT_MAX = 0x24, /* R/W word */
+ PMBUS_VOUT_MARGIN_HIGH = 0x25, /* R/W word */
+ PMBUS_VOUT_MARGIN_LOW = 0x26, /* R/W word */
+ PMBUS_VOUT_TRANSITION_RATE = 0x27, /* R/W word */
+ PMBUS_VOUT_DROOP = 0x28, /* R/W word */
+ PMBUS_VOUT_SCALE_LOOP = 0x29, /* R/W word */
+ PMBUS_VOUT_SCALE_MONITOR = 0x2A, /* R/W word */
+ PMBUS_VOUT_MIN = 0x2B, /* R/W word */
+ PMBUS_COEFFICIENTS = 0x30, /* Read-only block 5 bytes */
+ PMBUS_POUT_MAX = 0x31, /* R/W word */
+ PMBUS_MAX_DUTY = 0x32, /* R/W word */
+ PMBUS_FREQUENCY_SWITCH = 0x33, /* R/W word */
+ PMBUS_VIN_ON = 0x35, /* R/W word */
+ PMBUS_VIN_OFF = 0x36, /* R/W word */
+ PMBUS_INTERLEAVE = 0x37, /* R/W word */
+ PMBUS_IOUT_CAL_GAIN = 0x38, /* R/W word */
+ PMBUS_IOUT_CAL_OFFSET = 0x39, /* R/W word */
+ PMBUS_FAN_CONFIG_1_2 = 0x3A, /* R/W byte */
+ PMBUS_FAN_COMMAND_1 = 0x3B, /* R/W word */
+ PMBUS_FAN_COMMAND_2 = 0x3C, /* R/W word */
+ PMBUS_FAN_CONFIG_3_4 = 0x3D, /* R/W byte */
+ PMBUS_FAN_COMMAND_3 = 0x3E, /* R/W word */
+ PMBUS_FAN_COMMAND_4 = 0x3F, /* R/W word */
+ PMBUS_VOUT_OV_FAULT_LIMIT = 0x40, /* R/W word */
+ PMBUS_VOUT_OV_FAULT_RESPONSE = 0x41, /* R/W byte */
+ PMBUS_VOUT_OV_WARN_LIMIT = 0x42, /* R/W word */
+ PMBUS_VOUT_UV_WARN_LIMIT = 0x43, /* R/W word */
+ PMBUS_VOUT_UV_FAULT_LIMIT = 0x44, /* R/W word */
+ PMBUS_VOUT_UV_FAULT_RESPONSE = 0x45, /* R/W byte */
+ PMBUS_IOUT_OC_FAULT_LIMIT = 0x46, /* R/W word */
+ PMBUS_IOUT_OC_FAULT_RESPONSE = 0x47, /* R/W byte */
+ PMBUS_IOUT_OC_LV_FAULT_LIMIT = 0x48, /* R/W word */
+ PMBUS_IOUT_OC_LV_FAULT_RESPONSE = 0x49, /* R/W byte */
+ PMBUS_IOUT_OC_WARN_LIMIT = 0x4A, /* R/W word */
+ PMBUS_IOUT_UC_FAULT_LIMIT = 0x4B, /* R/W word */
+ PMBUS_IOUT_UC_FAULT_RESPONSE = 0x4C, /* R/W byte */
+ PMBUS_OT_FAULT_LIMIT = 0x4F, /* R/W word */
+ PMBUS_OT_FAULT_RESPONSE = 0x50, /* R/W byte */
+ PMBUS_OT_WARN_LIMIT = 0x51, /* R/W word */
+ PMBUS_UT_WARN_LIMIT = 0x52, /* R/W word */
+ PMBUS_UT_FAULT_LIMIT = 0x53, /* R/W word */
+ PMBUS_UT_FAULT_RESPONSE = 0x54, /* R/W byte */
+ PMBUS_VIN_OV_FAULT_LIMIT = 0x55, /* R/W word */
+ PMBUS_VIN_OV_FAULT_RESPONSE = 0x56, /* R/W byte */
+ PMBUS_VIN_OV_WARN_LIMIT = 0x57, /* R/W word */
+ PMBUS_VIN_UV_WARN_LIMIT = 0x58, /* R/W word */
+ PMBUS_VIN_UV_FAULT_LIMIT = 0x59, /* R/W word */
+ PMBUS_VIN_UV_FAULT_RESPONSE = 0x5A, /* R/W byte */
+ PMBUS_IIN_OC_FAULT_LIMIT = 0x5B, /* R/W word */
+ PMBUS_IIN_OC_FAULT_RESPONSE = 0x5C, /* R/W byte */
+ PMBUS_IIN_OC_WARN_LIMIT = 0x5D, /* R/W word */
+ PMBUS_POWER_GOOD_ON = 0x5E, /* R/W word */
+ PMBUS_POWER_GOOD_OFF = 0x5F, /* R/W word */
+ PMBUS_TON_DELAY = 0x60, /* R/W word */
+ PMBUS_TON_RISE = 0x61, /* R/W word */
+ PMBUS_TON_MAX_FAULT_LIMIT = 0x62, /* R/W word */
+ PMBUS_TON_MAX_FAULT_RESPONSE = 0x63, /* R/W byte */
+ PMBUS_TOFF_DELAY = 0x64, /* R/W word */
+ PMBUS_TOFF_FALL = 0x65, /* R/W word */
+ PMBUS_TOFF_MAX_WARN_LIMIT = 0x66, /* R/W word */
+ PMBUS_POUT_OP_FAULT_LIMIT = 0x68, /* R/W word */
+ PMBUS_POUT_OP_FAULT_RESPONSE = 0x69, /* R/W byte */
+ PMBUS_POUT_OP_WARN_LIMIT = 0x6A, /* R/W word */
+ PMBUS_PIN_OP_WARN_LIMIT = 0x6B, /* R/W word */
+ PMBUS_STATUS_BYTE = 0x78, /* R/W byte */
+ PMBUS_STATUS_WORD = 0x79, /* R/W word */
+ PMBUS_STATUS_VOUT = 0x7A, /* R/W byte */
+ PMBUS_STATUS_IOUT = 0x7B, /* R/W byte */
+ PMBUS_STATUS_INPUT = 0x7C, /* R/W byte */
+ PMBUS_STATUS_TEMPERATURE = 0x7D, /* R/W byte */
+ PMBUS_STATUS_CML = 0x7E, /* R/W byte */
+ PMBUS_STATUS_OTHER = 0x7F, /* R/W byte */
+ PMBUS_STATUS_MFR_SPECIFIC = 0x80, /* R/W byte */
+ PMBUS_STATUS_FANS_1_2 = 0x81, /* R/W byte */
+ PMBUS_STATUS_FANS_3_4 = 0x82, /* R/W byte */
+ PMBUS_READ_EIN = 0x86, /* Read-Only block 5 bytes */
+ PMBUS_READ_EOUT = 0x87, /* Read-Only block 5 bytes */
+ PMBUS_READ_VIN = 0x88, /* Read-Only word */
+ PMBUS_READ_IIN = 0x89, /* Read-Only word */
+ PMBUS_READ_VCAP = 0x8A, /* Read-Only word */
+ PMBUS_READ_VOUT = 0x8B, /* Read-Only word */
+ PMBUS_READ_IOUT = 0x8C, /* Read-Only word */
+ PMBUS_READ_TEMPERATURE_1 = 0x8D, /* Read-Only word */
+ PMBUS_READ_TEMPERATURE_2 = 0x8E, /* Read-Only word */
+ PMBUS_READ_TEMPERATURE_3 = 0x8F, /* Read-Only word */
+ PMBUS_READ_FAN_SPEED_1 = 0x90, /* Read-Only word */
+ PMBUS_READ_FAN_SPEED_2 = 0x91, /* Read-Only word */
+ PMBUS_READ_FAN_SPEED_3 = 0x92, /* Read-Only word */
+ PMBUS_READ_FAN_SPEED_4 = 0x93, /* Read-Only word */
+ PMBUS_READ_DUTY_CYCLE = 0x94, /* Read-Only word */
+ PMBUS_READ_FREQUENCY = 0x95, /* Read-Only word */
+ PMBUS_READ_POUT = 0x96, /* Read-Only word */
+ PMBUS_READ_PIN = 0x97, /* Read-Only word */
+ PMBUS_REVISION = 0x98, /* Read-Only byte */
+ PMBUS_MFR_ID = 0x99, /* R/W block */
+ PMBUS_MFR_MODEL = 0x9A, /* R/W block */
+ PMBUS_MFR_REVISION = 0x9B, /* R/W block */
+ PMBUS_MFR_LOCATION = 0x9C, /* R/W block */
+ PMBUS_MFR_DATE = 0x9D, /* R/W block */
+ PMBUS_MFR_SERIAL = 0x9E, /* R/W block */
+ PMBUS_APP_PROFILE_SUPPORT = 0x9F, /* Read-Only block-read */
+ PMBUS_MFR_VIN_MIN = 0xA0, /* Read-Only word */
+ PMBUS_MFR_VIN_MAX = 0xA1, /* Read-Only word */
+ PMBUS_MFR_IIN_MAX = 0xA2, /* Read-Only word */
+ PMBUS_MFR_PIN_MAX = 0xA3, /* Read-Only word */
+ PMBUS_MFR_VOUT_MIN = 0xA4, /* Read-Only word */
+ PMBUS_MFR_VOUT_MAX = 0xA5, /* Read-Only word */
+ PMBUS_MFR_IOUT_MAX = 0xA6, /* Read-Only word */
+ PMBUS_MFR_POUT_MAX = 0xA7, /* Read-Only word */
+ PMBUS_MFR_TAMBIENT_MAX = 0xA8, /* Read-Only word */
+ PMBUS_MFR_TAMBIENT_MIN = 0xA9, /* Read-Only word */
+ PMBUS_MFR_EFFICIENCY_LL = 0xAA, /* Read-Only block 14 bytes */
+ PMBUS_MFR_EFFICIENCY_HL = 0xAB, /* Read-Only block 14 bytes */
+ PMBUS_MFR_PIN_ACCURACY = 0xAC, /* Read-Only byte */
+ PMBUS_IC_DEVICE_ID = 0xAD, /* Read-Only block-read */
+ PMBUS_IC_DEVICE_REV = 0xAE, /* Read-Only block-read */
+ PMBUS_MFR_MAX_TEMP_1 = 0xC0, /* R/W word */
+ PMBUS_MFR_MAX_TEMP_2 = 0xC1, /* R/W word */
+ PMBUS_MFR_MAX_TEMP_3 = 0xC2, /* R/W word */
+ PMBUS_IDLE_STATE = 0xFF,
+};
+
+/* STATUS_WORD */
+#define PB_STATUS_VOUT BIT(15)
+#define PB_STATUS_IOUT_POUT BIT(14)
+#define PB_STATUS_INPUT BIT(13)
+#define PB_STATUS_WORD_MFR BIT(12)
+#define PB_STATUS_POWER_GOOD_N BIT(11)
+#define PB_STATUS_FAN BIT(10)
+#define PB_STATUS_OTHER BIT(9)
+#define PB_STATUS_UNKNOWN BIT(8)
+/* STATUS_BYTE */
+#define PB_STATUS_BUSY BIT(7)
+#define PB_STATUS_OFF BIT(6)
+#define PB_STATUS_VOUT_OV BIT(5)
+#define PB_STATUS_IOUT_OC BIT(4)
+#define PB_STATUS_VIN_UV BIT(3)
+#define PB_STATUS_TEMPERATURE BIT(2)
+#define PB_STATUS_CML BIT(1)
+#define PB_STATUS_NONE_ABOVE BIT(0)
+
+/* STATUS_VOUT */
+#define PB_STATUS_VOUT_OV_FAULT BIT(7) /* Output Overvoltage Fault */
+#define PB_STATUS_VOUT_OV_WARN BIT(6) /* Output Overvoltage Warning */
+#define PB_STATUS_VOUT_UV_WARN BIT(5) /* Output Undervoltage Warning */
+#define PB_STATUS_VOUT_UV_FAULT BIT(4) /* Output Undervoltage Fault */
+#define PB_STATUS_VOUT_MAX BIT(3)
+#define PB_STATUS_VOUT_TON_MAX_FAULT BIT(2)
+#define PB_STATUS_VOUT_TOFF_MAX_WARN BIT(1)
+
+/* STATUS_IOUT */
+#define PB_STATUS_IOUT_OC_FAULT BIT(7) /* Output Overcurrent Fault */
+#define PB_STATUS_IOUT_OC_LV_FAULT BIT(6) /* Output OC And Low Voltage Fault */
+#define PB_STATUS_IOUT_OC_WARN BIT(5) /* Output Overcurrent Warning */
+#define PB_STATUS_IOUT_UC_FAULT BIT(4) /* Output Undercurrent Fault */
+#define PB_STATUS_CURR_SHARE BIT(3) /* Current Share Fault */
+#define PB_STATUS_PWR_LIM_MODE BIT(2) /* In Power Limiting Mode */
+#define PB_STATUS_POUT_OP_FAULT BIT(1) /* Output Overpower Fault */
+#define PB_STATUS_POUT_OP_WARN BIT(0) /* Output Overpower Warning */
+
+/* STATUS_INPUT */
+#define PB_STATUS_INPUT_VIN_OV_FAULT BIT(7) /* Input Overvoltage Fault */
+#define PB_STATUS_INPUT_VIN_OV_WARN BIT(6) /* Input Overvoltage Warning */
+#define PB_STATUS_INPUT_VIN_UV_WARN BIT(5) /* Input Undervoltage Warning */
+#define PB_STATUS_INPUT_VIN_UV_FAULT BIT(4) /* Input Undervoltage Fault */
+#define PB_STATUS_INPUT_IIN_OC_FAULT BIT(2) /* Input Overcurrent Fault */
+#define PB_STATUS_INPUT_IIN_OC_WARN BIT(1) /* Input Overcurrent Warning */
+#define PB_STATUS_INPUT_PIN_OP_WARN BIT(0) /* Input Overpower Warning */
+
+/* STATUS_TEMPERATURE */
+#define PB_STATUS_OT_FAULT BIT(7) /* Overtemperature Fault */
+#define PB_STATUS_OT_WARN BIT(6) /* Overtemperature Warning */
+#define PB_STATUS_UT_WARN BIT(5) /* Undertemperature Warning */
+#define PB_STATUS_UT_FAULT BIT(4) /* Undertemperature Fault */
+
+/* STATUS_CML */
+#define PB_CML_FAULT_INVALID_CMD BIT(7) /* Invalid/Unsupported Command */
+#define PB_CML_FAULT_INVALID_DATA BIT(6) /* Invalid/Unsupported Data */
+#define PB_CML_FAULT_PEC BIT(5) /* Packet Error Check Failed */
+#define PB_CML_FAULT_MEMORY BIT(4) /* Memory Fault Detected */
+#define PB_CML_FAULT_PROCESSOR BIT(3) /* Processor Fault Detected */
+#define PB_CML_FAULT_OTHER_COMM BIT(1) /* Other communication fault */
+#define PB_CML_FAULT_OTHER_MEM_LOGIC BIT(0) /* Other Memory Or Logic Fault */
+
+/* OPERATION*/
+#define PB_OP_ON BIT(7) /* PSU is switched on */
+#define PB_OP_MARGIN_HIGH BIT(5) /* PSU vout is set to margin high */
+#define PB_OP_MARGIN_LOW BIT(4) /* PSU vout is set to margin low */
+
+/* PAGES */
+#define PB_MAX_PAGES 0x1F
+#define PB_ALL_PAGES 0xFF
+
+#define PMBUS_ERR_BYTE 0xFF
+
+#define TYPE_PMBUS_DEVICE "pmbus-device"
+OBJECT_DECLARE_TYPE(PMBusDevice, PMBusDeviceClass,
+ PMBUS_DEVICE)
+
+/* flags */
+#define PB_HAS_COEFFICIENTS BIT_ULL(9)
+#define PB_HAS_VIN BIT_ULL(10)
+#define PB_HAS_VOUT BIT_ULL(11)
+#define PB_HAS_VOUT_MARGIN BIT_ULL(12)
+#define PB_HAS_VIN_RATING BIT_ULL(13)
+#define PB_HAS_VOUT_RATING BIT_ULL(14)
+#define PB_HAS_VOUT_MODE BIT_ULL(15)
+#define PB_HAS_VCAP BIT_ULL(16)
+#define PB_HAS_IOUT BIT_ULL(21)
+#define PB_HAS_IIN BIT_ULL(22)
+#define PB_HAS_IOUT_RATING BIT_ULL(23)
+#define PB_HAS_IIN_RATING BIT_ULL(24)
+#define PB_HAS_IOUT_GAIN BIT_ULL(25)
+#define PB_HAS_POUT BIT_ULL(30)
+#define PB_HAS_PIN BIT_ULL(31)
+#define PB_HAS_EIN BIT_ULL(32)
+#define PB_HAS_EOUT BIT_ULL(33)
+#define PB_HAS_POUT_RATING BIT_ULL(34)
+#define PB_HAS_PIN_RATING BIT_ULL(35)
+#define PB_HAS_TEMPERATURE BIT_ULL(40)
+#define PB_HAS_TEMP2 BIT_ULL(41)
+#define PB_HAS_TEMP3 BIT_ULL(42)
+#define PB_HAS_TEMP_RATING BIT_ULL(43)
+#define PB_HAS_FAN BIT_ULL(44)
+#define PB_HAS_MFR_INFO BIT_ULL(50)
+#define PB_HAS_STATUS_MFR_SPECIFIC BIT_ULL(51)
+
+struct PMBusDeviceClass {
+ SMBusDeviceClass parent_class;
+ uint8_t device_num_pages;
+
+ /**
+ * Implement quick_cmd, receive byte, and write_data to support non-standard
+ * PMBus functionality
+ */
+ void (*quick_cmd)(PMBusDevice *dev, uint8_t read);
+ int (*write_data)(PMBusDevice *dev, const uint8_t *buf, uint8_t len);
+ uint8_t (*receive_byte)(PMBusDevice *dev);
+};
+
+/*
+ * According to the spec, each page may offer the full range of PMBus commands
+ * available for each output or non-PMBus device.
+ * Therefore, we can't assume that any registers will always be the same across
+ * all pages.
+ * The page 0xFF is intended for writes to all pages
+ */
+typedef struct PMBusPage {
+ uint64_t page_flags;
+
+ uint8_t page; /* R/W byte */
+ uint8_t operation; /* R/W byte */
+ uint8_t on_off_config; /* R/W byte */
+ uint8_t write_protect; /* R/W byte */
+ uint8_t phase; /* R/W byte */
+ uint8_t vout_mode; /* R/W byte */
+ uint16_t vout_command; /* R/W word */
+ uint16_t vout_trim; /* R/W word */
+ uint16_t vout_cal_offset; /* R/W word */
+ uint16_t vout_max; /* R/W word */
+ uint16_t vout_margin_high; /* R/W word */
+ uint16_t vout_margin_low; /* R/W word */
+ uint16_t vout_transition_rate; /* R/W word */
+ uint16_t vout_droop; /* R/W word */
+ uint16_t vout_scale_loop; /* R/W word */
+ uint16_t vout_scale_monitor; /* R/W word */
+ uint16_t vout_min; /* R/W word */
+ uint8_t coefficients[5]; /* Read-only block 5 bytes */
+ uint16_t pout_max; /* R/W word */
+ uint16_t max_duty; /* R/W word */
+ uint16_t frequency_switch; /* R/W word */
+ uint16_t vin_on; /* R/W word */
+ uint16_t vin_off; /* R/W word */
+ uint16_t iout_cal_gain; /* R/W word */
+ uint16_t iout_cal_offset; /* R/W word */
+ uint8_t fan_config_1_2; /* R/W byte */
+ uint16_t fan_command_1; /* R/W word */
+ uint16_t fan_command_2; /* R/W word */
+ uint8_t fan_config_3_4; /* R/W byte */
+ uint16_t fan_command_3; /* R/W word */
+ uint16_t fan_command_4; /* R/W word */
+ uint16_t vout_ov_fault_limit; /* R/W word */
+ uint8_t vout_ov_fault_response; /* R/W byte */
+ uint16_t vout_ov_warn_limit; /* R/W word */
+ uint16_t vout_uv_warn_limit; /* R/W word */
+ uint16_t vout_uv_fault_limit; /* R/W word */
+ uint8_t vout_uv_fault_response; /* R/W byte */
+ uint16_t iout_oc_fault_limit; /* R/W word */
+ uint8_t iout_oc_fault_response; /* R/W byte */
+ uint16_t iout_oc_lv_fault_limit; /* R/W word */
+ uint8_t iout_oc_lv_fault_response; /* R/W byte */
+ uint16_t iout_oc_warn_limit; /* R/W word */
+ uint16_t iout_uc_fault_limit; /* R/W word */
+ uint8_t iout_uc_fault_response; /* R/W byte */
+ uint16_t ot_fault_limit; /* R/W word */
+ uint8_t ot_fault_response; /* R/W byte */
+ uint16_t ot_warn_limit; /* R/W word */
+ uint16_t ut_warn_limit; /* R/W word */
+ uint16_t ut_fault_limit; /* R/W word */
+ uint8_t ut_fault_response; /* R/W byte */
+ uint16_t vin_ov_fault_limit; /* R/W word */
+ uint8_t vin_ov_fault_response; /* R/W byte */
+ uint16_t vin_ov_warn_limit; /* R/W word */
+ uint16_t vin_uv_warn_limit; /* R/W word */
+ uint16_t vin_uv_fault_limit; /* R/W word */
+ uint8_t vin_uv_fault_response; /* R/W byte */
+ uint16_t iin_oc_fault_limit; /* R/W word */
+ uint8_t iin_oc_fault_response; /* R/W byte */
+ uint16_t iin_oc_warn_limit; /* R/W word */
+ uint16_t power_good_on; /* R/W word */
+ uint16_t power_good_off; /* R/W word */
+ uint16_t ton_delay; /* R/W word */
+ uint16_t ton_rise; /* R/W word */
+ uint16_t ton_max_fault_limit; /* R/W word */
+ uint8_t ton_max_fault_response; /* R/W byte */
+ uint16_t toff_delay; /* R/W word */
+ uint16_t toff_fall; /* R/W word */
+ uint16_t toff_max_warn_limit; /* R/W word */
+ uint16_t pout_op_fault_limit; /* R/W word */
+ uint8_t pout_op_fault_response; /* R/W byte */
+ uint16_t pout_op_warn_limit; /* R/W word */
+ uint16_t pin_op_warn_limit; /* R/W word */
+ uint16_t status_word; /* R/W word */
+ uint8_t status_vout; /* R/W byte */
+ uint8_t status_iout; /* R/W byte */
+ uint8_t status_input; /* R/W byte */
+ uint8_t status_temperature; /* R/W byte */
+ uint8_t status_cml; /* R/W byte */
+ uint8_t status_other; /* R/W byte */
+ uint8_t status_mfr_specific; /* R/W byte */
+ uint8_t status_fans_1_2; /* R/W byte */
+ uint8_t status_fans_3_4; /* R/W byte */
+ uint8_t read_ein[5]; /* Read-Only block 5 bytes */
+ uint8_t read_eout[5]; /* Read-Only block 5 bytes */
+ uint16_t read_vin; /* Read-Only word */
+ uint16_t read_iin; /* Read-Only word */
+ uint16_t read_vcap; /* Read-Only word */
+ uint16_t read_vout; /* Read-Only word */
+ uint16_t read_iout; /* Read-Only word */
+ uint16_t read_temperature_1; /* Read-Only word */
+ uint16_t read_temperature_2; /* Read-Only word */
+ uint16_t read_temperature_3; /* Read-Only word */
+ uint16_t read_fan_speed_1; /* Read-Only word */
+ uint16_t read_fan_speed_2; /* Read-Only word */
+ uint16_t read_fan_speed_3; /* Read-Only word */
+ uint16_t read_fan_speed_4; /* Read-Only word */
+ uint16_t read_duty_cycle; /* Read-Only word */
+ uint16_t read_frequency; /* Read-Only word */
+ uint16_t read_pout; /* Read-Only word */
+ uint16_t read_pin; /* Read-Only word */
+ uint8_t revision; /* Read-Only byte */
+ const char *mfr_id; /* R/W block */
+ const char *mfr_model; /* R/W block */
+ const char *mfr_revision; /* R/W block */
+ const char *mfr_location; /* R/W block */
+ const char *mfr_date; /* R/W block */
+ const char *mfr_serial; /* R/W block */
+ const char *app_profile_support; /* Read-Only block-read */
+ uint16_t mfr_vin_min; /* Read-Only word */
+ uint16_t mfr_vin_max; /* Read-Only word */
+ uint16_t mfr_iin_max; /* Read-Only word */
+ uint16_t mfr_pin_max; /* Read-Only word */
+ uint16_t mfr_vout_min; /* Read-Only word */
+ uint16_t mfr_vout_max; /* Read-Only word */
+ uint16_t mfr_iout_max; /* Read-Only word */
+ uint16_t mfr_pout_max; /* Read-Only word */
+ uint16_t mfr_tambient_max; /* Read-Only word */
+ uint16_t mfr_tambient_min; /* Read-Only word */
+ uint8_t mfr_efficiency_ll[14]; /* Read-Only block 14 bytes */
+ uint8_t mfr_efficiency_hl[14]; /* Read-Only block 14 bytes */
+ uint8_t mfr_pin_accuracy; /* Read-Only byte */
+ uint16_t mfr_max_temp_1; /* R/W word */
+ uint16_t mfr_max_temp_2; /* R/W word */
+ uint16_t mfr_max_temp_3; /* R/W word */
+} PMBusPage;
+
+/* State */
+struct PMBusDevice {
+ SMBusDevice smb;
+
+ uint8_t num_pages;
+ uint8_t code;
+ uint8_t page;
+
+ /*
+ * PMBus registers are stored in a PMBusPage structure allocated by
+ * calling pmbus_pages_alloc()
+ */
+ PMBusPage *pages;
+ uint8_t capability;
+
+
+ int32_t in_buf_len;
+ uint8_t *in_buf;
+ int32_t out_buf_len;
+ uint8_t out_buf[SMBUS_DATA_MAX_LEN];
+};
+
+/**
+ * Direct mode coefficients
+ * @var m - mantissa
+ * @var b - offset
+ * @var R - exponent
+ */
+typedef struct PMBusCoefficients {
+ int32_t m; /* mantissa */
+ int64_t b; /* offset */
+ int32_t R; /* exponent */
+} PMBusCoefficients;
+
+/**
+ * VOUT_Mode bit fields
+ */
+typedef struct PMBusVoutMode {
+ uint8_t mode:3;
+ int8_t exp:5;
+} PMBusVoutMode;
+
+/**
+ * Convert sensor values to direct mode format
+ *
+ * Y = (m * x - b) * 10^R
+ *
+ * @return uint16_t
+ */
+uint16_t pmbus_data2direct_mode(PMBusCoefficients c, uint32_t value);
+
+/**
+ * Convert direct mode formatted data into sensor reading
+ *
+ * X = (Y * 10^-R - b) / m
+ *
+ * @return uint32_t
+ */
+uint32_t pmbus_direct_mode2data(PMBusCoefficients c, uint16_t value);
+
+/**
+ * Convert sensor values to linear mode format
+ *
+ * L = D * 2^(-e)
+ *
+ * @return uint16
+ */
+uint16_t pmbus_data2linear_mode(uint16_t value, int exp);
+
+/**
+ * Convert linear mode formatted data into sensor reading
+ *
+ * D = L * 2^e
+ *
+ * @return uint16
+ */
+uint16_t pmbus_linear_mode2data(uint16_t value, int exp);
+
+/**
+ * @brief Send a block of data over PMBus
+ * Assumes that the bytes in the block are already ordered correctly,
+ * also assumes the length has been prepended to the block if necessary
+ * | low_byte | ... | high_byte |
+ * @param state - maintains state of the PMBus device
+ * @param data - byte array to be sent by device
+ * @param len - number
+ */
+void pmbus_send(PMBusDevice *state, const uint8_t *data, uint16_t len);
+void pmbus_send8(PMBusDevice *state, uint8_t data);
+void pmbus_send16(PMBusDevice *state, uint16_t data);
+void pmbus_send32(PMBusDevice *state, uint32_t data);
+void pmbus_send64(PMBusDevice *state, uint64_t data);
+
+/**
+ * @brief Send a string over PMBus with length prepended.
+ * Length is calculated using str_len()
+ */
+void pmbus_send_string(PMBusDevice *state, const char *data);
+
+/**
+ * @brief Receive data sent with Block Write.
+ * @param dest - memory with enough capacity to receive the write
+ * @param len - the capacity of dest
+ */
+uint8_t pmbus_receive_block(PMBusDevice *pmdev, uint8_t *dest, size_t len);
+
+/**
+ * @brief Receive data over PMBus
+ * These methods help track how much data is being received over PMBus
+ * Log to GUEST_ERROR if too much or too little is sent.
+ */
+uint8_t pmbus_receive8(PMBusDevice *pmdev);
+uint16_t pmbus_receive16(PMBusDevice *pmdev);
+uint32_t pmbus_receive32(PMBusDevice *pmdev);
+uint64_t pmbus_receive64(PMBusDevice *pmdev);
+
+/**
+ * PMBus page config must be called before any page is first used.
+ * It will allocate memory for all the pages if needed.
+ * Passed in flags overwrite existing flags if any.
+ * @param page_index the page to which the flags are applied, setting page_index
+ * to 0xFF applies the passed in flags to all pages.
+ * @param flags
+ */
+int pmbus_page_config(PMBusDevice *pmdev, uint8_t page_index, uint64_t flags);
+
+/**
+ * Update the status registers when sensor values change.
+ * Useful if modifying sensors through qmp, this way status registers get
+ * updated
+ */
+void pmbus_check_limits(PMBusDevice *pmdev);
+
+/**
+ * Enter an idle state where only the PMBUS_ERR_BYTE will be returned
+ * indefinitely until a new command is issued.
+ */
+void pmbus_idle(PMBusDevice *pmdev);
+
+extern const VMStateDescription vmstate_pmbus_device;
+
+#define VMSTATE_PMBUS_DEVICE(_field, _state) { \
+ .name = (stringify(_field)), \
+ .size = sizeof(PMBusDevice), \
+ .vmsd = &vmstate_pmbus_device, \
+ .flags = VMS_STRUCT, \
+ .offset = vmstate_offset_value(_state, _field, PMBusDevice), \
+}
+
+#endif
diff --git a/include/hw/i2c/pnv_i2c_regs.h b/include/hw/i2c/pnv_i2c_regs.h
new file mode 100644
index 0000000000..85e96ff480
--- /dev/null
+++ b/include/hw/i2c/pnv_i2c_regs.h
@@ -0,0 +1,143 @@
+/*
+ * PowerNV I2C Controller Register Definitions
+ *
+ * Copyright (c) 2024, IBM Corporation.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef PNV_I2C_REGS_H
+#define PNV_I2C_REGS_H
+
+/* I2C FIFO register */
+#define I2C_FIFO_REG 0x4
+#define I2C_FIFO PPC_BITMASK(0, 7)
+
+/* I2C command register */
+#define I2C_CMD_REG 0x5
+#define I2C_CMD_WITH_START PPC_BIT(0)
+#define I2C_CMD_WITH_ADDR PPC_BIT(1)
+#define I2C_CMD_READ_CONT PPC_BIT(2)
+#define I2C_CMD_WITH_STOP PPC_BIT(3)
+#define I2C_CMD_INTR_STEERING PPC_BITMASK(6, 7) /* P9 */
+#define I2C_CMD_INTR_STEER_HOST 1
+#define I2C_CMD_INTR_STEER_OCC 2
+#define I2C_CMD_DEV_ADDR PPC_BITMASK(8, 14)
+#define I2C_CMD_READ_NOT_WRITE PPC_BIT(15)
+#define I2C_CMD_LEN_BYTES PPC_BITMASK(16, 31)
+#define I2C_MAX_TFR_LEN 0xfff0ull
+
+/* I2C mode register */
+#define I2C_MODE_REG 0x6
+#define I2C_MODE_BIT_RATE_DIV PPC_BITMASK(0, 15)
+#define I2C_MODE_PORT_NUM PPC_BITMASK(16, 21)
+#define I2C_MODE_ENHANCED PPC_BIT(28)
+#define I2C_MODE_DIAGNOSTIC PPC_BIT(29)
+#define I2C_MODE_PACING_ALLOW PPC_BIT(30)
+#define I2C_MODE_WRAP PPC_BIT(31)
+
+/* I2C watermark register */
+#define I2C_WATERMARK_REG 0x7
+#define I2C_WATERMARK_HIGH PPC_BITMASK(16, 19)
+#define I2C_WATERMARK_LOW PPC_BITMASK(24, 27)
+
+/*
+ * I2C interrupt mask and condition registers
+ *
+ * NB: The function of 0x9 and 0xa changes depending on whether you're reading
+ * or writing to them. When read they return the interrupt condition bits
+ * and on writes they update the interrupt mask register.
+ *
+ * The bit definitions are the same for all the interrupt registers.
+ */
+#define I2C_INTR_MASK_REG 0x8
+
+#define I2C_INTR_RAW_COND_REG 0x9 /* read */
+#define I2C_INTR_MASK_OR_REG 0x9 /* write*/
+
+#define I2C_INTR_COND_REG 0xa /* read */
+#define I2C_INTR_MASK_AND_REG 0xa /* write */
+
+#define I2C_INTR_ALL PPC_BITMASK(16, 31)
+#define I2C_INTR_INVALID_CMD PPC_BIT(16)
+#define I2C_INTR_LBUS_PARITY_ERR PPC_BIT(17)
+#define I2C_INTR_BKEND_OVERRUN_ERR PPC_BIT(18)
+#define I2C_INTR_BKEND_ACCESS_ERR PPC_BIT(19)
+#define I2C_INTR_ARBT_LOST_ERR PPC_BIT(20)
+#define I2C_INTR_NACK_RCVD_ERR PPC_BIT(21)
+#define I2C_INTR_DATA_REQ PPC_BIT(22)
+#define I2C_INTR_CMD_COMP PPC_BIT(23)
+#define I2C_INTR_STOP_ERR PPC_BIT(24)
+#define I2C_INTR_I2C_BUSY PPC_BIT(25)
+#define I2C_INTR_NOT_I2C_BUSY PPC_BIT(26)
+#define I2C_INTR_SCL_EQ_1 PPC_BIT(28)
+#define I2C_INTR_SCL_EQ_0 PPC_BIT(29)
+#define I2C_INTR_SDA_EQ_1 PPC_BIT(30)
+#define I2C_INTR_SDA_EQ_0 PPC_BIT(31)
+
+/* I2C status register */
+#define I2C_RESET_I2C_REG 0xb /* write */
+#define I2C_RESET_ERRORS 0xc
+#define I2C_STAT_REG 0xb /* read */
+#define I2C_STAT_INVALID_CMD PPC_BIT(0)
+#define I2C_STAT_LBUS_PARITY_ERR PPC_BIT(1)
+#define I2C_STAT_BKEND_OVERRUN_ERR PPC_BIT(2)
+#define I2C_STAT_BKEND_ACCESS_ERR PPC_BIT(3)
+#define I2C_STAT_ARBT_LOST_ERR PPC_BIT(4)
+#define I2C_STAT_NACK_RCVD_ERR PPC_BIT(5)
+#define I2C_STAT_DATA_REQ PPC_BIT(6)
+#define I2C_STAT_CMD_COMP PPC_BIT(7)
+#define I2C_STAT_STOP_ERR PPC_BIT(8)
+#define I2C_STAT_UPPER_THRS PPC_BITMASK(9, 15)
+#define I2C_STAT_ANY_I2C_INTR PPC_BIT(16)
+#define I2C_STAT_PORT_HISTORY_BUSY PPC_BIT(19)
+#define I2C_STAT_SCL_INPUT_LEVEL PPC_BIT(20)
+#define I2C_STAT_SDA_INPUT_LEVEL PPC_BIT(21)
+#define I2C_STAT_PORT_BUSY PPC_BIT(22)
+#define I2C_STAT_INTERFACE_BUSY PPC_BIT(23)
+#define I2C_STAT_FIFO_ENTRY_COUNT PPC_BITMASK(24, 31)
+
+#define I2C_STAT_ANY_ERR (I2C_STAT_INVALID_CMD | I2C_STAT_LBUS_PARITY_ERR | \
+ I2C_STAT_BKEND_OVERRUN_ERR | \
+ I2C_STAT_BKEND_ACCESS_ERR | I2C_STAT_ARBT_LOST_ERR | \
+ I2C_STAT_NACK_RCVD_ERR | I2C_STAT_STOP_ERR)
+
+
+#define I2C_INTR_ACTIVE \
+ ((I2C_STAT_ANY_ERR >> 16) | I2C_INTR_CMD_COMP | I2C_INTR_DATA_REQ)
+
+/* Pseudo-status used for timeouts */
+#define I2C_STAT_PSEUDO_TIMEOUT PPC_BIT(63)
+
+/* I2C extended status register */
+#define I2C_EXTD_STAT_REG 0xc
+#define I2C_EXTD_STAT_FIFO_SIZE PPC_BITMASK(0, 7)
+#define I2C_EXTD_STAT_MSM_CURSTATE PPC_BITMASK(11, 15)
+#define I2C_EXTD_STAT_SCL_IN_SYNC PPC_BIT(16)
+#define I2C_EXTD_STAT_SDA_IN_SYNC PPC_BIT(17)
+#define I2C_EXTD_STAT_S_SCL PPC_BIT(18)
+#define I2C_EXTD_STAT_S_SDA PPC_BIT(19)
+#define I2C_EXTD_STAT_M_SCL PPC_BIT(20)
+#define I2C_EXTD_STAT_M_SDA PPC_BIT(21)
+#define I2C_EXTD_STAT_HIGH_WATER PPC_BIT(22)
+#define I2C_EXTD_STAT_LOW_WATER PPC_BIT(23)
+#define I2C_EXTD_STAT_I2C_BUSY PPC_BIT(24)
+#define I2C_EXTD_STAT_SELF_BUSY PPC_BIT(25)
+#define I2C_EXTD_STAT_I2C_VERSION PPC_BITMASK(27, 31)
+
+/* I2C residual front end/back end length */
+#define I2C_RESIDUAL_LEN_REG 0xd
+#define I2C_RESIDUAL_FRONT_END PPC_BITMASK(0, 15)
+#define I2C_RESIDUAL_BACK_END PPC_BITMASK(16, 31)
+
+/* Port busy register */
+#define I2C_PORT_BUSY_REG 0xe
+#define I2C_SET_S_SCL_REG 0xd
+#define I2C_RESET_S_SCL_REG 0xf
+#define I2C_SET_S_SDA_REG 0x10
+#define I2C_RESET_S_SDA_REG 0x11
+
+#define PNV_I2C_FIFO_SIZE 8
+#define PNV_I2C_MAX_BUSSES 64
+
+#endif /* PNV_I2C_REGS_H */
diff --git a/include/hw/i2c/ppc4xx_i2c.h b/include/hw/i2c/ppc4xx_i2c.h
index f6f837fbec..4e882fa3c8 100644
--- a/include/hw/i2c/ppc4xx_i2c.h
+++ b/include/hw/i2c/ppc4xx_i2c.h
@@ -29,11 +29,12 @@
#include "hw/sysbus.h"
#include "hw/i2c/bitbang_i2c.h"
+#include "qom/object.h"
#define TYPE_PPC4xx_I2C "ppc4xx-i2c"
-#define PPC4xx_I2C(obj) OBJECT_CHECK(PPC4xxI2CState, (obj), TYPE_PPC4xx_I2C)
+OBJECT_DECLARE_SIMPLE_TYPE(PPC4xxI2CState, PPC4xx_I2C)
-typedef struct PPC4xxI2CState {
+struct PPC4xxI2CState {
/*< private >*/
SysBusDevice parent_obj;
@@ -57,6 +58,6 @@ typedef struct PPC4xxI2CState {
uint8_t xfrcnt;
uint8_t xtcntlss;
uint8_t directcntl;
-} PPC4xxI2CState;
+};
#endif /* PPC4XX_I2C_H */
diff --git a/include/hw/i2c/smbus_slave.h b/include/hw/i2c/smbus_slave.h
index ebe068304e..86bfe0a79e 100644
--- a/include/hw/i2c/smbus_slave.h
+++ b/include/hw/i2c/smbus_slave.h
@@ -26,19 +26,14 @@
#define HW_SMBUS_SLAVE_H
#include "hw/i2c/i2c.h"
+#include "qom/object.h"
#define TYPE_SMBUS_DEVICE "smbus-device"
-#define SMBUS_DEVICE(obj) \
- OBJECT_CHECK(SMBusDevice, (obj), TYPE_SMBUS_DEVICE)
-#define SMBUS_DEVICE_CLASS(klass) \
- OBJECT_CLASS_CHECK(SMBusDeviceClass, (klass), TYPE_SMBUS_DEVICE)
-#define SMBUS_DEVICE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(SMBusDeviceClass, (obj), TYPE_SMBUS_DEVICE)
+OBJECT_DECLARE_TYPE(SMBusDevice, SMBusDeviceClass,
+ SMBUS_DEVICE)
-typedef struct SMBusDevice SMBusDevice;
-typedef struct SMBusDeviceClass
-{
+struct SMBusDeviceClass {
I2CSlaveClass parent_class;
/*
@@ -67,7 +62,7 @@ typedef struct SMBusDeviceClass
* return 0xff in that case.
*/
uint8_t (*receive_byte)(SMBusDevice *dev);
-} SMBusDeviceClass;
+};
#define SMBUS_DATA_MAX_LEN 34 /* command + len + 32 bytes of data. */
diff --git a/include/hw/i386/apic.h b/include/hw/i386/apic.h
index da1d2fe155..eb606d6076 100644
--- a/include/hw/i386/apic.h
+++ b/include/hw/i386/apic.h
@@ -3,16 +3,14 @@
/* apic.c */
-void apic_deliver_irq(uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode,
- uint8_t vector_num, uint8_t trigger_mode);
+void apic_set_max_apic_id(uint32_t max_apic_id);
int apic_accept_pic_intr(DeviceState *s);
void apic_deliver_pic_intr(DeviceState *s, int level);
void apic_deliver_nmi(DeviceState *d);
int apic_get_interrupt(DeviceState *s);
-void apic_reset_irq_delivered(void);
-int apic_get_irq_delivered(void);
-void cpu_set_apic_base(DeviceState *s, uint64_t val);
+int cpu_set_apic_base(DeviceState *s, uint64_t val);
uint64_t cpu_get_apic_base(DeviceState *s);
+bool cpu_is_apic_enabled(DeviceState *s);
void cpu_set_apic_tpr(DeviceState *s, uint8_t val);
uint8_t cpu_get_apic_tpr(DeviceState *s);
void apic_init_reset(DeviceState *s);
@@ -20,6 +18,9 @@ void apic_sipi(DeviceState *s);
void apic_poll_irq(DeviceState *d);
void apic_designate_bsp(DeviceState *d, bool bsp);
int apic_get_highest_priority_irr(DeviceState *dev);
+int apic_msr_read(int index, uint64_t *val);
+int apic_msr_write(int index, uint64_t val);
+bool is_x2apic_mode(DeviceState *d);
/* pc.c */
DeviceState *cpu_get_current_apic(void);
diff --git a/include/hw/i386/apic_internal.h b/include/hw/i386/apic_internal.h
index 2597000e03..d6e85833da 100644
--- a/include/hw/i386/apic_internal.h
+++ b/include/hw/i386/apic_internal.h
@@ -7,7 +7,7 @@
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -25,6 +25,7 @@
#include "exec/memory.h"
#include "qemu/timer.h"
#include "target/i386/cpu-qom.h"
+#include "qom/object.h"
/* APIC Local Vector Table */
#define APIC_LVT_TIMER 0
@@ -45,8 +46,10 @@
#define APIC_DM_EXTINT 7
/* APIC destination mode */
-#define APIC_DESTMODE_FLAT 0xf
-#define APIC_DESTMODE_CLUSTER 1
+#define APIC_DESTMODE_PHYSICAL 0
+#define APIC_DESTMODE_LOGICAL 1
+#define APIC_DESTMODE_LOGICAL_FLAT 0xf
+#define APIC_DESTMODE_LOGICAL_CLUSTER 0
#define APIC_TRIGGER_EDGE 0
#define APIC_TRIGGER_LEVEL 1
@@ -125,20 +128,16 @@
typedef struct APICCommonState APICCommonState;
#define TYPE_APIC_COMMON "apic-common"
-#define APIC_COMMON(obj) \
- OBJECT_CHECK(APICCommonState, (obj), TYPE_APIC_COMMON)
-#define APIC_COMMON_CLASS(klass) \
- OBJECT_CLASS_CHECK(APICCommonClass, (klass), TYPE_APIC_COMMON)
-#define APIC_COMMON_GET_CLASS(obj) \
- OBJECT_GET_CLASS(APICCommonClass, (obj), TYPE_APIC_COMMON)
-
-typedef struct APICCommonClass
-{
+typedef struct APICCommonClass APICCommonClass;
+DECLARE_OBJ_CHECKERS(APICCommonState, APICCommonClass,
+ APIC_COMMON, TYPE_APIC_COMMON)
+
+struct APICCommonClass {
DeviceClass parent_class;
DeviceRealize realize;
DeviceUnrealize unrealize;
- void (*set_base)(APICCommonState *s, uint64_t val);
+ int (*set_base)(APICCommonState *s, uint64_t val);
void (*set_tpr)(APICCommonState *s, uint8_t val);
uint8_t (*get_tpr)(APICCommonState *s);
void (*enable_tpr_reporting)(APICCommonState *s, bool enable);
@@ -151,7 +150,7 @@ typedef struct APICCommonClass
* device, but it's convenient to have it here for now.
*/
void (*send_msi)(MSIMessage *msi);
-} APICCommonClass;
+};
struct APICCommonState {
/*< private >*/
@@ -190,6 +189,7 @@ struct APICCommonState {
DeviceState *vapic;
hwaddr vapic_paddr; /* note: persistence via kvmvapic */
bool legacy_instance_id;
+ uint32_t extended_log_dest;
};
typedef struct VAPICState {
@@ -202,7 +202,6 @@ typedef struct VAPICState {
extern bool apic_report_tpr_access;
-void apic_report_irq_delivered(int delivered);
bool apic_next_timer(APICCommonState *s, int64_t current_time);
void apic_enable_tpr_access_reporting(DeviceState *d, bool enable);
void apic_enable_vapic(DeviceState *d, hwaddr paddr);
@@ -229,6 +228,6 @@ static inline int apic_get_bit(uint32_t *tab, int index)
return !!(tab[i] & mask);
}
-APICCommonClass *apic_get_class(void);
+APICCommonClass *apic_get_class(Error **errp);
#endif /* QEMU_APIC_INTERNAL_H */
diff --git a/include/hw/i386/hostmem-epc.h b/include/hw/i386/hostmem-epc.h
new file mode 100644
index 0000000000..846c726085
--- /dev/null
+++ b/include/hw/i386/hostmem-epc.h
@@ -0,0 +1,28 @@
+/*
+ * SGX EPC backend
+ *
+ * Copyright (C) 2019 Intel Corporation
+ *
+ * Authors:
+ * Sean Christopherson <sean.j.christopherson@intel.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#ifndef QEMU_HOSTMEM_EPC_H
+#define QEMU_HOSTMEM_EPC_H
+
+#include "sysemu/hostmem.h"
+
+#define TYPE_MEMORY_BACKEND_EPC "memory-backend-epc"
+
+#define MEMORY_BACKEND_EPC(obj) \
+ OBJECT_CHECK(HostMemoryBackendEpc, (obj), TYPE_MEMORY_BACKEND_EPC)
+
+typedef struct HostMemoryBackendEpc HostMemoryBackendEpc;
+
+struct HostMemoryBackendEpc {
+ HostMemoryBackend parent_obj;
+};
+
+#endif
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index 3870052f5f..7fa0a695c8 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -24,10 +24,10 @@
#include "hw/i386/x86-iommu.h"
#include "qemu/iova-tree.h"
+#include "qom/object.h"
#define TYPE_INTEL_IOMMU_DEVICE "intel-iommu"
-#define INTEL_IOMMU_DEVICE(obj) \
- OBJECT_CHECK(IntelIOMMUState, (obj), TYPE_INTEL_IOMMU_DEVICE)
+OBJECT_DECLARE_SIMPLE_TYPE(IntelIOMMUState, INTEL_IOMMU_DEVICE)
#define TYPE_INTEL_IOMMU_MEMORY_REGION "intel-iommu-iommu-memory-region"
@@ -56,10 +56,8 @@
typedef struct VTDContextEntry VTDContextEntry;
typedef struct VTDContextCacheEntry VTDContextCacheEntry;
-typedef struct IntelIOMMUState IntelIOMMUState;
typedef struct VTDAddressSpace VTDAddressSpace;
typedef struct VTDIOTLBEntry VTDIOTLBEntry;
-typedef struct VTDBus VTDBus;
typedef union VTD_IR_TableEntry VTD_IR_TableEntry;
typedef union VTD_IR_MSIAddress VTD_IR_MSIAddress;
typedef struct VTDPASIDDirEntry VTDPASIDDirEntry;
@@ -99,28 +97,61 @@ struct VTDPASIDEntry {
struct VTDAddressSpace {
PCIBus *bus;
uint8_t devfn;
+ uint32_t pasid;
AddressSpace as;
IOMMUMemoryRegion iommu;
MemoryRegion root; /* The root container of the device */
MemoryRegion nodmar; /* The alias of shared nodmar MR */
MemoryRegion iommu_ir; /* Interrupt region: 0xfeeXXXXX */
+ MemoryRegion iommu_ir_fault; /* Interrupt region for catching fault */
IntelIOMMUState *iommu_state;
VTDContextCacheEntry context_cache_entry;
QLIST_ENTRY(VTDAddressSpace) next;
/* Superset of notifier flags that this address space has */
IOMMUNotifierFlag notifier_flags;
- IOVATree *iova_tree; /* Traces mapped IOVA ranges */
-};
-
-struct VTDBus {
- PCIBus* bus; /* A reference to the bus to provide translation for */
- /* A table of VTDAddressSpace objects indexed by devfn */
- VTDAddressSpace *dev_as[];
+ /*
+ * @iova_tree traces mapped IOVA ranges.
+ *
+ * The tree is not needed if no MAP notifier is registered with current
+ * VTD address space, because all guest invalidate commands can be
+ * directly passed to the IOMMU UNMAP notifiers without any further
+ * reshuffling.
+ *
+ * The tree OTOH is required for MAP typed iommu notifiers for a few
+ * reasons.
+ *
+ * Firstly, there's no way to identify whether an PSI (Page Selective
+ * Invalidations) or DSI (Domain Selective Invalidations) event is an
+ * MAP or UNMAP event within the message itself. Without having prior
+ * knowledge of existing state vIOMMU doesn't know whether it should
+ * notify MAP or UNMAP for a PSI message it received when caching mode
+ * is enabled (for MAP notifiers).
+ *
+ * Secondly, PSI messages received from guest driver can be enlarged in
+ * range, covers but not limited to what the guest driver wanted to
+ * invalidate. When the range to invalidates gets bigger than the
+ * limit of a PSI message, it can even become a DSI which will
+ * invalidate the whole domain. If the vIOMMU directly notifies the
+ * registered device with the unmodified range, it may confuse the
+ * registered drivers (e.g. vfio-pci) on either:
+ *
+ * (1) Trying to map the same region more than once (for
+ * VFIO_IOMMU_MAP_DMA, -EEXIST will trigger), or,
+ *
+ * (2) Trying to UNMAP a range that is still partially mapped.
+ *
+ * That accuracy is not required for UNMAP-only notifiers, but it is a
+ * must-to-have for notifiers registered with MAP events, because the
+ * vIOMMU needs to make sure the shadow page table is always in sync
+ * with the guest IOMMU pgtables for a device.
+ */
+ IOVATree *iova_tree;
};
struct VTDIOTLBEntry {
uint64_t gfn;
uint16_t domain_id;
+ uint32_t pasid;
uint64_t slpte;
uint64_t mask;
uint8_t access_flags;
@@ -146,38 +177,40 @@ enum {
/* Interrupt Remapping Table Entry Definition */
union VTD_IR_TableEntry {
struct {
-#ifdef HOST_WORDS_BIGENDIAN
- uint32_t __reserved_1:8; /* Reserved 1 */
- uint32_t vector:8; /* Interrupt Vector */
- uint32_t irte_mode:1; /* IRTE Mode */
- uint32_t __reserved_0:3; /* Reserved 0 */
- uint32_t __avail:4; /* Available spaces for software */
- uint32_t delivery_mode:3; /* Delivery Mode */
- uint32_t trigger_mode:1; /* Trigger Mode */
- uint32_t redir_hint:1; /* Redirection Hint */
- uint32_t dest_mode:1; /* Destination Mode */
- uint32_t fault_disable:1; /* Fault Processing Disable */
- uint32_t present:1; /* Whether entry present/available */
+#if HOST_BIG_ENDIAN
+ uint64_t dest_id:32; /* Destination ID */
+ uint64_t __reserved_1:8; /* Reserved 1 */
+ uint64_t vector:8; /* Interrupt Vector */
+ uint64_t irte_mode:1; /* IRTE Mode */
+ uint64_t __reserved_0:3; /* Reserved 0 */
+ uint64_t __avail:4; /* Available spaces for software */
+ uint64_t delivery_mode:3; /* Delivery Mode */
+ uint64_t trigger_mode:1; /* Trigger Mode */
+ uint64_t redir_hint:1; /* Redirection Hint */
+ uint64_t dest_mode:1; /* Destination Mode */
+ uint64_t fault_disable:1; /* Fault Processing Disable */
+ uint64_t present:1; /* Whether entry present/available */
#else
- uint32_t present:1; /* Whether entry present/available */
- uint32_t fault_disable:1; /* Fault Processing Disable */
- uint32_t dest_mode:1; /* Destination Mode */
- uint32_t redir_hint:1; /* Redirection Hint */
- uint32_t trigger_mode:1; /* Trigger Mode */
- uint32_t delivery_mode:3; /* Delivery Mode */
- uint32_t __avail:4; /* Available spaces for software */
- uint32_t __reserved_0:3; /* Reserved 0 */
- uint32_t irte_mode:1; /* IRTE Mode */
- uint32_t vector:8; /* Interrupt Vector */
- uint32_t __reserved_1:8; /* Reserved 1 */
+ uint64_t present:1; /* Whether entry present/available */
+ uint64_t fault_disable:1; /* Fault Processing Disable */
+ uint64_t dest_mode:1; /* Destination Mode */
+ uint64_t redir_hint:1; /* Redirection Hint */
+ uint64_t trigger_mode:1; /* Trigger Mode */
+ uint64_t delivery_mode:3; /* Delivery Mode */
+ uint64_t __avail:4; /* Available spaces for software */
+ uint64_t __reserved_0:3; /* Reserved 0 */
+ uint64_t irte_mode:1; /* IRTE Mode */
+ uint64_t vector:8; /* Interrupt Vector */
+ uint64_t __reserved_1:8; /* Reserved 1 */
+ uint64_t dest_id:32; /* Destination ID */
#endif
- uint32_t dest_id; /* Destination ID */
- uint16_t source_id; /* Source-ID */
-#ifdef HOST_WORDS_BIGENDIAN
+#if HOST_BIG_ENDIAN
uint64_t __reserved_2:44; /* Reserved 2 */
uint64_t sid_vtype:2; /* Source-ID Validation Type */
uint64_t sid_q:2; /* Source-ID Qualifier */
+ uint64_t source_id:16; /* Source-ID */
#else
+ uint64_t source_id:16; /* Source-ID */
uint64_t sid_q:2; /* Source-ID Qualifier */
uint64_t sid_vtype:2; /* Source-ID Validation Type */
uint64_t __reserved_2:44; /* Reserved 2 */
@@ -192,7 +225,7 @@ union VTD_IR_TableEntry {
/* Programming format for MSI/MSI-X addresses */
union VTD_IR_MSIAddress {
struct {
-#ifdef HOST_WORDS_BIGENDIAN
+#if HOST_BIG_ENDIAN
uint32_t __head:12; /* Should always be: 0x0fee */
uint32_t index_l:15; /* Interrupt index bit 14-0 */
uint32_t int_mode:1; /* Interrupt format */
@@ -229,6 +262,7 @@ struct IntelIOMMUState {
bool caching_mode; /* RO - is cap CM enabled? */
bool scalable_mode; /* RO - is Scalable Mode supported? */
+ bool snoop_control; /* RO - is SNP filed supported? */
dma_addr_t root; /* Current root table pointer */
bool root_scalable; /* Type of root table (scalable or not) */
@@ -253,8 +287,8 @@ struct IntelIOMMUState {
uint32_t context_cache_gen; /* Should be in [1,MAX] */
GHashTable *iotlb; /* IOTLB */
- GHashTable *vtd_as_by_busptr; /* VTDBus objects indexed by PCIBus* reference */
- VTDBus *vtd_as_by_bus_num[VTD_PCI_BUS_MAX]; /* VTDBus objects indexed by bus number */
+ GHashTable *vtd_address_spaces; /* VTD address spaces */
+ VTDAddressSpace *vtd_as_cache[VTD_PCI_BUS_MAX]; /* VTD address space cache */
/* list of registered notifiers */
QLIST_HEAD(, VTDAddressSpace) vtd_as_with_notifiers;
@@ -267,6 +301,8 @@ struct IntelIOMMUState {
bool buggy_eim; /* Force buggy EIM unless eim=off */
uint8_t aw_bits; /* Host/IOVA address width (in bits) */
bool dma_drain; /* Whether DMA r/w draining enabled */
+ bool dma_translation; /* Whether DMA translation supported */
+ bool pasid; /* Whether to support PASID */
/*
* Protects IOMMU states in general. Currently it protects the
@@ -278,6 +314,7 @@ struct IntelIOMMUState {
/* Find the VTD Address space associated with the given bus pointer,
* create a new one if none exists
*/
-VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn);
+VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus,
+ int devfn, unsigned int pasid);
#endif
diff --git a/include/hw/i386/ioapic_internal.h b/include/hw/i386/ioapic_internal.h
deleted file mode 100644
index fe06938bda..0000000000
--- a/include/hw/i386/ioapic_internal.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * IOAPIC emulation logic - internal interfaces
- *
- * Copyright (c) 2004-2005 Fabrice Bellard
- * Copyright (c) 2009 Xiantao Zhang, Intel
- * Copyright (c) 2011 Jan Kiszka, Siemens AG
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef QEMU_IOAPIC_INTERNAL_H
-#define QEMU_IOAPIC_INTERNAL_H
-
-#include "exec/memory.h"
-#include "hw/sysbus.h"
-#include "qemu/notify.h"
-
-#define MAX_IOAPICS 1
-
-#define IOAPIC_LVT_DEST_SHIFT 56
-#define IOAPIC_LVT_DEST_IDX_SHIFT 48
-#define IOAPIC_LVT_MASKED_SHIFT 16
-#define IOAPIC_LVT_TRIGGER_MODE_SHIFT 15
-#define IOAPIC_LVT_REMOTE_IRR_SHIFT 14
-#define IOAPIC_LVT_POLARITY_SHIFT 13
-#define IOAPIC_LVT_DELIV_STATUS_SHIFT 12
-#define IOAPIC_LVT_DEST_MODE_SHIFT 11
-#define IOAPIC_LVT_DELIV_MODE_SHIFT 8
-
-#define IOAPIC_LVT_MASKED (1 << IOAPIC_LVT_MASKED_SHIFT)
-#define IOAPIC_LVT_TRIGGER_MODE (1 << IOAPIC_LVT_TRIGGER_MODE_SHIFT)
-#define IOAPIC_LVT_REMOTE_IRR (1 << IOAPIC_LVT_REMOTE_IRR_SHIFT)
-#define IOAPIC_LVT_POLARITY (1 << IOAPIC_LVT_POLARITY_SHIFT)
-#define IOAPIC_LVT_DELIV_STATUS (1 << IOAPIC_LVT_DELIV_STATUS_SHIFT)
-#define IOAPIC_LVT_DEST_MODE (1 << IOAPIC_LVT_DEST_MODE_SHIFT)
-#define IOAPIC_LVT_DELIV_MODE (7 << IOAPIC_LVT_DELIV_MODE_SHIFT)
-
-/* Bits that are read-only for IOAPIC entry */
-#define IOAPIC_RO_BITS (IOAPIC_LVT_REMOTE_IRR | \
- IOAPIC_LVT_DELIV_STATUS)
-#define IOAPIC_RW_BITS (~(uint64_t)IOAPIC_RO_BITS)
-
-#define IOAPIC_TRIGGER_EDGE 0
-#define IOAPIC_TRIGGER_LEVEL 1
-
-/*io{apic,sapic} delivery mode*/
-#define IOAPIC_DM_FIXED 0x0
-#define IOAPIC_DM_LOWEST_PRIORITY 0x1
-#define IOAPIC_DM_PMI 0x2
-#define IOAPIC_DM_NMI 0x4
-#define IOAPIC_DM_INIT 0x5
-#define IOAPIC_DM_SIPI 0x6
-#define IOAPIC_DM_EXTINT 0x7
-#define IOAPIC_DM_MASK 0x7
-
-#define IOAPIC_VECTOR_MASK 0xff
-
-#define IOAPIC_IOREGSEL 0x00
-#define IOAPIC_IOWIN 0x10
-#define IOAPIC_EOI 0x40
-
-#define IOAPIC_REG_ID 0x00
-#define IOAPIC_REG_VER 0x01
-#define IOAPIC_REG_ARB 0x02
-#define IOAPIC_REG_REDTBL_BASE 0x10
-#define IOAPIC_ID 0x00
-
-#define IOAPIC_ID_SHIFT 24
-#define IOAPIC_ID_MASK 0xf
-
-#define IOAPIC_VER_ENTRIES_SHIFT 16
-
-typedef struct IOAPICCommonState IOAPICCommonState;
-
-#define TYPE_IOAPIC_COMMON "ioapic-common"
-#define IOAPIC_COMMON(obj) \
- OBJECT_CHECK(IOAPICCommonState, (obj), TYPE_IOAPIC_COMMON)
-#define IOAPIC_COMMON_CLASS(klass) \
- OBJECT_CLASS_CHECK(IOAPICCommonClass, (klass), TYPE_IOAPIC_COMMON)
-#define IOAPIC_COMMON_GET_CLASS(obj) \
- OBJECT_GET_CLASS(IOAPICCommonClass, (obj), TYPE_IOAPIC_COMMON)
-
-typedef struct IOAPICCommonClass {
- SysBusDeviceClass parent_class;
-
- DeviceRealize realize;
- DeviceUnrealize unrealize;
- void (*pre_save)(IOAPICCommonState *s);
- void (*post_load)(IOAPICCommonState *s);
-} IOAPICCommonClass;
-
-struct IOAPICCommonState {
- SysBusDevice busdev;
- MemoryRegion io_memory;
- uint8_t id;
- uint8_t ioregsel;
- uint32_t irr;
- uint64_t ioredtbl[IOAPIC_NUM_PINS];
- Notifier machine_done;
- uint8_t version;
- uint64_t irq_count[IOAPIC_NUM_PINS];
- int irq_level[IOAPIC_NUM_PINS];
- int irq_eoi[IOAPIC_NUM_PINS];
- QEMUTimer *delayed_ioapic_service_timer;
-};
-
-void ioapic_reset_common(DeviceState *dev);
-
-void ioapic_print_redtbl(Monitor *mon, IOAPICCommonState *s);
-void ioapic_stat_update_irq(IOAPICCommonState *s, int irq, int level);
-
-#endif /* QEMU_IOAPIC_INTERNAL_H */
diff --git a/include/hw/i386/microvm.h b/include/hw/i386/microvm.h
index fd34b78e0d..fad97a891d 100644
--- a/include/hw/i386/microvm.h
+++ b/include/hw/i386/microvm.h
@@ -18,54 +18,94 @@
#ifndef HW_I386_MICROVM_H
#define HW_I386_MICROVM_H
-#include "qemu-common.h"
#include "exec/hwaddr.h"
#include "qemu/notify.h"
#include "hw/boards.h"
#include "hw/i386/x86.h"
+#include "hw/acpi/acpi_dev_interface.h"
+#include "hw/pci-host/gpex.h"
+#include "qom/object.h"
+
+/*
+ * IRQ | pc | microvm (acpi=on)
+ * --------+------------+------------------
+ * 0 | pit |
+ * 1 | kbd |
+ * 2 | cascade |
+ * 3 | serial 1 |
+ * 4 | serial 0 | serial
+ * 5 | - |
+ * 6 | floppy |
+ * 7 | parallel |
+ * 8 | rtc | rtc (rtc=on)
+ * 9 | acpi | acpi (ged)
+ * 10 | pci lnk | xhci (usb=on)
+ * 11 | pci lnk |
+ * 12 | ps2 | pcie
+ * 13 | fpu | pcie
+ * 14 | ide 0 | pcie
+ * 15 | ide 1 | pcie
+ * 16-23 | pci gsi | virtio
+ */
/* Platform virtio definitions */
#define VIRTIO_MMIO_BASE 0xfeb00000
-#define VIRTIO_IRQ_BASE 5
-#define VIRTIO_NUM_TRANSPORTS 8
#define VIRTIO_CMDLINE_MAXLEN 64
+#define GED_MMIO_BASE 0xfea00000
+#define GED_MMIO_BASE_MEMHP (GED_MMIO_BASE + 0x100)
+#define GED_MMIO_BASE_REGS (GED_MMIO_BASE + 0x200)
+#define GED_MMIO_IRQ 9
+
+#define MICROVM_XHCI_BASE 0xfe900000
+#define MICROVM_XHCI_IRQ 10
+
+#define PCIE_MMIO_BASE 0xc0000000
+#define PCIE_MMIO_SIZE 0x20000000
+#define PCIE_ECAM_BASE 0xe0000000
+#define PCIE_ECAM_SIZE 0x10000000
+
/* Machine type options */
-#define MICROVM_MACHINE_PIT "pit"
-#define MICROVM_MACHINE_PIC "pic"
#define MICROVM_MACHINE_RTC "rtc"
+#define MICROVM_MACHINE_PCIE "pcie"
+#define MICROVM_MACHINE_IOAPIC2 "ioapic2"
#define MICROVM_MACHINE_ISA_SERIAL "isa-serial"
#define MICROVM_MACHINE_OPTION_ROMS "x-option-roms"
#define MICROVM_MACHINE_AUTO_KERNEL_CMDLINE "auto-kernel-cmdline"
-typedef struct {
+struct MicrovmMachineClass {
X86MachineClass parent;
HotplugHandler *(*orig_hotplug_handler)(MachineState *machine,
DeviceState *dev);
-} MicrovmMachineClass;
+};
-typedef struct {
+struct MicrovmMachineState {
X86MachineState parent;
/* Machine type options */
- OnOffAuto pic;
- OnOffAuto pit;
OnOffAuto rtc;
+ OnOffAuto pcie;
+ OnOffAuto ioapic2;
bool isa_serial;
bool option_roms;
bool auto_kernel_cmdline;
/* Machine state */
+ uint32_t pcie_irq_base;
+ uint32_t virtio_irq_base;
+ uint32_t virtio_num_transports;
bool kernel_cmdline_fixed;
-} MicrovmMachineState;
+ Notifier machine_done;
+ Notifier powerdown_req;
+ struct GPEXConfig gpex;
+
+ /* device tree */
+ void *fdt;
+ uint32_t ioapic_phandle[2];
+};
#define TYPE_MICROVM_MACHINE MACHINE_TYPE_NAME("microvm")
-#define MICROVM_MACHINE(obj) \
- OBJECT_CHECK(MicrovmMachineState, (obj), TYPE_MICROVM_MACHINE)
-#define MICROVM_MACHINE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(MicrovmMachineClass, obj, TYPE_MICROVM_MACHINE)
-#define MICROVM_MACHINE_CLASS(class) \
- OBJECT_CLASS_CHECK(MicrovmMachineClass, class, TYPE_MICROVM_MACHINE)
+OBJECT_DECLARE_TYPE(MicrovmMachineState, MicrovmMachineClass, MICROVM_MACHINE)
#endif
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 3d7ed3a55e..e52290916c 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -3,23 +3,25 @@
#include "qemu/notify.h"
#include "qapi/qapi-types-common.h"
+#include "qemu/uuid.h"
#include "hw/boards.h"
#include "hw/block/fdc.h"
#include "hw/block/flash.h"
#include "hw/i386/x86.h"
-#include "hw/acpi/acpi_dev_interface.h"
#include "hw/hotplug.h"
+#include "qom/object.h"
+#include "hw/i386/sgx-epc.h"
+#include "hw/cxl/cxl.h"
-#define HPET_INTCAP "hpet-intcap"
+#define MAX_IDE_BUS 2
/**
* PCMachineState:
* @acpi_dev: link to ACPI PM device that performs ACPI hotplug handling
* @boot_cpus: number of present VCPUs
- * @smp_dies: number of dies per one package
*/
-struct PCMachineState {
+typedef struct PCMachineState {
/*< private >*/
X86MachineState parent_obj;
@@ -29,36 +31,43 @@ struct PCMachineState {
Notifier machine_done;
/* Pointers to devices and objects: */
- HotplugHandler *acpi_dev;
- PCIBus *bus;
+ PCIBus *pcibus;
I2CBus *smbus;
PFlashCFI01 *flash[2];
ISADevice *pcspk;
+ DeviceState *iommu;
+ BusState *idebus[MAX_IDE_BUS];
/* Configuration options: */
uint64_t max_ram_below_4g;
OnOffAuto vmport;
+ SmbiosEntryPointType smbios_entry_point_type;
+ const char *south_bridge;
bool acpi_build_enabled;
bool smbus_enabled;
bool sata_enabled;
- bool pit_enabled;
-
- /* NUMA information: */
- uint64_t numa_nodes;
- uint64_t *node_mem;
+ bool hpet_enabled;
+ bool i8042_enabled;
+ bool default_bus_bypass_iommu;
+ bool fd_bootchk;
+ uint64_t max_fw_size;
/* ACPI Memory hotplug IO base address */
hwaddr memhp_io_base;
-};
+
+ SGXEPCState sgx_epc;
+ CXLState cxl_devices_state;
+} PCMachineState;
#define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device"
#define PC_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g"
-#define PC_MACHINE_DEVMEM_REGION_SIZE "device-memory-region-size"
#define PC_MACHINE_VMPORT "vmport"
#define PC_MACHINE_SMBUS "smbus"
#define PC_MACHINE_SATA "sata"
-#define PC_MACHINE_PIT "pit"
+#define PC_MACHINE_I8042 "i8042"
+#define PC_MACHINE_MAX_FW_SIZE "max-fw-size"
+#define PC_MACHINE_SMBIOS_EP "smbios-entry-point-type"
/**
* PCMachineClass:
@@ -76,7 +85,7 @@ struct PCMachineState {
* way we can use 1GByte pages in the host.
*
*/
-typedef struct PCMachineClass {
+struct PCMachineClass {
/*< private >*/
X86MachineClass parent_class;
@@ -84,8 +93,7 @@ typedef struct PCMachineClass {
/* Device configuration: */
bool pci_enabled;
- bool kvmclock_enabled;
- const char *default_nic_model;
+ const char *default_south_bridge;
/* Compat options: */
@@ -97,51 +105,55 @@ typedef struct PCMachineClass {
bool rsdp_in_ram;
int legacy_acpi_table_size;
unsigned acpi_data_size;
- bool do_not_add_smb_acpi;
+ int pci_root_uid;
/* SMBIOS compat: */
bool smbios_defaults;
bool smbios_legacy_mode;
bool smbios_uuid_encoded;
+ SmbiosEntryPointType default_smbios_ep_type;
/* RAM / address space compat: */
bool gigabyte_align;
bool has_reserved_memory;
bool enforce_aligned_dimm;
bool broken_reserved_end;
+ bool enforce_amd_1tb_hole;
/* generate legacy CPU hotplug AML */
bool legacy_cpu_hotplug;
- /* use DMA capable linuxboot option rom */
- bool linuxboot_dma_enabled;
-
/* use PVH to load kernels that support this feature */
bool pvh_enabled;
-} PCMachineClass;
+
+ /* create kvmclock device even when KVM PV features are not exposed */
+ bool kvmclock_create_always;
+
+ /* resizable acpi blob compat */
+ bool resizable_acpi_blob;
+
+ /*
+ * whether the machine type implements broken 32-bit address space bound
+ * check for memory.
+ */
+ bool broken_32bit_mem_addr_check;
+};
#define TYPE_PC_MACHINE "generic-pc-machine"
-#define PC_MACHINE(obj) \
- OBJECT_CHECK(PCMachineState, (obj), TYPE_PC_MACHINE)
-#define PC_MACHINE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(PCMachineClass, (obj), TYPE_PC_MACHINE)
-#define PC_MACHINE_CLASS(klass) \
- OBJECT_CLASS_CHECK(PCMachineClass, (klass), TYPE_PC_MACHINE)
+OBJECT_DECLARE_TYPE(PCMachineState, PCMachineClass, PC_MACHINE)
/* ioapic.c */
GSIState *pc_gsi_create(qemu_irq **irqs, bool pci_enabled);
/* pc.c */
-extern int fd_bootchk;
void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
-void pc_hot_add_cpu(MachineState *ms, const int64_t id, Error **errp);
-void pc_smp_parse(MachineState *ms, QemuOpts *opts);
-
-void pc_guest_info_init(PCMachineState *pcms);
-
+#define PCI_HOST_PROP_RAM_MEM "ram-mem"
+#define PCI_HOST_PROP_PCI_MEM "pci-mem"
+#define PCI_HOST_PROP_SYSTEM_MEM "system-mem"
+#define PCI_HOST_PROP_IO_MEM "io-mem"
#define PCI_HOST_PROP_PCI_HOLE_START "pci-hole-start"
#define PCI_HOST_PROP_PCI_HOLE_END "pci-hole-end"
#define PCI_HOST_PROP_PCI_HOLE64_START "pci-hole64-start"
@@ -149,36 +161,28 @@ void pc_guest_info_init(PCMachineState *pcms);
#define PCI_HOST_PROP_PCI_HOLE64_SIZE "pci-hole64-size"
#define PCI_HOST_BELOW_4G_MEM_SIZE "below-4g-mem-size"
#define PCI_HOST_ABOVE_4G_MEM_SIZE "above-4g-mem-size"
+#define PCI_HOST_PROP_SMM_RANGES "smm-ranges"
-void pc_pci_as_mapping_init(Object *owner, MemoryRegion *system_memory,
+void pc_pci_as_mapping_init(MemoryRegion *system_memory,
MemoryRegion *pci_address_space);
void xen_load_linux(PCMachineState *pcms);
void pc_memory_init(PCMachineState *pcms,
MemoryRegion *system_memory,
MemoryRegion *rom_memory,
- MemoryRegion **ram_memory);
+ uint64_t pci_hole64_size);
uint64_t pc_pci_hole64_start(void);
DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus);
void pc_basic_device_init(struct PCMachineState *pcms,
ISABus *isa_bus, qemu_irq *gsi,
- ISADevice **rtc_state,
+ ISADevice *rtc_state,
bool create_fdctrl,
uint32_t hpet_irqs);
-void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd);
-void pc_cmos_init(PCMachineState *pcms,
- BusState *ide0, BusState *ide1,
- ISADevice *s);
void pc_nic_init(PCMachineClass *pcmc, ISABus *isa_bus, PCIBus *pci_bus);
-void pc_pci_device_init(PCIBus *pci_bus);
-
-typedef void (*cpu_set_smm_t)(int smm, void *arg);
void pc_i8259_create(ISABus *isa_bus, qemu_irq *i8259_irqs);
-ISADevice *pc_find_fdc0(void);
-
/* port92.c */
#define PORT92_A20_LINE "a20"
@@ -188,10 +192,48 @@ ISADevice *pc_find_fdc0(void);
void pc_system_flash_create(PCMachineState *pcms);
void pc_system_flash_cleanup_unused(PCMachineState *pcms);
void pc_system_firmware_init(PCMachineState *pcms, MemoryRegion *rom_memory);
+bool pc_system_ovmf_table_find(const char *entry, uint8_t **data,
+ int *data_len);
+void pc_system_parse_ovmf_flash(uint8_t *flash_ptr, size_t flash_size);
+
+/* sgx.c */
+void pc_machine_init_sgx_epc(PCMachineState *pcms);
+
+extern GlobalProperty pc_compat_9_0[];
+extern const size_t pc_compat_9_0_len;
+
+extern GlobalProperty pc_compat_8_2[];
+extern const size_t pc_compat_8_2_len;
-/* acpi-build.c */
-void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
- const CPUArchIdList *apic_ids, GArray *entry);
+extern GlobalProperty pc_compat_8_1[];
+extern const size_t pc_compat_8_1_len;
+
+extern GlobalProperty pc_compat_8_0[];
+extern const size_t pc_compat_8_0_len;
+
+extern GlobalProperty pc_compat_7_2[];
+extern const size_t pc_compat_7_2_len;
+
+extern GlobalProperty pc_compat_7_1[];
+extern const size_t pc_compat_7_1_len;
+
+extern GlobalProperty pc_compat_7_0[];
+extern const size_t pc_compat_7_0_len;
+
+extern GlobalProperty pc_compat_6_2[];
+extern const size_t pc_compat_6_2_len;
+
+extern GlobalProperty pc_compat_6_1[];
+extern const size_t pc_compat_6_1_len;
+
+extern GlobalProperty pc_compat_6_0[];
+extern const size_t pc_compat_6_0_len;
+
+extern GlobalProperty pc_compat_5_2[];
+extern const size_t pc_compat_5_2_len;
+
+extern GlobalProperty pc_compat_5_1[];
+extern const size_t pc_compat_5_1_len;
extern GlobalProperty pc_compat_5_0[];
extern const size_t pc_compat_5_0_len;
@@ -250,26 +292,6 @@ extern const size_t pc_compat_2_1_len;
extern GlobalProperty pc_compat_2_0[];
extern const size_t pc_compat_2_0_len;
-extern GlobalProperty pc_compat_1_7[];
-extern const size_t pc_compat_1_7_len;
-
-extern GlobalProperty pc_compat_1_6[];
-extern const size_t pc_compat_1_6_len;
-
-extern GlobalProperty pc_compat_1_5[];
-extern const size_t pc_compat_1_5_len;
-
-extern GlobalProperty pc_compat_1_4[];
-extern const size_t pc_compat_1_4_len;
-
-/* Helper for setting model-id for CPU models that changed model-id
- * depending on QEMU versions up to QEMU 2.4.
- */
-#define PC_CPU_MODEL_IDS(v) \
- { "qemu32-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },\
- { "qemu64-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },\
- { "athlon-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },
-
#define DEFINE_PC_MACHINE(suffix, namestr, initfn, optsfn) \
static void pc_machine_##suffix##_class_init(ObjectClass *oc, void *data) \
{ \
@@ -288,5 +310,4 @@ extern const size_t pc_compat_1_4_len;
} \
type_init(pc_machine_init_##suffix)
-extern void igd_passthrough_isa_bridge_create(PCIBus *bus, uint16_t gpu_dev_id);
#endif
diff --git a/include/hw/i386/sgx-epc.h b/include/hw/i386/sgx-epc.h
new file mode 100644
index 0000000000..3e00efd870
--- /dev/null
+++ b/include/hw/i386/sgx-epc.h
@@ -0,0 +1,71 @@
+/*
+ * SGX EPC device
+ *
+ * Copyright (C) 2019 Intel Corporation
+ *
+ * Authors:
+ * Sean Christopherson <sean.j.christopherson@intel.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#ifndef QEMU_SGX_EPC_H
+#define QEMU_SGX_EPC_H
+
+#include "hw/qdev-core.h"
+#include "hw/i386/hostmem-epc.h"
+
+#define TYPE_SGX_EPC "sgx-epc"
+#define SGX_EPC(obj) \
+ OBJECT_CHECK(SGXEPCDevice, (obj), TYPE_SGX_EPC)
+#define SGX_EPC_CLASS(oc) \
+ OBJECT_CLASS_CHECK(SGXEPCDeviceClass, (oc), TYPE_SGX_EPC)
+#define SGX_EPC_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(SGXEPCDeviceClass, (obj), TYPE_SGX_EPC)
+
+#define SGX_EPC_ADDR_PROP "addr"
+#define SGX_EPC_SIZE_PROP "size"
+#define SGX_EPC_MEMDEV_PROP "memdev"
+#define SGX_EPC_NUMA_NODE_PROP "node"
+
+/**
+ * SGXEPCDevice:
+ * @addr: starting guest physical address, where @SGXEPCDevice is mapped.
+ * Default value: 0, means that address is auto-allocated.
+ * @hostmem: host memory backend providing memory for @SGXEPCDevice
+ */
+typedef struct SGXEPCDevice {
+ /* private */
+ DeviceState parent_obj;
+
+ /* public */
+ uint64_t addr;
+ uint32_t node;
+ HostMemoryBackendEpc *hostmem;
+} SGXEPCDevice;
+
+/*
+ * @base: address in guest physical address space where EPC regions start
+ * @mr: address space container for memory devices
+ */
+typedef struct SGXEPCState {
+ uint64_t base;
+ uint64_t size;
+
+ MemoryRegion mr;
+
+ struct SGXEPCDevice **sections;
+ int nr_sections;
+} SGXEPCState;
+
+bool sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size);
+void sgx_epc_build_srat(GArray *table_data);
+
+static inline uint64_t sgx_epc_above_4g_end(SGXEPCState *sgx_epc)
+{
+ assert(sgx_epc != NULL && sgx_epc->base >= 0x100000000ULL);
+
+ return sgx_epc->base + sgx_epc->size;
+}
+
+#endif
diff --git a/include/hw/i386/topology.h b/include/hw/i386/topology.h
index 07239f95f4..d4eeb7ab82 100644
--- a/include/hw/i386/topology.h
+++ b/include/hw/i386/topology.h
@@ -24,14 +24,15 @@
#ifndef HW_I386_TOPOLOGY_H
#define HW_I386_TOPOLOGY_H
-/* This file implements the APIC-ID-based CPU topology enumeration logic,
+/*
+ * This file implements the APIC-ID-based CPU topology enumeration logic,
* documented at the following document:
* Intel® 64 Architecture Processor Topology Enumeration
* http://software.intel.com/en-us/articles/intel-64-architecture-processor-topology-enumeration/
*
* This code should be compatible with AMD's "Extended Method" described at:
* AMD CPUID Specification (Publication #25481)
- * Section 3: Multiple Core Calcuation
+ * Section 3: Multiple Core Calculation
* as long as:
* nr_threads is set to 1;
* OFFSET_IDX is assumed to be 0;
@@ -41,27 +42,25 @@
#include "qemu/bitops.h"
-/* APIC IDs can be 32-bit, but beware: APIC IDs > 255 require x2APIC support
+/*
+ * APIC IDs can be 32-bit, but beware: APIC IDs > 255 require x2APIC support
*/
typedef uint32_t apic_id_t;
typedef struct X86CPUTopoIDs {
unsigned pkg_id;
- unsigned node_id;
unsigned die_id;
unsigned core_id;
unsigned smt_id;
} X86CPUTopoIDs;
typedef struct X86CPUTopoInfo {
- unsigned nodes_per_pkg;
unsigned dies_per_pkg;
unsigned cores_per_die;
unsigned threads_per_core;
} X86CPUTopoInfo;
-/* Return the bit width needed for 'count' IDs
- */
+/* Return the bit width needed for 'count' IDs */
static unsigned apicid_bitwidth_for_count(unsigned count)
{
g_assert(count >= 1);
@@ -69,15 +68,13 @@ static unsigned apicid_bitwidth_for_count(unsigned count)
return count ? 32 - clz32(count) : 0;
}
-/* Bit width of the SMT_ID (thread ID) field on the APIC ID
- */
+/* Bit width of the SMT_ID (thread ID) field on the APIC ID */
static inline unsigned apicid_smt_width(X86CPUTopoInfo *topo_info)
{
return apicid_bitwidth_for_count(topo_info->threads_per_core);
}
-/* Bit width of the Core_ID field
- */
+/* Bit width of the Core_ID field */
static inline unsigned apicid_core_width(X86CPUTopoInfo *topo_info)
{
return apicid_bitwidth_for_count(topo_info->cores_per_die);
@@ -89,13 +86,7 @@ static inline unsigned apicid_die_width(X86CPUTopoInfo *topo_info)
return apicid_bitwidth_for_count(topo_info->dies_per_pkg);
}
-/* Bit width of the node_id field per socket */
-static inline unsigned apicid_node_width_epyc(X86CPUTopoInfo *topo_info)
-{
- return apicid_bitwidth_for_count(MAX(topo_info->nodes_per_pkg, 1));
-}
-/* Bit offset of the Core_ID field
- */
+/* Bit offset of the Core_ID field */
static inline unsigned apicid_core_offset(X86CPUTopoInfo *topo_info)
{
return apicid_smt_width(topo_info);
@@ -107,111 +98,17 @@ static inline unsigned apicid_die_offset(X86CPUTopoInfo *topo_info)
return apicid_core_offset(topo_info) + apicid_core_width(topo_info);
}
-/* Bit offset of the Pkg_ID (socket ID) field
- */
+/* Bit offset of the Pkg_ID (socket ID) field */
static inline unsigned apicid_pkg_offset(X86CPUTopoInfo *topo_info)
{
return apicid_die_offset(topo_info) + apicid_die_width(topo_info);
}
-#define NODE_ID_OFFSET 3 /* Minimum node_id offset if numa configured */
-
-/*
- * Bit offset of the node_id field
- *
- * Make sure nodes_per_pkg > 0 if numa configured else zero.
- */
-static inline unsigned apicid_node_offset_epyc(X86CPUTopoInfo *topo_info)
-{
- unsigned offset = apicid_die_offset(topo_info) +
- apicid_die_width(topo_info);
-
- if (topo_info->nodes_per_pkg) {
- return MAX(NODE_ID_OFFSET, offset);
- } else {
- return offset;
- }
-}
-
-/* Bit offset of the Pkg_ID (socket ID) field */
-static inline unsigned apicid_pkg_offset_epyc(X86CPUTopoInfo *topo_info)
-{
- return apicid_node_offset_epyc(topo_info) +
- apicid_node_width_epyc(topo_info);
-}
-
/*
* Make APIC ID for the CPU based on Pkg_ID, Core_ID, SMT_ID
*
* The caller must make sure core_id < nr_cores and smt_id < nr_threads.
*/
-static inline apic_id_t
-x86_apicid_from_topo_ids_epyc(X86CPUTopoInfo *topo_info,
- const X86CPUTopoIDs *topo_ids)
-{
- return (topo_ids->pkg_id << apicid_pkg_offset_epyc(topo_info)) |
- (topo_ids->node_id << apicid_node_offset_epyc(topo_info)) |
- (topo_ids->die_id << apicid_die_offset(topo_info)) |
- (topo_ids->core_id << apicid_core_offset(topo_info)) |
- topo_ids->smt_id;
-}
-
-static inline void x86_topo_ids_from_idx_epyc(X86CPUTopoInfo *topo_info,
- unsigned cpu_index,
- X86CPUTopoIDs *topo_ids)
-{
- unsigned nr_nodes = MAX(topo_info->nodes_per_pkg, 1);
- unsigned nr_dies = topo_info->dies_per_pkg;
- unsigned nr_cores = topo_info->cores_per_die;
- unsigned nr_threads = topo_info->threads_per_core;
- unsigned cores_per_node = DIV_ROUND_UP((nr_dies * nr_cores * nr_threads),
- nr_nodes);
-
- topo_ids->pkg_id = cpu_index / (nr_dies * nr_cores * nr_threads);
- topo_ids->node_id = (cpu_index / cores_per_node) % nr_nodes;
- topo_ids->die_id = cpu_index / (nr_cores * nr_threads) % nr_dies;
- topo_ids->core_id = cpu_index / nr_threads % nr_cores;
- topo_ids->smt_id = cpu_index % nr_threads;
-}
-
-/*
- * Calculate thread/core/package IDs for a specific topology,
- * based on APIC ID
- */
-static inline void x86_topo_ids_from_apicid_epyc(apic_id_t apicid,
- X86CPUTopoInfo *topo_info,
- X86CPUTopoIDs *topo_ids)
-{
- topo_ids->smt_id = apicid &
- ~(0xFFFFFFFFUL << apicid_smt_width(topo_info));
- topo_ids->core_id =
- (apicid >> apicid_core_offset(topo_info)) &
- ~(0xFFFFFFFFUL << apicid_core_width(topo_info));
- topo_ids->die_id =
- (apicid >> apicid_die_offset(topo_info)) &
- ~(0xFFFFFFFFUL << apicid_die_width(topo_info));
- topo_ids->node_id =
- (apicid >> apicid_node_offset_epyc(topo_info)) &
- ~(0xFFFFFFFFUL << apicid_node_width_epyc(topo_info));
- topo_ids->pkg_id = apicid >> apicid_pkg_offset_epyc(topo_info);
-}
-
-/*
- * Make APIC ID for the CPU 'cpu_index'
- *
- * 'cpu_index' is a sequential, contiguous ID for the CPU.
- */
-static inline apic_id_t x86_apicid_from_cpu_idx_epyc(X86CPUTopoInfo *topo_info,
- unsigned cpu_index)
-{
- X86CPUTopoIDs topo_ids;
- x86_topo_ids_from_idx_epyc(topo_info, cpu_index, &topo_ids);
- return x86_apicid_from_topo_ids_epyc(topo_info, &topo_ids);
-}
-/* Make APIC ID for the CPU based on Pkg_ID, Core_ID, SMT_ID
- *
- * The caller must make sure core_id < nr_cores and smt_id < nr_threads.
- */
static inline apic_id_t x86_apicid_from_topo_ids(X86CPUTopoInfo *topo_info,
const X86CPUTopoIDs *topo_ids)
{
@@ -221,7 +118,8 @@ static inline apic_id_t x86_apicid_from_topo_ids(X86CPUTopoInfo *topo_info,
topo_ids->smt_id;
}
-/* Calculate thread/core/package IDs for a specific topology,
+/*
+ * Calculate thread/core/package IDs for a specific topology,
* based on (contiguous) CPU index
*/
static inline void x86_topo_ids_from_idx(X86CPUTopoInfo *topo_info,
@@ -238,7 +136,8 @@ static inline void x86_topo_ids_from_idx(X86CPUTopoInfo *topo_info,
topo_ids->smt_id = cpu_index % nr_threads;
}
-/* Calculate thread/core/package IDs for a specific topology,
+/*
+ * Calculate thread/core/package IDs for a specific topology,
* based on APIC ID
*/
static inline void x86_topo_ids_from_apicid(apic_id_t apicid,
@@ -256,7 +155,8 @@ static inline void x86_topo_ids_from_apicid(apic_id_t apicid,
topo_ids->pkg_id = apicid >> apicid_pkg_offset(topo_info);
}
-/* Make APIC ID for the CPU 'cpu_index'
+/*
+ * Make APIC ID for the CPU 'cpu_index'
*
* 'cpu_index' is a sequential, contiguous ID for the CPU.
*/
diff --git a/include/hw/i386/vmport.h b/include/hw/i386/vmport.h
index c380b9c1f0..8f5e27c6f5 100644
--- a/include/hw/i386/vmport.h
+++ b/include/hw/i386/vmport.h
@@ -4,7 +4,7 @@
#include "hw/isa/isa.h"
#define TYPE_VMPORT "vmport"
-typedef uint32_t (VMPortReadFunc)(void *opaque, uint32_t address);
+typedef uint32_t VMPortReadFunc(void *opaque, uint32_t address);
typedef enum {
VMPORT_CMD_GETVERSION = 10,
diff --git a/include/hw/i386/x86-iommu.h b/include/hw/i386/x86-iommu.h
index 8e10383b11..bfd21649d0 100644
--- a/include/hw/i386/x86-iommu.h
+++ b/include/hw/i386/x86-iommu.h
@@ -21,30 +21,17 @@
#define HW_I386_X86_IOMMU_H
#include "hw/sysbus.h"
-#include "hw/pci/pci.h"
#include "hw/pci/msi.h"
+#include "qom/object.h"
#define TYPE_X86_IOMMU_DEVICE ("x86-iommu")
-#define X86_IOMMU_DEVICE(obj) \
- OBJECT_CHECK(X86IOMMUState, (obj), TYPE_X86_IOMMU_DEVICE)
-#define X86_IOMMU_CLASS(klass) \
- OBJECT_CLASS_CHECK(X86IOMMUClass, (klass), TYPE_X86_IOMMU_DEVICE)
-#define X86_IOMMU_GET_CLASS(obj) \
- OBJECT_GET_CLASS(X86IOMMUClass, obj, TYPE_X86_IOMMU_DEVICE)
+OBJECT_DECLARE_TYPE(X86IOMMUState, X86IOMMUClass, X86_IOMMU_DEVICE)
#define X86_IOMMU_SID_INVALID (0xffff)
-typedef struct X86IOMMUState X86IOMMUState;
-typedef struct X86IOMMUClass X86IOMMUClass;
typedef struct X86IOMMUIrq X86IOMMUIrq;
typedef struct X86IOMMU_MSIMessage X86IOMMU_MSIMessage;
-typedef enum IommuType {
- TYPE_INTEL,
- TYPE_AMD,
- TYPE_NONE
-} IommuType;
-
struct X86IOMMUClass {
SysBusDeviceClass parent;
/* Intel/AMD specific realize() hook */
@@ -77,7 +64,6 @@ struct X86IOMMUState {
OnOffAuto intr_supported; /* Whether vIOMMU supports IR */
bool dt_supported; /* Whether vIOMMU supports DT */
bool pt_supported; /* Whether vIOMMU supports pass-through */
- IommuType type; /* IOMMU type - AMD/Intel */
QLIST_HEAD(, IEC_Notifier) iec_notifiers; /* IEC notify list */
};
@@ -100,41 +86,43 @@ struct X86IOMMUIrq {
struct X86IOMMU_MSIMessage {
union {
struct {
-#ifdef HOST_WORDS_BIGENDIAN
- uint32_t __addr_head:12; /* 0xfee */
- uint32_t dest:8;
- uint32_t __reserved:8;
- uint32_t redir_hint:1;
- uint32_t dest_mode:1;
- uint32_t __not_used:2;
+#if HOST_BIG_ENDIAN
+ uint64_t __addr_hi:32;
+ uint64_t __addr_head:12; /* 0xfee */
+ uint64_t dest:8;
+ uint64_t __reserved:8;
+ uint64_t redir_hint:1;
+ uint64_t dest_mode:1;
+ uint64_t __not_used:2;
#else
- uint32_t __not_used:2;
- uint32_t dest_mode:1;
- uint32_t redir_hint:1;
- uint32_t __reserved:8;
- uint32_t dest:8;
- uint32_t __addr_head:12; /* 0xfee */
+ uint64_t __not_used:2;
+ uint64_t dest_mode:1;
+ uint64_t redir_hint:1;
+ uint64_t __reserved:8;
+ uint64_t dest:8;
+ uint64_t __addr_head:12; /* 0xfee */
+ uint64_t __addr_hi:32;
#endif
- uint32_t __addr_hi;
} QEMU_PACKED;
uint64_t msi_addr;
};
union {
struct {
-#ifdef HOST_WORDS_BIGENDIAN
- uint16_t trigger_mode:1;
- uint16_t level:1;
- uint16_t __resved:3;
- uint16_t delivery_mode:3;
- uint16_t vector:8;
+#if HOST_BIG_ENDIAN
+ uint32_t __resved1:16;
+ uint32_t trigger_mode:1;
+ uint32_t level:1;
+ uint32_t __resved:3;
+ uint32_t delivery_mode:3;
+ uint32_t vector:8;
#else
- uint16_t vector:8;
- uint16_t delivery_mode:3;
- uint16_t __resved:3;
- uint16_t level:1;
- uint16_t trigger_mode:1;
+ uint32_t vector:8;
+ uint32_t delivery_mode:3;
+ uint32_t __resved:3;
+ uint32_t level:1;
+ uint32_t trigger_mode:1;
+ uint32_t __resved1:16;
#endif
- uint16_t __resved1;
} QEMU_PACKED;
uint32_t msi_data;
};
@@ -146,11 +134,6 @@ struct X86IOMMU_MSIMessage {
*/
X86IOMMUState *x86_iommu_get_default(void);
-/*
- * x86_iommu_get_type - get IOMMU type
- */
-IommuType x86_iommu_get_type(void);
-
/**
* x86_iommu_iec_register_notifier - register IEC (Interrupt Entry
* Cache) notifiers
diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
index b79f24e285..4dc30dcb4d 100644
--- a/include/hw/i386/x86.h
+++ b/include/hw/i386/x86.h
@@ -17,17 +17,14 @@
#ifndef HW_I386_X86_H
#define HW_I386_X86_H
-#include "qemu-common.h"
#include "exec/hwaddr.h"
-#include "qemu/notify.h"
-#include "hw/i386/topology.h"
#include "hw/boards.h"
-#include "hw/nmi.h"
+#include "hw/intc/ioapic.h"
#include "hw/isa/isa.h"
-#include "hw/i386/ioapic.h"
+#include "qom/object.h"
-typedef struct {
+struct X86MachineClass {
/*< private >*/
MachineClass parent;
@@ -35,11 +32,13 @@ typedef struct {
/* TSC rate migration: */
bool save_tsc_khz;
- /* Enables contiguous-apic-ID mode */
- bool compat_apic_id_mode;
-} X86MachineClass;
+ /* use DMA capable linuxboot option rom */
+ bool fwcfg_dma_enabled;
+ /* CPU and apic information: */
+ bool apic_xrupt_override;
+};
-typedef struct {
+struct X86MachineState {
/*< private >*/
MachineState parent;
@@ -49,48 +48,53 @@ typedef struct {
ISADevice *rtc;
FWCfgState *fw_cfg;
qemu_irq *gsi;
+ DeviceState *ioapic2;
GMappedFile *initrd_mapped_file;
+ HotplugHandler *acpi_dev;
/* RAM information (sizes, addresses, configuration): */
ram_addr_t below_4g_mem_size, above_4g_mem_size;
+ /* Start address of the initial RAM above 4G */
+ uint64_t above_4g_mem_start;
+
/* CPU and apic information: */
- bool apic_xrupt_override;
+ unsigned pci_irq_mask;
unsigned apic_id_limit;
uint16_t boot_cpus;
- unsigned smp_dies;
+ SgxEPCList *sgx_epc_list;
OnOffAuto smm;
OnOffAuto acpi;
+ OnOffAuto pit;
+ OnOffAuto pic;
- /* Apic id specific handlers */
- uint32_t (*apicid_from_cpu_idx)(X86CPUTopoInfo *topo_info,
- unsigned cpu_index);
- void (*topo_ids_from_apicid)(apic_id_t apicid, X86CPUTopoInfo *topo_info,
- X86CPUTopoIDs *topo_ids);
- apic_id_t (*apicid_from_topo_ids)(X86CPUTopoInfo *topo_info,
- const X86CPUTopoIDs *topo_ids);
- uint32_t (*apicid_pkg_offset)(X86CPUTopoInfo *topo_info);
-
+ char *oem_id;
+ char *oem_table_id;
/*
* Address space used by IOAPIC device. All IOAPIC interrupts
* will be translated to MSI messages in the address space.
*/
AddressSpace *ioapic_as;
-} X86MachineState;
+
+ /*
+ * Ratelimit enforced on detected bus locks in guest.
+ * The default value of the bus_lock_ratelimit is 0 per second,
+ * which means no limitation on the guest's bus locks.
+ */
+ uint64_t bus_lock_ratelimit;
+};
#define X86_MACHINE_SMM "smm"
#define X86_MACHINE_ACPI "acpi"
+#define X86_MACHINE_PIT "pit"
+#define X86_MACHINE_PIC "pic"
+#define X86_MACHINE_OEM_ID "x-oem-id"
+#define X86_MACHINE_OEM_TABLE_ID "x-oem-table-id"
+#define X86_MACHINE_BUS_LOCK_RATELIMIT "bus-lock-ratelimit"
#define TYPE_X86_MACHINE MACHINE_TYPE_NAME("x86")
-#define X86_MACHINE(obj) \
- OBJECT_CHECK(X86MachineState, (obj), TYPE_X86_MACHINE)
-#define X86_MACHINE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(X86MachineClass, obj, TYPE_X86_MACHINE)
-#define X86_MACHINE_CLASS(class) \
- OBJECT_CLASS_CHECK(X86MachineClass, class, TYPE_X86_MACHINE)
-
-void init_topo_info(X86CPUTopoInfo *topo_info, const X86MachineState *x86ms);
+OBJECT_DECLARE_TYPE(X86MachineState, X86MachineClass, X86_MACHINE)
uint32_t x86_cpu_apic_id_from_index(X86MachineState *pcms,
unsigned int cpu_index);
@@ -101,32 +105,44 @@ CpuInstanceProperties x86_cpu_index_to_props(MachineState *ms,
unsigned cpu_index);
int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx);
const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms);
-
-void x86_bios_rom_init(MemoryRegion *rom_memory, bool isapc_ram_fw);
+CPUArchId *x86_find_cpu_slot(MachineState *ms, uint32_t id, int *idx);
+void x86_rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count);
+void x86_cpu_pre_plug(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp);
+void x86_cpu_plug(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp);
+void x86_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp);
+void x86_cpu_unplug_cb(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp);
+
+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,
int acpi_data_size,
- bool pvh_enabled,
- bool linuxboot_dma_enabled);
+ bool pvh_enabled);
-bool x86_machine_is_smm_enabled(X86MachineState *x86ms);
-bool x86_machine_is_acpi_enabled(X86MachineState *x86ms);
+bool x86_machine_is_smm_enabled(const X86MachineState *x86ms);
+bool x86_machine_is_acpi_enabled(const X86MachineState *x86ms);
/* Global System Interrupts */
-#define GSI_NUM_PINS IOAPIC_NUM_PINS
+#define ACPI_BUILD_PCI_IRQS ((1<<5) | (1<<9) | (1<<10) | (1<<11))
typedef struct GSIState {
qemu_irq i8259_irq[ISA_NUM_IRQS];
qemu_irq ioapic_irq[IOAPIC_NUM_PINS];
+ qemu_irq ioapic2_irq[IOAPIC_NUM_PINS];
} GSIState;
qemu_irq x86_allocate_cpu_irq(void);
void gsi_handler(void *opaque, int n, int level);
-void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name);
+void ioapic_init_gsi(GSIState *gsi_state, Object *parent);
+DeviceState *ioapic_init_secondary(GSIState *gsi_state);
-/* hpet.c */
-extern int no_hpet;
+/* pc_sysfw.c */
+void x86_firmware_configure(void *ptr, int size);
#endif
diff --git a/include/hw/i386/xen_arch_hvm.h b/include/hw/i386/xen_arch_hvm.h
new file mode 100644
index 0000000000..1000f8f543
--- /dev/null
+++ b/include/hw/i386/xen_arch_hvm.h
@@ -0,0 +1,11 @@
+#ifndef HW_XEN_ARCH_I386_HVM_H
+#define HW_XEN_ARCH_I386_HVM_H
+
+#include <xen/hvm/ioreq.h>
+#include "hw/xen/xen-hvm-common.h"
+
+void arch_handle_ioreq(XenIOState *state, ioreq_t *req);
+void arch_xen_set_memory(XenIOState *state,
+ MemoryRegionSection *section,
+ bool add);
+#endif
diff --git a/include/hw/ide.h b/include/hw/ide.h
deleted file mode 100644
index c5ce5da4f4..0000000000
--- a/include/hw/ide.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef HW_IDE_H
-#define HW_IDE_H
-
-#include "hw/isa/isa.h"
-#include "exec/memory.h"
-
-/* ide-isa.c */
-ISADevice *isa_ide_init(ISABus *bus, int iobase, int iobase2, int isairq,
- DriveInfo *hd0, DriveInfo *hd1);
-
-/* ide-pci.c */
-int pci_piix3_xen_ide_unplug(DeviceState *dev, bool aux);
-
-/* ide-mmio.c */
-void mmio_ide_init_drives(DeviceState *dev, DriveInfo *hd0, DriveInfo *hd1);
-
-int ide_get_geometry(BusState *bus, int unit,
- int16_t *cyls, int8_t *heads, int8_t *secs);
-int ide_get_bios_chs_trans(BusState *bus, int unit);
-
-/* ide/core.c */
-void ide_drive_get(DriveInfo **hd, int max_bus);
-
-#endif /* HW_IDE_H */
diff --git a/include/hw/ide/ahci-pci.h b/include/hw/ide/ahci-pci.h
new file mode 100644
index 0000000000..c2ee616962
--- /dev/null
+++ b/include/hw/ide/ahci-pci.h
@@ -0,0 +1,22 @@
+/*
+ * QEMU AHCI Emulation (PCI devices)
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef HW_IDE_AHCI_PCI_H
+#define HW_IDE_AHCI_PCI_H
+
+#include "qom/object.h"
+#include "hw/ide/ahci.h"
+#include "hw/pci/pci_device.h"
+
+#define TYPE_ICH9_AHCI "ich9-ahci"
+OBJECT_DECLARE_SIMPLE_TYPE(AHCIPCIState, ICH9_AHCI)
+
+struct AHCIPCIState {
+ PCIDevice parent_obj;
+
+ AHCIState ahci;
+};
+
+#endif
diff --git a/include/hw/ide/ahci-sysbus.h b/include/hw/ide/ahci-sysbus.h
new file mode 100644
index 0000000000..06eaac8cb6
--- /dev/null
+++ b/include/hw/ide/ahci-sysbus.h
@@ -0,0 +1,35 @@
+/*
+ * QEMU AHCI Emulation (MMIO-mapped devices)
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef HW_IDE_AHCI_SYSBUS_H
+#define HW_IDE_AHCI_SYSBUS_H
+
+#include "qom/object.h"
+#include "hw/sysbus.h"
+#include "hw/ide/ahci.h"
+
+#define TYPE_SYSBUS_AHCI "sysbus-ahci"
+OBJECT_DECLARE_SIMPLE_TYPE(SysbusAHCIState, SYSBUS_AHCI)
+
+struct SysbusAHCIState {
+ SysBusDevice parent_obj;
+
+ AHCIState ahci;
+};
+
+#define TYPE_ALLWINNER_AHCI "allwinner-ahci"
+OBJECT_DECLARE_SIMPLE_TYPE(AllwinnerAHCIState, ALLWINNER_AHCI)
+
+#define ALLWINNER_AHCI_MMIO_OFF 0x80
+#define ALLWINNER_AHCI_MMIO_SIZE 0x80
+
+struct AllwinnerAHCIState {
+ SysbusAHCIState parent_obj;
+
+ MemoryRegion mmio;
+ uint32_t regs[ALLWINNER_AHCI_MMIO_SIZE / 4];
+};
+
+#endif
diff --git a/include/hw/ide/ahci.h b/include/hw/ide/ahci.h
index b44e3000cf..ba31e75ff9 100644
--- a/include/hw/ide/ahci.h
+++ b/include/hw/ide/ahci.h
@@ -9,7 +9,7 @@
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -24,7 +24,7 @@
#ifndef HW_IDE_AHCI_H
#define HW_IDE_AHCI_H
-#include "hw/sysbus.h"
+#include "exec/memory.h"
typedef struct AHCIDevice AHCIDevice;
@@ -45,41 +45,12 @@ typedef struct AHCIState {
MemoryRegion idp; /* Index-Data Pair I/O port space */
unsigned idp_offset; /* Offset of index in I/O port space */
uint32_t idp_index; /* Current IDP index */
- int32_t ports;
+ uint32_t ports;
qemu_irq irq;
AddressSpace *as;
} AHCIState;
-typedef struct AHCIPCIState AHCIPCIState;
-#define TYPE_ICH9_AHCI "ich9-ahci"
-
-int32_t ahci_get_num_ports(PCIDevice *dev);
-void ahci_ide_create_devs(PCIDevice *dev, DriveInfo **hd);
-
-#define TYPE_SYSBUS_AHCI "sysbus-ahci"
-
-typedef struct SysbusAHCIState {
- /*< private >*/
- SysBusDevice parent_obj;
- /*< public >*/
-
- AHCIState ahci;
- uint32_t num_ports;
-} SysbusAHCIState;
-
-#define TYPE_ALLWINNER_AHCI "allwinner-ahci"
-
-#define ALLWINNER_AHCI_MMIO_OFF 0x80
-#define ALLWINNER_AHCI_MMIO_SIZE 0x80
-
-typedef struct AllwinnerAHCIState {
- /*< private >*/
- SysbusAHCIState parent_obj;
- /*< public >*/
-
- MemoryRegion mmio;
- uint32_t regs[ALLWINNER_AHCI_MMIO_SIZE/4];
-} AllwinnerAHCIState;
+void ahci_ide_create_devs(AHCIState *ahci, DriveInfo **hd);
#endif /* HW_IDE_AHCI_H */
diff --git a/include/hw/ide/ide-bus.h b/include/hw/ide/ide-bus.h
new file mode 100644
index 0000000000..4841a7dcd6
--- /dev/null
+++ b/include/hw/ide/ide-bus.h
@@ -0,0 +1,42 @@
+#ifndef HW_IDE_BUS_H
+#define HW_IDE_BUS_H
+
+#include "exec/ioport.h"
+#include "hw/ide/ide-dev.h"
+#include "hw/ide/ide-dma.h"
+
+struct IDEBus {
+ BusState qbus;
+ IDEDevice *master;
+ IDEDevice *slave;
+ IDEState ifs[2];
+ QEMUBH *bh;
+
+ int bus_id;
+ int max_units;
+ IDEDMA *dma;
+ uint8_t unit;
+ uint8_t cmd;
+ qemu_irq irq; /* bus output */
+
+ int error_status;
+ uint8_t retry_unit;
+ int64_t retry_sector_num;
+ uint32_t retry_nsector;
+ PortioList portio_list;
+ PortioList portio2_list;
+ VMChangeStateEntry *vmstate;
+};
+
+#define TYPE_IDE_BUS "IDE"
+OBJECT_DECLARE_SIMPLE_TYPE(IDEBus, IDE_BUS)
+
+void ide_bus_init(IDEBus *idebus, size_t idebus_size, DeviceState *dev,
+ int bus_id, int max_units);
+IDEDevice *ide_bus_create_drive(IDEBus *bus, int unit, DriveInfo *drive);
+
+int ide_get_geometry(BusState *bus, int unit,
+ int16_t *cyls, int8_t *heads, int8_t *secs);
+int ide_get_bios_chs_trans(BusState *bus, int unit);
+
+#endif
diff --git a/include/hw/ide/ide-dev.h b/include/hw/ide/ide-dev.h
new file mode 100644
index 0000000000..9a0d71db4e
--- /dev/null
+++ b/include/hw/ide/ide-dev.h
@@ -0,0 +1,186 @@
+/*
+ * ide device definitions
+ *
+ * Copyright (c) 2009 Gerd Hoffmann <kraxel@redhat.com>
+ *
+ * This code is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef IDE_DEV_H
+#define IDE_DEV_H
+
+#include "sysemu/dma.h"
+#include "hw/qdev-properties.h"
+#include "hw/block/block.h"
+
+typedef struct IDEDevice IDEDevice;
+typedef struct IDEState IDEState;
+typedef struct IDEBus IDEBus;
+
+typedef void EndTransferFunc(IDEState *);
+
+#define MAX_IDE_DEVS 2
+
+#define TYPE_IDE_DEVICE "ide-device"
+OBJECT_DECLARE_TYPE(IDEDevice, IDEDeviceClass, IDE_DEVICE)
+
+typedef enum { IDE_HD, IDE_CD, IDE_CFATA } IDEDriveKind;
+
+struct unreported_events {
+ bool eject_request;
+ bool new_media;
+};
+
+enum ide_dma_cmd {
+ IDE_DMA_READ = 0,
+ IDE_DMA_WRITE,
+ IDE_DMA_TRIM,
+ IDE_DMA_ATAPI,
+ IDE_DMA__COUNT
+};
+
+/* NOTE: IDEState represents in fact one drive */
+struct IDEState {
+ IDEBus *bus;
+ uint8_t unit;
+ /* ide config */
+ IDEDriveKind drive_kind;
+ int drive_heads, drive_sectors;
+ int cylinders, heads, sectors, chs_trans;
+ int64_t nb_sectors;
+ int mult_sectors;
+ int identify_set;
+ uint8_t identify_data[512];
+ int drive_serial;
+ char drive_serial_str[21];
+ char drive_model_str[41];
+ bool win2k_install_hack;
+ uint64_t wwn;
+ /* ide regs */
+ uint8_t feature;
+ uint8_t error;
+ uint32_t nsector;
+ uint8_t sector;
+ uint8_t lcyl;
+ uint8_t hcyl;
+ /* other part of tf for lba48 support */
+ uint8_t hob_feature;
+ uint8_t hob_nsector;
+ uint8_t hob_sector;
+ uint8_t hob_lcyl;
+ uint8_t hob_hcyl;
+
+ uint8_t select;
+ uint8_t status;
+
+ bool io8;
+ bool reset_reverts;
+
+ /* set for lba48 access */
+ uint8_t lba48;
+ BlockBackend *blk;
+ char version[9];
+ /* ATAPI specific */
+ struct unreported_events events;
+ uint8_t sense_key;
+ uint8_t asc;
+ bool tray_open;
+ bool tray_locked;
+ uint8_t cdrom_changed;
+ int packet_transfer_size;
+ int elementary_transfer_size;
+ int32_t io_buffer_index;
+ int lba;
+ int cd_sector_size;
+ int atapi_dma; /* true if dma is requested for the packet cmd */
+ BlockAcctCookie acct;
+ BlockAIOCB *pio_aiocb;
+ QEMUIOVector qiov;
+ QLIST_HEAD(, IDEBufferedRequest) buffered_requests;
+ /* ATA DMA state */
+ uint64_t io_buffer_offset;
+ int32_t io_buffer_size;
+ QEMUSGList sg;
+ /* PIO transfer handling */
+ int req_nb_sectors; /* number of sectors per interrupt */
+ EndTransferFunc *end_transfer_func;
+ uint8_t *data_ptr;
+ uint8_t *data_end;
+ uint8_t *io_buffer;
+ /* PIO save/restore */
+ int32_t io_buffer_total_len;
+ int32_t cur_io_buffer_offset;
+ int32_t cur_io_buffer_len;
+ uint8_t end_transfer_fn_idx;
+ QEMUTimer *sector_write_timer; /* only used for win2k install hack */
+ uint32_t irq_count; /* counts IRQs when using win2k install hack */
+ /* CF-ATA extended error */
+ uint8_t ext_error;
+ /* CF-ATA metadata storage */
+ uint32_t mdata_size;
+ uint8_t *mdata_storage;
+ int media_changed;
+ enum ide_dma_cmd dma_cmd;
+ /* SMART */
+ uint8_t smart_enabled;
+ uint8_t smart_autosave;
+ int smart_errors;
+ uint8_t smart_selftest_count;
+ uint8_t *smart_selftest_data;
+ /* AHCI */
+ int ncq_queues;
+};
+
+struct IDEDeviceClass {
+ DeviceClass parent_class;
+ void (*realize)(IDEDevice *dev, Error **errp);
+};
+
+struct IDEDevice {
+ DeviceState qdev;
+ uint32_t unit;
+ BlockConf conf;
+ int chs_trans;
+ char *version;
+ char *serial;
+ char *model;
+ uint64_t wwn;
+ /*
+ * 0x0000 - rotation rate not reported
+ * 0x0001 - non-rotating medium (SSD)
+ * 0x0002-0x0400 - reserved
+ * 0x0401-0xffe - rotations per minute
+ * 0xffff - reserved
+ */
+ uint16_t rotation_rate;
+ bool win2k_install_hack;
+};
+
+typedef struct IDEDrive {
+ IDEDevice dev;
+} IDEDrive;
+
+#define DEFINE_IDE_DEV_PROPERTIES() \
+ DEFINE_BLOCK_PROPERTIES(IDEDrive, dev.conf), \
+ DEFINE_BLOCK_ERROR_PROPERTIES(IDEDrive, dev.conf), \
+ DEFINE_PROP_STRING("ver", IDEDrive, dev.version), \
+ DEFINE_PROP_UINT64("wwn", IDEDrive, dev.wwn, 0), \
+ DEFINE_PROP_STRING("serial", IDEDrive, dev.serial),\
+ DEFINE_PROP_STRING("model", IDEDrive, dev.model)
+
+void ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind, Error **errp);
+
+void ide_drive_get(DriveInfo **hd, int max_bus);
+
+#endif
diff --git a/include/hw/ide/ide-dma.h b/include/hw/ide/ide-dma.h
new file mode 100644
index 0000000000..d0b19ac9c5
--- /dev/null
+++ b/include/hw/ide/ide-dma.h
@@ -0,0 +1,37 @@
+#ifndef HW_IDE_DMA_H
+#define HW_IDE_DMA_H
+
+#include "block/aio.h"
+#include "qemu/iov.h"
+
+typedef struct IDEState IDEState;
+typedef struct IDEDMAOps IDEDMAOps;
+typedef struct IDEDMA IDEDMA;
+
+typedef void DMAStartFunc(const IDEDMA *, IDEState *, BlockCompletionFunc *);
+typedef void DMAVoidFunc(const IDEDMA *);
+typedef int DMAIntFunc(const IDEDMA *, bool);
+typedef int32_t DMAInt32Func(const IDEDMA *, int32_t len);
+typedef void DMAu32Func(const IDEDMA *, uint32_t);
+typedef void DMAStopFunc(const IDEDMA *, bool);
+
+struct IDEDMAOps {
+ DMAStartFunc *start_dma;
+ DMAVoidFunc *pio_transfer;
+ DMAInt32Func *prepare_buf;
+ DMAu32Func *commit_buf;
+ DMAIntFunc *rw_buf;
+ DMAVoidFunc *restart;
+ DMAVoidFunc *restart_dma;
+ DMAStopFunc *set_inactive;
+ DMAVoidFunc *cmd_done;
+ DMAVoidFunc *reset;
+};
+
+struct IDEDMA {
+ const IDEDMAOps *ops;
+ QEMUIOVector qiov;
+ BlockAIOCB *aiocb;
+};
+
+#endif
diff --git a/include/hw/ide/internal.h b/include/hw/ide/internal.h
deleted file mode 100644
index 1a7869e85d..0000000000
--- a/include/hw/ide/internal.h
+++ /dev/null
@@ -1,649 +0,0 @@
-#ifndef HW_IDE_INTERNAL_H
-#define HW_IDE_INTERNAL_H
-
-/*
- * QEMU IDE Emulation -- internal header file
- * only files in hw/ide/ are supposed to include this file.
- * non-internal declarations are in hw/ide.h
- */
-
-#include "qapi/qapi-types-run-state.h"
-#include "hw/ide.h"
-#include "hw/irq.h"
-#include "hw/isa/isa.h"
-#include "sysemu/dma.h"
-#include "hw/block/block.h"
-#include "scsi/constants.h"
-
-/* debug IDE devices */
-#define USE_DMA_CDROM
-
-typedef struct IDEBus IDEBus;
-typedef struct IDEDevice IDEDevice;
-typedef struct IDEState IDEState;
-typedef struct IDEDMA IDEDMA;
-typedef struct IDEDMAOps IDEDMAOps;
-
-#define TYPE_IDE_BUS "IDE"
-#define IDE_BUS(obj) OBJECT_CHECK(IDEBus, (obj), TYPE_IDE_BUS)
-
-#define MAX_IDE_DEVS 2
-
-/* Bits of HD_STATUS */
-#define ERR_STAT 0x01
-#define INDEX_STAT 0x02
-#define ECC_STAT 0x04 /* Corrected error */
-#define DRQ_STAT 0x08
-#define SEEK_STAT 0x10
-#define SRV_STAT 0x10
-#define WRERR_STAT 0x20
-#define READY_STAT 0x40
-#define BUSY_STAT 0x80
-
-/* Bits for HD_ERROR */
-#define MARK_ERR 0x01 /* Bad address mark */
-#define TRK0_ERR 0x02 /* couldn't find track 0 */
-#define ABRT_ERR 0x04 /* Command aborted */
-#define MCR_ERR 0x08 /* media change request */
-#define ID_ERR 0x10 /* ID field not found */
-#define MC_ERR 0x20 /* media changed */
-#define ECC_ERR 0x40 /* Uncorrectable ECC error */
-#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */
-#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */
-
-/* Bits of HD_NSECTOR */
-#define CD 0x01
-#define IO 0x02
-#define REL 0x04
-#define TAG_MASK 0xf8
-
-#define IDE_CMD_RESET 0x04
-#define IDE_CMD_DISABLE_IRQ 0x02
-
-/* ACS-2 T13/2015-D Table B.2 Command codes */
-#define WIN_NOP 0x00
-/* reserved 0x01..0x02 */
-#define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */
-/* reserved 0x04..0x05 */
-#define WIN_DSM 0x06
-/* reserved 0x07 */
-#define WIN_DEVICE_RESET 0x08
-/* reserved 0x09..0x0a */
-/* REQUEST SENSE DATA EXT 0x0B */
-/* reserved 0x0C..0x0F */
-#define WIN_RECAL 0x10 /* obsolete since ATA4 */
-/* obsolete since ATA3, retired in ATA4 0x11..0x1F */
-#define WIN_READ 0x20 /* 28-Bit */
-#define WIN_READ_ONCE 0x21 /* 28-Bit w/o retries, obsolete since ATA5 */
-/* obsolete since ATA4 0x22..0x23 */
-#define WIN_READ_EXT 0x24 /* 48-Bit */
-#define WIN_READDMA_EXT 0x25 /* 48-Bit */
-#define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit, obsolete since ACS2 */
-#define WIN_READ_NATIVE_MAX_EXT 0x27 /* 48-Bit */
-/* reserved 0x28 */
-#define WIN_MULTREAD_EXT 0x29 /* 48-Bit */
-/* READ STREAM DMA EXT 0x2A */
-/* READ STREAM EXT 0x2B */
-/* reserved 0x2C..0x2E */
-/* READ LOG EXT 0x2F */
-#define WIN_WRITE 0x30 /* 28-Bit */
-#define WIN_WRITE_ONCE 0x31 /* 28-Bit w/o retries, obsolete since ATA5 */
-/* obsolete since ATA4 0x32..0x33 */
-#define WIN_WRITE_EXT 0x34 /* 48-Bit */
-#define WIN_WRITEDMA_EXT 0x35 /* 48-Bit */
-#define WIN_WRITEDMA_QUEUED_EXT 0x36 /* 48-Bit */
-#define WIN_SET_MAX_EXT 0x37 /* 48-Bit, obsolete since ACS2 */
-#define WIN_SET_MAX_EXT 0x37 /* 48-Bit */
-#define CFA_WRITE_SECT_WO_ERASE 0x38 /* CFA Write Sectors without erase */
-#define WIN_MULTWRITE_EXT 0x39 /* 48-Bit */
-/* WRITE STREAM DMA EXT 0x3A */
-/* WRITE STREAM EXT 0x3B */
-#define WIN_WRITE_VERIFY 0x3C /* 28-Bit, obsolete since ATA4 */
-/* WRITE DMA FUA EXT 0x3D */
-/* obsolete since ACS2 0x3E */
-/* WRITE LOG EXT 0x3F */
-#define WIN_VERIFY 0x40 /* 28-Bit - Read Verify Sectors */
-#define WIN_VERIFY_ONCE 0x41 /* 28-Bit - w/o retries, obsolete since ATA5 */
-#define WIN_VERIFY_EXT 0x42 /* 48-Bit */
-/* reserved 0x43..0x44 */
-/* WRITE UNCORRECTABLE EXT 0x45 */
-/* reserved 0x46 */
-/* READ LOG DMA EXT 0x47 */
-/* reserved 0x48..0x4F */
-/* obsolete since ATA4 0x50 */
-/* CONFIGURE STREAM 0x51 */
-/* reserved 0x52..0x56 */
-/* WRITE LOG DMA EXT 0x57 */
-/* reserved 0x58..0x5A */
-/* TRUSTED NON DATA 0x5B */
-/* TRUSTED RECEIVE 0x5C */
-/* TRUSTED RECEIVE DMA 0x5D */
-/* TRUSTED SEND 0x5E */
-/* TRUSTED SEND DMA 0x5F */
-/* READ FPDMA QUEUED 0x60 */
-/* WRITE FPDMA QUEUED 0x61 */
-/* reserved 0x62->0x6F */
-#define WIN_SEEK 0x70 /* obsolete since ATA7 */
-/* reserved 0x71-0x7F */
-/* vendor specific 0x80-0x86 */
-#define CFA_TRANSLATE_SECTOR 0x87 /* CFA Translate Sector */
-/* vendor specific 0x88-0x8F */
-#define WIN_DIAGNOSE 0x90
-#define WIN_SPECIFY 0x91 /* set drive geometry translation, obsolete since ATA6 */
-#define WIN_DOWNLOAD_MICROCODE 0x92
-/* DOWNLOAD MICROCODE DMA 0x93 */
-#define WIN_STANDBYNOW2 0x94 /* retired in ATA4 */
-#define WIN_IDLEIMMEDIATE2 0x95 /* force drive to become "ready", retired in ATA4 */
-#define WIN_STANDBY2 0x96 /* retired in ATA4 */
-#define WIN_SETIDLE2 0x97 /* retired in ATA4 */
-#define WIN_CHECKPOWERMODE2 0x98 /* retired in ATA4 */
-#define WIN_SLEEPNOW2 0x99 /* retired in ATA4 */
-/* vendor specific 0x9A */
-/* reserved 0x9B..0x9F */
-#define WIN_PACKETCMD 0xA0 /* Send a packet command. */
-#define WIN_PIDENTIFY 0xA1 /* identify ATAPI device */
-#define WIN_QUEUED_SERVICE 0xA2 /* obsolete since ACS2 */
-/* reserved 0xA3..0xAF */
-#define WIN_SMART 0xB0 /* self-monitoring and reporting */
-/* Device Configuration Overlay 0xB1 */
-/* reserved 0xB2..0xB3 */
-/* Sanitize Device 0xB4 */
-/* reserved 0xB5 */
-/* NV Cache 0xB6 */
-/* reserved for CFA 0xB7..0xBB */
-#define CFA_ACCESS_METADATA_STORAGE 0xB8
-/* reserved 0xBC..0xBF */
-#define CFA_ERASE_SECTORS 0xC0 /* microdrives implement as NOP */
-/* vendor specific 0xC1..0xC3 */
-#define WIN_MULTREAD 0xC4 /* read sectors using multiple mode*/
-#define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */
-#define WIN_SETMULT 0xC6 /* enable/disable multiple mode */
-#define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers, obsolete since ACS2 */
-#define WIN_READDMA 0xC8 /* read sectors using DMA transfers */
-#define WIN_READDMA_ONCE 0xC9 /* 28-Bit - w/o retries, obsolete since ATA5 */
-#define WIN_WRITEDMA 0xCA /* write sectors using DMA transfers */
-#define WIN_WRITEDMA_ONCE 0xCB /* 28-Bit - w/o retries, obsolete since ATA5 */
-#define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers, obsolete since ACS2 */
-#define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */
-/* WRITE MULTIPLE FUA EXT 0xCE */
-/* reserved 0xCF..0xDO */
-/* CHECK MEDIA CARD TYPE 0xD1 */
-/* reserved for media card pass through 0xD2..0xD4 */
-/* reserved 0xD5..0xD9 */
-#define WIN_GETMEDIASTATUS 0xDA /* obsolete since ATA8 */
-/* obsolete since ATA3, retired in ATA4 0xDB..0xDD */
-#define WIN_DOORLOCK 0xDE /* lock door on removable drives, obsolete since ATA8 */
-#define WIN_DOORUNLOCK 0xDF /* unlock door on removable drives, obsolete since ATA8 */
-#define WIN_STANDBYNOW1 0xE0
-#define WIN_IDLEIMMEDIATE 0xE1 /* force drive to become "ready" */
-#define WIN_STANDBY 0xE2 /* Set device in Standby Mode */
-#define WIN_SETIDLE1 0xE3
-#define WIN_READ_BUFFER 0xE4 /* force read only 1 sector */
-#define WIN_CHECKPOWERMODE1 0xE5
-#define WIN_SLEEPNOW1 0xE6
-#define WIN_FLUSH_CACHE 0xE7
-#define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */
-/* READ BUFFER DMA 0xE9 */
-#define WIN_FLUSH_CACHE_EXT 0xEA /* 48-Bit */
-/* WRITE BUFFER DMA 0xEB */
-#define WIN_IDENTIFY 0xEC /* ask drive to identify itself */
-#define WIN_MEDIAEJECT 0xED /* obsolete since ATA8 */
-/* obsolete since ATA4 0xEE */
-#define WIN_SETFEATURES 0xEF /* set special drive features */
-#define IBM_SENSE_CONDITION 0xF0 /* measure disk temperature, vendor specific */
-#define WIN_SECURITY_SET_PASS 0xF1
-#define WIN_SECURITY_UNLOCK 0xF2
-#define WIN_SECURITY_ERASE_PREPARE 0xF3
-#define WIN_SECURITY_ERASE_UNIT 0xF4
-#define WIN_SECURITY_FREEZE_LOCK 0xF5
-#define CFA_WEAR_LEVEL 0xF5 /* microdrives implement as NOP; not specified in T13! */
-#define WIN_SECURITY_DISABLE 0xF6
-/* vendor specific 0xF7 */
-#define WIN_READ_NATIVE_MAX 0xF8 /* return the native maximum address */
-#define WIN_SET_MAX 0xF9
-/* vendor specific 0xFA..0xFF */
-
-/* set to 1 set disable mult support */
-#define MAX_MULT_SECTORS 16
-
-#define IDE_DMA_BUF_SECTORS 256
-
-/* feature values for Data Set Management */
-#define DSM_TRIM 0x01
-
-#if (IDE_DMA_BUF_SECTORS < MAX_MULT_SECTORS)
-#error "IDE_DMA_BUF_SECTORS must be bigger or equal to MAX_MULT_SECTORS"
-#endif
-
-/* ATAPI defines */
-
-#define ATAPI_PACKET_SIZE 12
-
-/* The generic packet command opcodes for CD/DVD Logical Units,
- * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
-#define GPCMD_BLANK 0xa1
-#define GPCMD_CLOSE_TRACK 0x5b
-#define GPCMD_FLUSH_CACHE 0x35
-#define GPCMD_FORMAT_UNIT 0x04
-#define GPCMD_GET_CONFIGURATION 0x46
-#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a
-#define GPCMD_GET_PERFORMANCE 0xac
-#define GPCMD_INQUIRY 0x12
-#define GPCMD_LOAD_UNLOAD 0xa6
-#define GPCMD_MECHANISM_STATUS 0xbd
-#define GPCMD_MODE_SELECT_10 0x55
-#define GPCMD_MODE_SENSE_10 0x5a
-#define GPCMD_PAUSE_RESUME 0x4b
-#define GPCMD_PLAY_AUDIO_10 0x45
-#define GPCMD_PLAY_AUDIO_MSF 0x47
-#define GPCMD_PLAY_AUDIO_TI 0x48
-#define GPCMD_PLAY_CD 0xbc
-#define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e
-#define GPCMD_READ_10 0x28
-#define GPCMD_READ_12 0xa8
-#define GPCMD_READ_CDVD_CAPACITY 0x25
-#define GPCMD_READ_CD 0xbe
-#define GPCMD_READ_CD_MSF 0xb9
-#define GPCMD_READ_DISC_INFO 0x51
-#define GPCMD_READ_DVD_STRUCTURE 0xad
-#define GPCMD_READ_FORMAT_CAPACITIES 0x23
-#define GPCMD_READ_HEADER 0x44
-#define GPCMD_READ_TRACK_RZONE_INFO 0x52
-#define GPCMD_READ_SUBCHANNEL 0x42
-#define GPCMD_READ_TOC_PMA_ATIP 0x43
-#define GPCMD_REPAIR_RZONE_TRACK 0x58
-#define GPCMD_REPORT_KEY 0xa4
-#define GPCMD_REQUEST_SENSE 0x03
-#define GPCMD_RESERVE_RZONE_TRACK 0x53
-#define GPCMD_SCAN 0xba
-#define GPCMD_SEEK 0x2b
-#define GPCMD_SEND_DVD_STRUCTURE 0xad
-#define GPCMD_SEND_EVENT 0xa2
-#define GPCMD_SEND_KEY 0xa3
-#define GPCMD_SEND_OPC 0x54
-#define GPCMD_SET_READ_AHEAD 0xa7
-#define GPCMD_SET_STREAMING 0xb6
-#define GPCMD_START_STOP_UNIT 0x1b
-#define GPCMD_STOP_PLAY_SCAN 0x4e
-#define GPCMD_TEST_UNIT_READY 0x00
-#define GPCMD_VERIFY_10 0x2f
-#define GPCMD_WRITE_10 0x2a
-#define GPCMD_WRITE_AND_VERIFY_10 0x2e
-/* This is listed as optional in ATAPI 2.6, but is (curiously)
- * missing from Mt. Fuji, Table 57. It _is_ mentioned in Mt. Fuji
- * Table 377 as an MMC command for SCSi devices though... Most ATAPI
- * drives support it. */
-#define GPCMD_SET_SPEED 0xbb
-/* This seems to be a SCSI specific CD-ROM opcode
- * to play data at track/index */
-#define GPCMD_PLAYAUDIO_TI 0x48
-/*
- * From MS Media Status Notification Support Specification. For
- * older drives only.
- */
-#define GPCMD_GET_MEDIA_STATUS 0xda
-#define GPCMD_MODE_SENSE_6 0x1a
-
-#define ATAPI_INT_REASON_CD 0x01 /* 0 = data transfer */
-#define ATAPI_INT_REASON_IO 0x02 /* 1 = transfer to the host */
-#define ATAPI_INT_REASON_REL 0x04
-#define ATAPI_INT_REASON_TAG 0xf8
-
-/* same constants as bochs */
-#define ASC_NO_SEEK_COMPLETE 0x02
-#define ASC_ILLEGAL_OPCODE 0x20
-#define ASC_LOGICAL_BLOCK_OOR 0x21
-#define ASC_INV_FIELD_IN_CMD_PACKET 0x24
-#define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28
-#define ASC_INCOMPATIBLE_FORMAT 0x30
-#define ASC_MEDIUM_NOT_PRESENT 0x3a
-#define ASC_SAVING_PARAMETERS_NOT_SUPPORTED 0x39
-#define ASC_DATA_PHASE_ERROR 0x4b
-#define ASC_MEDIA_REMOVAL_PREVENTED 0x53
-
-#define CFA_NO_ERROR 0x00
-#define CFA_MISC_ERROR 0x09
-#define CFA_INVALID_COMMAND 0x20
-#define CFA_INVALID_ADDRESS 0x21
-#define CFA_ADDRESS_OVERFLOW 0x2f
-
-#define SMART_READ_DATA 0xd0
-#define SMART_READ_THRESH 0xd1
-#define SMART_ATTR_AUTOSAVE 0xd2
-#define SMART_SAVE_ATTR 0xd3
-#define SMART_EXECUTE_OFFLINE 0xd4
-#define SMART_READ_LOG 0xd5
-#define SMART_WRITE_LOG 0xd6
-#define SMART_ENABLE 0xd8
-#define SMART_DISABLE 0xd9
-#define SMART_STATUS 0xda
-
-typedef enum { IDE_HD, IDE_CD, IDE_CFATA } IDEDriveKind;
-
-typedef void EndTransferFunc(IDEState *);
-
-typedef void DMAStartFunc(const IDEDMA *, IDEState *, BlockCompletionFunc *);
-typedef void DMAVoidFunc(const IDEDMA *);
-typedef int DMAIntFunc(const IDEDMA *, bool);
-typedef int32_t DMAInt32Func(const IDEDMA *, int32_t len);
-typedef void DMAu32Func(const IDEDMA *, uint32_t);
-typedef void DMAStopFunc(const IDEDMA *, bool);
-
-struct unreported_events {
- bool eject_request;
- bool new_media;
-};
-
-enum ide_dma_cmd {
- IDE_DMA_READ = 0,
- IDE_DMA_WRITE,
- IDE_DMA_TRIM,
- IDE_DMA_ATAPI,
- IDE_DMA__COUNT
-};
-
-extern const char *IDE_DMA_CMD_lookup[IDE_DMA__COUNT];
-
-#define ide_cmd_is_read(s) \
- ((s)->dma_cmd == IDE_DMA_READ)
-
-typedef struct IDEBufferedRequest {
- QLIST_ENTRY(IDEBufferedRequest) list;
- QEMUIOVector qiov;
- QEMUIOVector *original_qiov;
- BlockCompletionFunc *original_cb;
- void *original_opaque;
- bool orphaned;
-} IDEBufferedRequest;
-
-/* NOTE: IDEState represents in fact one drive */
-struct IDEState {
- IDEBus *bus;
- uint8_t unit;
- /* ide config */
- IDEDriveKind drive_kind;
- int cylinders, heads, sectors, chs_trans;
- int64_t nb_sectors;
- int mult_sectors;
- int identify_set;
- uint8_t identify_data[512];
- int drive_serial;
- char drive_serial_str[21];
- char drive_model_str[41];
- uint64_t wwn;
- /* ide regs */
- uint8_t feature;
- uint8_t error;
- uint32_t nsector;
- uint8_t sector;
- uint8_t lcyl;
- uint8_t hcyl;
- /* other part of tf for lba48 support */
- uint8_t hob_feature;
- uint8_t hob_nsector;
- uint8_t hob_sector;
- uint8_t hob_lcyl;
- uint8_t hob_hcyl;
-
- uint8_t select;
- uint8_t status;
-
- /* set for lba48 access */
- uint8_t lba48;
- BlockBackend *blk;
- char version[9];
- /* ATAPI specific */
- struct unreported_events events;
- uint8_t sense_key;
- uint8_t asc;
- bool tray_open;
- bool tray_locked;
- uint8_t cdrom_changed;
- int packet_transfer_size;
- int elementary_transfer_size;
- int32_t io_buffer_index;
- int lba;
- int cd_sector_size;
- int atapi_dma; /* true if dma is requested for the packet cmd */
- BlockAcctCookie acct;
- BlockAIOCB *pio_aiocb;
- QEMUIOVector qiov;
- QLIST_HEAD(, IDEBufferedRequest) buffered_requests;
- /* ATA DMA state */
- uint64_t io_buffer_offset;
- int32_t io_buffer_size;
- QEMUSGList sg;
- /* PIO transfer handling */
- int req_nb_sectors; /* number of sectors per interrupt */
- EndTransferFunc *end_transfer_func;
- uint8_t *data_ptr;
- uint8_t *data_end;
- uint8_t *io_buffer;
- /* PIO save/restore */
- int32_t io_buffer_total_len;
- int32_t cur_io_buffer_offset;
- int32_t cur_io_buffer_len;
- uint8_t end_transfer_fn_idx;
- QEMUTimer *sector_write_timer; /* only used for win2k install hack */
- uint32_t irq_count; /* counts IRQs when using win2k install hack */
- /* CF-ATA extended error */
- uint8_t ext_error;
- /* CF-ATA metadata storage */
- uint32_t mdata_size;
- uint8_t *mdata_storage;
- int media_changed;
- enum ide_dma_cmd dma_cmd;
- /* SMART */
- uint8_t smart_enabled;
- uint8_t smart_autosave;
- int smart_errors;
- uint8_t smart_selftest_count;
- uint8_t *smart_selftest_data;
- /* AHCI */
- int ncq_queues;
-};
-
-struct IDEDMAOps {
- DMAStartFunc *start_dma;
- DMAVoidFunc *pio_transfer;
- DMAInt32Func *prepare_buf;
- DMAu32Func *commit_buf;
- DMAIntFunc *rw_buf;
- DMAVoidFunc *restart;
- DMAVoidFunc *restart_dma;
- DMAStopFunc *set_inactive;
- DMAVoidFunc *cmd_done;
- DMAVoidFunc *reset;
-};
-
-struct IDEDMA {
- const struct IDEDMAOps *ops;
- QEMUIOVector qiov;
- BlockAIOCB *aiocb;
-};
-
-struct IDEBus {
- BusState qbus;
- IDEDevice *master;
- IDEDevice *slave;
- IDEState ifs[2];
- QEMUBH *bh;
-
- int bus_id;
- int max_units;
- IDEDMA *dma;
- uint8_t unit;
- uint8_t cmd;
- qemu_irq irq;
-
- int error_status;
- uint8_t retry_unit;
- int64_t retry_sector_num;
- uint32_t retry_nsector;
- PortioList portio_list;
- PortioList portio2_list;
- VMChangeStateEntry *vmstate;
-};
-
-#define TYPE_IDE_DEVICE "ide-device"
-#define IDE_DEVICE(obj) \
- OBJECT_CHECK(IDEDevice, (obj), TYPE_IDE_DEVICE)
-#define IDE_DEVICE_CLASS(klass) \
- OBJECT_CLASS_CHECK(IDEDeviceClass, (klass), TYPE_IDE_DEVICE)
-#define IDE_DEVICE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(IDEDeviceClass, (obj), TYPE_IDE_DEVICE)
-
-typedef struct IDEDeviceClass {
- DeviceClass parent_class;
- void (*realize)(IDEDevice *dev, Error **errp);
-} IDEDeviceClass;
-
-struct IDEDevice {
- DeviceState qdev;
- uint32_t unit;
- BlockConf conf;
- int chs_trans;
- char *version;
- char *serial;
- char *model;
- uint64_t wwn;
- /*
- * 0x0000 - rotation rate not reported
- * 0x0001 - non-rotating medium (SSD)
- * 0x0002-0x0400 - reserved
- * 0x0401-0xffe - rotations per minute
- * 0xffff - reserved
- */
- uint16_t rotation_rate;
-};
-
-/* These are used for the error_status field of IDEBus */
-#define IDE_RETRY_MASK 0xf8
-#define IDE_RETRY_DMA 0x08
-#define IDE_RETRY_PIO 0x10
-#define IDE_RETRY_ATAPI 0x20 /* reused IDE_RETRY_READ bit */
-#define IDE_RETRY_READ 0x20
-#define IDE_RETRY_FLUSH 0x40
-#define IDE_RETRY_TRIM 0x80
-#define IDE_RETRY_HBA 0x100
-
-#define IS_IDE_RETRY_DMA(_status) \
- ((_status) & IDE_RETRY_DMA)
-
-#define IS_IDE_RETRY_PIO(_status) \
- ((_status) & IDE_RETRY_PIO)
-
-/*
- * The method of the IDE_RETRY_ATAPI determination is to use a previously
- * impossible bit combination as a new status value.
- */
-#define IS_IDE_RETRY_ATAPI(_status) \
- (((_status) & IDE_RETRY_MASK) == IDE_RETRY_ATAPI)
-
-static inline uint8_t ide_dma_cmd_to_retry(uint8_t dma_cmd)
-{
- switch (dma_cmd) {
- case IDE_DMA_READ:
- return IDE_RETRY_DMA | IDE_RETRY_READ;
- case IDE_DMA_WRITE:
- return IDE_RETRY_DMA;
- case IDE_DMA_TRIM:
- return IDE_RETRY_DMA | IDE_RETRY_TRIM;
- case IDE_DMA_ATAPI:
- return IDE_RETRY_ATAPI;
- default:
- break;
- }
- return 0;
-}
-
-static inline IDEState *idebus_active_if(IDEBus *bus)
-{
- return bus->ifs + bus->unit;
-}
-
-static inline void ide_set_irq(IDEBus *bus)
-{
- if (!(bus->cmd & IDE_CMD_DISABLE_IRQ)) {
- qemu_irq_raise(bus->irq);
- }
-}
-
-/* hw/ide/core.c */
-extern const VMStateDescription vmstate_ide_bus;
-
-#define VMSTATE_IDE_BUS(_field, _state) \
- VMSTATE_STRUCT(_field, _state, 1, vmstate_ide_bus, IDEBus)
-
-#define VMSTATE_IDE_BUS_ARRAY(_field, _state, _num) \
- VMSTATE_STRUCT_ARRAY(_field, _state, _num, 1, vmstate_ide_bus, IDEBus)
-
-extern const VMStateDescription vmstate_ide_drive;
-
-#define VMSTATE_IDE_DRIVES(_field, _state) \
- VMSTATE_STRUCT_ARRAY(_field, _state, 2, 3, vmstate_ide_drive, IDEState)
-
-#define VMSTATE_IDE_DRIVE(_field, _state) \
- VMSTATE_STRUCT(_field, _state, 1, vmstate_ide_drive, IDEState)
-
-void ide_bus_reset(IDEBus *bus);
-int64_t ide_get_sector(IDEState *s);
-void ide_set_sector(IDEState *s, int64_t sector_num);
-
-void ide_start_dma(IDEState *s, BlockCompletionFunc *cb);
-void dma_buf_commit(IDEState *s, uint32_t tx_bytes);
-void ide_dma_error(IDEState *s);
-void ide_abort_command(IDEState *s);
-
-void ide_atapi_cmd_ok(IDEState *s);
-void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc);
-void ide_atapi_dma_restart(IDEState *s);
-void ide_atapi_io_error(IDEState *s, int ret);
-
-void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val);
-uint32_t ide_ioport_read(void *opaque, uint32_t addr1);
-uint32_t ide_status_read(void *opaque, uint32_t addr);
-void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val);
-void ide_data_writew(void *opaque, uint32_t addr, uint32_t val);
-uint32_t ide_data_readw(void *opaque, uint32_t addr);
-void ide_data_writel(void *opaque, uint32_t addr, uint32_t val);
-uint32_t ide_data_readl(void *opaque, uint32_t addr);
-
-int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind,
- const char *version, const char *serial, const char *model,
- uint64_t wwn,
- uint32_t cylinders, uint32_t heads, uint32_t secs,
- int chs_trans, Error **errp);
-void ide_init2(IDEBus *bus, qemu_irq irq);
-void ide_exit(IDEState *s);
-void ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2);
-void ide_register_restart_cb(IDEBus *bus);
-
-void ide_exec_cmd(IDEBus *bus, uint32_t val);
-
-void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
- EndTransferFunc *end_transfer_func);
-bool ide_transfer_start_norecurse(IDEState *s, uint8_t *buf, int size,
- EndTransferFunc *end_transfer_func);
-void ide_transfer_stop(IDEState *s);
-void ide_set_inactive(IDEState *s, bool more);
-BlockAIOCB *ide_issue_trim(
- int64_t offset, QEMUIOVector *qiov,
- BlockCompletionFunc *cb, void *cb_opaque, void *opaque);
-BlockAIOCB *ide_buffered_readv(IDEState *s, int64_t sector_num,
- QEMUIOVector *iov, int nb_sectors,
- BlockCompletionFunc *cb, void *opaque);
-void ide_cancel_dma_sync(IDEState *s);
-
-/* hw/ide/atapi.c */
-void ide_atapi_cmd(IDEState *s);
-void ide_atapi_cmd_reply_end(IDEState *s);
-
-/* hw/ide/qdev.c */
-void ide_bus_new(IDEBus *idebus, size_t idebus_size, DeviceState *dev,
- int bus_id, int max_units);
-IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive);
-
-int ide_handle_rw_error(IDEState *s, int error, int op);
-
-#endif /* HW_IDE_INTERNAL_H */
diff --git a/include/hw/ide/isa.h b/include/hw/ide/isa.h
new file mode 100644
index 0000000000..1cd0ff1fa6
--- /dev/null
+++ b/include/hw/ide/isa.h
@@ -0,0 +1,20 @@
+/*
+ * QEMU IDE Emulation: ISA Bus support.
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ * Copyright (c) 2006 Openedhand Ltd.
+ *
+ * SPDX-License-Identifier: MIT
+ */
+#ifndef HW_IDE_ISA_H
+#define HW_IDE_ISA_H
+
+#include "qom/object.h"
+
+#define TYPE_ISA_IDE "isa-ide"
+OBJECT_DECLARE_SIMPLE_TYPE(ISAIDEState, ISA_IDE)
+
+ISADevice *isa_ide_init(ISABus *bus, int iobase, int iobase2, int irqnum,
+ DriveInfo *hd0, DriveInfo *hd1);
+
+#endif
diff --git a/include/hw/ide/mmio.h b/include/hw/ide/mmio.h
new file mode 100644
index 0000000000..d726a49848
--- /dev/null
+++ b/include/hw/ide/mmio.h
@@ -0,0 +1,26 @@
+/*
+ * QEMU IDE Emulation: mmio support (for embedded).
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ * Copyright (c) 2006 Openedhand Ltd.
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#ifndef HW_IDE_MMIO_H
+#define HW_IDE_MMIO_H
+
+#include "qom/object.h"
+
+/*
+ * QEMU interface:
+ * + sysbus IRQ 0: asserted by the IDE channel
+ * + sysbus MMIO region 0: data registers
+ * + sysbus MMIO region 1: status & control registers
+ */
+#define TYPE_MMIO_IDE "mmio-ide"
+OBJECT_DECLARE_SIMPLE_TYPE(MMIOIDEState, MMIO_IDE)
+
+void mmio_ide_init_drives(DeviceState *dev, DriveInfo *hd0, DriveInfo *hd1);
+
+#endif
diff --git a/include/hw/ide/pci.h b/include/hw/ide/pci.h
index dd504e5a0b..ef03764caa 100644
--- a/include/hw/ide/pci.h
+++ b/include/hw/ide/pci.h
@@ -1,8 +1,9 @@
#ifndef HW_IDE_PCI_H
#define HW_IDE_PCI_H
-#include "hw/ide/internal.h"
-#include "hw/pci/pci.h"
+#include "hw/ide/ide-bus.h"
+#include "hw/pci/pci_device.h"
+#include "qom/object.h"
#define BM_STATUS_DMAING 0x01
#define BM_STATUS_ERROR 0x02
@@ -39,31 +40,28 @@ typedef struct BMDMAState {
} BMDMAState;
#define TYPE_PCI_IDE "pci-ide"
-#define PCI_IDE(obj) OBJECT_CHECK(PCIIDEState, (obj), TYPE_PCI_IDE)
+OBJECT_DECLARE_SIMPLE_TYPE(PCIIDEState, PCI_IDE)
-typedef struct PCIIDEState {
+struct PCIIDEState {
/*< private >*/
PCIDevice parent_obj;
/*< public >*/
IDEBus bus[2];
BMDMAState bmdma[2];
+ qemu_irq isa_irq[2];
uint32_t secondary; /* used only for cmd646 */
MemoryRegion bmdma_bar;
MemoryRegion cmd_bar[2];
MemoryRegion data_bar[2];
-} PCIIDEState;
-
-static inline IDEState *bmdma_active_if(BMDMAState *bmdma)
-{
- assert(bmdma->bus->retry_unit != (uint8_t)-1);
- return bmdma->bus->ifs + bmdma->bus->retry_unit;
-}
+};
void bmdma_init(IDEBus *bus, BMDMAState *bm, PCIIDEState *d);
void bmdma_cmd_writeb(BMDMAState *bm, uint32_t val);
+void bmdma_status_writeb(BMDMAState *bm, uint32_t val);
extern MemoryRegionOps bmdma_addr_ioport_ops;
void pci_ide_create_devs(PCIDevice *dev);
+void pci_ide_update_mode(PCIIDEState *s);
extern const VMStateDescription vmstate_ide_pci;
extern const MemoryRegionOps pci_ide_cmd_le_ops;
diff --git a/include/hw/ide/piix.h b/include/hw/ide/piix.h
new file mode 100644
index 0000000000..ef3ef3d62d
--- /dev/null
+++ b/include/hw/ide/piix.h
@@ -0,0 +1,7 @@
+#ifndef HW_IDE_PIIX_H
+#define HW_IDE_PIIX_H
+
+#define TYPE_PIIX3_IDE "piix3-ide"
+#define TYPE_PIIX4_IDE "piix4-ide"
+
+#endif /* HW_IDE_PIIX_H */
diff --git a/include/hw/input/adb.h b/include/hw/input/adb.h
index bb75a7b1e3..20fced15f7 100644
--- a/include/hw/input/adb.h
+++ b/include/hw/input/adb.h
@@ -27,12 +27,12 @@
#define ADB_H
#include "hw/qdev-core.h"
+#include "qom/object.h"
#define MAX_ADB_DEVICES 16
#define ADB_MAX_OUT_LEN 16
-typedef struct ADBBusState ADBBusState;
typedef struct ADBDevice ADBDevice;
/* buf = NULL means polling */
@@ -42,7 +42,7 @@ typedef int ADBDeviceRequest(ADBDevice *d, uint8_t *buf_out,
typedef bool ADBDeviceHasData(ADBDevice *d);
#define TYPE_ADB_DEVICE "adb-device"
-#define ADB_DEVICE(obj) OBJECT_CHECK(ADBDevice, (obj), TYPE_ADB_DEVICE)
+OBJECT_DECLARE_TYPE(ADBDevice, ADBDeviceClass, ADB_DEVICE)
struct ADBDevice {
/*< private >*/
@@ -53,22 +53,18 @@ struct ADBDevice {
int handler;
};
-#define ADB_DEVICE_CLASS(cls) \
- OBJECT_CLASS_CHECK(ADBDeviceClass, (cls), TYPE_ADB_DEVICE)
-#define ADB_DEVICE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(ADBDeviceClass, (obj), TYPE_ADB_DEVICE)
-typedef struct ADBDeviceClass {
+struct ADBDeviceClass {
/*< private >*/
DeviceClass parent_class;
/*< public >*/
ADBDeviceRequest *devreq;
ADBDeviceHasData *devhasdata;
-} ADBDeviceClass;
+};
#define TYPE_ADB_BUS "apple-desktop-bus"
-#define ADB_BUS(obj) OBJECT_CHECK(ADBBusState, (obj), TYPE_ADB_BUS)
+OBJECT_DECLARE_SIMPLE_TYPE(ADBBusState, ADB_BUS)
#define ADB_STATUS_BUSTIMEOUT 0x1
#define ADB_STATUS_POLLREPLY 0x2
diff --git a/include/hw/input/gamepad.h b/include/hw/input/gamepad.h
deleted file mode 100644
index 6f6aa2406a..0000000000
--- a/include/hw/input/gamepad.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Gamepad style buttons connected to IRQ/GPIO lines
- *
- * Copyright (c) 2007 CodeSourcery.
- * Written by Paul Brook
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#ifndef HW_INPUT_GAMEPAD_H
-#define HW_INPUT_GAMEPAD_H
-
-
-/* stellaris_input.c */
-void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode);
-
-#endif
diff --git a/include/hw/input/i8042.h b/include/hw/input/i8042.h
index 8eaebf50ce..e90f008b66 100644
--- a/include/hw/input/i8042.h
+++ b/include/hw/input/i8042.h
@@ -9,17 +9,100 @@
#define HW_INPUT_I8042_H
#include "hw/isa/isa.h"
+#include "hw/sysbus.h"
+#include "hw/input/ps2.h"
+#include "qom/object.h"
+
+#define I8042_KBD_IRQ 0
+#define I8042_MOUSE_IRQ 1
+
+typedef struct KBDState {
+ uint8_t write_cmd; /* if non zero, write data to port 60 is expected */
+ uint8_t status;
+ uint8_t mode;
+ uint8_t outport;
+ uint32_t migration_flags;
+ uint32_t obsrc;
+ bool outport_present;
+ bool extended_state;
+ bool extended_state_loaded;
+ /* Bitmask of devices with data available. */
+ uint8_t pending;
+ uint8_t obdata;
+ uint8_t cbdata;
+ uint8_t pending_tmp;
+ PS2KbdState ps2kbd;
+ PS2MouseState ps2mouse;
+ QEMUTimer *throttle_timer;
+
+ qemu_irq irqs[2];
+ qemu_irq a20_out;
+ hwaddr mask;
+} KBDState;
+
+/*
+ * QEMU interface:
+ * + Named GPIO input "ps2-kbd-input-irq": set to 1 if the downstream PS2
+ * keyboard device has asserted its irq
+ * + Named GPIO input "ps2-mouse-input-irq": set to 1 if the downstream PS2
+ * mouse device has asserted its irq
+ * + Named GPIO output "a20": A20 line for x86 PCs
+ * + Unnamed GPIO output 0-1: i8042 output irqs for keyboard (0) or mouse (1)
+ */
#define TYPE_I8042 "i8042"
+OBJECT_DECLARE_SIMPLE_TYPE(ISAKBDState, I8042)
+
+struct ISAKBDState {
+ ISADevice parent_obj;
+
+ KBDState kbd;
+ bool kbd_throttle;
+ MemoryRegion io[2];
+ uint8_t kbd_irq;
+ uint8_t mouse_irq;
+};
+
+/*
+ * QEMU interface:
+ * + sysbus MMIO region 0: MemoryRegion defining the command/status/data
+ * registers (access determined by mask property and access type)
+ * + Named GPIO input "ps2-kbd-input-irq": set to 1 if the downstream PS2
+ * keyboard device has asserted its irq
+ * + Named GPIO input "ps2-mouse-input-irq": set to 1 if the downstream PS2
+ * mouse device has asserted its irq
+ * + Unnamed GPIO output 0-1: i8042 output irqs for keyboard (0) or mouse (1)
+ */
+
+#define TYPE_I8042_MMIO "i8042-mmio"
+OBJECT_DECLARE_SIMPLE_TYPE(MMIOKBDState, I8042_MMIO)
+
+struct MMIOKBDState {
+ SysBusDevice parent_obj;
+
+ KBDState kbd;
+ uint32_t size;
+ MemoryRegion region;
+};
#define I8042_A20_LINE "a20"
-typedef struct ISAKBDState ISAKBDState;
-void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq,
- MemoryRegion *region, ram_addr_t size,
- hwaddr mask);
void i8042_isa_mouse_fake_event(ISAKBDState *isa);
-void i8042_setup_a20_line(ISADevice *dev, qemu_irq a20_out);
+
+static inline bool i8042_present(void)
+{
+ bool amb = false;
+ return object_resolve_path_type("", TYPE_I8042, &amb) || amb;
+}
+
+/*
+ * ACPI v2, Table 5-10 - Fixed ACPI Description Table Boot Architecture
+ * Flags, bit offset 1 - 8042.
+ */
+static inline uint16_t iapc_boot_arch_8042(void)
+{
+ return i8042_present() ? 0x1 << 1 : 0x0 ;
+}
#endif /* HW_INPUT_I8042_H */
diff --git a/include/hw/input/lasips2.h b/include/hw/input/lasips2.h
index 0cd7b59064..01911c50f9 100644
--- a/include/hw/input/lasips2.h
+++ b/include/hw/input/lasips2.h
@@ -4,13 +4,77 @@
* Copyright (c) 2019 Sven Schnelle
*
*/
+
+/*
+ * QEMU interface:
+ * + sysbus MMIO region 0: MemoryRegion defining the LASI PS2 keyboard
+ * registers
+ * + sysbus MMIO region 1: MemoryRegion defining the LASI PS2 mouse
+ * registers
+ * + sysbus IRQ 0: LASI PS2 output irq
+ * + Named GPIO input "lasips2-port-input-irq[0..1]": set to 1 if the downstream
+ * LASIPS2Port has asserted its irq
+ */
+
#ifndef HW_INPUT_LASIPS2_H
#define HW_INPUT_LASIPS2_H
#include "exec/hwaddr.h"
+#include "hw/sysbus.h"
+#include "hw/input/ps2.h"
-#define TYPE_LASIPS2 "lasips2"
+#define TYPE_LASIPS2_PORT "lasips2-port"
+OBJECT_DECLARE_TYPE(LASIPS2Port, LASIPS2PortDeviceClass, LASIPS2_PORT)
+
+struct LASIPS2PortDeviceClass {
+ DeviceClass parent;
+
+ DeviceRealize parent_realize;
+};
+
+typedef struct LASIPS2State LASIPS2State;
+
+struct LASIPS2Port {
+ DeviceState parent_obj;
+
+ LASIPS2State *lasips2;
+ MemoryRegion reg;
+ PS2State *ps2dev;
+ uint8_t id;
+ uint8_t control;
+ uint8_t buf;
+ bool loopback_rbne;
+ qemu_irq irq;
+};
-void lasips2_init(MemoryRegion *address_space, hwaddr base, qemu_irq irq);
+#define TYPE_LASIPS2_KBD_PORT "lasips2-kbd-port"
+OBJECT_DECLARE_SIMPLE_TYPE(LASIPS2KbdPort, LASIPS2_KBD_PORT)
+
+struct LASIPS2KbdPort {
+ LASIPS2Port parent_obj;
+
+ PS2KbdState kbd;
+};
+
+#define TYPE_LASIPS2_MOUSE_PORT "lasips2-mouse-port"
+OBJECT_DECLARE_SIMPLE_TYPE(LASIPS2MousePort, LASIPS2_MOUSE_PORT)
+
+struct LASIPS2MousePort {
+ LASIPS2Port parent_obj;
+
+ PS2MouseState mouse;
+};
+
+struct LASIPS2State {
+ SysBusDevice parent_obj;
+
+ LASIPS2KbdPort kbd_port;
+ LASIPS2MousePort mouse_port;
+ uint8_t int_status;
+ qemu_irq irq;
+};
+
+#define TYPE_LASIPS2 "lasips2"
+OBJECT_DECLARE_SIMPLE_TYPE(LASIPS2State, LASIPS2)
#endif /* HW_INPUT_LASIPS2_H */
diff --git a/include/hw/input/lm832x.h b/include/hw/input/lm832x.h
new file mode 100644
index 0000000000..e0e5d5ef20
--- /dev/null
+++ b/include/hw/input/lm832x.h
@@ -0,0 +1,28 @@
+/*
+ * National Semiconductor LM8322/8323 GPIO keyboard & PWM chips.
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_INPUT_LM832X_H
+#define HW_INPUT_LM832X_H
+
+#define TYPE_LM8323 "lm8323"
+
+void lm832x_key_event(DeviceState *dev, int key, int state);
+
+#endif
diff --git a/include/hw/input/pl050.h b/include/hw/input/pl050.h
new file mode 100644
index 0000000000..4cb8985f31
--- /dev/null
+++ b/include/hw/input/pl050.h
@@ -0,0 +1,58 @@
+/*
+ * Arm PrimeCell PL050 Keyboard / Mouse Interface
+ *
+ * Copyright (c) 2006-2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the GPL.
+ */
+
+#ifndef HW_PL050_H
+#define HW_PL050_H
+
+#include "hw/sysbus.h"
+#include "migration/vmstate.h"
+#include "hw/input/ps2.h"
+#include "hw/irq.h"
+
+struct PL050DeviceClass {
+ SysBusDeviceClass parent_class;
+
+ DeviceRealize parent_realize;
+};
+
+#define TYPE_PL050 "pl050"
+OBJECT_DECLARE_TYPE(PL050State, PL050DeviceClass, PL050)
+
+struct PL050State {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ PS2State *ps2dev;
+ uint32_t cr;
+ uint32_t clk;
+ uint32_t last;
+ int pending;
+ qemu_irq irq;
+ bool is_mouse;
+};
+
+#define TYPE_PL050_KBD_DEVICE "pl050_keyboard"
+OBJECT_DECLARE_SIMPLE_TYPE(PL050KbdState, PL050_KBD_DEVICE)
+
+struct PL050KbdState {
+ PL050State parent_obj;
+
+ PS2KbdState kbd;
+};
+
+#define TYPE_PL050_MOUSE_DEVICE "pl050_mouse"
+OBJECT_DECLARE_SIMPLE_TYPE(PL050MouseState, PL050_MOUSE_DEVICE)
+
+struct PL050MouseState {
+ PL050State parent_obj;
+
+ PS2MouseState mouse;
+};
+
+#endif
diff --git a/include/hw/input/ps2.h b/include/hw/input/ps2.h
index 35d983897a..cd61a634c3 100644
--- a/include/hw/input/ps2.h
+++ b/include/hw/input/ps2.h
@@ -25,28 +25,89 @@
#ifndef HW_PS2_H
#define HW_PS2_H
+#include "hw/sysbus.h"
+
#define PS2_MOUSE_BUTTON_LEFT 0x01
#define PS2_MOUSE_BUTTON_RIGHT 0x02
#define PS2_MOUSE_BUTTON_MIDDLE 0x04
#define PS2_MOUSE_BUTTON_SIDE 0x08
#define PS2_MOUSE_BUTTON_EXTRA 0x10
-typedef struct PS2State PS2State;
+struct PS2DeviceClass {
+ SysBusDeviceClass parent_class;
+
+ ResettablePhases parent_phases;
+};
+
+/*
+ * PS/2 buffer size. Keep 256 bytes for compatibility with
+ * older QEMU versions.
+ */
+#define PS2_BUFFER_SIZE 256
+
+typedef struct {
+ uint8_t data[PS2_BUFFER_SIZE];
+ int rptr, wptr, cwptr, count;
+} PS2Queue;
+
+/* Output IRQ */
+#define PS2_DEVICE_IRQ 0
+
+struct PS2State {
+ SysBusDevice parent_obj;
+
+ PS2Queue queue;
+ int32_t write_cmd;
+ qemu_irq irq;
+};
+
+#define TYPE_PS2_DEVICE "ps2-device"
+OBJECT_DECLARE_TYPE(PS2State, PS2DeviceClass, PS2_DEVICE)
+
+struct PS2KbdState {
+ PS2State parent_obj;
+
+ int scan_enabled;
+ int translate;
+ int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
+ int ledstate;
+ bool need_high_bit;
+ unsigned int modifiers; /* bitmask of MOD_* constants above */
+};
+
+#define TYPE_PS2_KBD_DEVICE "ps2-kbd"
+OBJECT_DECLARE_SIMPLE_TYPE(PS2KbdState, PS2_KBD_DEVICE)
+
+struct PS2MouseState {
+ PS2State parent_obj;
+
+ uint8_t mouse_status;
+ uint8_t mouse_resolution;
+ uint8_t mouse_sample_rate;
+ uint8_t mouse_wrap;
+ uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
+ uint8_t mouse_detect_state;
+ int mouse_dx; /* current values, needed for 'poll' mode */
+ int mouse_dy;
+ int mouse_dz;
+ int mouse_dw;
+ uint8_t mouse_buttons;
+};
+
+#define TYPE_PS2_MOUSE_DEVICE "ps2-mouse"
+OBJECT_DECLARE_SIMPLE_TYPE(PS2MouseState, PS2_MOUSE_DEVICE)
/* ps2.c */
-void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg);
-void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg);
-void ps2_write_mouse(void *, int val);
-void ps2_write_keyboard(void *, int val);
+void ps2_write_mouse(PS2MouseState *s, int val);
+void ps2_write_keyboard(PS2KbdState *s, int val);
uint32_t ps2_read_data(PS2State *s);
void ps2_queue_noirq(PS2State *s, int b);
-void ps2_raise_irq(PS2State *s);
void ps2_queue(PS2State *s, int b);
void ps2_queue_2(PS2State *s, int b1, int b2);
void ps2_queue_3(PS2State *s, int b1, int b2, int b3);
void ps2_queue_4(PS2State *s, int b1, int b2, int b3, int b4);
-void ps2_keyboard_set_translation(void *opaque, int mode);
-void ps2_mouse_fake_event(void *opaque);
+void ps2_keyboard_set_translation(PS2KbdState *s, int mode);
+void ps2_mouse_fake_event(PS2MouseState *s);
int ps2_queue_empty(PS2State *s);
#endif /* HW_PS2_H */
diff --git a/include/hw/input/stellaris_gamepad.h b/include/hw/input/stellaris_gamepad.h
new file mode 100644
index 0000000000..51085e166c
--- /dev/null
+++ b/include/hw/input/stellaris_gamepad.h
@@ -0,0 +1,37 @@
+/*
+ * Gamepad style buttons connected to IRQ/GPIO lines
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef HW_INPUT_STELLARIS_GAMEPAD_H
+#define HW_INPUT_STELLARIS_GAMEPAD_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+/*
+ * QEMU interface:
+ * + QOM array property "keycodes": uint32_t QEMU keycodes to handle
+ * (these are QCodes, ie the Q_KEY_* values)
+ * + unnamed GPIO outputs: one per keycode, in the same order as the
+ * "keycodes" array property entries; asserted when key is down
+ */
+
+#define TYPE_STELLARIS_GAMEPAD "stellaris-gamepad"
+OBJECT_DECLARE_SIMPLE_TYPE(StellarisGamepad, STELLARIS_GAMEPAD)
+
+struct StellarisGamepad {
+ SysBusDevice parent_obj;
+
+ uint32_t num_buttons;
+ qemu_irq *irqs;
+ uint32_t *keycodes;
+ uint8_t *pressed;
+};
+
+#endif
diff --git a/include/hw/input/tsc2xxx.h b/include/hw/input/tsc2xxx.h
index 3cd8f1bf55..00eca17674 100644
--- a/include/hw/input/tsc2xxx.h
+++ b/include/hw/input/tsc2xxx.h
@@ -11,7 +11,13 @@
#ifndef HW_INPUT_TSC2XXX_H
#define HW_INPUT_TSC2XXX_H
-#include "ui/console.h"
+typedef struct MouseTransformInfo {
+ /* Touchscreen resolution */
+ int x;
+ int y;
+ /* Calibration values as used/generated by tslib */
+ int a[7];
+} MouseTransformInfo;
typedef struct uWireSlave {
uint16_t (*receive)(void *opaque);
@@ -24,12 +30,12 @@ uWireSlave *tsc2102_init(qemu_irq pint);
uWireSlave *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, qemu_irq dav);
I2SCodec *tsc210x_codec(uWireSlave *chip);
uint32_t tsc210x_txrx(void *opaque, uint32_t value, int len);
-void tsc210x_set_transform(uWireSlave *chip, MouseTransformInfo *info);
+void tsc210x_set_transform(uWireSlave *chip, const MouseTransformInfo *info);
void tsc210x_key_event(uWireSlave *chip, int key, int down);
/* tsc2005.c */
void *tsc2005_init(qemu_irq pintdav);
uint32_t tsc2005_txrx(void *opaque, uint32_t value, int len);
-void tsc2005_set_transform(void *opaque, MouseTransformInfo *info);
+void tsc2005_set_transform(void *opaque, const MouseTransformInfo *info);
#endif
diff --git a/include/hw/intc/allwinner-a10-pic.h b/include/hw/intc/allwinner-a10-pic.h
index a5895401d1..b8364d3ed4 100644
--- a/include/hw/intc/allwinner-a10-pic.h
+++ b/include/hw/intc/allwinner-a10-pic.h
@@ -2,9 +2,10 @@
#define ALLWINNER_A10_PIC_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_AW_A10_PIC "allwinner-a10-pic"
-#define AW_A10_PIC(obj) OBJECT_CHECK(AwA10PICState, (obj), TYPE_AW_A10_PIC)
+OBJECT_DECLARE_SIMPLE_TYPE(AwA10PICState, AW_A10_PIC)
#define AW_A10_PIC_VECTOR 0
#define AW_A10_PIC_BASE_ADDR 4
@@ -19,7 +20,7 @@
#define AW_A10_PIC_INT_NR 95
#define AW_A10_PIC_REG_NUM DIV_ROUND_UP(AW_A10_PIC_INT_NR, 32)
-typedef struct AwA10PICState {
+struct AwA10PICState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -37,6 +38,6 @@ typedef struct AwA10PICState {
uint32_t enable[AW_A10_PIC_REG_NUM];
uint32_t mask[AW_A10_PIC_REG_NUM];
/*priority setting here*/
-} AwA10PICState;
+};
#endif
diff --git a/include/hw/intc/arm_gic.h b/include/hw/intc/arm_gic.h
index 303b9748cb..48f6a51a70 100644
--- a/include/hw/intc/arm_gic.h
+++ b/include/hw/intc/arm_gic.h
@@ -65,6 +65,7 @@
#define HW_ARM_GIC_H
#include "arm_gic_common.h"
+#include "qom/object.h"
/* Number of SGI target-list bits */
#define GIC_TARGETLIST_BITS 8
@@ -72,19 +73,19 @@
#define GIC_MIN_PRIORITY_BITS 4
#define TYPE_ARM_GIC "arm_gic"
-#define ARM_GIC(obj) \
- OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC)
-#define ARM_GIC_CLASS(klass) \
- OBJECT_CLASS_CHECK(ARMGICClass, (klass), TYPE_ARM_GIC)
-#define ARM_GIC_GET_CLASS(obj) \
- OBJECT_GET_CLASS(ARMGICClass, (obj), TYPE_ARM_GIC)
+typedef struct ARMGICClass ARMGICClass;
+/* This is reusing the GICState typedef from TYPE_ARM_GIC_COMMON */
+DECLARE_OBJ_CHECKERS(GICState, ARMGICClass,
+ ARM_GIC, TYPE_ARM_GIC)
-typedef struct ARMGICClass {
+struct ARMGICClass {
/*< private >*/
ARMGICCommonClass parent_class;
/*< public >*/
DeviceRealize parent_realize;
-} ARMGICClass;
+};
+
+const char *gic_class_name(void);
#endif
diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h
index 6e0d6b8a88..7080375008 100644
--- a/include/hw/intc/arm_gic_common.h
+++ b/include/hw/intc/arm_gic_common.h
@@ -22,6 +22,7 @@
#define HW_ARM_GIC_COMMON_H
#include "hw/sysbus.h"
+#include "qom/object.h"
/* Maximum number of possible interrupts, determined by the GIC architecture */
#define GIC_MAXIRQ 1020
@@ -61,7 +62,7 @@ typedef struct gic_irq_state {
uint8_t group;
} gic_irq_state;
-typedef struct GICState {
+struct GICState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -143,24 +144,22 @@ typedef struct GICState {
bool irq_reset_nonsecure; /* configure IRQs as group 1 (NS) on reset? */
int dev_fd; /* kvm device fd if backed by kvm vgic support */
Error *migration_blocker;
-} GICState;
+};
+typedef struct GICState GICState;
#define TYPE_ARM_GIC_COMMON "arm_gic_common"
-#define ARM_GIC_COMMON(obj) \
- OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC_COMMON)
-#define ARM_GIC_COMMON_CLASS(klass) \
- OBJECT_CLASS_CHECK(ARMGICCommonClass, (klass), TYPE_ARM_GIC_COMMON)
-#define ARM_GIC_COMMON_GET_CLASS(obj) \
- OBJECT_GET_CLASS(ARMGICCommonClass, (obj), TYPE_ARM_GIC_COMMON)
-
-typedef struct ARMGICCommonClass {
+typedef struct ARMGICCommonClass ARMGICCommonClass;
+DECLARE_OBJ_CHECKERS(GICState, ARMGICCommonClass,
+ ARM_GIC_COMMON, TYPE_ARM_GIC_COMMON)
+
+struct ARMGICCommonClass {
/*< private >*/
SysBusDeviceClass parent_class;
/*< public >*/
void (*pre_save)(GICState *s);
void (*post_load)(GICState *s);
-} ARMGICCommonClass;
+};
void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
const MemoryRegionOps *ops,
diff --git a/include/hw/intc/arm_gicv3.h b/include/hw/intc/arm_gicv3.h
index 4a6fd85e22..a81a6ae7ec 100644
--- a/include/hw/intc/arm_gicv3.h
+++ b/include/hw/intc/arm_gicv3.h
@@ -13,20 +13,20 @@
#define HW_ARM_GICV3_H
#include "arm_gicv3_common.h"
+#include "qom/object.h"
#define TYPE_ARM_GICV3 "arm-gicv3"
-#define ARM_GICV3(obj) OBJECT_CHECK(GICv3State, (obj), TYPE_ARM_GICV3)
-#define ARM_GICV3_CLASS(klass) \
- OBJECT_CLASS_CHECK(ARMGICv3Class, (klass), TYPE_ARM_GICV3)
-#define ARM_GICV3_GET_CLASS(obj) \
- OBJECT_GET_CLASS(ARMGICv3Class, (obj), TYPE_ARM_GICV3)
+typedef struct ARMGICv3Class ARMGICv3Class;
+/* This is reusing the GICState typedef from TYPE_ARM_GICV3_COMMON */
+DECLARE_OBJ_CHECKERS(GICv3State, ARMGICv3Class,
+ ARM_GICV3, TYPE_ARM_GICV3)
-typedef struct ARMGICv3Class {
+struct ARMGICv3Class {
/*< private >*/
ARMGICv3CommonClass parent_class;
/*< public >*/
DeviceRealize parent_realize;
-} ARMGICv3Class;
+};
#endif
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
index 31ec9a1ae4..4e2fb518e7 100644
--- a/include/hw/intc/arm_gicv3_common.h
+++ b/include/hw/intc/arm_gicv3_common.h
@@ -26,6 +26,7 @@
#include "hw/sysbus.h"
#include "hw/intc/arm_gic_common.h"
+#include "qom/object.h"
/*
* Maximum number of possible interrupts, determined by the GIC architecture.
@@ -35,7 +36,14 @@
#define GICV3_MAXIRQ 1020
#define GICV3_MAXSPI (GICV3_MAXIRQ - GIC_INTERNAL)
+#define GICV3_LPI_INTID_START 8192
+
+/*
+ * The redistributor in GICv3 has two 64KB frames per CPU; in
+ * GICv4 it has four 64KB frames per CPU.
+ */
#define GICV3_REDIST_SIZE 0x20000
+#define GICV4_REDIST_SIZE 0x40000
/* Number of SGI target-list bits */
#define GICV3_TARGETLIST_BITS 16
@@ -43,11 +51,6 @@
/* Maximum number of list registers (architectural limit) */
#define GICV3_LR_MAX 16
-/* Minimum BPR for Secure, or when security not enabled */
-#define GIC_MIN_BPR 0
-/* Minimum BPR for Nonsecure when security is enabled */
-#define GIC_MIN_BPR_NS (GIC_MIN_BPR + 1)
-
/* For some distributor fields we want to model the array of 32-bit
* register values which hold various bitmaps corresponding to enabled,
* pending, etc bits. These macros and functions facilitate that; the
@@ -152,7 +155,6 @@ struct GICv3CPUState {
qemu_irq parent_fiq;
qemu_irq parent_virq;
qemu_irq parent_vfiq;
- qemu_irq maintenance_irq;
/* Redistributor */
uint32_t level; /* Current IRQ level */
@@ -172,6 +174,9 @@ struct GICv3CPUState {
uint32_t gicr_igrpmodr0;
uint32_t gicr_nsacr;
uint8_t gicr_ipriorityr[GIC_INTERNAL];
+ /* VLPI_base page registers */
+ uint64_t gicr_vpropbaser;
+ uint64_t gicr_vpendbaser;
/* CPU interface */
uint64_t icc_sre_el1;
@@ -196,36 +201,63 @@ struct GICv3CPUState {
int num_list_regs;
int vpribits; /* number of virtual priority bits */
int vprebits; /* number of virtual preemption bits */
+ int pribits; /* number of physical priority bits */
+ int prebits; /* number of physical preemption bits */
/* Current highest priority pending interrupt for this CPU.
* This is cached information that can be recalculated from the
* real state above; it doesn't need to be migrated.
*/
PendingIrq hppi;
+
+ /*
+ * Cached information recalculated from LPI tables
+ * in guest memory
+ */
+ PendingIrq hpplpi;
+
+ /* Cached information recalculated from vLPI tables in guest memory */
+ PendingIrq hppvlpi;
+
/* This is temporary working state, to avoid a malloc in gicv3_update() */
bool seenbetter;
};
+/*
+ * The redistributor pages might be split into more than one region
+ * on some machine types if there are many CPUs.
+ */
+typedef struct GICv3RedistRegion {
+ GICv3State *gic;
+ MemoryRegion iomem;
+ uint32_t cpuidx; /* index of first CPU this region covers */
+} GICv3RedistRegion;
+
struct GICv3State {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
MemoryRegion iomem_dist; /* Distributor */
- MemoryRegion *iomem_redist; /* Redistributor Regions */
+ GICv3RedistRegion *redist_regions; /* Redistributor Regions */
uint32_t *redist_region_count; /* redistributor count within each region */
uint32_t nb_redist_regions; /* number of redist regions */
uint32_t num_cpu;
uint32_t num_irq;
uint32_t revision;
+ bool lpi_enable;
bool security_extn;
+ bool force_8bit_prio;
bool irq_reset_nonsecure;
bool gicd_no_migration_shift_bug;
int dev_fd; /* kvm device fd if backed by kvm vgic support */
Error *migration_blocker;
+ MemoryRegion *dma;
+ AddressSpace dma_as;
+
/* Distributor */
/* for a GIC with the security extensions the NS banked version of this
@@ -249,6 +281,8 @@ struct GICv3State {
uint32_t gicd_nsacr[DIV_ROUND_UP(GICV3_MAXIRQ, 16)];
GICv3CPUState *cpu;
+ /* List of all ITSes connected to this GIC */
+ GPtrArray *itslist;
};
#define GICV3_BITMAP_ACCESSORS(BMP) \
@@ -279,23 +313,30 @@ GICV3_BITMAP_ACCESSORS(level)
GICV3_BITMAP_ACCESSORS(edge_trigger)
#define TYPE_ARM_GICV3_COMMON "arm-gicv3-common"
-#define ARM_GICV3_COMMON(obj) \
- OBJECT_CHECK(GICv3State, (obj), TYPE_ARM_GICV3_COMMON)
-#define ARM_GICV3_COMMON_CLASS(klass) \
- OBJECT_CLASS_CHECK(ARMGICv3CommonClass, (klass), TYPE_ARM_GICV3_COMMON)
-#define ARM_GICV3_COMMON_GET_CLASS(obj) \
- OBJECT_GET_CLASS(ARMGICv3CommonClass, (obj), TYPE_ARM_GICV3_COMMON)
-
-typedef struct ARMGICv3CommonClass {
+typedef struct ARMGICv3CommonClass ARMGICv3CommonClass;
+DECLARE_OBJ_CHECKERS(GICv3State, ARMGICv3CommonClass,
+ ARM_GICV3_COMMON, TYPE_ARM_GICV3_COMMON)
+
+struct ARMGICv3CommonClass {
/*< private >*/
SysBusDeviceClass parent_class;
/*< public >*/
void (*pre_save)(GICv3State *s);
void (*post_load)(GICv3State *s);
-} ARMGICv3CommonClass;
+};
void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
- const MemoryRegionOps *ops, Error **errp);
+ const MemoryRegionOps *ops);
+
+/**
+ * gicv3_class_name
+ *
+ * Return name of GICv3 class to use depending on whether KVM acceleration is
+ * in use. May throw an error if the chosen implementation is not available.
+ *
+ * Returns: class name to use
+ */
+const char *gicv3_class_name(void);
#endif
diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h
index fd1fe64c03..7dc712b38d 100644
--- a/include/hw/intc/arm_gicv3_its_common.h
+++ b/include/hw/intc/arm_gicv3_its_common.h
@@ -23,6 +23,9 @@
#include "hw/sysbus.h"
#include "hw/intc/arm_gicv3_common.h"
+#include "qom/object.h"
+
+#define TYPE_ARM_GICV3_ITS "arm-gicv3-its"
#define ITS_CONTROL_SIZE 0x10000
#define ITS_TRANS_SIZE 0x10000
@@ -30,11 +33,27 @@
#define GITS_CTLR 0x0
#define GITS_IIDR 0x4
+#define GITS_TYPER 0x8
#define GITS_CBASER 0x80
#define GITS_CWRITER 0x88
#define GITS_CREADR 0x90
#define GITS_BASER 0x100
+#define GITS_TRANSLATER 0x0040
+
+typedef struct {
+ bool indirect;
+ uint16_t entry_sz;
+ uint32_t page_sz;
+ uint32_t num_entries;
+ uint64_t base_addr;
+} TableDesc;
+
+typedef struct {
+ uint32_t num_entries;
+ uint64_t base_addr;
+} CmdQDesc;
+
struct GICv3ITSState {
SysBusDevice parent_obj;
@@ -51,25 +70,47 @@ struct GICv3ITSState {
/* Registers */
uint32_t ctlr;
uint32_t iidr;
+ uint64_t typer;
uint64_t cbaser;
uint64_t cwriter;
uint64_t creadr;
uint64_t baser[8];
+ TableDesc dt;
+ TableDesc ct;
+ TableDesc vpet;
+ CmdQDesc cq;
+
Error *migration_blocker;
};
typedef struct GICv3ITSState GICv3ITSState;
-void gicv3_its_init_mmio(GICv3ITSState *s, const MemoryRegionOps *ops);
+void gicv3_its_init_mmio(GICv3ITSState *s, const MemoryRegionOps *ops,
+ const MemoryRegionOps *tops);
+
+/*
+ * The ITS should call this when it is realized to add itself
+ * to its GIC's list of connected ITSes.
+ */
+static inline void gicv3_add_its(GICv3State *s, DeviceState *its)
+{
+ g_ptr_array_add(s->itslist, its);
+}
+
+/*
+ * The ITS can use this for operations that must be performed on
+ * every ITS connected to the same GIC that it is
+ */
+static inline void gicv3_foreach_its(GICv3State *s, GFunc func, void *opaque)
+{
+ g_ptr_array_foreach(s->itslist, func, opaque);
+}
#define TYPE_ARM_GICV3_ITS_COMMON "arm-gicv3-its-common"
-#define ARM_GICV3_ITS_COMMON(obj) \
- OBJECT_CHECK(GICv3ITSState, (obj), TYPE_ARM_GICV3_ITS_COMMON)
-#define ARM_GICV3_ITS_COMMON_CLASS(klass) \
- OBJECT_CLASS_CHECK(GICv3ITSCommonClass, (klass), TYPE_ARM_GICV3_ITS_COMMON)
-#define ARM_GICV3_ITS_COMMON_GET_CLASS(obj) \
- OBJECT_GET_CLASS(GICv3ITSCommonClass, (obj), TYPE_ARM_GICV3_ITS_COMMON)
+typedef struct GICv3ITSCommonClass GICv3ITSCommonClass;
+DECLARE_OBJ_CHECKERS(GICv3ITSState, GICv3ITSCommonClass,
+ ARM_GICV3_ITS_COMMON, TYPE_ARM_GICV3_ITS_COMMON)
struct GICv3ITSCommonClass {
/*< private >*/
@@ -81,6 +122,14 @@ struct GICv3ITSCommonClass {
void (*post_load)(GICv3ITSState *s);
};
-typedef struct GICv3ITSCommonClass GICv3ITSCommonClass;
+/**
+ * its_class_name:
+ *
+ * Return the ITS class name to use depending on whether KVM acceleration
+ * and KVM CAP_SIGNAL_MSI are supported
+ *
+ * Returns: class name to use or NULL
+ */
+const char *its_class_name(void);
#endif
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
index a472c9b8f0..89fe8aedaa 100644
--- a/include/hw/intc/armv7m_nvic.h
+++ b/include/hw/intc/armv7m_nvic.h
@@ -10,14 +10,13 @@
#ifndef HW_ARM_ARMV7M_NVIC_H
#define HW_ARM_ARMV7M_NVIC_H
-#include "target/arm/cpu.h"
+#include "target/arm/cpu-qom.h"
#include "hw/sysbus.h"
#include "hw/timer/armv7m_systick.h"
+#include "qom/object.h"
#define TYPE_NVIC "armv7m_nvic"
-
-#define NVIC(obj) \
- OBJECT_CHECK(NVICState, (obj), TYPE_NVIC)
+OBJECT_DECLARE_SIMPLE_TYPE(NVICState, NVIC)
/* Highest permitted number of exceptions (architectural limit) */
#define NVIC_MAX_VECTORS 512
@@ -35,7 +34,7 @@ typedef struct VecInfo {
uint8_t level; /* exceptions <=15 never set level */
} VecInfo;
-typedef struct NVICState {
+struct NVICState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -75,19 +74,136 @@ typedef struct NVICState {
*/
bool vectpending_is_s_banked;
int exception_prio; /* group prio of the highest prio active exception */
- int vectpending_prio; /* group prio of the exeception in vectpending */
+ int vectpending_prio; /* group prio of the exception in vectpending */
MemoryRegion sysregmem;
- MemoryRegion sysreg_ns_mem;
- MemoryRegion systickmem;
- MemoryRegion systick_ns_mem;
- MemoryRegion container;
uint32_t num_irq;
qemu_irq excpout;
qemu_irq sysresetreq;
+};
- SysTickState systick[M_REG_NUM_BANKS];
-} NVICState;
+/* Interface between CPU and Interrupt controller. */
+/**
+ * armv7m_nvic_set_pending: mark the specified exception as pending
+ * @s: the NVIC
+ * @irq: the exception number to mark pending
+ * @secure: false for non-banked exceptions or for the nonsecure
+ * version of a banked exception, true for the secure version of a banked
+ * exception.
+ *
+ * Marks the specified exception as pending. Note that we will assert()
+ * if @secure is true and @irq does not specify one of the fixed set
+ * of architecturally banked exceptions.
+ */
+void armv7m_nvic_set_pending(NVICState *s, int irq, bool secure);
+/**
+ * armv7m_nvic_set_pending_derived: mark this derived exception as pending
+ * @s: the NVIC
+ * @irq: the exception number to mark pending
+ * @secure: false for non-banked exceptions or for the nonsecure
+ * version of a banked exception, true for the secure version of a banked
+ * exception.
+ *
+ * Similar to armv7m_nvic_set_pending(), but specifically for derived
+ * exceptions (exceptions generated in the course of trying to take
+ * a different exception).
+ */
+void armv7m_nvic_set_pending_derived(NVICState *s, int irq, bool secure);
+/**
+ * armv7m_nvic_set_pending_lazyfp: mark this lazy FP exception as pending
+ * @s: the NVIC
+ * @irq: the exception number to mark pending
+ * @secure: false for non-banked exceptions or for the nonsecure
+ * version of a banked exception, true for the secure version of a banked
+ * exception.
+ *
+ * Similar to armv7m_nvic_set_pending(), but specifically for exceptions
+ * generated in the course of lazy stacking of FP registers.
+ */
+void armv7m_nvic_set_pending_lazyfp(NVICState *s, int irq, bool secure);
+/**
+ * armv7m_nvic_get_pending_irq_info: return highest priority pending
+ * exception, and whether it targets Secure state
+ * @s: the NVIC
+ * @pirq: set to pending exception number
+ * @ptargets_secure: set to whether pending exception targets Secure
+ *
+ * This function writes the number of the highest priority pending
+ * exception (the one which would be made active by
+ * armv7m_nvic_acknowledge_irq()) to @pirq, and sets @ptargets_secure
+ * to true if the current highest priority pending exception should
+ * be taken to Secure state, false for NS.
+ */
+void armv7m_nvic_get_pending_irq_info(NVICState *s, int *pirq,
+ bool *ptargets_secure);
+/**
+ * armv7m_nvic_acknowledge_irq: make highest priority pending exception active
+ * @s: the NVIC
+ *
+ * Move the current highest priority pending exception from the pending
+ * state to the active state, and update v7m.exception to indicate that
+ * it is the exception currently being handled.
+ */
+void armv7m_nvic_acknowledge_irq(NVICState *s);
+/**
+ * armv7m_nvic_complete_irq: complete specified interrupt or exception
+ * @s: the NVIC
+ * @irq: the exception number to complete
+ * @secure: true if this exception was secure
+ *
+ * Returns: -1 if the irq was not active
+ * 1 if completing this irq brought us back to base (no active irqs)
+ * 0 if there is still an irq active after this one was completed
+ * (Ignoring -1, this is the same as the RETTOBASE value before completion.)
+ */
+int armv7m_nvic_complete_irq(NVICState *s, int irq, bool secure);
+/**
+ * armv7m_nvic_get_ready_status(void *opaque, int irq, bool secure)
+ * @s: the NVIC
+ * @irq: the exception number to mark pending
+ * @secure: false for non-banked exceptions or for the nonsecure
+ * version of a banked exception, true for the secure version of a banked
+ * exception.
+ *
+ * Return whether an exception is "ready", i.e. whether the exception is
+ * enabled and is configured at a priority which would allow it to
+ * interrupt the current execution priority. This controls whether the
+ * RDY bit for it in the FPCCR is set.
+ */
+bool armv7m_nvic_get_ready_status(NVICState *s, int irq, bool secure);
+/**
+ * armv7m_nvic_raw_execution_priority: return the raw execution priority
+ * @s: the NVIC
+ *
+ * Returns: the raw execution priority as defined by the v8M architecture.
+ * This is the execution priority minus the effects of AIRCR.PRIS,
+ * and minus any PRIMASK/FAULTMASK/BASEPRI priority boosting.
+ * (v8M ARM ARM I_PKLD.)
+ */
+int armv7m_nvic_raw_execution_priority(NVICState *s);
+/**
+ * armv7m_nvic_neg_prio_requested: return true if the requested execution
+ * priority is negative for the specified security state.
+ * @s: the NVIC
+ * @secure: the security state to test
+ * This corresponds to the pseudocode IsReqExecPriNeg().
+ */
+#ifndef CONFIG_USER_ONLY
+bool armv7m_nvic_neg_prio_requested(NVICState *s, bool secure);
+#else
+static inline bool armv7m_nvic_neg_prio_requested(NVICState *s, bool secure)
+{
+ return false;
+}
+#endif
+#ifndef CONFIG_USER_ONLY
+bool armv7m_nvic_can_take_pending_exception(NVICState *s);
+#else
+static inline bool armv7m_nvic_can_take_pending_exception(NVICState *s)
+{
+ return true;
+}
+#endif
#endif
diff --git a/include/hw/intc/aspeed_vic.h b/include/hw/intc/aspeed_vic.h
index 107ff17c3b..68d6ab997a 100644
--- a/include/hw/intc/aspeed_vic.h
+++ b/include/hw/intc/aspeed_vic.h
@@ -14,13 +14,14 @@
#define ASPEED_VIC_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_ASPEED_VIC "aspeed.vic"
-#define ASPEED_VIC(obj) OBJECT_CHECK(AspeedVICState, (obj), TYPE_ASPEED_VIC)
+OBJECT_DECLARE_SIMPLE_TYPE(AspeedVICState, ASPEED_VIC)
#define ASPEED_VIC_NR_IRQS 51
-typedef struct AspeedVICState {
+struct AspeedVICState {
/*< private >*/
SysBusDevice parent_obj;
@@ -43,6 +44,6 @@ typedef struct AspeedVICState {
/* 0=low-sensitive/falling-edge, 1=high-sensitive/rising-edge */
uint64_t event;
-} AspeedVICState;
+};
#endif /* ASPEED_VIC_H */
diff --git a/include/hw/intc/bcm2835_ic.h b/include/hw/intc/bcm2835_ic.h
index 392ded1cb3..588eb76c5c 100644
--- a/include/hw/intc/bcm2835_ic.h
+++ b/include/hw/intc/bcm2835_ic.h
@@ -9,14 +9,15 @@
#define BCM2835_IC_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_BCM2835_IC "bcm2835-ic"
-#define BCM2835_IC(obj) OBJECT_CHECK(BCM2835ICState, (obj), TYPE_BCM2835_IC)
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835ICState, BCM2835_IC)
#define BCM2835_IC_GPU_IRQ "gpu-irq"
#define BCM2835_IC_ARM_IRQ "arm-irq"
-typedef struct BCM2835ICState {
+struct BCM2835ICState {
/*< private >*/
SysBusDevice busdev;
/*< public >*/
@@ -30,6 +31,6 @@ typedef struct BCM2835ICState {
uint8_t arm_irq_level, arm_irq_enable;
bool fiq_enable;
uint8_t fiq_select;
-} BCM2835ICState;
+};
#endif
diff --git a/include/hw/intc/bcm2836_control.h b/include/hw/intc/bcm2836_control.h
index 2c22405686..a410c817e8 100644
--- a/include/hw/intc/bcm2836_control.h
+++ b/include/hw/intc/bcm2836_control.h
@@ -17,16 +17,16 @@
#include "hw/sysbus.h"
#include "qemu/timer.h"
+#include "qom/object.h"
/* 4 mailboxes per core, for 16 total */
#define BCM2836_NCORES 4
#define BCM2836_MBPERCORE 4
#define TYPE_BCM2836_CONTROL "bcm2836-control"
-#define BCM2836_CONTROL(obj) \
- OBJECT_CHECK(BCM2836ControlState, (obj), TYPE_BCM2836_CONTROL)
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2836ControlState, BCM2836_CONTROL)
-typedef struct BCM2836ControlState {
+struct BCM2836ControlState {
/*< private >*/
SysBusDevice busdev;
/*< public >*/
@@ -56,6 +56,6 @@ typedef struct BCM2836ControlState {
/* outputs to CPU cores */
qemu_irq irq[BCM2836_NCORES];
qemu_irq fiq[BCM2836_NCORES];
-} BCM2836ControlState;
+};
#endif
diff --git a/include/hw/intc/exynos4210_combiner.h b/include/hw/intc/exynos4210_combiner.h
new file mode 100644
index 0000000000..bd207a7e6e
--- /dev/null
+++ b/include/hw/intc/exynos4210_combiner.h
@@ -0,0 +1,57 @@
+/*
+ * Samsung exynos4210 Interrupt Combiner
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
+ * All rights reserved.
+ *
+ * Evgeny Voevodin <e.voevodin@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_INTC_EXYNOS4210_COMBINER_H
+#define HW_INTC_EXYNOS4210_COMBINER_H
+
+#include "hw/sysbus.h"
+
+/*
+ * State for each output signal of internal combiner
+ */
+typedef struct CombinerGroupState {
+ uint8_t src_mask; /* 1 - source enabled, 0 - disabled */
+ uint8_t src_pending; /* Pending source interrupts before masking */
+} CombinerGroupState;
+
+#define TYPE_EXYNOS4210_COMBINER "exynos4210.combiner"
+OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210CombinerState, EXYNOS4210_COMBINER)
+
+/* Number of groups and total number of interrupts for the internal combiner */
+#define IIC_NGRP 64
+#define IIC_NIRQ (IIC_NGRP * 8)
+#define IIC_REGSET_SIZE 0x41
+
+struct Exynos4210CombinerState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+
+ struct CombinerGroupState group[IIC_NGRP];
+ uint32_t reg_set[IIC_REGSET_SIZE];
+ uint32_t icipsr[2];
+ uint32_t external; /* 1 means that this combiner is external */
+
+ qemu_irq output_irq[IIC_NGRP];
+};
+
+#endif
diff --git a/include/hw/intc/exynos4210_gic.h b/include/hw/intc/exynos4210_gic.h
new file mode 100644
index 0000000000..f64c4069c6
--- /dev/null
+++ b/include/hw/intc/exynos4210_gic.h
@@ -0,0 +1,43 @@
+/*
+ * Samsung exynos4210 GIC implementation. Based on hw/arm_gic.c
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
+ * All rights reserved.
+ *
+ * Evgeny Voevodin <e.voevodin@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef HW_INTC_EXYNOS4210_GIC_H
+#define HW_INTC_EXYNOS4210_GIC_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_EXYNOS4210_GIC "exynos4210.gic"
+OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210GicState, EXYNOS4210_GIC)
+
+#define EXYNOS4210_GIC_NCPUS 2
+
+struct Exynos4210GicState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion cpu_container;
+ MemoryRegion dist_container;
+ MemoryRegion cpu_alias[EXYNOS4210_GIC_NCPUS];
+ MemoryRegion dist_alias[EXYNOS4210_GIC_NCPUS];
+ uint32_t num_cpu;
+ DeviceState *gic;
+};
+
+#endif
diff --git a/include/hw/intc/goldfish_pic.h b/include/hw/intc/goldfish_pic.h
new file mode 100644
index 0000000000..3e79580367
--- /dev/null
+++ b/include/hw/intc/goldfish_pic.h
@@ -0,0 +1,35 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Goldfish PIC
+ *
+ * (c) 2020 Laurent Vivier <laurent@vivier.eu>
+ *
+ */
+
+#ifndef HW_INTC_GOLDFISH_PIC_H
+#define HW_INTC_GOLDFISH_PIC_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_GOLDFISH_PIC "goldfish_pic"
+OBJECT_DECLARE_SIMPLE_TYPE(GoldfishPICState, GOLDFISH_PIC)
+
+#define GOLDFISH_PIC_IRQ_NB 32
+
+struct GoldfishPICState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ qemu_irq irq;
+
+ uint32_t pending;
+ uint32_t enabled;
+
+ /* statistics */
+ uint64_t stats_irq_count[32];
+ /* for tracing */
+ uint8_t idx;
+};
+
+#endif
diff --git a/include/hw/sparc/grlib.h b/include/hw/intc/grlib_irqmp.h
index 78b6178fcd..a76acbf940 100644
--- a/include/hw/sparc/grlib.h
+++ b/include/hw/intc/grlib_irqmp.h
@@ -1,7 +1,9 @@
/*
* QEMU GRLIB Components
*
- * Copyright (c) 2010-2019 AdaCore
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright (c) 2010-2024 AdaCore
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,8 +24,8 @@
* THE SOFTWARE.
*/
-#ifndef GRLIB_H
-#define GRLIB_H
+#ifndef GRLIB_IRQMP_H
+#define GRLIB_IRQMP_H
#include "hw/sysbus.h"
@@ -32,18 +34,8 @@
*/
/* IRQMP */
-#define TYPE_GRLIB_IRQMP "grlib,irqmp"
-
-typedef void (*set_pil_in_fn) (void *opaque, uint32_t pil_in);
-
-void grlib_irqmp_set_irq(void *opaque, int irq, int level);
-
-void grlib_irqmp_ack(DeviceState *dev, int intno);
-
-/* GPTimer */
-#define TYPE_GRLIB_GPTIMER "grlib,gptimer"
+#define TYPE_GRLIB_IRQMP "grlib-irqmp"
-/* APB UART */
-#define TYPE_GRLIB_APB_UART "grlib,apbuart"
+void grlib_irqmp_ack(DeviceState *dev, unsigned int cpu, int intno);
-#endif /* GRLIB_H */
+#endif /* GRLIB_IRQMP_H */
diff --git a/include/hw/intc/heathrow_pic.h b/include/hw/intc/heathrow_pic.h
index b163e27ab9..c0a7f6f546 100644
--- a/include/hw/intc/heathrow_pic.h
+++ b/include/hw/intc/heathrow_pic.h
@@ -27,9 +27,10 @@
#define HW_INTC_HEATHROW_PIC_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_HEATHROW "heathrow"
-#define HEATHROW(obj) OBJECT_CHECK(HeathrowState, (obj), TYPE_HEATHROW)
+OBJECT_DECLARE_SIMPLE_TYPE(HeathrowState, HEATHROW)
typedef struct HeathrowPICState {
uint32_t events;
@@ -38,13 +39,13 @@ typedef struct HeathrowPICState {
uint32_t level_triggered;
} HeathrowPICState;
-typedef struct HeathrowState {
+struct HeathrowState {
SysBusDevice parent_obj;
MemoryRegion mem;
HeathrowPICState pics[2];
qemu_irq irqs[1];
-} HeathrowState;
+};
#define HEATHROW_NUM_IRQS 64
diff --git a/include/hw/intc/i8259.h b/include/hw/intc/i8259.h
index e2b1e8c59a..c412575775 100644
--- a/include/hw/intc/i8259.h
+++ b/include/hw/intc/i8259.h
@@ -3,10 +3,18 @@
/* i8259.c */
-extern DeviceState *isa_pic;
-qemu_irq *i8259_init(ISABus *bus, qemu_irq parent_irq);
+extern PICCommonState *isa_pic;
+
+/*
+ * i8259_init()
+ *
+ * Create a i8259 device on an ISA @bus,
+ * connect its output to @parent_irq_in,
+ * return an (allocated) array of 16 input IRQs.
+ */
+qemu_irq *i8259_init(ISABus *bus, qemu_irq parent_irq_in);
qemu_irq *kvm_i8259_init(ISABus *bus);
-int pic_get_output(DeviceState *d);
-int pic_read_irq(DeviceState *d);
+int pic_get_output(PICCommonState *s);
+int pic_read_irq(PICCommonState *s);
#endif
diff --git a/include/hw/intc/ibex_plic.h b/include/hw/intc/ibex_plic.h
deleted file mode 100644
index ddc7909903..0000000000
--- a/include/hw/intc/ibex_plic.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * QEMU RISC-V lowRISC Ibex PLIC
- *
- * Copyright (c) 2020 Western Digital
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2 or later, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef HW_IBEX_PLIC_H
-#define HW_IBEX_PLIC_H
-
-#include "hw/sysbus.h"
-
-#define TYPE_IBEX_PLIC "ibex-plic"
-#define IBEX_PLIC(obj) \
- OBJECT_CHECK(IbexPlicState, (obj), TYPE_IBEX_PLIC)
-
-typedef struct IbexPlicState {
- /*< private >*/
- SysBusDevice parent_obj;
-
- /*< public >*/
- MemoryRegion mmio;
-
- uint32_t *pending;
- uint32_t *source;
- uint32_t *priority;
- uint32_t *enable;
- uint32_t threshold;
- uint32_t claim;
-
- /* config */
- uint32_t num_cpus;
- uint32_t num_sources;
-
- uint32_t pending_base;
- uint32_t pending_num;
-
- uint32_t source_base;
- uint32_t source_num;
-
- uint32_t priority_base;
- uint32_t priority_num;
-
- uint32_t enable_base;
- uint32_t enable_num;
-
- uint32_t threshold_base;
-
- uint32_t claim_base;
-} IbexPlicState;
-
-#endif /* HW_IBEX_PLIC_H */
diff --git a/include/hw/intc/imx_avic.h b/include/hw/intc/imx_avic.h
index 1b80769018..75fbd1a89c 100644
--- a/include/hw/intc/imx_avic.h
+++ b/include/hw/intc/imx_avic.h
@@ -18,9 +18,10 @@
#define IMX_AVIC_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_IMX_AVIC "imx.avic"
-#define IMX_AVIC(obj) OBJECT_CHECK(IMXAVICState, (obj), TYPE_IMX_AVIC)
+OBJECT_DECLARE_SIMPLE_TYPE(IMXAVICState, IMX_AVIC)
#define IMX_AVIC_NUM_IRQS 64
@@ -36,7 +37,7 @@
#define PRIO_PER_WORD (sizeof(uint32_t) * 8 / 4)
#define PRIO_WORDS (IMX_AVIC_NUM_IRQS/PRIO_PER_WORD)
-typedef struct IMXAVICState{
+struct IMXAVICState {
/*< private >*/
SysBusDevice parent_obj;
@@ -50,6 +51,6 @@ typedef struct IMXAVICState{
qemu_irq irq;
qemu_irq fiq;
uint32_t prio[PRIO_WORDS]; /* Priorities are 4-bits each */
-} IMXAVICState;
+};
#endif /* IMX_AVIC_H */
diff --git a/include/hw/intc/imx_gpcv2.h b/include/hw/intc/imx_gpcv2.h
index ed978b24bb..7bdee7e80a 100644
--- a/include/hw/intc/imx_gpcv2.h
+++ b/include/hw/intc/imx_gpcv2.h
@@ -2,21 +2,22 @@
#define IMX_GPCV2_H
#include "hw/sysbus.h"
+#include "qom/object.h"
enum IMXGPCv2Registers {
GPC_NUM = 0xE00 / sizeof(uint32_t),
};
-typedef struct IMXGPCv2State {
+struct IMXGPCv2State {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
MemoryRegion iomem;
uint32_t regs[GPC_NUM];
-} IMXGPCv2State;
+};
#define TYPE_IMX_GPCV2 "imx-gpcv2"
-#define IMX_GPCV2(obj) OBJECT_CHECK(IMXGPCv2State, (obj), TYPE_IMX_GPCV2)
+OBJECT_DECLARE_SIMPLE_TYPE(IMXGPCv2State, IMX_GPCV2)
#endif /* IMX_GPCV2_H */
diff --git a/include/hw/intc/intc.h b/include/hw/intc/intc.h
index fb3e8e621f..7018f608ca 100644
--- a/include/hw/intc/intc.h
+++ b/include/hw/intc/intc.h
@@ -5,19 +5,16 @@
#define TYPE_INTERRUPT_STATS_PROVIDER "intctrl"
-#define INTERRUPT_STATS_PROVIDER_CLASS(klass) \
- OBJECT_CLASS_CHECK(InterruptStatsProviderClass, (klass), \
+typedef struct InterruptStatsProviderClass InterruptStatsProviderClass;
+DECLARE_CLASS_CHECKERS(InterruptStatsProviderClass, INTERRUPT_STATS_PROVIDER,
TYPE_INTERRUPT_STATS_PROVIDER)
-#define INTERRUPT_STATS_PROVIDER_GET_CLASS(obj) \
- OBJECT_GET_CLASS(InterruptStatsProviderClass, (obj), \
- TYPE_INTERRUPT_STATS_PROVIDER)
#define INTERRUPT_STATS_PROVIDER(obj) \
INTERFACE_CHECK(InterruptStatsProvider, (obj), \
TYPE_INTERRUPT_STATS_PROVIDER)
typedef struct InterruptStatsProvider InterruptStatsProvider;
-typedef struct InterruptStatsProviderClass {
+struct InterruptStatsProviderClass {
InterfaceClass parent;
/* The returned pointer and statistics must remain valid until
@@ -26,6 +23,6 @@ typedef struct InterruptStatsProviderClass {
bool (*get_statistics)(InterruptStatsProvider *obj, uint64_t **irq_counts,
unsigned int *nb_irqs);
void (*print_info)(InterruptStatsProvider *obj, Monitor *mon);
-} InterruptStatsProviderClass;
+};
#endif
diff --git a/include/hw/i386/ioapic.h b/include/hw/intc/ioapic.h
index 59fcb158a7..aa122e25e3 100644
--- a/include/hw/i386/ioapic.h
+++ b/include/hw/intc/ioapic.h
@@ -6,7 +6,7 @@
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -17,15 +17,17 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef HW_IOAPIC_H
-#define HW_IOAPIC_H
+#ifndef HW_INTC_IOAPIC_H
+#define HW_INTC_IOAPIC_H
#define IOAPIC_NUM_PINS 24
#define IO_APIC_DEFAULT_ADDRESS 0xfec00000
+#define IO_APIC_SECONDARY_ADDRESS (IO_APIC_DEFAULT_ADDRESS + 0x10000)
+#define IO_APIC_SECONDARY_IRQBASE 24 /* primary 0 -> 23, secondary 24 -> 47 */
#define TYPE_KVM_IOAPIC "kvm-ioapic"
#define TYPE_IOAPIC "ioapic"
void ioapic_eoi_broadcast(int vector);
-#endif /* HW_IOAPIC_H */
+#endif /* HW_INTC_IOAPIC_H */
diff --git a/include/hw/intc/kvm_irqcount.h b/include/hw/intc/kvm_irqcount.h
new file mode 100644
index 0000000000..0ed5999e49
--- /dev/null
+++ b/include/hw/intc/kvm_irqcount.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#ifndef KVM_IRQCOUNT_H
+#define KVM_IRQCOUNT_H
+
+void kvm_report_irq_delivered(int delivered);
+void kvm_reset_irq_delivered(void);
+int kvm_get_irq_delivered(void);
+
+#endif
diff --git a/include/hw/intc/loongarch_extioi.h b/include/hw/intc/loongarch_extioi.h
new file mode 100644
index 0000000000..a0a46b888c
--- /dev/null
+++ b/include/hw/intc/loongarch_extioi.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch 3A5000 ext interrupt controller definitions
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "hw/sysbus.h"
+#include "hw/loongarch/virt.h"
+
+#ifndef LOONGARCH_EXTIOI_H
+#define LOONGARCH_EXTIOI_H
+
+#define LS3A_INTC_IP 8
+#define EXTIOI_IRQS (256)
+#define EXTIOI_IRQS_BITMAP_SIZE (256 / 8)
+/* irq from EXTIOI is routed to no more than 4 cpus */
+#define EXTIOI_CPUS (4)
+/* map to ipnum per 32 irqs */
+#define EXTIOI_IRQS_IPMAP_SIZE (256 / 32)
+#define EXTIOI_IRQS_COREMAP_SIZE 256
+#define EXTIOI_IRQS_NODETYPE_COUNT 16
+#define EXTIOI_IRQS_GROUP_COUNT 8
+
+#define APIC_OFFSET 0x400
+#define APIC_BASE (0x1000ULL + APIC_OFFSET)
+
+#define EXTIOI_NODETYPE_START (0x4a0 - APIC_OFFSET)
+#define EXTIOI_NODETYPE_END (0x4c0 - APIC_OFFSET)
+#define EXTIOI_IPMAP_START (0x4c0 - APIC_OFFSET)
+#define EXTIOI_IPMAP_END (0x4c8 - APIC_OFFSET)
+#define EXTIOI_ENABLE_START (0x600 - APIC_OFFSET)
+#define EXTIOI_ENABLE_END (0x620 - APIC_OFFSET)
+#define EXTIOI_BOUNCE_START (0x680 - APIC_OFFSET)
+#define EXTIOI_BOUNCE_END (0x6a0 - APIC_OFFSET)
+#define EXTIOI_ISR_START (0x700 - APIC_OFFSET)
+#define EXTIOI_ISR_END (0x720 - APIC_OFFSET)
+#define EXTIOI_COREISR_START (0x800 - APIC_OFFSET)
+#define EXTIOI_COREISR_END (0xB20 - APIC_OFFSET)
+#define EXTIOI_COREMAP_START (0xC00 - APIC_OFFSET)
+#define EXTIOI_COREMAP_END (0xD00 - APIC_OFFSET)
+
+typedef struct ExtIOICore {
+ uint32_t coreisr[EXTIOI_IRQS_GROUP_COUNT];
+ DECLARE_BITMAP(sw_isr[LS3A_INTC_IP], EXTIOI_IRQS);
+ qemu_irq parent_irq[LS3A_INTC_IP];
+} ExtIOICore;
+
+#define TYPE_LOONGARCH_EXTIOI "loongarch.extioi"
+OBJECT_DECLARE_SIMPLE_TYPE(LoongArchExtIOI, LOONGARCH_EXTIOI)
+struct LoongArchExtIOI {
+ SysBusDevice parent_obj;
+ uint32_t num_cpu;
+ /* hardware state */
+ uint32_t nodetype[EXTIOI_IRQS_NODETYPE_COUNT / 2];
+ uint32_t bounce[EXTIOI_IRQS_GROUP_COUNT];
+ uint32_t isr[EXTIOI_IRQS / 32];
+ uint32_t enable[EXTIOI_IRQS / 32];
+ uint32_t ipmap[EXTIOI_IRQS_IPMAP_SIZE / 4];
+ uint32_t coremap[EXTIOI_IRQS / 4];
+ uint32_t sw_pending[EXTIOI_IRQS / 32];
+ uint8_t sw_ipmap[EXTIOI_IRQS_IPMAP_SIZE];
+ uint8_t sw_coremap[EXTIOI_IRQS];
+ qemu_irq irq[EXTIOI_IRQS];
+ ExtIOICore *cpu;
+ MemoryRegion extioi_system_mem;
+};
+#endif /* LOONGARCH_EXTIOI_H */
diff --git a/include/hw/intc/loongarch_ipi.h b/include/hw/intc/loongarch_ipi.h
new file mode 100644
index 0000000000..1c1e834849
--- /dev/null
+++ b/include/hw/intc/loongarch_ipi.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch ipi interrupt header files
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef HW_LOONGARCH_IPI_H
+#define HW_LOONGARCH_IPI_H
+
+#include "hw/sysbus.h"
+
+/* Mainy used by iocsr read and write */
+#define SMP_IPI_MAILBOX 0x1000ULL
+#define CORE_STATUS_OFF 0x0
+#define CORE_EN_OFF 0x4
+#define CORE_SET_OFF 0x8
+#define CORE_CLEAR_OFF 0xc
+#define CORE_BUF_20 0x20
+#define CORE_BUF_28 0x28
+#define CORE_BUF_30 0x30
+#define CORE_BUF_38 0x38
+#define IOCSR_IPI_SEND 0x40
+#define IOCSR_MAIL_SEND 0x48
+#define IOCSR_ANY_SEND 0x158
+
+#define MAIL_SEND_ADDR (SMP_IPI_MAILBOX + IOCSR_MAIL_SEND)
+#define MAIL_SEND_OFFSET 0
+#define ANY_SEND_OFFSET (IOCSR_ANY_SEND - IOCSR_MAIL_SEND)
+
+#define IPI_MBX_NUM 4
+
+#define TYPE_LOONGARCH_IPI "loongarch_ipi"
+OBJECT_DECLARE_SIMPLE_TYPE(LoongArchIPI, LOONGARCH_IPI)
+
+typedef struct IPICore {
+ uint32_t status;
+ uint32_t en;
+ uint32_t set;
+ uint32_t clear;
+ /* 64bit buf divide into 2 32bit buf */
+ uint32_t buf[IPI_MBX_NUM * 2];
+ qemu_irq irq;
+} IPICore;
+
+struct LoongArchIPI {
+ SysBusDevice parent_obj;
+ MemoryRegion ipi_iocsr_mem;
+ MemoryRegion ipi64_iocsr_mem;
+ uint32_t num_cpu;
+ IPICore *cpu;
+};
+
+#endif
diff --git a/include/hw/intc/loongarch_pch_msi.h b/include/hw/intc/loongarch_pch_msi.h
new file mode 100644
index 0000000000..b8586fb3b6
--- /dev/null
+++ b/include/hw/intc/loongarch_pch_msi.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch 7A1000 I/O interrupt controller definitions
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "hw/sysbus.h"
+
+#define TYPE_LOONGARCH_PCH_MSI "loongarch_pch_msi"
+OBJECT_DECLARE_SIMPLE_TYPE(LoongArchPCHMSI, LOONGARCH_PCH_MSI)
+
+/* MSI irq start from 32 to 255 */
+#define PCH_MSI_IRQ_START 32
+#define PCH_MSI_IRQ_END 255
+#define PCH_MSI_IRQ_NUM 224
+
+struct LoongArchPCHMSI {
+ SysBusDevice parent_obj;
+ qemu_irq *pch_msi_irq;
+ MemoryRegion msi_mmio;
+ /* irq base passed to upper extioi intc */
+ unsigned int irq_base;
+ unsigned int irq_num;
+};
diff --git a/include/hw/intc/loongarch_pch_pic.h b/include/hw/intc/loongarch_pch_pic.h
new file mode 100644
index 0000000000..d5437e88f2
--- /dev/null
+++ b/include/hw/intc/loongarch_pch_pic.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch 7A1000 I/O interrupt controller definitions
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "hw/sysbus.h"
+
+#define TYPE_LOONGARCH_PCH_PIC "loongarch_pch_pic"
+#define PCH_PIC_NAME(name) TYPE_LOONGARCH_PCH_PIC#name
+OBJECT_DECLARE_SIMPLE_TYPE(LoongArchPCHPIC, LOONGARCH_PCH_PIC)
+
+#define PCH_PIC_INT_ID_VAL 0x7000000UL
+#define PCH_PIC_INT_ID_VER 0x1UL
+
+#define PCH_PIC_INT_ID_LO 0x00
+#define PCH_PIC_INT_ID_HI 0x04
+#define PCH_PIC_INT_MASK_LO 0x20
+#define PCH_PIC_INT_MASK_HI 0x24
+#define PCH_PIC_HTMSI_EN_LO 0x40
+#define PCH_PIC_HTMSI_EN_HI 0x44
+#define PCH_PIC_INT_EDGE_LO 0x60
+#define PCH_PIC_INT_EDGE_HI 0x64
+#define PCH_PIC_INT_CLEAR_LO 0x80
+#define PCH_PIC_INT_CLEAR_HI 0x84
+#define PCH_PIC_AUTO_CTRL0_LO 0xc0
+#define PCH_PIC_AUTO_CTRL0_HI 0xc4
+#define PCH_PIC_AUTO_CTRL1_LO 0xe0
+#define PCH_PIC_AUTO_CTRL1_HI 0xe4
+#define PCH_PIC_ROUTE_ENTRY_OFFSET 0x100
+#define PCH_PIC_ROUTE_ENTRY_END 0x13f
+#define PCH_PIC_HTMSI_VEC_OFFSET 0x200
+#define PCH_PIC_HTMSI_VEC_END 0x23f
+#define PCH_PIC_INT_STATUS_LO 0x3a0
+#define PCH_PIC_INT_STATUS_HI 0x3a4
+#define PCH_PIC_INT_POL_LO 0x3e0
+#define PCH_PIC_INT_POL_HI 0x3e4
+
+#define STATUS_LO_START 0
+#define STATUS_HI_START 0x4
+#define POL_LO_START 0x40
+#define POL_HI_START 0x44
+struct LoongArchPCHPIC {
+ SysBusDevice parent_obj;
+ qemu_irq parent_irq[64];
+ uint64_t int_mask; /*0x020 interrupt mask register*/
+ uint64_t htmsi_en; /*0x040 1=msi*/
+ uint64_t intedge; /*0x060 edge=1 level =0*/
+ uint64_t intclr; /*0x080 for clean edge int,set 1 clean,set 0 is noused*/
+ uint64_t auto_crtl0; /*0x0c0*/
+ uint64_t auto_crtl1; /*0x0e0*/
+ uint64_t last_intirr; /* edge detection */
+ uint64_t intirr; /* 0x380 interrupt request register */
+ uint64_t intisr; /* 0x3a0 interrupt service register */
+ /*
+ * 0x3e0 interrupt level polarity selection
+ * register 0 for high level trigger
+ */
+ uint64_t int_polarity;
+
+ uint8_t route_entry[64]; /*0x100 - 0x138*/
+ uint8_t htmsi_vector[64]; /*0x200 - 0x238*/
+
+ MemoryRegion iomem32_low;
+ MemoryRegion iomem32_high;
+ MemoryRegion iomem8;
+ unsigned int irq_num;
+};
diff --git a/include/hw/intc/loongson_liointc.h b/include/hw/intc/loongson_liointc.h
new file mode 100644
index 0000000000..848e65eb35
--- /dev/null
+++ b/include/hw/intc/loongson_liointc.h
@@ -0,0 +1,22 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2020 Huacai Chen <chenhc@lemote.com>
+ * Copyright (c) 2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
+ *
+ */
+
+#ifndef LOONGSON_LIOINTC_H
+#define LOONGSON_LIOINTC_H
+
+#include "qemu/units.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_LOONGSON_LIOINTC "loongson.liointc"
+DECLARE_INSTANCE_CHECKER(struct loongson_liointc, LOONGSON_LIOINTC,
+ TYPE_LOONGSON_LIOINTC)
+
+#endif /* LOONGSON_LIOINTC_H */
diff --git a/include/hw/intc/m68k_irqc.h b/include/hw/intc/m68k_irqc.h
new file mode 100644
index 0000000000..693e33b0aa
--- /dev/null
+++ b/include/hw/intc/m68k_irqc.h
@@ -0,0 +1,42 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * QEMU Motorola 680x0 IRQ Controller
+ *
+ * (c) 2020 Laurent Vivier <laurent@vivier.eu>
+ *
+ */
+
+#ifndef M68K_IRQC_H
+#define M68K_IRQC_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_M68K_IRQC "m68k-irq-controller"
+#define M68K_IRQC(obj) OBJECT_CHECK(M68KIRQCState, (obj), \
+ TYPE_M68K_IRQC)
+
+#define M68K_IRQC_AUTOVECTOR_BASE 25
+
+enum {
+ M68K_IRQC_LEVEL_1 = 0,
+ M68K_IRQC_LEVEL_2,
+ M68K_IRQC_LEVEL_3,
+ M68K_IRQC_LEVEL_4,
+ M68K_IRQC_LEVEL_5,
+ M68K_IRQC_LEVEL_6,
+ M68K_IRQC_LEVEL_7,
+};
+#define M68K_IRQC_LEVEL_NUM (M68K_IRQC_LEVEL_7 - M68K_IRQC_LEVEL_1 + 1)
+
+typedef struct M68KIRQCState {
+ SysBusDevice parent_obj;
+
+ uint8_t ipr;
+ ArchCPU *cpu;
+
+ /* statistics */
+ uint64_t stats_irq_count[M68K_IRQC_LEVEL_NUM];
+} M68KIRQCState;
+
+#endif
diff --git a/include/hw/intc/mips_gic.h b/include/hw/intc/mips_gic.h
index 8428287bf9..5e4c71edd4 100644
--- a/include/hw/intc/mips_gic.h
+++ b/include/hw/intc/mips_gic.h
@@ -15,6 +15,7 @@
#include "hw/timer/mips_gictimer.h"
#include "hw/sysbus.h"
#include "cpu.h"
+#include "qom/object.h"
/*
* GIC Specific definitions
*/
@@ -170,13 +171,12 @@
#define GIC_LOCAL_INT_WD 0 /* GIC watchdog */
#define TYPE_MIPS_GIC "mips-gic"
-#define MIPS_GIC(obj) OBJECT_CHECK(MIPSGICState, (obj), TYPE_MIPS_GIC)
+OBJECT_DECLARE_SIMPLE_TYPE(MIPSGICState, MIPS_GIC)
/* Support up to 32 VPs and 256 IRQs */
#define GIC_MAX_VPS 32
#define GIC_MAX_INTRS 256
-typedef struct MIPSGICState MIPSGICState;
typedef struct MIPSGICIRQState MIPSGICIRQState;
typedef struct MIPSGICVPState MIPSGICVPState;
@@ -211,8 +211,8 @@ struct MIPSGICState {
/* GIC VP Timer */
MIPSGICTimerState *gic_timer;
- int32_t num_vps;
- int32_t num_irq;
+ uint32_t num_vps;
+ uint32_t num_irq;
};
#endif /* MIPS_GIC_H */
diff --git a/include/hw/intc/ppc-uic.h b/include/hw/intc/ppc-uic.h
new file mode 100644
index 0000000000..4d82e9a3c6
--- /dev/null
+++ b/include/hw/intc/ppc-uic.h
@@ -0,0 +1,78 @@
+/*
+ * "Universal" Interrupt Controller for PowerPPC 4xx embedded processors
+ *
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * 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.
+ */
+
+#ifndef HW_INTC_PPC_UIC_H
+#define HW_INTC_PPC_UIC_H
+
+#include "hw/ppc/ppc4xx.h"
+
+#define TYPE_PPC_UIC "ppc-uic"
+OBJECT_DECLARE_SIMPLE_TYPE(PPCUIC, PPC_UIC)
+
+/*
+ * QEMU interface:
+ * QOM property "cpu": link to the PPC CPU
+ * (no default, must be set)
+ * QOM property "dcr-base": base of the bank of DCR registers for the UIC
+ * (default 0x30)
+ * QOM property "use-vectors": true if the UIC has vector registers
+ * (default true)
+ * unnamed GPIO inputs 0..UIC_MAX_IRQ: input IRQ lines
+ * sysbus IRQs:
+ * 0 (PPCUIC_OUTPUT_INT): output INT line to the CPU
+ * 1 (PPCUIC_OUTPUT_CINT): output CINT line to the CPU
+ */
+
+#define UIC_MAX_IRQ 32
+
+/* Symbolic constants for the sysbus IRQ outputs */
+enum {
+ PPCUIC_OUTPUT_INT = 0,
+ PPCUIC_OUTPUT_CINT = 1,
+ PPCUIC_OUTPUT_NB,
+};
+
+struct PPCUIC {
+ /*< private >*/
+ Ppc4xxDcrDeviceState parent_obj;
+
+ /*< public >*/
+ qemu_irq output_int;
+ qemu_irq output_cint;
+
+ /* properties */
+ uint32_t dcr_base;
+ bool use_vectors;
+
+ uint32_t level; /* Remembers the state of level-triggered interrupts. */
+ uint32_t uicsr; /* Status register */
+ uint32_t uicer; /* Enable register */
+ uint32_t uiccr; /* Critical register */
+ uint32_t uicpr; /* Polarity register */
+ uint32_t uictr; /* Triggering register */
+ uint32_t uicvcr; /* Vector configuration register */
+ uint32_t uicvr;
+};
+
+#endif
diff --git a/include/hw/intc/realview_gic.h b/include/hw/intc/realview_gic.h
index 1783ea11b9..f37339dc0b 100644
--- a/include/hw/intc/realview_gic.h
+++ b/include/hw/intc/realview_gic.h
@@ -12,17 +12,17 @@
#include "hw/sysbus.h"
#include "hw/intc/arm_gic.h"
+#include "qom/object.h"
#define TYPE_REALVIEW_GIC "realview_gic"
-#define REALVIEW_GIC(obj) \
- OBJECT_CHECK(RealViewGICState, (obj), TYPE_REALVIEW_GIC)
+OBJECT_DECLARE_SIMPLE_TYPE(RealViewGICState, REALVIEW_GIC)
-typedef struct RealViewGICState {
+struct RealViewGICState {
SysBusDevice parent_obj;
MemoryRegion container;
GICState gic;
-} RealViewGICState;
+};
#endif
diff --git a/include/hw/intc/riscv_aclint.h b/include/hw/intc/riscv_aclint.h
new file mode 100644
index 0000000000..693415eb6d
--- /dev/null
+++ b/include/hw/intc/riscv_aclint.h
@@ -0,0 +1,83 @@
+/*
+ * RISC-V ACLINT (Advanced Core Local Interruptor) interface
+ *
+ * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
+ * Copyright (c) 2017 SiFive, Inc.
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_RISCV_ACLINT_H
+#define HW_RISCV_ACLINT_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_RISCV_ACLINT_MTIMER "riscv.aclint.mtimer"
+
+#define RISCV_ACLINT_MTIMER(obj) \
+ OBJECT_CHECK(RISCVAclintMTimerState, (obj), TYPE_RISCV_ACLINT_MTIMER)
+
+typedef struct RISCVAclintMTimerState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ uint64_t time_delta;
+ uint64_t *timecmp;
+ QEMUTimer **timers;
+
+ /*< public >*/
+ MemoryRegion mmio;
+ uint32_t hartid_base;
+ uint32_t num_harts;
+ uint32_t timecmp_base;
+ uint32_t time_base;
+ uint32_t aperture_size;
+ uint32_t timebase_freq;
+ qemu_irq *timer_irqs;
+} RISCVAclintMTimerState;
+
+DeviceState *riscv_aclint_mtimer_create(hwaddr addr, hwaddr size,
+ uint32_t hartid_base, uint32_t num_harts,
+ uint32_t timecmp_base, uint32_t time_base, uint32_t timebase_freq,
+ bool provide_rdtime);
+
+#define TYPE_RISCV_ACLINT_SWI "riscv.aclint.swi"
+
+#define RISCV_ACLINT_SWI(obj) \
+ OBJECT_CHECK(RISCVAclintSwiState, (obj), TYPE_RISCV_ACLINT_SWI)
+
+typedef struct RISCVAclintSwiState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion mmio;
+ uint32_t hartid_base;
+ uint32_t num_harts;
+ uint32_t sswi;
+ qemu_irq *soft_irqs;
+} RISCVAclintSwiState;
+
+DeviceState *riscv_aclint_swi_create(hwaddr addr, uint32_t hartid_base,
+ uint32_t num_harts, bool sswi);
+
+enum {
+ RISCV_ACLINT_DEFAULT_MTIMECMP = 0x0,
+ RISCV_ACLINT_DEFAULT_MTIME = 0x7ff8,
+ RISCV_ACLINT_DEFAULT_MTIMER_SIZE = 0x8000,
+ RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ = 10000000,
+ RISCV_ACLINT_MAX_HARTS = 4095,
+ RISCV_ACLINT_SWI_SIZE = 0x4000
+};
+
+#endif
diff --git a/include/hw/intc/riscv_aplic.h b/include/hw/intc/riscv_aplic.h
new file mode 100644
index 0000000000..de8532fbc3
--- /dev/null
+++ b/include/hw/intc/riscv_aplic.h
@@ -0,0 +1,79 @@
+/*
+ * RISC-V APLIC (Advanced Platform Level Interrupt Controller) interface
+ *
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_RISCV_APLIC_H
+#define HW_RISCV_APLIC_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_RISCV_APLIC "riscv.aplic"
+
+typedef struct RISCVAPLICState RISCVAPLICState;
+DECLARE_INSTANCE_CHECKER(RISCVAPLICState, RISCV_APLIC, TYPE_RISCV_APLIC)
+
+#define APLIC_MIN_SIZE 0x4000
+#define APLIC_SIZE_ALIGN(__x) (((__x) + (APLIC_MIN_SIZE - 1)) & \
+ ~(APLIC_MIN_SIZE - 1))
+#define APLIC_SIZE(__num_harts) (APLIC_MIN_SIZE + \
+ APLIC_SIZE_ALIGN(32 * (__num_harts)))
+
+struct RISCVAPLICState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ qemu_irq *external_irqs;
+
+ /*< public >*/
+ MemoryRegion mmio;
+ uint32_t bitfield_words;
+ uint32_t domaincfg;
+ uint32_t mmsicfgaddr;
+ uint32_t mmsicfgaddrH;
+ uint32_t smsicfgaddr;
+ uint32_t smsicfgaddrH;
+ uint32_t genmsi;
+ uint32_t *sourcecfg;
+ uint32_t *state;
+ uint32_t *target;
+ uint32_t *idelivery;
+ uint32_t *iforce;
+ uint32_t *ithreshold;
+
+ /* topology */
+#define QEMU_APLIC_MAX_CHILDREN 16
+ struct RISCVAPLICState *parent;
+ struct RISCVAPLICState *children[QEMU_APLIC_MAX_CHILDREN];
+ uint16_t num_children;
+
+ /* config */
+ uint32_t aperture_size;
+ uint32_t hartid_base;
+ uint32_t num_harts;
+ uint32_t iprio_mask;
+ uint32_t num_irqs;
+ bool msimode;
+ bool mmode;
+};
+
+void riscv_aplic_add_child(DeviceState *parent, DeviceState *child);
+
+DeviceState *riscv_aplic_create(hwaddr addr, hwaddr size,
+ uint32_t hartid_base, uint32_t num_harts, uint32_t num_sources,
+ uint32_t iprio_bits, bool msimode, bool mmode, DeviceState *parent);
+
+#endif
diff --git a/include/hw/intc/riscv_imsic.h b/include/hw/intc/riscv_imsic.h
new file mode 100644
index 0000000000..58c2aaa8dc
--- /dev/null
+++ b/include/hw/intc/riscv_imsic.h
@@ -0,0 +1,68 @@
+/*
+ * RISC-V IMSIC (Incoming Message Signal Interrupt Controller) interface
+ *
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_RISCV_IMSIC_H
+#define HW_RISCV_IMSIC_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_RISCV_IMSIC "riscv.imsic"
+
+typedef struct RISCVIMSICState RISCVIMSICState;
+DECLARE_INSTANCE_CHECKER(RISCVIMSICState, RISCV_IMSIC, TYPE_RISCV_IMSIC)
+
+#define IMSIC_MMIO_PAGE_SHIFT 12
+#define IMSIC_MMIO_PAGE_SZ (1UL << IMSIC_MMIO_PAGE_SHIFT)
+#define IMSIC_MMIO_SIZE(__num_pages) ((__num_pages) * IMSIC_MMIO_PAGE_SZ)
+
+#define IMSIC_MMIO_HART_GUEST_MAX_BTIS 6
+#define IMSIC_MMIO_GROUP_MIN_SHIFT 24
+
+#define IMSIC_HART_NUM_GUESTS(__guest_bits) \
+ (1U << (__guest_bits))
+#define IMSIC_HART_SIZE(__guest_bits) \
+ (IMSIC_HART_NUM_GUESTS(__guest_bits) * IMSIC_MMIO_PAGE_SZ)
+#define IMSIC_GROUP_NUM_HARTS(__hart_bits) \
+ (1U << (__hart_bits))
+#define IMSIC_GROUP_SIZE(__hart_bits, __guest_bits) \
+ (IMSIC_GROUP_NUM_HARTS(__hart_bits) * IMSIC_HART_SIZE(__guest_bits))
+
+struct RISCVIMSICState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ qemu_irq *external_irqs;
+
+ /*< public >*/
+ MemoryRegion mmio;
+ uint32_t num_eistate;
+ uint32_t *eidelivery;
+ uint32_t *eithreshold;
+ uint32_t *eistate;
+
+ /* config */
+ bool mmode;
+ uint32_t hartid;
+ uint32_t num_pages;
+ uint32_t num_irqs;
+};
+
+DeviceState *riscv_imsic_create(hwaddr addr, uint32_t hartid, bool mmode,
+ uint32_t num_pages, uint32_t num_ids);
+
+#endif
diff --git a/include/hw/intc/rx_icu.h b/include/hw/intc/rx_icu.h
index 7176015cd9..b23504f3dd 100644
--- a/include/hw/intc/rx_icu.h
+++ b/include/hw/intc/rx_icu.h
@@ -22,6 +22,7 @@
#define HW_INTC_RX_ICU_H
#include "hw/sysbus.h"
+#include "qom/object.h"
enum TRG_MODE {
TRG_LEVEL = 0,
@@ -68,9 +69,8 @@ struct RXICUState {
qemu_irq _fir;
qemu_irq _swi;
};
-typedef struct RXICUState RXICUState;
#define TYPE_RX_ICU "rx-icu"
-#define RX_ICU(obj) OBJECT_CHECK(RXICUState, (obj), TYPE_RX_ICU)
+OBJECT_DECLARE_SIMPLE_TYPE(RXICUState, RX_ICU)
-#endif /* RX_ICU_H */
+#endif /* HW_INTC_RX_ICU_H */
diff --git a/include/hw/riscv/sifive_plic.h b/include/hw/intc/sifive_plic.h
index 4421e81249..d3f45ec248 100644
--- a/include/hw/riscv/sifive_plic.h
+++ b/include/hw/intc/sifive_plic.h
@@ -22,16 +22,17 @@
#define HW_SIFIVE_PLIC_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_SIFIVE_PLIC "riscv.sifive.plic"
-#define SIFIVE_PLIC(obj) \
- OBJECT_CHECK(SiFivePLICState, (obj), TYPE_SIFIVE_PLIC)
+typedef struct SiFivePLICState SiFivePLICState;
+DECLARE_INSTANCE_CHECKER(SiFivePLICState, SIFIVE_PLIC,
+ TYPE_SIFIVE_PLIC)
typedef enum PLICMode {
PLICMode_U,
PLICMode_S,
- PLICMode_H,
PLICMode_M
} PLICMode;
@@ -41,14 +42,16 @@ typedef struct PLICAddr {
PLICMode mode;
} PLICAddr;
-typedef struct SiFivePLICState {
+struct SiFivePLICState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
MemoryRegion mmio;
uint32_t num_addrs;
+ uint32_t num_harts;
uint32_t bitfield_words;
+ uint32_t num_enables;
PLICAddr *addr_config;
uint32_t *source_priority;
uint32_t *target_priority;
@@ -58,6 +61,7 @@ typedef struct SiFivePLICState {
/* config */
char *hart_config;
+ uint32_t hartid_base;
uint32_t num_sources;
uint32_t num_priorities;
uint32_t priority_base;
@@ -67,13 +71,17 @@ typedef struct SiFivePLICState {
uint32_t context_base;
uint32_t context_stride;
uint32_t aperture_size;
-} SiFivePLICState;
+
+ qemu_irq *m_external_irqs;
+ qemu_irq *s_external_irqs;
+};
DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
- uint32_t num_sources, uint32_t num_priorities,
- uint32_t priority_base, uint32_t pending_base,
- uint32_t enable_base, uint32_t enable_stride,
- uint32_t context_base, uint32_t context_stride,
- uint32_t aperture_size);
+ uint32_t num_harts,
+ uint32_t hartid_base, uint32_t num_sources,
+ uint32_t num_priorities, uint32_t priority_base,
+ uint32_t pending_base, uint32_t enable_base,
+ uint32_t enable_stride, uint32_t context_base,
+ uint32_t context_stride, uint32_t aperture_size);
#endif
diff --git a/include/hw/intc/xlnx-pmu-iomod-intc.h b/include/hw/intc/xlnx-pmu-iomod-intc.h
index 0bd118884a..ccc8bd272a 100644
--- a/include/hw/intc/xlnx-pmu-iomod-intc.h
+++ b/include/hw/intc/xlnx-pmu-iomod-intc.h
@@ -27,16 +27,16 @@
#include "hw/sysbus.h"
#include "hw/register.h"
+#include "qom/object.h"
#define TYPE_XLNX_PMU_IO_INTC "xlnx.pmu_io_intc"
-#define XLNX_PMU_IO_INTC(obj) \
- OBJECT_CHECK(XlnxPMUIOIntc, (obj), TYPE_XLNX_PMU_IO_INTC)
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxPMUIOIntc, XLNX_PMU_IO_INTC)
/* This is R_PIT3_CONTROL + 1 */
#define XLNXPMUIOINTC_R_MAX (0x78 + 1)
-typedef struct XlnxPMUIOIntc {
+struct XlnxPMUIOIntc {
SysBusDevice parent_obj;
MemoryRegion iomem;
@@ -52,6 +52,6 @@ typedef struct XlnxPMUIOIntc {
uint32_t regs[XLNXPMUIOINTC_R_MAX];
RegisterInfo regs_info[XLNXPMUIOINTC_R_MAX];
-} XlnxPMUIOIntc;
+};
#endif /* HW_INTC_XLNX_PMU_IOMOD_INTC_H */
diff --git a/include/hw/intc/xlnx-zynqmp-ipi.h b/include/hw/intc/xlnx-zynqmp-ipi.h
index 866c719c6f..33eff1d4f6 100644
--- a/include/hw/intc/xlnx-zynqmp-ipi.h
+++ b/include/hw/intc/xlnx-zynqmp-ipi.h
@@ -27,18 +27,18 @@
#include "hw/sysbus.h"
#include "hw/register.h"
+#include "qom/object.h"
#define TYPE_XLNX_ZYNQMP_IPI "xlnx.zynqmp_ipi"
-#define XLNX_ZYNQMP_IPI(obj) \
- OBJECT_CHECK(XlnxZynqMPIPI, (obj), TYPE_XLNX_ZYNQMP_IPI)
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPIPI, XLNX_ZYNQMP_IPI)
/* This is R_IPI_IDR + 1 */
#define R_XLNX_ZYNQMP_IPI_MAX ((0x1c / 4) + 1)
#define NUM_IPIS 11
-typedef struct XlnxZynqMPIPI {
+struct XlnxZynqMPIPI {
/* Private */
SysBusDevice parent_obj;
@@ -51,6 +51,6 @@ typedef struct XlnxZynqMPIPI {
uint32_t regs[R_XLNX_ZYNQMP_IPI_MAX];
RegisterInfo regs_info[R_XLNX_ZYNQMP_IPI_MAX];
-} XlnxZynqMPIPI;
+};
#endif /* XLNX_ZYNQMP_IPI_H */
diff --git a/include/hw/ipack/ipack.h b/include/hw/ipack/ipack.h
index 1c07969bc9..cbcdda509d 100644
--- a/include/hw/ipack/ipack.h
+++ b/include/hw/ipack/ipack.h
@@ -12,11 +12,11 @@
#define QEMU_IPACK_H
#include "hw/qdev-core.h"
+#include "qom/object.h"
-typedef struct IPackBus IPackBus;
#define TYPE_IPACK_BUS "IndustryPack"
-#define IPACK_BUS(obj) OBJECT_CHECK(IPackBus, (obj), TYPE_IPACK_BUS)
+OBJECT_DECLARE_SIMPLE_TYPE(IPackBus, IPACK_BUS)
struct IPackBus {
/*< private >*/
@@ -28,16 +28,10 @@ struct IPackBus {
qemu_irq_handler set_irq;
};
-typedef struct IPackDevice IPackDevice;
-typedef struct IPackDeviceClass IPackDeviceClass;
#define TYPE_IPACK_DEVICE "ipack-device"
-#define IPACK_DEVICE(obj) \
- OBJECT_CHECK(IPackDevice, (obj), TYPE_IPACK_DEVICE)
-#define IPACK_DEVICE_CLASS(klass) \
- OBJECT_CLASS_CHECK(IPackDeviceClass, (klass), TYPE_IPACK_DEVICE)
-#define IPACK_DEVICE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(IPackDeviceClass, (obj), TYPE_IPACK_DEVICE)
+OBJECT_DECLARE_TYPE(IPackDevice, IPackDeviceClass,
+ IPACK_DEVICE)
struct IPackDeviceClass {
/*< private >*/
@@ -79,9 +73,9 @@ extern const VMStateDescription vmstate_ipack_device;
VMSTATE_STRUCT(_field, _state, 1, vmstate_ipack_device, IPackDevice)
IPackDevice *ipack_device_find(IPackBus *bus, int32_t slot);
-void ipack_bus_new_inplace(IPackBus *bus, size_t bus_size,
- DeviceState *parent,
- const char *name, uint8_t n_slots,
- qemu_irq_handler handler);
+void ipack_bus_init(IPackBus *bus, size_t bus_size,
+ DeviceState *parent,
+ uint8_t n_slots,
+ qemu_irq_handler handler);
#endif
diff --git a/include/hw/ipmi/ipmi.h b/include/hw/ipmi/ipmi.h
index 8a99d958bb..77a7213ed9 100644
--- a/include/hw/ipmi/ipmi.h
+++ b/include/hw/ipmi/ipmi.h
@@ -27,6 +27,7 @@
#include "exec/memory.h"
#include "hw/qdev-core.h"
+#include "qom/object.h"
#define MAX_IPMI_MSG_SIZE 300
@@ -53,6 +54,7 @@ enum ipmi_op {
#define IPMI_CC_INVALID_DATA_FIELD 0xcc
#define IPMI_CC_BMC_INIT_IN_PROGRESS 0xd2
#define IPMI_CC_COMMAND_NOT_SUPPORTED 0xd5
+#define IPMI_CC_UNSPECIFIED 0xff
#define IPMI_NETFN_APP 0x06
#define IPMI_NETFN_OEM 0x3a
@@ -109,14 +111,13 @@ uint32_t ipmi_next_uuid(void);
#define TYPE_IPMI_INTERFACE "ipmi-interface"
#define IPMI_INTERFACE(obj) \
INTERFACE_CHECK(IPMIInterface, (obj), TYPE_IPMI_INTERFACE)
-#define IPMI_INTERFACE_CLASS(class) \
- OBJECT_CLASS_CHECK(IPMIInterfaceClass, (class), TYPE_IPMI_INTERFACE)
-#define IPMI_INTERFACE_GET_CLASS(class) \
- OBJECT_GET_CLASS(IPMIInterfaceClass, (class), TYPE_IPMI_INTERFACE)
+typedef struct IPMIInterfaceClass IPMIInterfaceClass;
+DECLARE_CLASS_CHECKERS(IPMIInterfaceClass, IPMI_INTERFACE,
+ TYPE_IPMI_INTERFACE)
typedef struct IPMIInterface IPMIInterface;
-typedef struct IPMIInterfaceClass {
+struct IPMIInterfaceClass {
InterfaceClass parent;
/*
@@ -169,28 +170,24 @@ typedef struct IPMIInterfaceClass {
* Return the firmware info for a device.
*/
void (*get_fwinfo)(struct IPMIInterface *s, IPMIFwInfo *info);
-} IPMIInterfaceClass;
+};
/*
* Define a BMC simulator (or perhaps a connection to a real BMC)
*/
#define TYPE_IPMI_BMC "ipmi-bmc"
-#define IPMI_BMC(obj) \
- OBJECT_CHECK(IPMIBmc, (obj), TYPE_IPMI_BMC)
-#define IPMI_BMC_CLASS(obj_class) \
- OBJECT_CLASS_CHECK(IPMIBmcClass, (obj_class), TYPE_IPMI_BMC)
-#define IPMI_BMC_GET_CLASS(obj) \
- OBJECT_GET_CLASS(IPMIBmcClass, (obj), TYPE_IPMI_BMC)
-
-typedef struct IPMIBmc {
+OBJECT_DECLARE_TYPE(IPMIBmc, IPMIBmcClass,
+ IPMI_BMC)
+
+struct IPMIBmc {
DeviceState parent;
uint8_t slave_addr;
IPMIInterface *intf;
-} IPMIBmc;
+};
-typedef struct IPMIBmcClass {
+struct IPMIBmcClass {
DeviceClass parent;
/* Called when the system resets to report to the bmc. */
@@ -203,7 +200,7 @@ typedef struct IPMIBmcClass {
uint8_t *cmd, unsigned int cmd_len,
unsigned int max_cmd_len,
uint8_t msg_id);
-} IPMIBmcClass;
+};
/*
* Add a link property to obj that points to a BMC.
@@ -267,10 +264,8 @@ int ipmi_bmc_sdr_find(IPMIBmc *b, uint16_t recid,
void ipmi_bmc_gen_event(IPMIBmc *b, uint8_t *evt, bool log);
#define TYPE_IPMI_BMC_SIMULATOR "ipmi-bmc-sim"
-#define IPMI_BMC_SIMULATOR(obj) OBJECT_CHECK(IPMIBmcSim, (obj), \
- TYPE_IPMI_BMC_SIMULATOR)
+OBJECT_DECLARE_SIMPLE_TYPE(IPMIBmcSim, IPMI_BMC_SIMULATOR)
-typedef struct IPMIBmcSim IPMIBmcSim;
typedef struct RspBuffer {
uint8_t buffer[MAX_IPMI_MSG_SIZE];
diff --git a/include/hw/irq.h b/include/hw/irq.h
index dc7abf199e..645b73d251 100644
--- a/include/hw/irq.h
+++ b/include/hw/irq.h
@@ -46,11 +46,6 @@ void qemu_free_irq(qemu_irq irq);
/* Returns a new IRQ with opposite polarity. */
qemu_irq qemu_irq_invert(qemu_irq irq);
-/* Returns a new IRQ which feeds into both the passed IRQs.
- * It's probably better to use the TYPE_SPLIT_IRQ device instead.
- */
-qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2);
-
/* For internal use in qtest. Similar to qemu_irq_split, but operating
on an existing vector of qemu_irq. */
void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n);
diff --git a/include/hw/isa/i8259_internal.h b/include/hw/isa/i8259_internal.h
index 861d70d8f8..f9dcc4163e 100644
--- a/include/hw/isa/i8259_internal.h
+++ b/include/hw/isa/i8259_internal.h
@@ -28,24 +28,18 @@
#include "hw/isa/isa.h"
#include "hw/intc/intc.h"
#include "hw/intc/i8259.h"
+#include "qom/object.h"
-typedef struct PICCommonState PICCommonState;
#define TYPE_PIC_COMMON "pic-common"
-#define PIC_COMMON(obj) \
- OBJECT_CHECK(PICCommonState, (obj), TYPE_PIC_COMMON)
-#define PIC_COMMON_CLASS(klass) \
- OBJECT_CLASS_CHECK(PICCommonClass, (klass), TYPE_PIC_COMMON)
-#define PIC_COMMON_GET_CLASS(obj) \
- OBJECT_GET_CLASS(PICCommonClass, (obj), TYPE_PIC_COMMON)
+OBJECT_DECLARE_TYPE(PICCommonState, PICCommonClass, PIC_COMMON)
-typedef struct PICCommonClass
-{
- ISADeviceClass parent_class;
+struct PICCommonClass {
+ DeviceClass parent_class;
void (*pre_save)(PICCommonState *s);
void (*post_load)(PICCommonState *s);
-} PICCommonClass;
+};
struct PICCommonState {
ISADevice parent_obj;
@@ -67,6 +61,7 @@ struct PICCommonState {
uint8_t single_mode; /* true if slave pic is not initialized */
uint8_t elcr; /* PIIX edge/trigger selection*/
uint8_t elcr_mask;
+ uint8_t ltim; /* Edge/Level Bank Select (pre-PIIX, chip-wide) */
qemu_irq int_out[1];
uint32_t master; /* reflects /SP input pin */
uint32_t iobase;
@@ -78,8 +73,5 @@ struct PICCommonState {
void pic_reset_common(PICCommonState *s);
ISADevice *i8259_init_chip(const char *name, ISABus *bus, bool master);
void pic_stat_update_irq(int irq, int level);
-bool pic_get_statistics(InterruptStatsProvider *obj,
- uint64_t **irq_counts, unsigned int *nb_irqs);
-void pic_print_info(InterruptStatsProvider *obj, Monitor *mon);
#endif /* QEMU_I8259_INTERNAL_H */
diff --git a/include/hw/isa/isa.h b/include/hw/isa/isa.h
index 52b61eed88..40d6224a4e 100644
--- a/include/hw/isa/isa.h
+++ b/include/hw/isa/isa.h
@@ -6,40 +6,21 @@
#include "exec/memory.h"
#include "exec/ioport.h"
#include "hw/qdev-core.h"
+#include "qom/object.h"
#define ISA_NUM_IRQS 16
#define TYPE_ISA_DEVICE "isa-device"
-#define ISA_DEVICE(obj) \
- OBJECT_CHECK(ISADevice, (obj), TYPE_ISA_DEVICE)
-#define ISA_DEVICE_CLASS(klass) \
- OBJECT_CLASS_CHECK(ISADeviceClass, (klass), TYPE_ISA_DEVICE)
-#define ISA_DEVICE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(ISADeviceClass, (obj), TYPE_ISA_DEVICE)
+OBJECT_DECLARE_SIMPLE_TYPE(ISADevice, ISA_DEVICE)
#define TYPE_ISA_BUS "ISA"
-#define ISA_BUS(obj) OBJECT_CHECK(ISABus, (obj), TYPE_ISA_BUS)
-
-#define TYPE_APPLE_SMC "isa-applesmc"
-#define APPLESMC_MAX_DATA_LENGTH 32
-#define APPLESMC_PROP_IO_BASE "iobase"
-
-static inline uint16_t applesmc_port(void)
-{
- Object *obj = object_resolve_path_type("", TYPE_APPLE_SMC, NULL);
-
- if (obj) {
- return object_property_get_uint(obj, APPLESMC_PROP_IO_BASE, NULL);
- }
- return 0;
-}
+OBJECT_DECLARE_SIMPLE_TYPE(ISABus, ISA_BUS)
#define TYPE_ISADMA "isa-dma"
-#define ISADMA_CLASS(klass) \
- OBJECT_CLASS_CHECK(IsaDmaClass, (klass), TYPE_ISADMA)
-#define ISADMA_GET_CLASS(obj) \
- OBJECT_GET_CLASS(IsaDmaClass, (obj), TYPE_ISADMA)
+typedef struct IsaDmaClass IsaDmaClass;
+DECLARE_CLASS_CHECKERS(IsaDmaClass, ISADMA,
+ TYPE_ISADMA)
#define ISADMA(obj) \
INTERFACE_CHECK(IsaDma, (obj), TYPE_ISADMA)
@@ -53,7 +34,7 @@ typedef enum {
typedef int (*IsaDmaTransferHandler)(void *opaque, int nchan, int pos,
int size);
-typedef struct IsaDmaClass {
+struct IsaDmaClass {
InterfaceClass parent;
bool (*has_autoinitialization)(IsaDma *obj, int nchan);
@@ -65,12 +46,7 @@ typedef struct IsaDmaClass {
void (*register_channel)(IsaDma *obj, int nchan,
IsaDmaTransferHandler transfer_handler,
void *opaque);
-} IsaDmaClass;
-
-typedef struct ISADeviceClass {
- DeviceClass parent_class;
- void (*build_aml)(ISADevice *dev, Aml *scope);
-} ISADeviceClass;
+};
struct ISABus {
/*< private >*/
@@ -79,7 +55,7 @@ struct ISABus {
MemoryRegion *address_space;
MemoryRegion *address_space_io;
- qemu_irq *irqs;
+ qemu_irq *irqs_in;
IsaDma *dma[2];
};
@@ -88,28 +64,34 @@ struct ISADevice {
DeviceState parent_obj;
/*< public >*/
- int8_t isairq[2]; /* -1 = unassigned */
- int nirqs;
int ioport_id;
};
ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space,
MemoryRegion *address_space_io, Error **errp);
-void isa_bus_irqs(ISABus *bus, qemu_irq *irqs);
-qemu_irq isa_get_irq(ISADevice *dev, unsigned isairq);
-void isa_init_irq(ISADevice *dev, qemu_irq *p, unsigned isairq);
-void isa_connect_gpio_out(ISADevice *isadev, int gpioirq, unsigned isairq);
+void isa_bus_register_input_irqs(ISABus *bus, qemu_irq *irqs_in);
void isa_bus_dma(ISABus *bus, IsaDma *dma8, IsaDma *dma16);
-IsaDma *isa_get_dma(ISABus *bus, int nchan);
-MemoryRegion *isa_address_space(ISADevice *dev);
-MemoryRegion *isa_address_space_io(ISADevice *dev);
+IsaDma *isa_bus_get_dma(ISABus *bus, int nchan);
+/**
+ * isa_bus_get_irq: Return input IRQ on ISA bus.
+ * @bus: the #ISABus to plug ISA devices on.
+ * @irqnum: the ISA IRQ number.
+ *
+ * Return IRQ @irqnum from the PIC associated on ISA @bus.
+ */
+qemu_irq isa_bus_get_irq(ISABus *bus, unsigned irqnum);
ISADevice *isa_new(const char *name);
ISADevice *isa_try_new(const char *name);
bool isa_realize_and_unref(ISADevice *dev, ISABus *bus, Error **errp);
ISADevice *isa_create_simple(ISABus *bus, const char *name);
ISADevice *isa_vga_init(ISABus *bus);
-void isa_build_aml(ISABus *bus, Aml *scope);
+
+qemu_irq isa_get_irq(ISADevice *dev, unsigned isairq);
+void isa_connect_gpio_out(ISADevice *isadev, int gpioirq, unsigned isairq);
+MemoryRegion *isa_address_space(ISADevice *dev);
+MemoryRegion *isa_address_space_io(ISADevice *dev);
+ISABus *isa_bus_from_device(ISADevice *dev);
/**
* isa_register_ioport: Install an I/O port region on the ISA bus.
@@ -137,18 +119,14 @@ void isa_register_ioport(ISADevice *dev, MemoryRegion *io, uint16_t start);
* @portio: the ports, sorted by offset.
* @opaque: passed into the portio callbacks.
* @name: passed into memory_region_init_io.
+ *
+ * Returns: 0 on success, negative error code otherwise (e.g. if the
+ * ISA bus is not available)
*/
-void isa_register_portio_list(ISADevice *dev,
- PortioList *piolist,
- uint16_t start,
- const MemoryRegionPortio *portio,
- void *opaque, const char *name);
-
-static inline ISABus *isa_bus_from_device(ISADevice *d)
-{
- return ISA_BUS(qdev_get_parent_bus(DEVICE(d)));
-}
-
-#define TYPE_PIIX4_PCI_DEVICE "piix4-isa"
+int isa_register_portio_list(ISADevice *dev,
+ PortioList *piolist,
+ uint16_t start,
+ const MemoryRegionPortio *portio,
+ void *opaque, const char *name);
#endif
diff --git a/include/hw/isa/pc87312.h b/include/hw/isa/pc87312.h
index e16263d4b1..edaf723f4d 100644
--- a/include/hw/isa/pc87312.h
+++ b/include/hw/isa/pc87312.h
@@ -26,12 +26,13 @@
#define QEMU_PC87312_H
#include "hw/isa/superio.h"
+#include "qom/object.h"
-#define TYPE_PC87312_SUPERIO "pc87312"
-#define PC87312(obj) OBJECT_CHECK(PC87312State, (obj), TYPE_PC87312_SUPERIO)
+#define TYPE_PC87312 "pc87312"
+OBJECT_DECLARE_SIMPLE_TYPE(PC87312State, PC87312)
-typedef struct PC87312State {
+struct PC87312State {
/*< private >*/
ISASuperIODevice parent_dev;
/*< public >*/
@@ -49,7 +50,7 @@ typedef struct PC87312State {
uint8_t selected_index;
uint8_t regs[3];
-} PC87312State;
+};
#endif
diff --git a/include/hw/isa/superio.h b/include/hw/isa/superio.h
index 147cc0a7b7..0dc45104d4 100644
--- a/include/hw/isa/superio.h
+++ b/include/hw/isa/superio.h
@@ -12,18 +12,17 @@
#include "sysemu/sysemu.h"
#include "hw/isa/isa.h"
+#include "qom/object.h"
#define TYPE_ISA_SUPERIO "isa-superio"
-#define ISA_SUPERIO(obj) \
- OBJECT_CHECK(ISASuperIODevice, (obj), TYPE_ISA_SUPERIO)
-#define ISA_SUPERIO_GET_CLASS(obj) \
- OBJECT_GET_CLASS(ISASuperIOClass, (obj), TYPE_ISA_SUPERIO)
-#define ISA_SUPERIO_CLASS(klass) \
- OBJECT_CLASS_CHECK(ISASuperIOClass, (klass), TYPE_ISA_SUPERIO)
+typedef struct ISASuperIOClass ISASuperIOClass;
+typedef struct ISASuperIODevice ISASuperIODevice;
+DECLARE_OBJ_CHECKERS(ISASuperIODevice, ISASuperIOClass,
+ ISA_SUPERIO, TYPE_ISA_SUPERIO)
#define SUPERIO_MAX_SERIAL_PORTS 4
-typedef struct ISASuperIODevice {
+struct ISASuperIODevice {
/*< private >*/
ISADevice parent_obj;
/*< public >*/
@@ -33,7 +32,7 @@ typedef struct ISASuperIODevice {
ISADevice *floppy;
ISADevice *kbc;
ISADevice *ide;
-} ISASuperIODevice;
+};
typedef struct ISASuperIOFuncs {
size_t count;
@@ -43,9 +42,9 @@ typedef struct ISASuperIOFuncs {
unsigned int (*get_dma)(ISASuperIODevice *sio, uint8_t index);
} ISASuperIOFuncs;
-typedef struct ISASuperIOClass {
+struct ISASuperIOClass {
/*< private >*/
- ISADeviceClass parent_class;
+ DeviceClass parent_class;
/*< public >*/
DeviceRealize parent_realize;
@@ -53,7 +52,7 @@ typedef struct ISASuperIOClass {
ISASuperIOFuncs serial;
ISASuperIOFuncs floppy;
ISASuperIOFuncs ide;
-} ISASuperIOClass;
+};
#define TYPE_FDC37M81X_SUPERIO "fdc37m81x-superio"
#define TYPE_SMC37C669_SUPERIO "smc37c669-superio"
diff --git a/include/hw/isa/vt82c686.h b/include/hw/isa/vt82c686.h
index f23f45dfb1..da1722daf2 100644
--- a/include/hw/isa/vt82c686.h
+++ b/include/hw/isa/vt82c686.h
@@ -1,14 +1,39 @@
#ifndef HW_VT82C686_H
#define HW_VT82C686_H
+#include "hw/pci/pci_device.h"
+#include "audio/audio.h"
-#define TYPE_VT82C686B_SUPERIO "vt82c686b-superio"
+#define TYPE_VT82C686B_ISA "vt82c686b-isa"
+#define TYPE_VT82C686B_USB_UHCI "vt82c686b-usb-uhci"
+#define TYPE_VT8231_ISA "vt8231-isa"
+#define TYPE_VIA_AC97 "via-ac97"
+#define TYPE_VIA_IDE "via-ide"
+#define TYPE_VIA_MC97 "via-mc97"
-/* vt82c686.c */
-ISABus *vt82c686b_isa_init(PCIBus * bus, int devfn);
-void vt82c686b_ac97_init(PCIBus *bus, int devfn);
-void vt82c686b_mc97_init(PCIBus *bus, int devfn);
-I2CBus *vt82c686b_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
- qemu_irq sci_irq);
+typedef struct {
+ uint8_t stat;
+ uint8_t type;
+ uint32_t base;
+ uint32_t curr;
+ uint32_t addr;
+ uint32_t clen;
+} ViaAC97SGDChannel;
+
+OBJECT_DECLARE_SIMPLE_TYPE(ViaAC97State, VIA_AC97);
+
+struct ViaAC97State {
+ PCIDevice dev;
+ QEMUSoundCard card;
+ MemoryRegion sgd;
+ MemoryRegion fm;
+ MemoryRegion midi;
+ SWVoiceOut *vo;
+ ViaAC97SGDChannel aur;
+ uint16_t codec_regs[128];
+ uint32_t ac97_cmd;
+};
+
+void via_isa_set_irq(PCIDevice *d, int n, int level);
#endif
diff --git a/include/hw/kvm/clock.h b/include/hw/kvm/clock.h
deleted file mode 100644
index 81c66b2302..0000000000
--- a/include/hw/kvm/clock.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * QEMU KVM support, paravirtual clock device
- *
- * Copyright (C) 2011 Siemens AG
- *
- * Authors:
- * Jan Kiszka <jan.kiszka@siemens.com>
- *
- * This work is licensed under the terms of the GNU GPL version 2.
- * See the COPYING file in the top-level directory.
- */
-
-#ifndef HW_KVM_CLOCK_H
-#define HW_KVM_CLOCK_H
-
-#ifdef CONFIG_KVM
-
-void kvmclock_create(void);
-
-#else /* CONFIG_KVM */
-
-static inline void kvmclock_create(void)
-{
-}
-
-#endif /* !CONFIG_KVM */
-
-#endif
diff --git a/include/hw/lm32/lm32_pic.h b/include/hw/lm32/lm32_pic.h
deleted file mode 100644
index 9e5e038437..0000000000
--- a/include/hw/lm32/lm32_pic.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef QEMU_HW_LM32_PIC_H
-#define QEMU_HW_LM32_PIC_H
-
-
-uint32_t lm32_pic_get_ip(DeviceState *d);
-uint32_t lm32_pic_get_im(DeviceState *d);
-void lm32_pic_set_ip(DeviceState *d, uint32_t ip);
-void lm32_pic_set_im(DeviceState *d, uint32_t im);
-
-#endif /* QEMU_HW_LM32_PIC_H */
diff --git a/include/hw/loader-fit.h b/include/hw/loader-fit.h
index 0284c3e02c..0832e379dc 100644
--- a/include/hw/loader-fit.h
+++ b/include/hw/loader-fit.h
@@ -6,7 +6,7 @@
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/include/hw/loader.h b/include/hw/loader.h
index a9eeea3952..8685e27334 100644
--- a/include/hw/loader.h
+++ b/include/hw/loader.h
@@ -40,8 +40,8 @@ ssize_t load_image_size(const char *filename, void *addr, size_t size);
*
* Returns the size of the loaded image on success, -1 otherwise.
*/
-int load_image_targphys_as(const char *filename,
- hwaddr addr, uint64_t max_sz, AddressSpace *as);
+ssize_t load_image_targphys_as(const char *filename,
+ hwaddr addr, uint64_t max_sz, AddressSpace *as);
/**load_targphys_hex_as:
* @filename: Path to the .hex file
@@ -53,14 +53,15 @@ int load_image_targphys_as(const char *filename,
*
* Returns the size of the loaded .hex file on success, -1 otherwise.
*/
-int load_targphys_hex_as(const char *filename, hwaddr *entry, AddressSpace *as);
+ssize_t load_targphys_hex_as(const char *filename, hwaddr *entry,
+ AddressSpace *as);
/** load_image_targphys:
* Same as load_image_targphys_as(), but doesn't allow the caller to specify
* an AddressSpace.
*/
-int load_image_targphys(const char *filename, hwaddr,
- uint64_t max_sz);
+ssize_t load_image_targphys(const char *filename, hwaddr,
+ uint64_t max_sz);
/**
* load_image_mr: load an image into a memory region
@@ -73,7 +74,7 @@ int load_image_targphys(const char *filename, hwaddr,
* If the file is larger than the memory region's size the call will fail.
* Returns -1 on failure, or the size of the file.
*/
-int load_image_mr(const char *filename, MemoryRegion *mr);
+ssize_t load_image_mr(const char *filename, MemoryRegion *mr);
/* This is the limit on the maximum uncompressed image size that
* load_image_gzipped_buffer() and load_image_gzipped() will read. It prevents
@@ -81,16 +82,35 @@ int load_image_mr(const char *filename, MemoryRegion *mr);
*/
#define LOAD_IMAGE_MAX_GUNZIP_BYTES (256 << 20)
-int load_image_gzipped_buffer(const char *filename, uint64_t max_sz,
- uint8_t **buffer);
-int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz);
+ssize_t load_image_gzipped_buffer(const char *filename, uint64_t max_sz,
+ uint8_t **buffer);
+ssize_t load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz);
+
+/**
+ * unpack_efi_zboot_image:
+ * @buffer: pointer to a variable holding the address of a buffer containing the
+ * image
+ * @size: pointer to a variable holding the size of the buffer
+ *
+ * Check whether the buffer contains a EFI zboot image, and if it does, extract
+ * the compressed payload and decompress it into a new buffer. If successful,
+ * the old buffer is freed, and the *buffer and size variables pointed to by the
+ * function arguments are updated to refer to the newly populated buffer.
+ *
+ * Returns 0 if the image could not be identified as a EFI zboot image.
+ * Returns -1 if the buffer contents were identified as a EFI zboot image, but
+ * unpacking failed for any reason.
+ * Returns the size of the decompressed payload if decompression was performed
+ * successfully.
+ */
+ssize_t unpack_efi_zboot_image(uint8_t **buffer, int *size);
#define ELF_LOAD_FAILED -1
#define ELF_LOAD_NOT_ELF -2
#define ELF_LOAD_WRONG_ARCH -3
#define ELF_LOAD_WRONG_ENDIAN -4
#define ELF_LOAD_TOO_BIG -5
-const char *load_elf_strerror(int error);
+const char *load_elf_strerror(ssize_t error);
/** load_elf_ram_sym:
* @filename: Path of ELF file
@@ -128,48 +148,48 @@ const char *load_elf_strerror(int error);
typedef void (*symbol_fn_t)(const char *st_name, int st_info,
uint64_t st_value, uint64_t st_size);
-int load_elf_ram_sym(const char *filename,
- uint64_t (*elf_note_fn)(void *, void *, bool),
- uint64_t (*translate_fn)(void *, uint64_t),
- void *translate_opaque, uint64_t *pentry,
- uint64_t *lowaddr, uint64_t *highaddr, uint32_t *pflags,
- int big_endian, int elf_machine,
- int clear_lsb, int data_swab,
- AddressSpace *as, bool load_rom, symbol_fn_t sym_cb);
+ssize_t load_elf_ram_sym(const char *filename,
+ uint64_t (*elf_note_fn)(void *, void *, bool),
+ uint64_t (*translate_fn)(void *, uint64_t),
+ void *translate_opaque, uint64_t *pentry,
+ uint64_t *lowaddr, uint64_t *highaddr,
+ uint32_t *pflags, int big_endian, int elf_machine,
+ int clear_lsb, int data_swab,
+ AddressSpace *as, bool load_rom, symbol_fn_t sym_cb);
/** load_elf_ram:
* Same as load_elf_ram_sym(), but doesn't allow the caller to specify a
* symbol callback function
*/
-int load_elf_ram(const char *filename,
- uint64_t (*elf_note_fn)(void *, void *, bool),
- uint64_t (*translate_fn)(void *, uint64_t),
- void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
- uint64_t *highaddr, uint32_t *pflags, int big_endian,
- int elf_machine, int clear_lsb, int data_swab,
- AddressSpace *as, bool load_rom);
+ssize_t load_elf_ram(const char *filename,
+ uint64_t (*elf_note_fn)(void *, void *, bool),
+ uint64_t (*translate_fn)(void *, uint64_t),
+ void *translate_opaque, uint64_t *pentry,
+ uint64_t *lowaddr, uint64_t *highaddr, uint32_t *pflags,
+ int big_endian, int elf_machine, int clear_lsb,
+ int data_swab, AddressSpace *as, bool load_rom);
/** load_elf_as:
* Same as load_elf_ram(), but always loads the elf as ROM
*/
-int load_elf_as(const char *filename,
- uint64_t (*elf_note_fn)(void *, void *, bool),
- uint64_t (*translate_fn)(void *, uint64_t),
- void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
- uint64_t *highaddr, uint32_t *pflags, int big_endian,
- int elf_machine, int clear_lsb, int data_swab,
- AddressSpace *as);
+ssize_t load_elf_as(const char *filename,
+ uint64_t (*elf_note_fn)(void *, void *, bool),
+ uint64_t (*translate_fn)(void *, uint64_t),
+ void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
+ uint64_t *highaddr, uint32_t *pflags, int big_endian,
+ int elf_machine, int clear_lsb, int data_swab,
+ AddressSpace *as);
/** load_elf:
* Same as load_elf_as(), but doesn't allow the caller to specify an
* AddressSpace.
*/
-int load_elf(const char *filename,
- uint64_t (*elf_note_fn)(void *, void *, bool),
- uint64_t (*translate_fn)(void *, uint64_t),
- void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
- uint64_t *highaddr, uint32_t *pflags, int big_endian,
- int elf_machine, int clear_lsb, int data_swab);
+ssize_t load_elf(const char *filename,
+ uint64_t (*elf_note_fn)(void *, void *, bool),
+ uint64_t (*translate_fn)(void *, uint64_t),
+ void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
+ uint64_t *highaddr, uint32_t *pflags, int big_endian,
+ int elf_machine, int clear_lsb, int data_swab);
/** load_elf_hdr:
* @filename: Path of ELF file
@@ -183,8 +203,8 @@ int load_elf(const char *filename,
*/
void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp);
-int load_aout(const char *filename, hwaddr addr, int max_sz,
- int bswap_needed, hwaddr target_page_size);
+ssize_t load_aout(const char *filename, hwaddr addr, int max_sz,
+ int bswap_needed, hwaddr target_page_size);
#define LOAD_UIMAGE_LOADADDR_INVALID (-1)
@@ -205,19 +225,19 @@ int load_aout(const char *filename, hwaddr addr, int max_sz,
*
* Returns the size of the loaded image on success, -1 otherwise.
*/
-int load_uimage_as(const char *filename, hwaddr *ep,
- hwaddr *loadaddr, int *is_linux,
- uint64_t (*translate_fn)(void *, uint64_t),
- void *translate_opaque, AddressSpace *as);
+ssize_t load_uimage_as(const char *filename, hwaddr *ep,
+ hwaddr *loadaddr, int *is_linux,
+ uint64_t (*translate_fn)(void *, uint64_t),
+ void *translate_opaque, AddressSpace *as);
/** load_uimage:
* Same as load_uimage_as(), but doesn't allow the caller to specify an
* AddressSpace.
*/
-int load_uimage(const char *filename, hwaddr *ep,
- hwaddr *loadaddr, int *is_linux,
- uint64_t (*translate_fn)(void *, uint64_t),
- void *translate_opaque);
+ssize_t load_uimage(const char *filename, hwaddr *ep,
+ hwaddr *loadaddr, int *is_linux,
+ uint64_t (*translate_fn)(void *, uint64_t),
+ void *translate_opaque);
/**
* load_ramdisk_as:
@@ -232,15 +252,15 @@ int load_uimage(const char *filename, hwaddr *ep,
*
* Returns the size of the loaded image on success, -1 otherwise.
*/
-int load_ramdisk_as(const char *filename, hwaddr addr, uint64_t max_sz,
- AddressSpace *as);
+ssize_t load_ramdisk_as(const char *filename, hwaddr addr, uint64_t max_sz,
+ AddressSpace *as);
/**
* load_ramdisk:
* Same as load_ramdisk_as(), but doesn't allow the caller to specify
* an AddressSpace.
*/
-int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz);
+ssize_t load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz);
ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src, size_t srclen);
@@ -250,12 +270,9 @@ void pstrcpy_targphys(const char *name,
hwaddr dest, int buf_size,
const char *source);
-extern bool option_rom_has_mr;
-extern bool rom_file_has_mr;
-
-int rom_add_file(const char *file, const char *fw_dir,
- hwaddr addr, int32_t bootindex,
- bool option_rom, MemoryRegion *mr, AddressSpace *as);
+ssize_t rom_add_file(const char *file, const char *fw_dir,
+ hwaddr addr, int32_t bootindex,
+ bool has_option_rom, MemoryRegion *mr, AddressSpace *as);
MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len,
size_t max_len, hwaddr addr,
const char *fw_file_name,
@@ -290,6 +307,37 @@ void rom_transaction_end(bool commit);
int rom_copy(uint8_t *dest, hwaddr addr, size_t size);
void *rom_ptr(hwaddr addr, size_t size);
+/**
+ * rom_ptr_for_as: Return a pointer to ROM blob data for the address
+ * @as: AddressSpace to look for the ROM blob in
+ * @addr: Address within @as
+ * @size: size of data required in bytes
+ *
+ * Returns: pointer into the data which backs the matching ROM blob,
+ * or NULL if no blob covers the address range.
+ *
+ * This function looks for a ROM blob which covers the specified range
+ * of bytes of length @size starting at @addr within the address space
+ * @as. This is useful for code which runs as part of board
+ * initialization or CPU reset which wants to read data that is part
+ * of a user-supplied guest image or other guest memory contents, but
+ * which runs before the ROM loader's reset function has copied the
+ * blobs into guest memory.
+ *
+ * rom_ptr_for_as() will look not just for blobs loaded directly to
+ * the specified address, but also for blobs which were loaded to an
+ * alias of the region at a different location in the AddressSpace.
+ * In other words, if a machine model has RAM at address 0x0000_0000
+ * which is aliased to also appear at 0x1000_0000, rom_ptr_for_as()
+ * will return the correct data whether the guest image was linked and
+ * loaded at 0x0000_0000 or 0x1000_0000. Contrast rom_ptr(), which
+ * will only return data if the image load address is an exact match
+ * with the queried address.
+ *
+ * New code should prefer to use rom_ptr_for_as() instead of
+ * rom_ptr().
+ */
+void *rom_ptr_for_as(AddressSpace *as, hwaddr addr, size_t size);
void hmp_info_roms(Monitor *mon, const QDict *qdict);
#define rom_add_file_fixed(_f, _a, _i) \
@@ -305,17 +353,25 @@ void hmp_info_roms(Monitor *mon, const QDict *qdict);
#define rom_add_blob_fixed_as(_f, _b, _l, _a, _as) \
rom_add_blob(_f, _b, _l, _l, _a, NULL, NULL, NULL, _as, true)
-#define PC_ROM_MIN_VGA 0xc0000
-#define PC_ROM_MIN_OPTION 0xc8000
-#define PC_ROM_MAX 0xe0000
-#define PC_ROM_ALIGN 0x800
-#define PC_ROM_SIZE (PC_ROM_MAX - PC_ROM_MIN_VGA)
-
-int rom_add_vga(const char *file);
-int rom_add_option(const char *file, int32_t bootindex);
+ssize_t rom_add_vga(const char *file);
+ssize_t rom_add_option(const char *file, int32_t bootindex);
/* This is the usual maximum in uboot, so if a uImage overflows this, it would
* overflow on real hardware too. */
#define UBOOT_MAX_GUNZIP_BYTES (64 << 20)
+typedef struct RomGap {
+ hwaddr base;
+ size_t size;
+} RomGap;
+
+/**
+ * rom_find_largest_gap_between: return largest gap between ROMs in given range
+ *
+ * Given a range of addresses, this function finds the largest
+ * contiguous subrange which has no ROMs loaded to it. That is,
+ * it finds the biggest gap which is free for use for other things.
+ */
+RomGap rom_find_largest_gap_between(hwaddr base, size_t size);
+
#endif
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
new file mode 100644
index 0000000000..252f7df7f4
--- /dev/null
+++ b/include/hw/loongarch/virt.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Definitions for loongarch board emulation.
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef HW_LOONGARCH_H
+#define HW_LOONGARCH_H
+
+#include "target/loongarch/cpu.h"
+#include "hw/boards.h"
+#include "qemu/queue.h"
+#include "hw/intc/loongarch_ipi.h"
+#include "hw/block/flash.h"
+
+#define LOONGARCH_MAX_CPUS 256
+
+#define VIRT_FWCFG_BASE 0x1e020000UL
+#define VIRT_BIOS_BASE 0x1c000000UL
+#define VIRT_BIOS_SIZE (16 * MiB)
+#define VIRT_FLASH_SECTOR_SIZE (128 * KiB)
+#define VIRT_FLASH0_BASE VIRT_BIOS_BASE
+#define VIRT_FLASH0_SIZE VIRT_BIOS_SIZE
+#define VIRT_FLASH1_BASE 0x1d000000UL
+#define VIRT_FLASH1_SIZE (16 * MiB)
+
+#define VIRT_LOWMEM_BASE 0
+#define VIRT_LOWMEM_SIZE 0x10000000
+#define VIRT_HIGHMEM_BASE 0x80000000
+#define VIRT_GED_EVT_ADDR 0x100e0000
+#define VIRT_GED_MEM_ADDR (VIRT_GED_EVT_ADDR + ACPI_GED_EVT_SEL_LEN)
+#define VIRT_GED_REG_ADDR (VIRT_GED_MEM_ADDR + MEMORY_HOTPLUG_IO_LEN)
+
+struct LoongArchMachineState {
+ /*< private >*/
+ MachineState parent_obj;
+
+ MemoryRegion lowmem;
+ MemoryRegion highmem;
+ MemoryRegion bios;
+ bool bios_loaded;
+ /* State for other subsystems/APIs: */
+ FWCfgState *fw_cfg;
+ Notifier machine_done;
+ Notifier powerdown_notifier;
+ OnOffAuto acpi;
+ char *oem_id;
+ char *oem_table_id;
+ DeviceState *acpi_ged;
+ int fdt_size;
+ DeviceState *platform_bus_dev;
+ PCIBus *pci_bus;
+ PFlashCFI01 *flash[2];
+ MemoryRegion system_iocsr;
+ MemoryRegion iocsr_mem;
+ AddressSpace as_iocsr;
+};
+
+#define TYPE_LOONGARCH_MACHINE MACHINE_TYPE_NAME("virt")
+OBJECT_DECLARE_SIMPLE_TYPE(LoongArchMachineState, LOONGARCH_MACHINE)
+bool loongarch_is_acpi_enabled(LoongArchMachineState *lams);
+void loongarch_acpi_setup(LoongArchMachineState *lams);
+#endif
diff --git a/include/hw/m68k/mcf.h b/include/hw/m68k/mcf.h
index 0db49c5e60..5d9f876ffe 100644
--- a/include/hw/m68k/mcf.h
+++ b/include/hw/m68k/mcf.h
@@ -2,6 +2,7 @@
#define HW_MCF_H
/* Motorola ColdFire device prototypes. */
+#include "exec/hwaddr.h"
#include "target/m68k/cpu-qom.h"
/* mcf_uart.c */
@@ -9,8 +10,8 @@ uint64_t mcf_uart_read(void *opaque, hwaddr addr,
unsigned size);
void mcf_uart_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size);
-void *mcf_uart_init(qemu_irq irq, Chardev *chr);
-void mcf_uart_mm_init(hwaddr base, qemu_irq irq, Chardev *chr);
+DeviceState *mcf_uart_create(qemu_irq irq, Chardev *chr);
+DeviceState *mcf_uart_create_mmap(hwaddr base, qemu_irq irq, Chardev *chr);
/* mcf_intc.c */
qemu_irq *mcf_intc_init(struct MemoryRegion *sysmem,
@@ -18,7 +19,6 @@ qemu_irq *mcf_intc_init(struct MemoryRegion *sysmem,
M68kCPU *cpu);
/* mcf5206.c */
-qemu_irq *mcf5206_init(struct MemoryRegion *sysmem,
- uint32_t base, M68kCPU *cpu);
+#define TYPE_MCF5206_MBAR "mcf5206-mbar"
#endif
diff --git a/include/hw/m68k/mcf_fec.h b/include/hw/m68k/mcf_fec.h
index eeb471f9c9..80d4f651ba 100644
--- a/include/hw/m68k/mcf_fec.h
+++ b/include/hw/m68k/mcf_fec.h
@@ -9,9 +9,10 @@
#ifndef HW_M68K_MCF_FEC_H
#define HW_M68K_MCF_FEC_H
+#include "qom/object.h"
#define TYPE_MCF_FEC_NET "mcf-fec"
-#define MCF_FEC_NET(obj) OBJECT_CHECK(mcf_fec_state, (obj), TYPE_MCF_FEC_NET)
+OBJECT_DECLARE_SIMPLE_TYPE(mcf_fec_state, MCF_FEC_NET)
#define FEC_NUM_IRQ 13
diff --git a/include/hw/m68k/next-cube.h b/include/hw/m68k/next-cube.h
index a3be2b32ab..43577282d1 100644
--- a/include/hw/m68k/next-cube.h
+++ b/include/hw/m68k/next-cube.h
@@ -1,3 +1,13 @@
+/*
+ * NeXT Cube
+ *
+ * Copyright (c) 2011 Bryce Lanham
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ */
#ifndef NEXT_CUBE_H
#define NEXT_CUBE_H
@@ -39,9 +49,8 @@ enum next_irqs {
NEXT_ENRX_DMA_I,
NEXT_SCSI_DMA_I,
NEXT_SCC_DMA_I,
- NEXT_SND_I
+ NEXT_SND_I,
+ NEXT_NUM_IRQS
};
-void next_irq(void *opaque, int number, int level);
-
#endif /* NEXT_CUBE_H */
diff --git a/include/hw/m68k/q800-glue.h b/include/hw/m68k/q800-glue.h
new file mode 100644
index 0000000000..04fac25f6c
--- /dev/null
+++ b/include/hw/m68k/q800-glue.h
@@ -0,0 +1,51 @@
+/*
+ * QEMU q800 logic GLUE (General Logic Unit)
+ *
+ * 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.
+ */
+
+#ifndef HW_Q800_GLUE_H
+#define HW_Q800_GLUE_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_GLUE "q800-glue"
+OBJECT_DECLARE_SIMPLE_TYPE(GLUEState, GLUE)
+
+struct GLUEState {
+ SysBusDevice parent_obj;
+
+ M68kCPU *cpu;
+ uint8_t ipr;
+ uint8_t auxmode;
+ qemu_irq irqs[2];
+ QEMUTimer *nmi_release;
+};
+
+#define GLUE_IRQ_IN_VIA1 0
+#define GLUE_IRQ_IN_VIA2 1
+#define GLUE_IRQ_IN_SONIC 2
+#define GLUE_IRQ_IN_ESCC 3
+#define GLUE_IRQ_IN_NMI 4
+#define GLUE_IRQ_IN_ASC 5
+
+#define GLUE_IRQ_NUBUS_9 0
+#define GLUE_IRQ_ASC 1
+
+#endif
diff --git a/include/hw/m68k/q800.h b/include/hw/m68k/q800.h
new file mode 100644
index 0000000000..34365c9860
--- /dev/null
+++ b/include/hw/m68k/q800.h
@@ -0,0 +1,78 @@
+/*
+ * QEMU Motorla 680x0 Macintosh hardware System Emulator
+ *
+ * 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.
+ */
+
+#ifndef HW_Q800_H
+#define HW_Q800_H
+
+#include "hw/boards.h"
+#include "qom/object.h"
+#include "target/m68k/cpu-qom.h"
+#include "exec/memory.h"
+#include "hw/m68k/q800-glue.h"
+#include "hw/misc/mac_via.h"
+#include "hw/net/dp8393x.h"
+#include "hw/char/escc.h"
+#include "hw/or-irq.h"
+#include "hw/scsi/esp.h"
+#include "hw/block/swim.h"
+#include "hw/nubus/mac-nubus-bridge.h"
+#include "hw/display/macfb.h"
+#include "hw/misc/djmemc.h"
+#include "hw/misc/iosb.h"
+#include "hw/audio/asc.h"
+
+/*
+ * The main Q800 machine
+ */
+
+struct Q800MachineState {
+ MachineState parent_obj;
+
+ bool easc;
+ M68kCPU cpu;
+ MemoryRegion rom;
+ MemoryRegion rom_alias;
+ GLUEState glue;
+ MOS6522Q800VIA1State via1;
+ MOS6522Q800VIA2State via2;
+ dp8393xState dp8393x;
+ MemoryRegion dp8393x_prom;
+ ESCCState escc;
+ OrIRQState escc_orgate;
+ SysBusESPState esp;
+ Swim swim;
+ MacNubusBridge mac_nubus_bridge;
+ MacfbNubusState macfb;
+ DJMEMCState djmemc;
+ IOSBState iosb;
+ ASCState asc;
+ MemoryRegion ramio;
+ MemoryRegion macio;
+ MemoryRegion macio_alias;
+ MemoryRegion machine_id;
+ MemoryRegion escc_alias;
+};
+
+#define TYPE_Q800_MACHINE MACHINE_TYPE_NAME("q800")
+OBJECT_DECLARE_SIMPLE_TYPE(Q800MachineState, Q800_MACHINE)
+
+#endif
diff --git a/include/hw/mem/memory-device.h b/include/hw/mem/memory-device.h
index 04476acb8f..e0571c8a31 100644
--- a/include/hw/mem/memory-device.h
+++ b/include/hw/mem/memory-device.h
@@ -14,15 +14,14 @@
#define MEMORY_DEVICE_H
#include "hw/qdev-core.h"
-#include "qapi/qapi-types-misc.h"
+#include "qapi/qapi-types-machine.h"
#include "qom/object.h"
#define TYPE_MEMORY_DEVICE "memory-device"
-#define MEMORY_DEVICE_CLASS(klass) \
- OBJECT_CLASS_CHECK(MemoryDeviceClass, (klass), TYPE_MEMORY_DEVICE)
-#define MEMORY_DEVICE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(MemoryDeviceClass, (obj), TYPE_MEMORY_DEVICE)
+typedef struct MemoryDeviceClass MemoryDeviceClass;
+DECLARE_CLASS_CHECKERS(MemoryDeviceClass, MEMORY_DEVICE,
+ TYPE_MEMORY_DEVICE)
#define MEMORY_DEVICE(obj) \
INTERFACE_CHECK(MemoryDeviceState, (obj), TYPE_MEMORY_DEVICE)
@@ -38,12 +37,27 @@ typedef struct MemoryDeviceState MemoryDeviceState;
* address in guest physical memory can either be specified explicitly
* or get assigned automatically.
*
+ * Some memory device might not own a memory region in certain device
+ * configurations. Such devices can logically get (un)plugged, however,
+ * empty memory devices are mostly ignored by the memory device code.
+ *
* Conceptually, memory devices only span one memory region. If multiple
* successive memory regions are used, a covering memory region has to
* be provided. Scattered memory regions are not supported for single
* devices.
+ *
+ * The device memory region returned via @get_memory_region may either be a
+ * single RAM memory region or a memory region container with subregions
+ * that are RAM memory regions or aliases to RAM memory regions. Other
+ * memory regions or subregions are not supported.
+ *
+ * If the device memory region returned via @get_memory_region is a
+ * memory region container, it's supported to dynamically (un)map subregions
+ * as long as the number of memslots returned by @get_memslots() won't
+ * be exceeded and as long as all memory regions are of the same kind (e.g.,
+ * all RAM or all ROM).
*/
-typedef struct MemoryDeviceClass {
+struct MemoryDeviceClass {
/* private */
InterfaceClass parent_class;
@@ -80,7 +94,8 @@ typedef struct MemoryDeviceClass {
uint64_t (*get_plugged_size)(const MemoryDeviceState *md, Error **errp);
/*
- * Return the memory region of the memory device.
+ * Return the memory region of the memory device. If the device is
+ * completely empty, returns NULL without an error.
*
* Called when (un)plugging the memory device, to (un)map the
* memory region in guest physical memory, but also to detect the
@@ -90,14 +105,69 @@ typedef struct MemoryDeviceClass {
MemoryRegion *(*get_memory_region)(MemoryDeviceState *md, Error **errp);
/*
+ * Optional: Instruct the memory device to decide how many memory slots
+ * it requires, not exceeding the given limit.
+ *
+ * Called exactly once when pre-plugging the memory device, before
+ * querying the number of memslots using @get_memslots the first time.
+ */
+ void (*decide_memslots)(MemoryDeviceState *md, unsigned int limit);
+
+ /*
+ * Optional for memory devices that require only a single memslot,
+ * required for all other memory devices: Return the number of memslots
+ * (distinct RAM memory regions in the device memory region) that are
+ * required by the device.
+ *
+ * If this function is not implemented, the assumption is "1".
+ *
+ * Called when (un)plugging the memory device, to check if the requirements
+ * can be satisfied, and to do proper accounting.
+ */
+ unsigned int (*get_memslots)(MemoryDeviceState *md);
+
+ /*
+ * Optional: Return the desired minimum alignment of the device in guest
+ * physical address space. The final alignment is computed based on this
+ * alignment and the alignment requirements of the memory region.
+ *
+ * Called when plugging the memory device to detect the required alignment
+ * during address assignment.
+ */
+ uint64_t (*get_min_alignment)(const MemoryDeviceState *md);
+
+ /*
* Translate the memory device into #MemoryDeviceInfo.
*/
void (*fill_device_info)(const MemoryDeviceState *md,
MemoryDeviceInfo *info);
-} MemoryDeviceClass;
+};
+
+/*
+ * Traditionally, KVM/vhost in many setups supported 509 memslots, whereby
+ * 253 memslots were "reserved" for boot memory and other devices (such
+ * as PCI BARs, which can get mapped dynamically) and 256 memslots were
+ * dedicated for DIMMs. These magic numbers worked reliably in the past.
+ *
+ * Further, using many memslots can negatively affect performance, so setting
+ * the soft-limit of memslots used by memory devices to the traditional
+ * DIMM limit of 256 sounds reasonable.
+ *
+ * If we have less than 509 memslots, we will instruct memory devices that
+ * support automatically deciding how many memslots to use to only use a single
+ * one.
+ *
+ * Hotplugging vhost devices with at least 509 memslots is not expected to
+ * cause problems, not even when devices automatically decided how many memslots
+ * to use.
+ */
+#define MEMORY_DEVICES_SOFT_MEMSLOT_LIMIT 256
+#define MEMORY_DEVICES_SAFE_MAX_MEMSLOTS 509
MemoryDeviceInfoList *qmp_memory_device_list(void);
uint64_t get_plugged_memory_size(void);
+unsigned int memory_devices_get_reserved_memslots(void);
+bool memory_devices_memslot_auto_decision_active(void);
void memory_device_pre_plug(MemoryDeviceState *md, MachineState *ms,
const uint64_t *legacy_align, Error **errp);
void memory_device_plug(MemoryDeviceState *md, MachineState *ms);
diff --git a/include/hw/mem/npcm7xx_mc.h b/include/hw/mem/npcm7xx_mc.h
new file mode 100644
index 0000000000..7ed38be243
--- /dev/null
+++ b/include/hw/mem/npcm7xx_mc.h
@@ -0,0 +1,36 @@
+/*
+ * Nuvoton NPCM7xx Memory Controller stub
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_MC_H
+#define NPCM7XX_MC_H
+
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+
+/**
+ * struct NPCM7xxMCState - Device state for the memory controller.
+ * @parent: System bus device.
+ * @mmio: Memory region through which registers are accessed.
+ */
+typedef struct NPCM7xxMCState {
+ SysBusDevice parent;
+
+ MemoryRegion mmio;
+} NPCM7xxMCState;
+
+#define TYPE_NPCM7XX_MC "npcm7xx-mc"
+#define NPCM7XX_MC(obj) OBJECT_CHECK(NPCM7xxMCState, (obj), TYPE_NPCM7XX_MC)
+
+#endif /* NPCM7XX_MC_H */
diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h
index b67a1aedf6..d3b763453a 100644
--- a/include/hw/mem/nvdimm.h
+++ b/include/hw/mem/nvdimm.h
@@ -27,14 +27,7 @@
#include "hw/acpi/bios-linker-loader.h"
#include "qemu/uuid.h"
#include "hw/acpi/aml-build.h"
-
-#define NVDIMM_DEBUG 0
-#define nvdimm_debug(fmt, ...) \
- do { \
- if (NVDIMM_DEBUG) { \
- fprintf(stderr, "nvdimm: " fmt, ## __VA_ARGS__); \
- } \
- } while (0)
+#include "qom/object.h"
/*
* The minimum label data size is required by NVDIMM Namespace
@@ -45,10 +38,7 @@
#define MIN_NAMESPACE_LABEL_SIZE (128UL << 10)
#define TYPE_NVDIMM "nvdimm"
-#define NVDIMM(obj) OBJECT_CHECK(NVDIMMDevice, (obj), TYPE_NVDIMM)
-#define NVDIMM_CLASS(oc) OBJECT_CLASS_CHECK(NVDIMMClass, (oc), TYPE_NVDIMM)
-#define NVDIMM_GET_CLASS(obj) OBJECT_GET_CLASS(NVDIMMClass, (obj), \
- TYPE_NVDIMM)
+OBJECT_DECLARE_TYPE(NVDIMMDevice, NVDIMMClass, NVDIMM)
#define NVDIMM_LABEL_SIZE_PROP "label-size"
#define NVDIMM_UUID_PROP "uuid"
@@ -88,11 +78,16 @@ struct NVDIMMDevice {
bool unarmed;
/*
+ * Whether our DIMM is backed by ROM, and even label data cannot be
+ * written. If set, implies that "unarmed" is also set.
+ */
+ bool readonly;
+
+ /*
* The PPC64 - spapr requires each nvdimm device have a uuid.
*/
QemuUUID uuid;
};
-typedef struct NVDIMMDevice NVDIMMDevice;
struct NVDIMMClass {
/* private */
@@ -106,8 +101,9 @@ struct NVDIMMClass {
/* write @size bytes from @buf to NVDIMM label data at @offset. */
void (*write_label_data)(NVDIMMDevice *nvdimm, const void *buf,
uint64_t size, uint64_t offset);
+ void (*realize)(NVDIMMDevice *nvdimm, Error **errp);
+ void (*unrealize)(NVDIMMDevice *nvdimm);
};
-typedef struct NVDIMMClass NVDIMMClass;
#define NVDIMM_DSM_MEM_FILE "etc/acpi/nvdimm-mem"
@@ -158,7 +154,8 @@ void nvdimm_init_acpi_state(NVDIMMState *state, MemoryRegion *io,
void nvdimm_build_srat(GArray *table_data);
void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
BIOSLinker *linker, NVDIMMState *state,
- uint32_t ram_slots);
+ uint32_t ram_slots, const char *oem_id,
+ const char *oem_table_id);
void nvdimm_plug(NVDIMMState *state);
void nvdimm_acpi_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev);
#endif
diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h
index 289edc0f3d..322bebe555 100644
--- a/include/hw/mem/pc-dimm.h
+++ b/include/hw/mem/pc-dimm.h
@@ -18,14 +18,11 @@
#include "exec/memory.h"
#include "hw/qdev-core.h"
+#include "qom/object.h"
#define TYPE_PC_DIMM "pc-dimm"
-#define PC_DIMM(obj) \
- OBJECT_CHECK(PCDIMMDevice, (obj), TYPE_PC_DIMM)
-#define PC_DIMM_CLASS(oc) \
- OBJECT_CLASS_CHECK(PCDIMMDeviceClass, (oc), TYPE_PC_DIMM)
-#define PC_DIMM_GET_CLASS(obj) \
- OBJECT_GET_CLASS(PCDIMMDeviceClass, (obj), TYPE_PC_DIMM)
+OBJECT_DECLARE_TYPE(PCDIMMDevice, PCDIMMDeviceClass,
+ PC_DIMM)
#define PC_DIMM_ADDR_PROP "addr"
#define PC_DIMM_SLOT_PROP "slot"
@@ -44,7 +41,7 @@
* Default value: -1, means that slot is auto-allocated.
* @hostmem: host memory backend providing memory for @PCDIMMDevice
*/
-typedef struct PCDIMMDevice {
+struct PCDIMMDevice {
/* private */
DeviceState parent_obj;
@@ -53,28 +50,24 @@ typedef struct PCDIMMDevice {
uint32_t node;
int32_t slot;
HostMemoryBackend *hostmem;
-} PCDIMMDevice;
+};
/**
* PCDIMMDeviceClass:
* @realize: called after common dimm is realized so that the dimm based
* devices get the chance to do specified operations.
- * @get_vmstate_memory_region: returns #MemoryRegion which indicates the
- * memory of @dimm should be kept during live migration. Will not fail
- * after the device was realized.
*/
-typedef struct PCDIMMDeviceClass {
+struct PCDIMMDeviceClass {
/* private */
DeviceClass parent_class;
/* public */
void (*realize)(PCDIMMDevice *dimm, Error **errp);
- MemoryRegion *(*get_vmstate_memory_region)(PCDIMMDevice *dimm,
- Error **errp);
-} PCDIMMDeviceClass;
+ void (*unrealize)(PCDIMMDevice *dimm);
+};
void pc_dimm_pre_plug(PCDIMMDevice *dimm, MachineState *machine,
const uint64_t *legacy_align, Error **errp);
-void pc_dimm_plug(PCDIMMDevice *dimm, MachineState *machine, Error **errp);
+void pc_dimm_plug(PCDIMMDevice *dimm, MachineState *machine);
void pc_dimm_unplug(PCDIMMDevice *dimm, MachineState *machine);
#endif
diff --git a/include/hw/mem/sparse-mem.h b/include/hw/mem/sparse-mem.h
new file mode 100644
index 0000000000..f9863b154b
--- /dev/null
+++ b/include/hw/mem/sparse-mem.h
@@ -0,0 +1,19 @@
+/*
+ * A sparse memory device. Useful for fuzzing
+ *
+ * Copyright Red Hat Inc., 2021
+ *
+ * Authors:
+ * Alexander Bulekov <alxndr@bu.edu>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef SPARSE_MEM_H
+#define SPARSE_MEM_H
+#define TYPE_SPARSE_MEM "sparse-mem"
+
+MemoryRegion *sparse_mem_init(uint64_t addr, uint64_t length);
+
+#endif
diff --git a/include/hw/mips/bios.h b/include/hw/mips/bios.h
deleted file mode 100644
index c03007999a..0000000000
--- a/include/hw/mips/bios.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef HW_MIPS_BIOS_H
-#define HW_MIPS_BIOS_H
-
-#include "qemu/units.h"
-#include "cpu.h"
-
-#define BIOS_SIZE (4 * MiB)
-#ifdef TARGET_WORDS_BIGENDIAN
-#define BIOS_FILENAME "mips_bios.bin"
-#else
-#define BIOS_FILENAME "mipsel_bios.bin"
-#endif
-
-#endif
diff --git a/include/hw/mips/bootloader.h b/include/hw/mips/bootloader.h
new file mode 100644
index 0000000000..c32f6c2835
--- /dev/null
+++ b/include/hw/mips/bootloader.h
@@ -0,0 +1,26 @@
+/*
+ * Utility for QEMU MIPS to generate it's simple bootloader
+ *
+ * Copyright (C) 2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_MIPS_BOOTLOADER_H
+#define HW_MIPS_BOOTLOADER_H
+
+#include "exec/cpu-defs.h"
+
+void bl_gen_jump_to(void **ptr, target_ulong jump_addr);
+void bl_gen_jump_kernel(void **ptr,
+ bool set_sp, target_ulong sp,
+ bool set_a0, target_ulong a0,
+ bool set_a1, target_ulong a1,
+ bool set_a2, target_ulong a2,
+ bool set_a3, target_ulong a3,
+ target_ulong kernel_addr);
+void bl_gen_write_ulong(void **ptr, target_ulong addr, target_ulong val);
+void bl_gen_write_u32(void **ptr, target_ulong addr, uint32_t val);
+void bl_gen_write_u64(void **ptr, target_ulong addr, uint64_t val);
+
+#endif
diff --git a/include/hw/mips/cps.h b/include/hw/mips/cps.h
index a941c55f27..04d636246a 100644
--- a/include/hw/mips/cps.h
+++ b/include/hw/mips/cps.h
@@ -6,7 +6,7 @@
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -21,16 +21,18 @@
#define MIPS_CPS_H
#include "hw/sysbus.h"
+#include "hw/clock.h"
#include "hw/misc/mips_cmgcr.h"
#include "hw/intc/mips_gic.h"
#include "hw/misc/mips_cpc.h"
#include "hw/misc/mips_itu.h"
#include "target/mips/cpu.h"
+#include "qom/object.h"
#define TYPE_MIPS_CPS "mips-cps"
-#define MIPS_CPS(obj) OBJECT_CHECK(MIPSCPSState, (obj), TYPE_MIPS_CPS)
+OBJECT_DECLARE_SIMPLE_TYPE(MIPSCPSState, MIPS_CPS)
-typedef struct MIPSCPSState {
+struct MIPSCPSState {
SysBusDevice parent_obj;
uint32_t num_vp;
@@ -42,7 +44,8 @@ typedef struct MIPSCPSState {
MIPSGICState gic;
MIPSCPCState cpc;
MIPSITUState itu;
-} MIPSCPSState;
+ Clock *clock;
+};
qemu_irq get_cps_irq(MIPSCPSState *cps, int pin_number);
diff --git a/include/hw/mips/cpudevs.h b/include/hw/mips/cpudevs.h
deleted file mode 100644
index 291f59281a..0000000000
--- a/include/hw/mips/cpudevs.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef HW_MIPS_CPUDEVS_H
-#define HW_MIPS_CPUDEVS_H
-
-#include "target/mips/cpu-qom.h"
-
-/* Definitions for MIPS CPU internal devices. */
-
-/* addr.c */
-uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr);
-uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr);
-uint64_t cpu_mips_kvm_um_phys_to_kseg0(void *opaque, uint64_t addr);
-bool mips_um_ksegs_enabled(void);
-void mips_um_ksegs_enable(void);
-
-/* mips_int.c */
-void cpu_mips_irq_init_cpu(MIPSCPU *cpu);
-
-/* mips_timer.c */
-void cpu_mips_clock_init(MIPSCPU *cpu);
-
-#endif
diff --git a/include/hw/mips/mips.h b/include/hw/mips/mips.h
index 0af4c3d5d7..101799f7d3 100644
--- a/include/hw/mips/mips.h
+++ b/include/hw/mips/mips.h
@@ -2,14 +2,13 @@
#define HW_MIPS_H
/* Definitions for mips board emulation. */
+#include "qemu/units.h"
+
/* Kernels can be configured with 64KB pages */
-#define INITRD_PAGE_MASK (~((1 << 16) - 1))
+#define INITRD_PAGE_SIZE (64 * KiB)
#include "exec/memory.h"
-/* gt64xxx.c */
-PCIBus *gt64120_register(qemu_irq *pic);
-
/* bonito.c */
PCIBus *bonito_init(qemu_irq *pic);
diff --git a/include/hw/misc/a9scu.h b/include/hw/misc/a9scu.h
index efb0c305c2..c3759fb8c8 100644
--- a/include/hw/misc/a9scu.h
+++ b/include/hw/misc/a9scu.h
@@ -11,10 +11,11 @@
#define HW_MISC_A9SCU_H
#include "hw/sysbus.h"
+#include "qom/object.h"
/* A9MP private memory region. */
-typedef struct A9SCUState {
+struct A9SCUState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -23,9 +24,9 @@ typedef struct A9SCUState {
uint32_t control;
uint32_t status;
uint32_t num_cpu;
-} A9SCUState;
+};
#define TYPE_A9_SCU "a9-scu"
-#define A9_SCU(obj) OBJECT_CHECK(A9SCUState, (obj), TYPE_A9_SCU)
+OBJECT_DECLARE_SIMPLE_TYPE(A9SCUState, A9_SCU)
#endif
diff --git a/include/hw/misc/allwinner-a10-ccm.h b/include/hw/misc/allwinner-a10-ccm.h
new file mode 100644
index 0000000000..7f22532efa
--- /dev/null
+++ b/include/hw/misc/allwinner-a10-ccm.h
@@ -0,0 +1,67 @@
+/*
+ * Allwinner A10 Clock Control Module emulation
+ *
+ * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
+ *
+ * This file is derived from Allwinner H3 CCU,
+ * by Niek Linnenbank.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_MISC_ALLWINNER_A10_CCM_H
+#define HW_MISC_ALLWINNER_A10_CCM_H
+
+#include "qom/object.h"
+#include "hw/sysbus.h"
+
+/**
+ * @name Constants
+ * @{
+ */
+
+/** Size of register I/O address space used by CCM device */
+#define AW_A10_CCM_IOSIZE (0x400)
+
+/** Total number of known registers */
+#define AW_A10_CCM_REGS_NUM (AW_A10_CCM_IOSIZE / sizeof(uint32_t))
+
+/** @} */
+
+/**
+ * @name Object model
+ * @{
+ */
+
+#define TYPE_AW_A10_CCM "allwinner-a10-ccm"
+OBJECT_DECLARE_SIMPLE_TYPE(AwA10ClockCtlState, AW_A10_CCM)
+
+/** @} */
+
+/**
+ * Allwinner A10 CCM object instance state.
+ */
+struct AwA10ClockCtlState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ /** Maps I/O registers in physical memory */
+ MemoryRegion iomem;
+
+ /** Array of hardware registers */
+ uint32_t regs[AW_A10_CCM_REGS_NUM];
+};
+
+#endif /* HW_MISC_ALLWINNER_H3_CCU_H */
diff --git a/include/hw/misc/allwinner-a10-dramc.h b/include/hw/misc/allwinner-a10-dramc.h
new file mode 100644
index 0000000000..b61fbecbe7
--- /dev/null
+++ b/include/hw/misc/allwinner-a10-dramc.h
@@ -0,0 +1,68 @@
+/*
+ * Allwinner A10 DRAM Controller emulation
+ *
+ * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
+ *
+ * This file is derived from Allwinner H3 DRAMC,
+ * by Niek Linnenbank.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_MISC_ALLWINNER_A10_DRAMC_H
+#define HW_MISC_ALLWINNER_A10_DRAMC_H
+
+#include "qom/object.h"
+#include "hw/sysbus.h"
+#include "hw/register.h"
+
+/**
+ * @name Constants
+ * @{
+ */
+
+/** Size of register I/O address space used by DRAMC device */
+#define AW_A10_DRAMC_IOSIZE (0x1000)
+
+/** Total number of known registers */
+#define AW_A10_DRAMC_REGS_NUM (AW_A10_DRAMC_IOSIZE / sizeof(uint32_t))
+
+/** @} */
+
+/**
+ * @name Object model
+ * @{
+ */
+
+#define TYPE_AW_A10_DRAMC "allwinner-a10-dramc"
+OBJECT_DECLARE_SIMPLE_TYPE(AwA10DramControllerState, AW_A10_DRAMC)
+
+/** @} */
+
+/**
+ * Allwinner A10 DRAMC object instance state.
+ */
+struct AwA10DramControllerState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ /** Maps I/O registers in physical memory */
+ MemoryRegion iomem;
+
+ /** Array of hardware registers */
+ uint32_t regs[AW_A10_DRAMC_REGS_NUM];
+};
+
+#endif /* HW_MISC_ALLWINNER_A10_DRAMC_H */
diff --git a/include/hw/misc/allwinner-cpucfg.h b/include/hw/misc/allwinner-cpucfg.h
index 2c3693a8be..a717b47299 100644
--- a/include/hw/misc/allwinner-cpucfg.h
+++ b/include/hw/misc/allwinner-cpucfg.h
@@ -29,15 +29,14 @@
*/
#define TYPE_AW_CPUCFG "allwinner-cpucfg"
-#define AW_CPUCFG(obj) \
- OBJECT_CHECK(AwCpuCfgState, (obj), TYPE_AW_CPUCFG)
+OBJECT_DECLARE_SIMPLE_TYPE(AwCpuCfgState, AW_CPUCFG)
/** @} */
/**
* Allwinner CPU Configuration Module instance state
*/
-typedef struct AwCpuCfgState {
+struct AwCpuCfgState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -47,6 +46,6 @@ typedef struct AwCpuCfgState {
uint32_t super_standby;
uint32_t entry_addr;
-} AwCpuCfgState;
+};
#endif /* HW_MISC_ALLWINNER_CPUCFG_H */
diff --git a/include/hw/misc/allwinner-h3-ccu.h b/include/hw/misc/allwinner-h3-ccu.h
index eec59649f3..a04875bfca 100644
--- a/include/hw/misc/allwinner-h3-ccu.h
+++ b/include/hw/misc/allwinner-h3-ccu.h
@@ -42,15 +42,14 @@
*/
#define TYPE_AW_H3_CCU "allwinner-h3-ccu"
-#define AW_H3_CCU(obj) \
- OBJECT_CHECK(AwH3ClockCtlState, (obj), TYPE_AW_H3_CCU)
+OBJECT_DECLARE_SIMPLE_TYPE(AwH3ClockCtlState, AW_H3_CCU)
/** @} */
/**
* Allwinner H3 CCU object instance state.
*/
-typedef struct AwH3ClockCtlState {
+struct AwH3ClockCtlState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -61,6 +60,6 @@ typedef struct AwH3ClockCtlState {
/** Array of hardware registers */
uint32_t regs[AW_H3_CCU_REGS_NUM];
-} AwH3ClockCtlState;
+};
#endif /* HW_MISC_ALLWINNER_H3_CCU_H */
diff --git a/include/hw/misc/allwinner-h3-dramc.h b/include/hw/misc/allwinner-h3-dramc.h
index bacdf236b7..0b6c877ef7 100644
--- a/include/hw/misc/allwinner-h3-dramc.h
+++ b/include/hw/misc/allwinner-h3-dramc.h
@@ -58,15 +58,14 @@
*/
#define TYPE_AW_H3_DRAMC "allwinner-h3-dramc"
-#define AW_H3_DRAMC(obj) \
- OBJECT_CHECK(AwH3DramCtlState, (obj), TYPE_AW_H3_DRAMC)
+OBJECT_DECLARE_SIMPLE_TYPE(AwH3DramCtlState, AW_H3_DRAMC)
/** @} */
/**
* Allwinner H3 SDRAM Controller object instance state.
*/
-typedef struct AwH3DramCtlState {
+struct AwH3DramCtlState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -101,6 +100,6 @@ typedef struct AwH3DramCtlState {
/** @} */
-} AwH3DramCtlState;
+};
#endif /* HW_MISC_ALLWINNER_H3_DRAMC_H */
diff --git a/include/hw/misc/allwinner-h3-sysctrl.h b/include/hw/misc/allwinner-h3-sysctrl.h
index af4119e026..ec1c220535 100644
--- a/include/hw/misc/allwinner-h3-sysctrl.h
+++ b/include/hw/misc/allwinner-h3-sysctrl.h
@@ -43,15 +43,14 @@
*/
#define TYPE_AW_H3_SYSCTRL "allwinner-h3-sysctrl"
-#define AW_H3_SYSCTRL(obj) \
- OBJECT_CHECK(AwH3SysCtrlState, (obj), TYPE_AW_H3_SYSCTRL)
+OBJECT_DECLARE_SIMPLE_TYPE(AwH3SysCtrlState, AW_H3_SYSCTRL)
/** @} */
/**
* Allwinner H3 System Control object instance state
*/
-typedef struct AwH3SysCtrlState {
+struct AwH3SysCtrlState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -62,6 +61,6 @@ typedef struct AwH3SysCtrlState {
/** Array of hardware registers */
uint32_t regs[AW_H3_SYSCTRL_REGS_NUM];
-} AwH3SysCtrlState;
+};
#endif /* HW_MISC_ALLWINNER_H3_SYSCTRL_H */
diff --git a/include/hw/misc/allwinner-r40-ccu.h b/include/hw/misc/allwinner-r40-ccu.h
new file mode 100644
index 0000000000..ceb74eff92
--- /dev/null
+++ b/include/hw/misc/allwinner-r40-ccu.h
@@ -0,0 +1,65 @@
+/*
+ * Allwinner R40 Clock Control Unit emulation
+ *
+ * Copyright (C) 2023 qianfan Zhao <qianfanguijin@163.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_MISC_ALLWINNER_R40_CCU_H
+#define HW_MISC_ALLWINNER_R40_CCU_H
+
+#include "qom/object.h"
+#include "hw/sysbus.h"
+
+/**
+ * @name Constants
+ * @{
+ */
+
+/** Size of register I/O address space used by CCU device */
+#define AW_R40_CCU_IOSIZE (0x400)
+
+/** Total number of known registers */
+#define AW_R40_CCU_REGS_NUM (AW_R40_CCU_IOSIZE / sizeof(uint32_t))
+
+/** @} */
+
+/**
+ * @name Object model
+ * @{
+ */
+
+#define TYPE_AW_R40_CCU "allwinner-r40-ccu"
+OBJECT_DECLARE_SIMPLE_TYPE(AwR40ClockCtlState, AW_R40_CCU)
+
+/** @} */
+
+/**
+ * Allwinner R40 CCU object instance state.
+ */
+struct AwR40ClockCtlState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ /** Maps I/O registers in physical memory */
+ MemoryRegion iomem;
+
+ /** Array of hardware registers */
+ uint32_t regs[AW_R40_CCU_REGS_NUM];
+
+};
+
+#endif /* HW_MISC_ALLWINNER_R40_CCU_H */
diff --git a/include/hw/misc/allwinner-r40-dramc.h b/include/hw/misc/allwinner-r40-dramc.h
new file mode 100644
index 0000000000..6a1a3a7893
--- /dev/null
+++ b/include/hw/misc/allwinner-r40-dramc.h
@@ -0,0 +1,108 @@
+/*
+ * Allwinner R40 SDRAM Controller emulation
+ *
+ * Copyright (C) 2023 qianfan Zhao <qianfanguijin@163.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_MISC_ALLWINNER_R40_DRAMC_H
+#define HW_MISC_ALLWINNER_R40_DRAMC_H
+
+#include "qom/object.h"
+#include "hw/sysbus.h"
+#include "exec/hwaddr.h"
+
+/**
+ * Constants
+ * @{
+ */
+
+/** Highest register address used by DRAMCOM module */
+#define AW_R40_DRAMCOM_REGS_MAXADDR (0x804)
+
+/** Total number of known DRAMCOM registers */
+#define AW_R40_DRAMCOM_REGS_NUM (AW_R40_DRAMCOM_REGS_MAXADDR / \
+ sizeof(uint32_t))
+
+/** Highest register address used by DRAMCTL module */
+#define AW_R40_DRAMCTL_REGS_MAXADDR (0x88c)
+
+/** Total number of known DRAMCTL registers */
+#define AW_R40_DRAMCTL_REGS_NUM (AW_R40_DRAMCTL_REGS_MAXADDR / \
+ sizeof(uint32_t))
+
+/** Highest register address used by DRAMPHY module */
+#define AW_R40_DRAMPHY_REGS_MAXADDR (0x4)
+
+/** Total number of known DRAMPHY registers */
+#define AW_R40_DRAMPHY_REGS_NUM (AW_R40_DRAMPHY_REGS_MAXADDR / \
+ sizeof(uint32_t))
+
+/** @} */
+
+/**
+ * Object model
+ * @{
+ */
+
+#define TYPE_AW_R40_DRAMC "allwinner-r40-dramc"
+OBJECT_DECLARE_SIMPLE_TYPE(AwR40DramCtlState, AW_R40_DRAMC)
+
+/** @} */
+
+/**
+ * Allwinner R40 SDRAM Controller object instance state.
+ */
+struct AwR40DramCtlState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ /** Physical base address for start of RAM */
+ hwaddr ram_addr;
+
+ /** Total RAM size in megabytes */
+ uint32_t ram_size;
+
+ uint8_t set_row_bits;
+ uint8_t set_bank_bits;
+ uint8_t set_col_bits;
+
+ /**
+ * @name Memory Regions
+ * @{
+ */
+ MemoryRegion dramcom_iomem; /**< DRAMCOM module I/O registers */
+ MemoryRegion dramctl_iomem; /**< DRAMCTL module I/O registers */
+ MemoryRegion dramphy_iomem; /**< DRAMPHY module I/O registers */
+ MemoryRegion dram_high; /**< The high 1G dram for dualrank detect */
+ MemoryRegion detect_cells; /**< DRAM memory cells for auto detect */
+
+ /** @} */
+
+ /**
+ * @name Hardware Registers
+ * @{
+ */
+
+ uint32_t dramcom[AW_R40_DRAMCOM_REGS_NUM]; /**< DRAMCOM registers */
+ uint32_t dramctl[AW_R40_DRAMCTL_REGS_NUM]; /**< DRAMCTL registers */
+ uint32_t dramphy[AW_R40_DRAMPHY_REGS_NUM] ;/**< DRAMPHY registers */
+
+ /** @} */
+
+};
+
+#endif /* HW_MISC_ALLWINNER_R40_DRAMC_H */
diff --git a/include/hw/misc/allwinner-sid.h b/include/hw/misc/allwinner-sid.h
index 4c1fa4762b..3bfa887a96 100644
--- a/include/hw/misc/allwinner-sid.h
+++ b/include/hw/misc/allwinner-sid.h
@@ -30,15 +30,14 @@
*/
#define TYPE_AW_SID "allwinner-sid"
-#define AW_SID(obj) \
- OBJECT_CHECK(AwSidState, (obj), TYPE_AW_SID)
+OBJECT_DECLARE_SIMPLE_TYPE(AwSidState, AW_SID)
/** @} */
/**
* Allwinner Security ID object instance state
*/
-typedef struct AwSidState {
+struct AwSidState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -55,6 +54,6 @@ typedef struct AwSidState {
/** Stores the emulated device identifier */
QemuUUID identifier;
-} AwSidState;
+};
#endif /* HW_MISC_ALLWINNER_SID_H */
diff --git a/include/hw/misc/allwinner-sramc.h b/include/hw/misc/allwinner-sramc.h
new file mode 100644
index 0000000000..66b01b8d04
--- /dev/null
+++ b/include/hw/misc/allwinner-sramc.h
@@ -0,0 +1,69 @@
+/*
+ * Allwinner SRAM controller emulation
+ *
+ * Copyright (C) 2023 qianfan Zhao <qianfanguijin@163.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_MISC_ALLWINNER_SRAMC_H
+#define HW_MISC_ALLWINNER_SRAMC_H
+
+#include "qom/object.h"
+#include "hw/sysbus.h"
+#include "qemu/uuid.h"
+
+/**
+ * Object model
+ * @{
+ */
+#define TYPE_AW_SRAMC "allwinner-sramc"
+#define TYPE_AW_SRAMC_SUN8I_R40 TYPE_AW_SRAMC "-sun8i-r40"
+OBJECT_DECLARE_TYPE(AwSRAMCState, AwSRAMCClass, AW_SRAMC)
+
+/** @} */
+
+/**
+ * Allwinner SRAMC object instance state
+ */
+struct AwSRAMCState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ /** Maps I/O registers in physical memory */
+ MemoryRegion iomem;
+
+ /* registers */
+ uint32_t sram_ctl1;
+ uint32_t sram_ver;
+ uint32_t sram_soft_entry_reg0;
+};
+
+/**
+ * Allwinner SRAM Controller class-level struct.
+ *
+ * This struct is filled by each sunxi device specific code
+ * such that the generic code can use this struct to support
+ * all devices.
+ */
+struct AwSRAMCClass {
+ /*< private >*/
+ SysBusDeviceClass parent_class;
+ /*< public >*/
+
+ uint32_t sram_version_code;
+};
+
+#endif /* HW_MISC_ALLWINNER_SRAMC_H */
diff --git a/include/hw/misc/arm11scu.h b/include/hw/misc/arm11scu.h
index 5ad0f3d339..e5c0282aec 100644
--- a/include/hw/misc/arm11scu.h
+++ b/include/hw/misc/arm11scu.h
@@ -12,11 +12,12 @@
#define HW_MISC_ARM11SCU_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_ARM11_SCU "arm11-scu"
-#define ARM11_SCU(obj) OBJECT_CHECK(ARM11SCUState, (obj), TYPE_ARM11_SCU)
+OBJECT_DECLARE_SIMPLE_TYPE(ARM11SCUState, ARM11_SCU)
-typedef struct ARM11SCUState {
+struct ARM11SCUState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -24,6 +25,6 @@ typedef struct ARM11SCUState {
uint32_t control;
uint32_t num_cpu;
MemoryRegion iomem;
-} ARM11SCUState;
+};
#endif
diff --git a/include/hw/misc/arm_integrator_debug.h b/include/hw/misc/arm_integrator_debug.h
index 0077dacb44..798b082164 100644
--- a/include/hw/misc/arm_integrator_debug.h
+++ b/include/hw/misc/arm_integrator_debug.h
@@ -3,7 +3,7 @@
*
* Browse the data sheet:
*
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0159b/Babbfijf.html
+ * https://developer.arm.com/documentation/dui0159/b/peripherals-and-interfaces/debug-leds-and-dip-switch-interface
*
* Copyright (c) 2013 Alex Bennée <alex@bennee.com>
*
diff --git a/include/hw/misc/armsse-cpu-pwrctrl.h b/include/hw/misc/armsse-cpu-pwrctrl.h
new file mode 100644
index 0000000000..51d45ede7d
--- /dev/null
+++ b/include/hw/misc/armsse-cpu-pwrctrl.h
@@ -0,0 +1,40 @@
+/*
+ * ARM SSE CPU PWRCTRL register block
+ *
+ * Copyright (c) 2021 Linaro Limited
+ * Written by Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or
+ * (at your option) any later version.
+ */
+
+/*
+ * This is a model of the "CPU<N>_PWRCTRL block" which is part of the
+ * Arm Corstone SSE-300 Example Subsystem and documented in
+ * https://developer.arm.com/documentation/101773/0000
+ *
+ * QEMU interface:
+ * + sysbus MMIO region 0: the register bank
+ */
+
+#ifndef HW_MISC_ARMSSE_CPU_PWRCTRL_H
+#define HW_MISC_ARMSSE_CPU_PWRCTRL_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_ARMSSE_CPU_PWRCTRL "armsse-cpu-pwrctrl"
+OBJECT_DECLARE_SIMPLE_TYPE(ARMSSECPUPwrCtrl, ARMSSE_CPU_PWRCTRL)
+
+struct ARMSSECPUPwrCtrl {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+
+ uint32_t cpupwrcfg;
+};
+
+#endif
diff --git a/include/hw/misc/armsse-cpuid.h b/include/hw/misc/armsse-cpuid.h
index 0ef33fcaba..9c0926322c 100644
--- a/include/hw/misc/armsse-cpuid.h
+++ b/include/hw/misc/armsse-cpuid.h
@@ -12,7 +12,7 @@
/*
* This is a model of the "CPU_IDENTITY" register block which is part of the
* Arm SSE-200 and documented in
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
+ * https://developer.arm.com/documentation/101104/latest/
*
* QEMU interface:
* + QOM property "CPUID": the value to use for the CPUID register
@@ -23,11 +23,12 @@
#define HW_MISC_ARMSSE_CPUID_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_ARMSSE_CPUID "armsse-cpuid"
-#define ARMSSE_CPUID(obj) OBJECT_CHECK(ARMSSECPUID, (obj), TYPE_ARMSSE_CPUID)
+OBJECT_DECLARE_SIMPLE_TYPE(ARMSSECPUID, ARMSSE_CPUID)
-typedef struct ARMSSECPUID {
+struct ARMSSECPUID {
/*< private >*/
SysBusDevice parent_obj;
@@ -36,6 +37,6 @@ typedef struct ARMSSECPUID {
/* Properties */
uint32_t cpuid;
-} ARMSSECPUID;
+};
#endif
diff --git a/include/hw/misc/armsse-mhu.h b/include/hw/misc/armsse-mhu.h
index cf5d8a73e6..41925ded89 100644
--- a/include/hw/misc/armsse-mhu.h
+++ b/include/hw/misc/armsse-mhu.h
@@ -12,7 +12,7 @@
/*
* This is a model of the Message Handling Unit (MHU) which is part of the
* Arm SSE-200 and documented in
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
+ * https://developer.arm.com/documentation/101104/latest/
*
* QEMU interface:
* + sysbus MMIO region 0: the system information register bank
@@ -24,11 +24,12 @@
#define HW_MISC_ARMSSE_MHU_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_ARMSSE_MHU "armsse-mhu"
-#define ARMSSE_MHU(obj) OBJECT_CHECK(ARMSSEMHU, (obj), TYPE_ARMSSE_MHU)
+OBJECT_DECLARE_SIMPLE_TYPE(ARMSSEMHU, ARMSSE_MHU)
-typedef struct ARMSSEMHU {
+struct ARMSSEMHU {
/*< private >*/
SysBusDevice parent_obj;
@@ -39,6 +40,6 @@ typedef struct ARMSSEMHU {
uint32_t cpu0intr;
uint32_t cpu1intr;
-} ARMSSEMHU;
+};
#endif
diff --git a/include/hw/misc/armv7m_ras.h b/include/hw/misc/armv7m_ras.h
new file mode 100644
index 0000000000..ba6daccf3f
--- /dev/null
+++ b/include/hw/misc/armv7m_ras.h
@@ -0,0 +1,37 @@
+/*
+ * Arm M-profile RAS (Reliability, Availability and Serviceability) block
+ *
+ * Copyright (c) 2021 Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or
+ * (at your option) any later version.
+ */
+
+/*
+ * This is a model of the RAS register block of an M-profile CPU
+ * (the registers starting at 0xE0005000 with ERRFRn).
+ *
+ * QEMU interface:
+ * + sysbus MMIO region 0: the register bank
+ *
+ * The QEMU implementation currently provides "minimal RAS" only.
+ */
+
+#ifndef HW_MISC_ARMV7M_RAS_H
+#define HW_MISC_ARMV7M_RAS_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_ARMV7M_RAS "armv7m-ras"
+OBJECT_DECLARE_SIMPLE_TYPE(ARMv7MRAS, ARMV7M_RAS)
+
+struct ARMv7MRAS {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+};
+
+#endif
diff --git a/include/hw/misc/aspeed_hace.h b/include/hw/misc/aspeed_hace.h
new file mode 100644
index 0000000000..ecb1b67de8
--- /dev/null
+++ b/include/hw/misc/aspeed_hace.h
@@ -0,0 +1,50 @@
+/*
+ * ASPEED Hash and Crypto Engine
+ *
+ * Copyright (C) 2021 IBM Corp.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef ASPEED_HACE_H
+#define ASPEED_HACE_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_ASPEED_HACE "aspeed.hace"
+#define TYPE_ASPEED_AST2400_HACE TYPE_ASPEED_HACE "-ast2400"
+#define TYPE_ASPEED_AST2500_HACE TYPE_ASPEED_HACE "-ast2500"
+#define TYPE_ASPEED_AST2600_HACE TYPE_ASPEED_HACE "-ast2600"
+#define TYPE_ASPEED_AST1030_HACE TYPE_ASPEED_HACE "-ast1030"
+
+OBJECT_DECLARE_TYPE(AspeedHACEState, AspeedHACEClass, ASPEED_HACE)
+
+#define ASPEED_HACE_NR_REGS (0x64 >> 2)
+#define ASPEED_HACE_MAX_SG 256 /* max number of entries */
+
+struct AspeedHACEState {
+ SysBusDevice parent;
+
+ MemoryRegion iomem;
+ qemu_irq irq;
+
+ struct iovec iov_cache[ASPEED_HACE_MAX_SG];
+ uint32_t regs[ASPEED_HACE_NR_REGS];
+ uint32_t total_req_len;
+ uint32_t iov_count;
+
+ MemoryRegion *dram_mr;
+ AddressSpace dram_as;
+};
+
+
+struct AspeedHACEClass {
+ SysBusDeviceClass parent_class;
+
+ uint32_t src_mask;
+ uint32_t dest_mask;
+ uint32_t key_mask;
+ uint32_t hash_mask;
+};
+
+#endif /* ASPEED_HACE_H */
diff --git a/include/hw/misc/aspeed_i3c.h b/include/hw/misc/aspeed_i3c.h
new file mode 100644
index 0000000000..39679dfa1a
--- /dev/null
+++ b/include/hw/misc/aspeed_i3c.h
@@ -0,0 +1,48 @@
+/*
+ * ASPEED I3C Controller
+ *
+ * Copyright (C) 2021 ASPEED Technology Inc.
+ *
+ * This code is licensed under the GPL version 2 or later. See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef ASPEED_I3C_H
+#define ASPEED_I3C_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_ASPEED_I3C "aspeed.i3c"
+#define TYPE_ASPEED_I3C_DEVICE "aspeed.i3c.device"
+OBJECT_DECLARE_TYPE(AspeedI3CState, AspeedI3CClass, ASPEED_I3C)
+
+#define ASPEED_I3C_NR_REGS (0x70 >> 2)
+#define ASPEED_I3C_DEVICE_NR_REGS (0x300 >> 2)
+#define ASPEED_I3C_NR_DEVICES 6
+
+OBJECT_DECLARE_SIMPLE_TYPE(AspeedI3CDevice, ASPEED_I3C_DEVICE)
+typedef struct AspeedI3CDevice {
+ /* <private> */
+ SysBusDevice parent;
+
+ /* <public> */
+ MemoryRegion mr;
+ qemu_irq irq;
+
+ uint8_t id;
+ uint32_t regs[ASPEED_I3C_DEVICE_NR_REGS];
+} AspeedI3CDevice;
+
+typedef struct AspeedI3CState {
+ /* <private> */
+ SysBusDevice parent;
+
+ /* <public> */
+ MemoryRegion iomem;
+ MemoryRegion iomem_container;
+ qemu_irq irq;
+
+ uint32_t regs[ASPEED_I3C_NR_REGS];
+ AspeedI3CDevice devices[ASPEED_I3C_NR_DEVICES];
+} AspeedI3CState;
+#endif /* ASPEED_I3C_H */
diff --git a/include/hw/misc/aspeed_lpc.h b/include/hw/misc/aspeed_lpc.h
new file mode 100644
index 0000000000..fa398959af
--- /dev/null
+++ b/include/hw/misc/aspeed_lpc.h
@@ -0,0 +1,45 @@
+/*
+ * ASPEED LPC Controller
+ *
+ * Copyright (C) 2017-2018 IBM Corp.
+ *
+ * This code is licensed under the GPL version 2 or later. See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef ASPEED_LPC_H
+#define ASPEED_LPC_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_ASPEED_LPC "aspeed.lpc"
+#define ASPEED_LPC(obj) OBJECT_CHECK(AspeedLPCState, (obj), TYPE_ASPEED_LPC)
+
+#define ASPEED_LPC_NR_REGS (0x260 >> 2)
+
+enum aspeed_lpc_subdevice {
+ aspeed_lpc_kcs_1 = 0,
+ aspeed_lpc_kcs_2,
+ aspeed_lpc_kcs_3,
+ aspeed_lpc_kcs_4,
+ aspeed_lpc_ibt,
+};
+
+#define ASPEED_LPC_NR_SUBDEVS 5
+
+typedef struct AspeedLPCState {
+ /* <private> */
+ SysBusDevice parent;
+
+ /*< public >*/
+ MemoryRegion iomem;
+ qemu_irq irq;
+
+ qemu_irq subdevice_irqs[ASPEED_LPC_NR_SUBDEVS];
+ uint32_t subdevice_irqs_pending;
+
+ uint32_t regs[ASPEED_LPC_NR_REGS];
+ uint32_t hicr7;
+} AspeedLPCState;
+
+#endif /* ASPEED_LPC_H */
diff --git a/include/hw/misc/aspeed_peci.h b/include/hw/misc/aspeed_peci.h
new file mode 100644
index 0000000000..8382707d9f
--- /dev/null
+++ b/include/hw/misc/aspeed_peci.h
@@ -0,0 +1,29 @@
+/*
+ * Aspeed PECI Controller
+ *
+ * Copyright (c) Meta Platforms, Inc. and affiliates. (http://www.meta.com)
+ *
+ * This code is licensed under the GPL version 2 or later. See the COPYING
+ * file in the top-level directory.
+ */
+
+#ifndef ASPEED_PECI_H
+#define ASPEED_PECI_H
+
+#include "hw/sysbus.h"
+
+#define ASPEED_PECI_NR_REGS ((0xFC + 4) >> 2)
+#define TYPE_ASPEED_PECI "aspeed.peci"
+OBJECT_DECLARE_SIMPLE_TYPE(AspeedPECIState, ASPEED_PECI);
+
+struct AspeedPECIState {
+ /* <private> */
+ SysBusDevice parent;
+
+ MemoryRegion mmio;
+ qemu_irq irq;
+
+ uint32_t regs[ASPEED_PECI_NR_REGS];
+};
+
+#endif
diff --git a/include/hw/misc/aspeed_sbc.h b/include/hw/misc/aspeed_sbc.h
new file mode 100644
index 0000000000..405e6782b9
--- /dev/null
+++ b/include/hw/misc/aspeed_sbc.h
@@ -0,0 +1,45 @@
+/*
+ * ASPEED Secure Boot Controller
+ *
+ * Copyright (C) 2021-2022 IBM Corp.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef ASPEED_SBC_H
+#define ASPEED_SBC_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_ASPEED_SBC "aspeed.sbc"
+#define TYPE_ASPEED_AST2600_SBC TYPE_ASPEED_SBC "-ast2600"
+OBJECT_DECLARE_TYPE(AspeedSBCState, AspeedSBCClass, ASPEED_SBC)
+
+#define ASPEED_SBC_NR_REGS (0x93c >> 2)
+
+#define QSR_AES BIT(27)
+#define QSR_RSA1024 (0x0 << 12)
+#define QSR_RSA2048 (0x1 << 12)
+#define QSR_RSA3072 (0x2 << 12)
+#define QSR_RSA4096 (0x3 << 12)
+#define QSR_SHA224 (0x0 << 10)
+#define QSR_SHA256 (0x1 << 10)
+#define QSR_SHA384 (0x2 << 10)
+#define QSR_SHA512 (0x3 << 10)
+
+struct AspeedSBCState {
+ SysBusDevice parent;
+
+ bool emmc_abr;
+ uint32_t signing_settings;
+
+ MemoryRegion iomem;
+
+ uint32_t regs[ASPEED_SBC_NR_REGS];
+};
+
+struct AspeedSBCClass {
+ SysBusDeviceClass parent_class;
+};
+
+#endif /* ASPEED_SBC_H */
diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h
index a6739bb846..7cb6018dbc 100644
--- a/include/hw/misc/aspeed_scu.h
+++ b/include/hw/misc/aspeed_scu.h
@@ -12,17 +12,19 @@
#define ASPEED_SCU_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_ASPEED_SCU "aspeed.scu"
-#define ASPEED_SCU(obj) OBJECT_CHECK(AspeedSCUState, (obj), TYPE_ASPEED_SCU)
+OBJECT_DECLARE_TYPE(AspeedSCUState, AspeedSCUClass, ASPEED_SCU)
#define TYPE_ASPEED_2400_SCU TYPE_ASPEED_SCU "-ast2400"
#define TYPE_ASPEED_2500_SCU TYPE_ASPEED_SCU "-ast2500"
#define TYPE_ASPEED_2600_SCU TYPE_ASPEED_SCU "-ast2600"
+#define TYPE_ASPEED_1030_SCU TYPE_ASPEED_SCU "-ast1030"
#define ASPEED_SCU_NR_REGS (0x1A8 >> 2)
#define ASPEED_AST2600_SCU_NR_REGS (0xE20 >> 2)
-typedef struct AspeedSCUState {
+struct AspeedSCUState {
/*< private >*/
SysBusDevice parent_obj;
@@ -34,7 +36,7 @@ typedef struct AspeedSCUState {
uint32_t hw_strap1;
uint32_t hw_strap2;
uint32_t hw_prot_key;
-} AspeedSCUState;
+};
#define AST2400_A0_SILICON_REV 0x02000303U
#define AST2400_A1_SILICON_REV 0x02010303U
@@ -42,25 +44,27 @@ typedef struct AspeedSCUState {
#define AST2500_A1_SILICON_REV 0x04010303U
#define AST2600_A0_SILICON_REV 0x05000303U
#define AST2600_A1_SILICON_REV 0x05010303U
+#define AST2600_A2_SILICON_REV 0x05020303U
+#define AST2600_A3_SILICON_REV 0x05030303U
+#define AST1030_A0_SILICON_REV 0x80000000U
+#define AST1030_A1_SILICON_REV 0x80010000U
#define ASPEED_IS_AST2500(si_rev) ((((si_rev) >> 24) & 0xff) == 0x04)
-extern bool is_supported_silicon_rev(uint32_t silicon_rev);
+bool is_supported_silicon_rev(uint32_t silicon_rev);
-#define ASPEED_SCU_CLASS(klass) \
- OBJECT_CLASS_CHECK(AspeedSCUClass, (klass), TYPE_ASPEED_SCU)
-#define ASPEED_SCU_GET_CLASS(obj) \
- OBJECT_GET_CLASS(AspeedSCUClass, (obj), TYPE_ASPEED_SCU)
-typedef struct AspeedSCUClass {
+struct AspeedSCUClass {
SysBusDeviceClass parent_class;
const uint32_t *resets;
uint32_t (*calc_hpll)(AspeedSCUState *s, uint32_t hpll_reg);
+ uint32_t (*get_apb)(AspeedSCUState *s);
uint32_t apb_divider;
uint32_t nr_regs;
+ bool clkin_25Mhz;
const MemoryRegionOps *ops;
-} AspeedSCUClass;
+};
#define ASPEED_SCU_PROT_KEY 0x1688A8A8
@@ -286,6 +290,7 @@ uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s);
#define SCU_AST2500_HW_STRAP_ESPI_FLASH_ENABLE (0x1 << 26)
#define SCU_AST2500_HW_STRAP_ESPI_ENABLE (0x1 << 25)
#define SCU_AST2500_HW_STRAP_DDR4_ENABLE (0x1 << 24)
+#define SCU_AST2500_HW_STRAP_25HZ_CLOCK_MODE (0x1 << 23)
#define SCU_AST2500_HW_STRAP_ACPI_ENABLE (0x1 << 19)
#define SCU_AST2500_HW_STRAP_USBCKI_FREQ (0x1 << 18)
@@ -316,4 +321,44 @@ uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s);
SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) | \
SCU_AST2500_HW_STRAP_RESERVED1)
+/*
+ * SCU200 H-PLL Parameter Register (for Aspeed AST2600 SOC)
+ *
+ * 28:26 H-PLL Parameters
+ * 25 Enable H-PLL reset
+ * 24 Enable H-PLL bypass mode
+ * 23 Turn off H-PLL
+ * 22:19 H-PLL Post Divider (P)
+ * 18:13 H-PLL Numerator (M)
+ * 12:0 H-PLL Denumerator (N)
+ *
+ * (Output frequency) = CLKIN(25MHz) * [(M+1) / (N+1)] / (P+1)
+ *
+ * The default frequency is 1200Mhz when CLKIN = 25MHz
+ */
+#define SCU_AST2600_H_PLL_BYPASS_EN (0x1 << 24)
+#define SCU_AST2600_H_PLL_OFF (0x1 << 23)
+
+/*
+ * SCU310 Clock Selection Register Set 4 (for Aspeed AST1030 SOC)
+ *
+ * 31 I3C Clock Source selection
+ * 30:28 I3C clock divider selection
+ * 26:24 MAC AHB clock divider selection
+ * 22:20 RGMII 125MHz clock divider ration
+ * 19:16 RGMII 50MHz clock divider ration
+ * 15 LHCLK clock generation/output enable control
+ * 14:12 LHCLK divider selection
+ * 11:8 APB Bus PCLK divider selection
+ * 7 Select PECI clock source
+ * 6 Select UART debug port clock source
+ * 5 Select UART6 clock source
+ * 4 Select UART5 clock source
+ * 3 Select UART4 clock source
+ * 2 Select UART3 clock source
+ * 1 Select UART2 clock source
+ * 0 Select UART1 clock source
+ */
+#define SCU_AST1030_CLK_GET_PCLK_DIV(x) (((x) >> 8) & 0xf)
+
#endif /* ASPEED_SCU_H */
diff --git a/include/hw/misc/aspeed_sdmc.h b/include/hw/misc/aspeed_sdmc.h
index cea1e67fe3..ec2d59a14f 100644
--- a/include/hw/misc/aspeed_sdmc.h
+++ b/include/hw/misc/aspeed_sdmc.h
@@ -10,16 +10,28 @@
#define ASPEED_SDMC_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_ASPEED_SDMC "aspeed.sdmc"
-#define ASPEED_SDMC(obj) OBJECT_CHECK(AspeedSDMCState, (obj), TYPE_ASPEED_SDMC)
+OBJECT_DECLARE_TYPE(AspeedSDMCState, AspeedSDMCClass, ASPEED_SDMC)
#define TYPE_ASPEED_2400_SDMC TYPE_ASPEED_SDMC "-ast2400"
#define TYPE_ASPEED_2500_SDMC TYPE_ASPEED_SDMC "-ast2500"
#define TYPE_ASPEED_2600_SDMC TYPE_ASPEED_SDMC "-ast2600"
-#define ASPEED_SDMC_NR_REGS (0x174 >> 2)
+/*
+ * SDMC has 174 documented registers. In addition the u-boot device tree
+ * describes the following regions:
+ * - PHY status regs at offset 0x400, length 0x200
+ * - PHY setting regs at offset 0x100, length 0x300
+ *
+ * There are two sets of MRS (Mode Registers) configuration in ast2600 memory
+ * system: one is in the SDRAM MC (memory controller) which is used in run
+ * time, and the other is in the DDR-PHY IP which is used during DDR-PHY
+ * training.
+ */
+#define ASPEED_SDMC_NR_REGS (0x500 >> 2)
-typedef struct AspeedSDMCState {
+struct AspeedSDMCState {
/*< private >*/
SysBusDevice parent_obj;
@@ -29,20 +41,16 @@ typedef struct AspeedSDMCState {
uint32_t regs[ASPEED_SDMC_NR_REGS];
uint64_t ram_size;
uint64_t max_ram_size;
-} AspeedSDMCState;
+};
-#define ASPEED_SDMC_CLASS(klass) \
- OBJECT_CLASS_CHECK(AspeedSDMCClass, (klass), TYPE_ASPEED_SDMC)
-#define ASPEED_SDMC_GET_CLASS(obj) \
- OBJECT_GET_CLASS(AspeedSDMCClass, (obj), TYPE_ASPEED_SDMC)
-typedef struct AspeedSDMCClass {
+struct AspeedSDMCClass {
SysBusDeviceClass parent_class;
uint64_t max_ram_size;
const uint64_t *valid_ram_sizes;
uint32_t (*compute_conf)(AspeedSDMCState *s, uint32_t data);
void (*write)(AspeedSDMCState *s, uint32_t reg, uint32_t data);
-} AspeedSDMCClass;
+};
#endif /* ASPEED_SDMC_H */
diff --git a/include/hw/misc/aspeed_xdma.h b/include/hw/misc/aspeed_xdma.h
index 00b45d931f..b1478fd1c6 100644
--- a/include/hw/misc/aspeed_xdma.h
+++ b/include/hw/misc/aspeed_xdma.h
@@ -3,21 +3,25 @@
* Eddie James <eajames@linux.ibm.com>
*
* Copyright (C) 2019 IBM Corp.
- * SPDX-License-Identifer: GPL-2.0-or-later
+ * SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef ASPEED_XDMA_H
#define ASPEED_XDMA_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_ASPEED_XDMA "aspeed.xdma"
-#define ASPEED_XDMA(obj) OBJECT_CHECK(AspeedXDMAState, (obj), TYPE_ASPEED_XDMA)
+#define TYPE_ASPEED_2400_XDMA TYPE_ASPEED_XDMA "-ast2400"
+#define TYPE_ASPEED_2500_XDMA TYPE_ASPEED_XDMA "-ast2500"
+#define TYPE_ASPEED_2600_XDMA TYPE_ASPEED_XDMA "-ast2600"
+OBJECT_DECLARE_TYPE(AspeedXDMAState, AspeedXDMAClass, ASPEED_XDMA)
#define ASPEED_XDMA_NUM_REGS (ASPEED_XDMA_REG_SIZE / sizeof(uint32_t))
#define ASPEED_XDMA_REG_SIZE 0x7C
-typedef struct AspeedXDMAState {
+struct AspeedXDMAState {
SysBusDevice parent;
MemoryRegion iomem;
@@ -25,6 +29,18 @@ typedef struct AspeedXDMAState {
char bmc_cmdq_readp_set;
uint32_t regs[ASPEED_XDMA_NUM_REGS];
-} AspeedXDMAState;
+};
+
+struct AspeedXDMAClass {
+ SysBusDeviceClass parent_class;
+
+ uint8_t cmdq_endp;
+ uint8_t cmdq_wrp;
+ uint8_t cmdq_rdp;
+ uint8_t intr_ctrl;
+ uint32_t intr_ctrl_mask;
+ uint8_t intr_status;
+ uint32_t intr_complete;
+};
#endif /* ASPEED_XDMA_H */
diff --git a/include/hw/misc/auxbus.h b/include/hw/misc/auxbus.h
index 15a8973517..03cacdee42 100644
--- a/include/hw/misc/auxbus.h
+++ b/include/hw/misc/auxbus.h
@@ -27,12 +27,14 @@
#include "exec/memory.h"
#include "hw/qdev-core.h"
+#include "qom/object.h"
-typedef struct AUXBus AUXBus;
typedef struct AUXSlave AUXSlave;
typedef enum AUXCommand AUXCommand;
typedef enum AUXReply AUXReply;
-typedef struct AUXTOI2CState AUXTOI2CState;
+
+#define TYPE_AUXTOI2C "aux-to-i2c-bridge"
+OBJECT_DECLARE_SIMPLE_TYPE(AUXTOI2CState, AUXTOI2C)
enum AUXCommand {
WRITE_I2C = 0,
@@ -53,7 +55,7 @@ enum AUXReply {
};
#define TYPE_AUX_BUS "aux-bus"
-#define AUX_BUS(obj) OBJECT_CHECK(AUXBus, (obj), TYPE_AUX_BUS)
+OBJECT_DECLARE_SIMPLE_TYPE(AUXBus, AUX_BUS)
struct AUXBus {
/* < private > */
@@ -72,8 +74,7 @@ struct AUXBus {
};
#define TYPE_AUX_SLAVE "aux-slave"
-#define AUX_SLAVE(obj) \
- OBJECT_CHECK(AUXSlave, (obj), TYPE_AUX_SLAVE)
+OBJECT_DECLARE_SIMPLE_TYPE(AUXSlave, AUX_SLAVE)
struct AUXSlave {
/* < private > */
@@ -105,7 +106,7 @@ void aux_bus_realize(AUXBus *bus);
*
* Returns the reply of the request.
*
- * @bus Ths bus where the request happen.
+ * @bus The bus where the request happen.
* @cmd The command requested.
* @address The 20bits address of the slave.
* @len The length of the read or write.
diff --git a/include/hw/misc/avr_power.h b/include/hw/misc/avr_power.h
index e08e44f629..388e421aa7 100644
--- a/include/hw/misc/avr_power.h
+++ b/include/hw/misc/avr_power.h
@@ -26,13 +26,13 @@
#define HW_MISC_AVR_POWER_H
#include "hw/sysbus.h"
-#include "hw/hw.h"
+#include "qom/object.h"
#define TYPE_AVR_MASK "avr-power"
-#define AVR_MASK(obj) OBJECT_CHECK(AVRMaskState, (obj), TYPE_AVR_MASK)
+OBJECT_DECLARE_SIMPLE_TYPE(AVRMaskState, AVR_MASK)
-typedef struct {
+struct AVRMaskState {
/* <private> */
SysBusDevice parent_obj;
@@ -41,6 +41,6 @@ typedef struct {
uint8_t val;
qemu_irq irq[8];
-} AVRMaskState;
+};
#endif /* HW_MISC_AVR_POWER_H */
diff --git a/include/hw/misc/bcm2835_cprman.h b/include/hw/misc/bcm2835_cprman.h
new file mode 100644
index 0000000000..0d38036728
--- /dev/null
+++ b/include/hw/misc/bcm2835_cprman.h
@@ -0,0 +1,210 @@
+/*
+ * BCM2835 CPRMAN clock manager
+ *
+ * Copyright (c) 2020 Luc Michel <luc@lmichel.fr>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_MISC_BCM2835_CPRMAN_H
+#define HW_MISC_BCM2835_CPRMAN_H
+
+#include "hw/sysbus.h"
+#include "hw/qdev-clock.h"
+
+#define TYPE_BCM2835_CPRMAN "bcm2835-cprman"
+
+typedef struct BCM2835CprmanState BCM2835CprmanState;
+
+DECLARE_INSTANCE_CHECKER(BCM2835CprmanState, CPRMAN,
+ TYPE_BCM2835_CPRMAN)
+
+#define CPRMAN_NUM_REGS (0x2000 / sizeof(uint32_t))
+
+typedef enum CprmanPll {
+ CPRMAN_PLLA = 0,
+ CPRMAN_PLLC,
+ CPRMAN_PLLD,
+ CPRMAN_PLLH,
+ CPRMAN_PLLB,
+
+ CPRMAN_NUM_PLL
+} CprmanPll;
+
+typedef enum CprmanPllChannel {
+ CPRMAN_PLLA_CHANNEL_DSI0 = 0,
+ CPRMAN_PLLA_CHANNEL_CORE,
+ CPRMAN_PLLA_CHANNEL_PER,
+ CPRMAN_PLLA_CHANNEL_CCP2,
+
+ CPRMAN_PLLC_CHANNEL_CORE2,
+ CPRMAN_PLLC_CHANNEL_CORE1,
+ CPRMAN_PLLC_CHANNEL_PER,
+ CPRMAN_PLLC_CHANNEL_CORE0,
+
+ CPRMAN_PLLD_CHANNEL_DSI0,
+ CPRMAN_PLLD_CHANNEL_CORE,
+ CPRMAN_PLLD_CHANNEL_PER,
+ CPRMAN_PLLD_CHANNEL_DSI1,
+
+ CPRMAN_PLLH_CHANNEL_AUX,
+ CPRMAN_PLLH_CHANNEL_RCAL,
+ CPRMAN_PLLH_CHANNEL_PIX,
+
+ CPRMAN_PLLB_CHANNEL_ARM,
+
+ CPRMAN_NUM_PLL_CHANNEL,
+
+ /* Special values used when connecting clock sources to clocks */
+ CPRMAN_CLOCK_SRC_NORMAL = -1,
+ CPRMAN_CLOCK_SRC_FORCE_GROUND = -2,
+ CPRMAN_CLOCK_SRC_DSI0HSCK = -3,
+} CprmanPllChannel;
+
+typedef enum CprmanClockMux {
+ CPRMAN_CLOCK_GNRIC,
+ CPRMAN_CLOCK_VPU,
+ CPRMAN_CLOCK_SYS,
+ CPRMAN_CLOCK_PERIA,
+ CPRMAN_CLOCK_PERII,
+ CPRMAN_CLOCK_H264,
+ CPRMAN_CLOCK_ISP,
+ CPRMAN_CLOCK_V3D,
+ CPRMAN_CLOCK_CAM0,
+ CPRMAN_CLOCK_CAM1,
+ CPRMAN_CLOCK_CCP2,
+ CPRMAN_CLOCK_DSI0E,
+ CPRMAN_CLOCK_DSI0P,
+ CPRMAN_CLOCK_DPI,
+ CPRMAN_CLOCK_GP0,
+ CPRMAN_CLOCK_GP1,
+ CPRMAN_CLOCK_GP2,
+ CPRMAN_CLOCK_HSM,
+ CPRMAN_CLOCK_OTP,
+ CPRMAN_CLOCK_PCM,
+ CPRMAN_CLOCK_PWM,
+ CPRMAN_CLOCK_SLIM,
+ CPRMAN_CLOCK_SMI,
+ CPRMAN_CLOCK_TEC,
+ CPRMAN_CLOCK_TD0,
+ CPRMAN_CLOCK_TD1,
+ CPRMAN_CLOCK_TSENS,
+ CPRMAN_CLOCK_TIMER,
+ CPRMAN_CLOCK_UART,
+ CPRMAN_CLOCK_VEC,
+ CPRMAN_CLOCK_PULSE,
+ CPRMAN_CLOCK_SDC,
+ CPRMAN_CLOCK_ARM,
+ CPRMAN_CLOCK_AVEO,
+ CPRMAN_CLOCK_EMMC,
+ CPRMAN_CLOCK_EMMC2,
+
+ CPRMAN_NUM_CLOCK_MUX
+} CprmanClockMux;
+
+typedef enum CprmanClockMuxSource {
+ CPRMAN_CLOCK_SRC_GND = 0,
+ CPRMAN_CLOCK_SRC_XOSC,
+ CPRMAN_CLOCK_SRC_TD0,
+ CPRMAN_CLOCK_SRC_TD1,
+ CPRMAN_CLOCK_SRC_PLLA,
+ CPRMAN_CLOCK_SRC_PLLC,
+ CPRMAN_CLOCK_SRC_PLLD,
+ CPRMAN_CLOCK_SRC_PLLH,
+ CPRMAN_CLOCK_SRC_PLLC_CORE1,
+ CPRMAN_CLOCK_SRC_PLLC_CORE2,
+
+ CPRMAN_NUM_CLOCK_MUX_SRC
+} CprmanClockMuxSource;
+
+typedef struct CprmanPllState {
+ /*< private >*/
+ DeviceState parent_obj;
+
+ /*< public >*/
+ CprmanPll id;
+
+ uint32_t *reg_cm;
+ uint32_t *reg_a2w_ctrl;
+ uint32_t *reg_a2w_ana; /* ANA[0] .. ANA[3] */
+ uint32_t prediv_mask; /* prediv bit in ana[1] */
+ uint32_t *reg_a2w_frac;
+
+ Clock *xosc_in;
+ Clock *out;
+} CprmanPllState;
+
+typedef struct CprmanPllChannelState {
+ /*< private >*/
+ DeviceState parent_obj;
+
+ /*< public >*/
+ CprmanPllChannel id;
+ CprmanPll parent;
+
+ uint32_t *reg_cm;
+ uint32_t hold_mask;
+ uint32_t load_mask;
+ uint32_t *reg_a2w_ctrl;
+ int fixed_divider;
+
+ Clock *pll_in;
+ Clock *out;
+} CprmanPllChannelState;
+
+typedef struct CprmanClockMuxState {
+ /*< private >*/
+ DeviceState parent_obj;
+
+ /*< public >*/
+ CprmanClockMux id;
+
+ uint32_t *reg_ctl;
+ uint32_t *reg_div;
+ int int_bits;
+ int frac_bits;
+
+ Clock *srcs[CPRMAN_NUM_CLOCK_MUX_SRC];
+ Clock *out;
+
+ /*
+ * Used by clock srcs update callback to retrieve both the clock and the
+ * source number.
+ */
+ struct CprmanClockMuxState *backref[CPRMAN_NUM_CLOCK_MUX_SRC];
+} CprmanClockMuxState;
+
+typedef struct CprmanDsi0HsckMuxState {
+ /*< private >*/
+ DeviceState parent_obj;
+
+ /*< public >*/
+ CprmanClockMux id;
+
+ uint32_t *reg_cm;
+
+ Clock *plla_in;
+ Clock *plld_in;
+ Clock *out;
+} CprmanDsi0HsckMuxState;
+
+struct BCM2835CprmanState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+
+ CprmanPllState plls[CPRMAN_NUM_PLL];
+ CprmanPllChannelState channels[CPRMAN_NUM_PLL_CHANNEL];
+ CprmanClockMuxState clock_muxes[CPRMAN_NUM_CLOCK_MUX];
+ CprmanDsi0HsckMuxState dsi0hsck_mux;
+
+ uint32_t regs[CPRMAN_NUM_REGS];
+ uint32_t xosc_freq;
+
+ Clock *xosc;
+ Clock *gnd;
+};
+
+#endif
diff --git a/include/hw/misc/bcm2835_cprman_internals.h b/include/hw/misc/bcm2835_cprman_internals.h
new file mode 100644
index 0000000000..7617aff96f
--- /dev/null
+++ b/include/hw/misc/bcm2835_cprman_internals.h
@@ -0,0 +1,1019 @@
+/*
+ * BCM2835 CPRMAN clock manager
+ *
+ * Copyright (c) 2020 Luc Michel <luc@lmichel.fr>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_MISC_BCM2835_CPRMAN_INTERNALS_H
+#define HW_MISC_BCM2835_CPRMAN_INTERNALS_H
+
+#include "hw/registerfields.h"
+#include "hw/misc/bcm2835_cprman.h"
+
+#define TYPE_CPRMAN_PLL "bcm2835-cprman-pll"
+#define TYPE_CPRMAN_PLL_CHANNEL "bcm2835-cprman-pll-channel"
+#define TYPE_CPRMAN_CLOCK_MUX "bcm2835-cprman-clock-mux"
+#define TYPE_CPRMAN_DSI0HSCK_MUX "bcm2835-cprman-dsi0hsck-mux"
+
+DECLARE_INSTANCE_CHECKER(CprmanPllState, CPRMAN_PLL,
+ TYPE_CPRMAN_PLL)
+DECLARE_INSTANCE_CHECKER(CprmanPllChannelState, CPRMAN_PLL_CHANNEL,
+ TYPE_CPRMAN_PLL_CHANNEL)
+DECLARE_INSTANCE_CHECKER(CprmanClockMuxState, CPRMAN_CLOCK_MUX,
+ TYPE_CPRMAN_CLOCK_MUX)
+DECLARE_INSTANCE_CHECKER(CprmanDsi0HsckMuxState, CPRMAN_DSI0HSCK_MUX,
+ TYPE_CPRMAN_DSI0HSCK_MUX)
+
+/* Register map */
+
+/* PLLs */
+REG32(CM_PLLA, 0x104)
+ FIELD(CM_PLLA, LOADDSI0, 0, 1)
+ FIELD(CM_PLLA, HOLDDSI0, 1, 1)
+ FIELD(CM_PLLA, LOADCCP2, 2, 1)
+ FIELD(CM_PLLA, HOLDCCP2, 3, 1)
+ FIELD(CM_PLLA, LOADCORE, 4, 1)
+ FIELD(CM_PLLA, HOLDCORE, 5, 1)
+ FIELD(CM_PLLA, LOADPER, 6, 1)
+ FIELD(CM_PLLA, HOLDPER, 7, 1)
+ FIELD(CM_PLLx, ANARST, 8, 1)
+REG32(CM_PLLC, 0x108)
+ FIELD(CM_PLLC, LOADCORE0, 0, 1)
+ FIELD(CM_PLLC, HOLDCORE0, 1, 1)
+ FIELD(CM_PLLC, LOADCORE1, 2, 1)
+ FIELD(CM_PLLC, HOLDCORE1, 3, 1)
+ FIELD(CM_PLLC, LOADCORE2, 4, 1)
+ FIELD(CM_PLLC, HOLDCORE2, 5, 1)
+ FIELD(CM_PLLC, LOADPER, 6, 1)
+ FIELD(CM_PLLC, HOLDPER, 7, 1)
+REG32(CM_PLLD, 0x10c)
+ FIELD(CM_PLLD, LOADDSI0, 0, 1)
+ FIELD(CM_PLLD, HOLDDSI0, 1, 1)
+ FIELD(CM_PLLD, LOADDSI1, 2, 1)
+ FIELD(CM_PLLD, HOLDDSI1, 3, 1)
+ FIELD(CM_PLLD, LOADCORE, 4, 1)
+ FIELD(CM_PLLD, HOLDCORE, 5, 1)
+ FIELD(CM_PLLD, LOADPER, 6, 1)
+ FIELD(CM_PLLD, HOLDPER, 7, 1)
+REG32(CM_PLLH, 0x110)
+ FIELD(CM_PLLH, LOADPIX, 0, 1)
+ FIELD(CM_PLLH, LOADAUX, 1, 1)
+ FIELD(CM_PLLH, LOADRCAL, 2, 1)
+REG32(CM_PLLB, 0x170)
+ FIELD(CM_PLLB, LOADARM, 0, 1)
+ FIELD(CM_PLLB, HOLDARM, 1, 1)
+
+REG32(A2W_PLLA_CTRL, 0x1100)
+ FIELD(A2W_PLLx_CTRL, NDIV, 0, 10)
+ FIELD(A2W_PLLx_CTRL, PDIV, 12, 3)
+ FIELD(A2W_PLLx_CTRL, PWRDN, 16, 1)
+ FIELD(A2W_PLLx_CTRL, PRST_DISABLE, 17, 1)
+REG32(A2W_PLLC_CTRL, 0x1120)
+REG32(A2W_PLLD_CTRL, 0x1140)
+REG32(A2W_PLLH_CTRL, 0x1160)
+REG32(A2W_PLLB_CTRL, 0x11e0)
+
+REG32(A2W_PLLA_ANA0, 0x1010)
+REG32(A2W_PLLA_ANA1, 0x1014)
+ FIELD(A2W_PLLx_ANA1, FB_PREDIV, 14, 1)
+REG32(A2W_PLLA_ANA2, 0x1018)
+REG32(A2W_PLLA_ANA3, 0x101c)
+
+REG32(A2W_PLLC_ANA0, 0x1030)
+REG32(A2W_PLLC_ANA1, 0x1034)
+REG32(A2W_PLLC_ANA2, 0x1038)
+REG32(A2W_PLLC_ANA3, 0x103c)
+
+REG32(A2W_PLLD_ANA0, 0x1050)
+REG32(A2W_PLLD_ANA1, 0x1054)
+REG32(A2W_PLLD_ANA2, 0x1058)
+REG32(A2W_PLLD_ANA3, 0x105c)
+
+REG32(A2W_PLLH_ANA0, 0x1070)
+REG32(A2W_PLLH_ANA1, 0x1074)
+ FIELD(A2W_PLLH_ANA1, FB_PREDIV, 11, 1)
+REG32(A2W_PLLH_ANA2, 0x1078)
+REG32(A2W_PLLH_ANA3, 0x107c)
+
+REG32(A2W_PLLB_ANA0, 0x10f0)
+REG32(A2W_PLLB_ANA1, 0x10f4)
+REG32(A2W_PLLB_ANA2, 0x10f8)
+REG32(A2W_PLLB_ANA3, 0x10fc)
+
+REG32(A2W_PLLA_FRAC, 0x1200)
+ FIELD(A2W_PLLx_FRAC, FRAC, 0, 20)
+REG32(A2W_PLLC_FRAC, 0x1220)
+REG32(A2W_PLLD_FRAC, 0x1240)
+REG32(A2W_PLLH_FRAC, 0x1260)
+REG32(A2W_PLLB_FRAC, 0x12e0)
+
+/* PLL channels */
+REG32(A2W_PLLA_DSI0, 0x1300)
+ FIELD(A2W_PLLx_CHANNELy, DIV, 0, 8)
+ FIELD(A2W_PLLx_CHANNELy, DISABLE, 8, 1)
+REG32(A2W_PLLA_CORE, 0x1400)
+REG32(A2W_PLLA_PER, 0x1500)
+REG32(A2W_PLLA_CCP2, 0x1600)
+
+REG32(A2W_PLLC_CORE2, 0x1320)
+REG32(A2W_PLLC_CORE1, 0x1420)
+REG32(A2W_PLLC_PER, 0x1520)
+REG32(A2W_PLLC_CORE0, 0x1620)
+
+REG32(A2W_PLLD_DSI0, 0x1340)
+REG32(A2W_PLLD_CORE, 0x1440)
+REG32(A2W_PLLD_PER, 0x1540)
+REG32(A2W_PLLD_DSI1, 0x1640)
+
+REG32(A2W_PLLH_AUX, 0x1360)
+REG32(A2W_PLLH_RCAL, 0x1460)
+REG32(A2W_PLLH_PIX, 0x1560)
+REG32(A2W_PLLH_STS, 0x1660)
+
+REG32(A2W_PLLB_ARM, 0x13e0)
+
+/* Clock muxes */
+REG32(CM_GNRICCTL, 0x000)
+ FIELD(CM_CLOCKx_CTL, SRC, 0, 4)
+ FIELD(CM_CLOCKx_CTL, ENABLE, 4, 1)
+ FIELD(CM_CLOCKx_CTL, KILL, 5, 1)
+ FIELD(CM_CLOCKx_CTL, GATE, 6, 1)
+ FIELD(CM_CLOCKx_CTL, BUSY, 7, 1)
+ FIELD(CM_CLOCKx_CTL, BUSYD, 8, 1)
+ FIELD(CM_CLOCKx_CTL, MASH, 9, 2)
+ FIELD(CM_CLOCKx_CTL, FLIP, 11, 1)
+REG32(CM_GNRICDIV, 0x004)
+ FIELD(CM_CLOCKx_DIV, FRAC, 0, 12)
+REG32(CM_VPUCTL, 0x008)
+REG32(CM_VPUDIV, 0x00c)
+REG32(CM_SYSCTL, 0x010)
+REG32(CM_SYSDIV, 0x014)
+REG32(CM_PERIACTL, 0x018)
+REG32(CM_PERIADIV, 0x01c)
+REG32(CM_PERIICTL, 0x020)
+REG32(CM_PERIIDIV, 0x024)
+REG32(CM_H264CTL, 0x028)
+REG32(CM_H264DIV, 0x02c)
+REG32(CM_ISPCTL, 0x030)
+REG32(CM_ISPDIV, 0x034)
+REG32(CM_V3DCTL, 0x038)
+REG32(CM_V3DDIV, 0x03c)
+REG32(CM_CAM0CTL, 0x040)
+REG32(CM_CAM0DIV, 0x044)
+REG32(CM_CAM1CTL, 0x048)
+REG32(CM_CAM1DIV, 0x04c)
+REG32(CM_CCP2CTL, 0x050)
+REG32(CM_CCP2DIV, 0x054)
+REG32(CM_DSI0ECTL, 0x058)
+REG32(CM_DSI0EDIV, 0x05c)
+REG32(CM_DSI0PCTL, 0x060)
+REG32(CM_DSI0PDIV, 0x064)
+REG32(CM_DPICTL, 0x068)
+REG32(CM_DPIDIV, 0x06c)
+REG32(CM_GP0CTL, 0x070)
+REG32(CM_GP0DIV, 0x074)
+REG32(CM_GP1CTL, 0x078)
+REG32(CM_GP1DIV, 0x07c)
+REG32(CM_GP2CTL, 0x080)
+REG32(CM_GP2DIV, 0x084)
+REG32(CM_HSMCTL, 0x088)
+REG32(CM_HSMDIV, 0x08c)
+REG32(CM_OTPCTL, 0x090)
+REG32(CM_OTPDIV, 0x094)
+REG32(CM_PCMCTL, 0x098)
+REG32(CM_PCMDIV, 0x09c)
+REG32(CM_PWMCTL, 0x0a0)
+REG32(CM_PWMDIV, 0x0a4)
+REG32(CM_SLIMCTL, 0x0a8)
+REG32(CM_SLIMDIV, 0x0ac)
+REG32(CM_SMICTL, 0x0b0)
+REG32(CM_SMIDIV, 0x0b4)
+REG32(CM_TCNTCTL, 0x0c0)
+REG32(CM_TCNTCNT, 0x0c4)
+REG32(CM_TECCTL, 0x0c8)
+REG32(CM_TECDIV, 0x0cc)
+REG32(CM_TD0CTL, 0x0d0)
+REG32(CM_TD0DIV, 0x0d4)
+REG32(CM_TD1CTL, 0x0d8)
+REG32(CM_TD1DIV, 0x0dc)
+REG32(CM_TSENSCTL, 0x0e0)
+REG32(CM_TSENSDIV, 0x0e4)
+REG32(CM_TIMERCTL, 0x0e8)
+REG32(CM_TIMERDIV, 0x0ec)
+REG32(CM_UARTCTL, 0x0f0)
+REG32(CM_UARTDIV, 0x0f4)
+REG32(CM_VECCTL, 0x0f8)
+REG32(CM_VECDIV, 0x0fc)
+REG32(CM_PULSECTL, 0x190)
+REG32(CM_PULSEDIV, 0x194)
+REG32(CM_SDCCTL, 0x1a8)
+REG32(CM_SDCDIV, 0x1ac)
+REG32(CM_ARMCTL, 0x1b0)
+REG32(CM_AVEOCTL, 0x1b8)
+REG32(CM_AVEODIV, 0x1bc)
+REG32(CM_EMMCCTL, 0x1c0)
+REG32(CM_EMMCDIV, 0x1c4)
+REG32(CM_EMMC2CTL, 0x1d0)
+REG32(CM_EMMC2DIV, 0x1d4)
+
+/* misc registers */
+REG32(CM_LOCK, 0x114)
+ FIELD(CM_LOCK, FLOCKH, 12, 1)
+ FIELD(CM_LOCK, FLOCKD, 11, 1)
+ FIELD(CM_LOCK, FLOCKC, 10, 1)
+ FIELD(CM_LOCK, FLOCKB, 9, 1)
+ FIELD(CM_LOCK, FLOCKA, 8, 1)
+
+REG32(CM_DSI0HSCK, 0x120)
+ FIELD(CM_DSI0HSCK, SELPLLD, 0, 1)
+
+/*
+ * This field is common to all registers. Each register write value must match
+ * the CPRMAN_PASSWORD magic value in its 8 MSB.
+ */
+FIELD(CPRMAN, PASSWORD, 24, 8)
+#define CPRMAN_PASSWORD 0x5a
+
+/* PLL init info */
+typedef struct PLLInitInfo {
+ const char *name;
+ size_t cm_offset;
+ size_t a2w_ctrl_offset;
+ size_t a2w_ana_offset;
+ uint32_t prediv_mask; /* Prediv bit in ana[1] */
+ size_t a2w_frac_offset;
+} PLLInitInfo;
+
+#define FILL_PLL_INIT_INFO(pll_) \
+ .cm_offset = R_CM_ ## pll_, \
+ .a2w_ctrl_offset = R_A2W_ ## pll_ ## _CTRL, \
+ .a2w_ana_offset = R_A2W_ ## pll_ ## _ANA0, \
+ .a2w_frac_offset = R_A2W_ ## pll_ ## _FRAC
+
+static const PLLInitInfo PLL_INIT_INFO[] = {
+ [CPRMAN_PLLA] = {
+ .name = "plla",
+ .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK,
+ FILL_PLL_INIT_INFO(PLLA),
+ },
+ [CPRMAN_PLLC] = {
+ .name = "pllc",
+ .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK,
+ FILL_PLL_INIT_INFO(PLLC),
+ },
+ [CPRMAN_PLLD] = {
+ .name = "plld",
+ .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK,
+ FILL_PLL_INIT_INFO(PLLD),
+ },
+ [CPRMAN_PLLH] = {
+ .name = "pllh",
+ .prediv_mask = R_A2W_PLLH_ANA1_FB_PREDIV_MASK,
+ FILL_PLL_INIT_INFO(PLLH),
+ },
+ [CPRMAN_PLLB] = {
+ .name = "pllb",
+ .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK,
+ FILL_PLL_INIT_INFO(PLLB),
+ },
+};
+
+#undef FILL_PLL_CHANNEL_INIT_INFO
+
+static inline void set_pll_init_info(BCM2835CprmanState *s,
+ CprmanPllState *pll,
+ CprmanPll id)
+{
+ pll->id = id;
+ pll->reg_cm = &s->regs[PLL_INIT_INFO[id].cm_offset];
+ pll->reg_a2w_ctrl = &s->regs[PLL_INIT_INFO[id].a2w_ctrl_offset];
+ pll->reg_a2w_ana = &s->regs[PLL_INIT_INFO[id].a2w_ana_offset];
+ pll->prediv_mask = PLL_INIT_INFO[id].prediv_mask;
+ pll->reg_a2w_frac = &s->regs[PLL_INIT_INFO[id].a2w_frac_offset];
+}
+
+
+/* PLL channel init info */
+typedef struct PLLChannelInitInfo {
+ const char *name;
+ CprmanPll parent;
+ size_t cm_offset;
+ uint32_t cm_hold_mask;
+ uint32_t cm_load_mask;
+ size_t a2w_ctrl_offset;
+ unsigned int fixed_divider;
+} PLLChannelInitInfo;
+
+#define FILL_PLL_CHANNEL_INIT_INFO_common(pll_, channel_) \
+ .parent = CPRMAN_ ## pll_, \
+ .cm_offset = R_CM_ ## pll_, \
+ .cm_load_mask = R_CM_ ## pll_ ## _ ## LOAD ## channel_ ## _MASK, \
+ .a2w_ctrl_offset = R_A2W_ ## pll_ ## _ ## channel_
+
+#define FILL_PLL_CHANNEL_INIT_INFO(pll_, channel_) \
+ FILL_PLL_CHANNEL_INIT_INFO_common(pll_, channel_), \
+ .cm_hold_mask = R_CM_ ## pll_ ## _ ## HOLD ## channel_ ## _MASK, \
+ .fixed_divider = 1
+
+#define FILL_PLL_CHANNEL_INIT_INFO_nohold(pll_, channel_) \
+ FILL_PLL_CHANNEL_INIT_INFO_common(pll_, channel_), \
+ .cm_hold_mask = 0
+
+static PLLChannelInitInfo PLL_CHANNEL_INIT_INFO[] = {
+ [CPRMAN_PLLA_CHANNEL_DSI0] = {
+ .name = "plla-dsi0",
+ FILL_PLL_CHANNEL_INIT_INFO(PLLA, DSI0),
+ },
+ [CPRMAN_PLLA_CHANNEL_CORE] = {
+ .name = "plla-core",
+ FILL_PLL_CHANNEL_INIT_INFO(PLLA, CORE),
+ },
+ [CPRMAN_PLLA_CHANNEL_PER] = {
+ .name = "plla-per",
+ FILL_PLL_CHANNEL_INIT_INFO(PLLA, PER),
+ },
+ [CPRMAN_PLLA_CHANNEL_CCP2] = {
+ .name = "plla-ccp2",
+ FILL_PLL_CHANNEL_INIT_INFO(PLLA, CCP2),
+ },
+
+ [CPRMAN_PLLC_CHANNEL_CORE2] = {
+ .name = "pllc-core2",
+ FILL_PLL_CHANNEL_INIT_INFO(PLLC, CORE2),
+ },
+ [CPRMAN_PLLC_CHANNEL_CORE1] = {
+ .name = "pllc-core1",
+ FILL_PLL_CHANNEL_INIT_INFO(PLLC, CORE1),
+ },
+ [CPRMAN_PLLC_CHANNEL_PER] = {
+ .name = "pllc-per",
+ FILL_PLL_CHANNEL_INIT_INFO(PLLC, PER),
+ },
+ [CPRMAN_PLLC_CHANNEL_CORE0] = {
+ .name = "pllc-core0",
+ FILL_PLL_CHANNEL_INIT_INFO(PLLC, CORE0),
+ },
+
+ [CPRMAN_PLLD_CHANNEL_DSI0] = {
+ .name = "plld-dsi0",
+ FILL_PLL_CHANNEL_INIT_INFO(PLLD, DSI0),
+ },
+ [CPRMAN_PLLD_CHANNEL_CORE] = {
+ .name = "plld-core",
+ FILL_PLL_CHANNEL_INIT_INFO(PLLD, CORE),
+ },
+ [CPRMAN_PLLD_CHANNEL_PER] = {
+ .name = "plld-per",
+ FILL_PLL_CHANNEL_INIT_INFO(PLLD, PER),
+ },
+ [CPRMAN_PLLD_CHANNEL_DSI1] = {
+ .name = "plld-dsi1",
+ FILL_PLL_CHANNEL_INIT_INFO(PLLD, DSI1),
+ },
+
+ [CPRMAN_PLLH_CHANNEL_AUX] = {
+ .name = "pllh-aux",
+ .fixed_divider = 1,
+ FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH, AUX),
+ },
+ [CPRMAN_PLLH_CHANNEL_RCAL] = {
+ .name = "pllh-rcal",
+ .fixed_divider = 10,
+ FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH, RCAL),
+ },
+ [CPRMAN_PLLH_CHANNEL_PIX] = {
+ .name = "pllh-pix",
+ .fixed_divider = 10,
+ FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH, PIX),
+ },
+
+ [CPRMAN_PLLB_CHANNEL_ARM] = {
+ .name = "pllb-arm",
+ FILL_PLL_CHANNEL_INIT_INFO(PLLB, ARM),
+ },
+};
+
+#undef FILL_PLL_CHANNEL_INIT_INFO_nohold
+#undef FILL_PLL_CHANNEL_INIT_INFO
+#undef FILL_PLL_CHANNEL_INIT_INFO_common
+
+static inline void set_pll_channel_init_info(BCM2835CprmanState *s,
+ CprmanPllChannelState *channel,
+ CprmanPllChannel id)
+{
+ channel->id = id;
+ channel->parent = PLL_CHANNEL_INIT_INFO[id].parent;
+ channel->reg_cm = &s->regs[PLL_CHANNEL_INIT_INFO[id].cm_offset];
+ channel->hold_mask = PLL_CHANNEL_INIT_INFO[id].cm_hold_mask;
+ channel->load_mask = PLL_CHANNEL_INIT_INFO[id].cm_load_mask;
+ channel->reg_a2w_ctrl = &s->regs[PLL_CHANNEL_INIT_INFO[id].a2w_ctrl_offset];
+ channel->fixed_divider = PLL_CHANNEL_INIT_INFO[id].fixed_divider;
+}
+
+/* Clock mux init info */
+typedef struct ClockMuxInitInfo {
+ const char *name;
+ size_t cm_offset; /* cm_offset[0]->CM_CTL, cm_offset[1]->CM_DIV */
+ int int_bits;
+ int frac_bits;
+
+ CprmanPllChannel src_mapping[CPRMAN_NUM_CLOCK_MUX_SRC];
+} ClockMuxInitInfo;
+
+/*
+ * Each clock mux can have up to 10 sources. Sources 0 to 3 are always the
+ * same (ground, xosc, td0, td1). Sources 4 to 9 are mux specific, and are not
+ * always populated. The following macros catch all those cases.
+ */
+
+/* Unknown mapping. Connect everything to ground */
+#define SRC_MAPPING_INFO_unknown \
+ .src_mapping = { \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* gnd */ \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* xosc */ \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* test debug 0 */ \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* test debug 1 */ \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll a */ \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll c */ \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll d */ \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll h */ \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll c, core1 */ \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll c, core2 */ \
+ }
+
+/* Only the oscillator and the two test debug clocks */
+#define SRC_MAPPING_INFO_xosc \
+ .src_mapping = { \
+ CPRMAN_CLOCK_SRC_NORMAL, \
+ CPRMAN_CLOCK_SRC_NORMAL, \
+ CPRMAN_CLOCK_SRC_NORMAL, \
+ CPRMAN_CLOCK_SRC_NORMAL, \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
+ }
+
+/* All the PLL "core" channels */
+#define SRC_MAPPING_INFO_core \
+ .src_mapping = { \
+ CPRMAN_CLOCK_SRC_NORMAL, \
+ CPRMAN_CLOCK_SRC_NORMAL, \
+ CPRMAN_CLOCK_SRC_NORMAL, \
+ CPRMAN_CLOCK_SRC_NORMAL, \
+ CPRMAN_PLLA_CHANNEL_CORE, \
+ CPRMAN_PLLC_CHANNEL_CORE0, \
+ CPRMAN_PLLD_CHANNEL_CORE, \
+ CPRMAN_PLLH_CHANNEL_AUX, \
+ CPRMAN_PLLC_CHANNEL_CORE1, \
+ CPRMAN_PLLC_CHANNEL_CORE2, \
+ }
+
+/* All the PLL "per" channels */
+#define SRC_MAPPING_INFO_periph \
+ .src_mapping = { \
+ CPRMAN_CLOCK_SRC_NORMAL, \
+ CPRMAN_CLOCK_SRC_NORMAL, \
+ CPRMAN_CLOCK_SRC_NORMAL, \
+ CPRMAN_CLOCK_SRC_NORMAL, \
+ CPRMAN_PLLA_CHANNEL_PER, \
+ CPRMAN_PLLC_CHANNEL_PER, \
+ CPRMAN_PLLD_CHANNEL_PER, \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
+ }
+
+/*
+ * The DSI0 channels. This one got an intermediate mux between the PLL channels
+ * and the clock input.
+ */
+#define SRC_MAPPING_INFO_dsi0 \
+ .src_mapping = { \
+ CPRMAN_CLOCK_SRC_NORMAL, \
+ CPRMAN_CLOCK_SRC_NORMAL, \
+ CPRMAN_CLOCK_SRC_NORMAL, \
+ CPRMAN_CLOCK_SRC_NORMAL, \
+ CPRMAN_CLOCK_SRC_DSI0HSCK, \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
+ }
+
+/* The DSI1 channel */
+#define SRC_MAPPING_INFO_dsi1 \
+ .src_mapping = { \
+ CPRMAN_CLOCK_SRC_NORMAL, \
+ CPRMAN_CLOCK_SRC_NORMAL, \
+ CPRMAN_CLOCK_SRC_NORMAL, \
+ CPRMAN_CLOCK_SRC_NORMAL, \
+ CPRMAN_PLLD_CHANNEL_DSI1, \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
+ }
+
+#define FILL_CLOCK_MUX_SRC_MAPPING_INIT_INFO(kind_) \
+ SRC_MAPPING_INFO_ ## kind_
+
+#define FILL_CLOCK_MUX_INIT_INFO(clock_, kind_) \
+ .cm_offset = R_CM_ ## clock_ ## CTL, \
+ FILL_CLOCK_MUX_SRC_MAPPING_INIT_INFO(kind_)
+
+static ClockMuxInitInfo CLOCK_MUX_INIT_INFO[] = {
+ [CPRMAN_CLOCK_GNRIC] = {
+ .name = "gnric",
+ FILL_CLOCK_MUX_INIT_INFO(GNRIC, unknown),
+ },
+ [CPRMAN_CLOCK_VPU] = {
+ .name = "vpu",
+ .int_bits = 12,
+ .frac_bits = 8,
+ FILL_CLOCK_MUX_INIT_INFO(VPU, core),
+ },
+ [CPRMAN_CLOCK_SYS] = {
+ .name = "sys",
+ FILL_CLOCK_MUX_INIT_INFO(SYS, unknown),
+ },
+ [CPRMAN_CLOCK_PERIA] = {
+ .name = "peria",
+ FILL_CLOCK_MUX_INIT_INFO(PERIA, unknown),
+ },
+ [CPRMAN_CLOCK_PERII] = {
+ .name = "perii",
+ FILL_CLOCK_MUX_INIT_INFO(PERII, unknown),
+ },
+ [CPRMAN_CLOCK_H264] = {
+ .name = "h264",
+ .int_bits = 4,
+ .frac_bits = 8,
+ FILL_CLOCK_MUX_INIT_INFO(H264, core),
+ },
+ [CPRMAN_CLOCK_ISP] = {
+ .name = "isp",
+ .int_bits = 4,
+ .frac_bits = 8,
+ FILL_CLOCK_MUX_INIT_INFO(ISP, core),
+ },
+ [CPRMAN_CLOCK_V3D] = {
+ .name = "v3d",
+ FILL_CLOCK_MUX_INIT_INFO(V3D, core),
+ },
+ [CPRMAN_CLOCK_CAM0] = {
+ .name = "cam0",
+ .int_bits = 4,
+ .frac_bits = 8,
+ FILL_CLOCK_MUX_INIT_INFO(CAM0, periph),
+ },
+ [CPRMAN_CLOCK_CAM1] = {
+ .name = "cam1",
+ .int_bits = 4,
+ .frac_bits = 8,
+ FILL_CLOCK_MUX_INIT_INFO(CAM1, periph),
+ },
+ [CPRMAN_CLOCK_CCP2] = {
+ .name = "ccp2",
+ FILL_CLOCK_MUX_INIT_INFO(CCP2, unknown),
+ },
+ [CPRMAN_CLOCK_DSI0E] = {
+ .name = "dsi0e",
+ .int_bits = 4,
+ .frac_bits = 8,
+ FILL_CLOCK_MUX_INIT_INFO(DSI0E, dsi0),
+ },
+ [CPRMAN_CLOCK_DSI0P] = {
+ .name = "dsi0p",
+ .int_bits = 0,
+ .frac_bits = 0,
+ FILL_CLOCK_MUX_INIT_INFO(DSI0P, dsi0),
+ },
+ [CPRMAN_CLOCK_DPI] = {
+ .name = "dpi",
+ .int_bits = 4,
+ .frac_bits = 8,
+ FILL_CLOCK_MUX_INIT_INFO(DPI, periph),
+ },
+ [CPRMAN_CLOCK_GP0] = {
+ .name = "gp0",
+ .int_bits = 12,
+ .frac_bits = 12,
+ FILL_CLOCK_MUX_INIT_INFO(GP0, periph),
+ },
+ [CPRMAN_CLOCK_GP1] = {
+ .name = "gp1",
+ .int_bits = 12,
+ .frac_bits = 12,
+ FILL_CLOCK_MUX_INIT_INFO(GP1, periph),
+ },
+ [CPRMAN_CLOCK_GP2] = {
+ .name = "gp2",
+ .int_bits = 12,
+ .frac_bits = 12,
+ FILL_CLOCK_MUX_INIT_INFO(GP2, periph),
+ },
+ [CPRMAN_CLOCK_HSM] = {
+ .name = "hsm",
+ .int_bits = 4,
+ .frac_bits = 8,
+ FILL_CLOCK_MUX_INIT_INFO(HSM, periph),
+ },
+ [CPRMAN_CLOCK_OTP] = {
+ .name = "otp",
+ .int_bits = 4,
+ .frac_bits = 0,
+ FILL_CLOCK_MUX_INIT_INFO(OTP, xosc),
+ },
+ [CPRMAN_CLOCK_PCM] = {
+ .name = "pcm",
+ .int_bits = 12,
+ .frac_bits = 12,
+ FILL_CLOCK_MUX_INIT_INFO(PCM, periph),
+ },
+ [CPRMAN_CLOCK_PWM] = {
+ .name = "pwm",
+ .int_bits = 12,
+ .frac_bits = 12,
+ FILL_CLOCK_MUX_INIT_INFO(PWM, periph),
+ },
+ [CPRMAN_CLOCK_SLIM] = {
+ .name = "slim",
+ .int_bits = 12,
+ .frac_bits = 12,
+ FILL_CLOCK_MUX_INIT_INFO(SLIM, periph),
+ },
+ [CPRMAN_CLOCK_SMI] = {
+ .name = "smi",
+ .int_bits = 4,
+ .frac_bits = 8,
+ FILL_CLOCK_MUX_INIT_INFO(SMI, periph),
+ },
+ [CPRMAN_CLOCK_TEC] = {
+ .name = "tec",
+ .int_bits = 6,
+ .frac_bits = 0,
+ FILL_CLOCK_MUX_INIT_INFO(TEC, xosc),
+ },
+ [CPRMAN_CLOCK_TD0] = {
+ .name = "td0",
+ FILL_CLOCK_MUX_INIT_INFO(TD0, unknown),
+ },
+ [CPRMAN_CLOCK_TD1] = {
+ .name = "td1",
+ FILL_CLOCK_MUX_INIT_INFO(TD1, unknown),
+ },
+ [CPRMAN_CLOCK_TSENS] = {
+ .name = "tsens",
+ .int_bits = 5,
+ .frac_bits = 0,
+ FILL_CLOCK_MUX_INIT_INFO(TSENS, xosc),
+ },
+ [CPRMAN_CLOCK_TIMER] = {
+ .name = "timer",
+ .int_bits = 6,
+ .frac_bits = 12,
+ FILL_CLOCK_MUX_INIT_INFO(TIMER, xosc),
+ },
+ [CPRMAN_CLOCK_UART] = {
+ .name = "uart",
+ .int_bits = 10,
+ .frac_bits = 12,
+ FILL_CLOCK_MUX_INIT_INFO(UART, periph),
+ },
+ [CPRMAN_CLOCK_VEC] = {
+ .name = "vec",
+ .int_bits = 4,
+ .frac_bits = 0,
+ FILL_CLOCK_MUX_INIT_INFO(VEC, periph),
+ },
+ [CPRMAN_CLOCK_PULSE] = {
+ .name = "pulse",
+ FILL_CLOCK_MUX_INIT_INFO(PULSE, xosc),
+ },
+ [CPRMAN_CLOCK_SDC] = {
+ .name = "sdram",
+ .int_bits = 6,
+ .frac_bits = 0,
+ FILL_CLOCK_MUX_INIT_INFO(SDC, core),
+ },
+ [CPRMAN_CLOCK_ARM] = {
+ .name = "arm",
+ FILL_CLOCK_MUX_INIT_INFO(ARM, unknown),
+ },
+ [CPRMAN_CLOCK_AVEO] = {
+ .name = "aveo",
+ .int_bits = 4,
+ .frac_bits = 0,
+ FILL_CLOCK_MUX_INIT_INFO(AVEO, periph),
+ },
+ [CPRMAN_CLOCK_EMMC] = {
+ .name = "emmc",
+ .int_bits = 4,
+ .frac_bits = 8,
+ FILL_CLOCK_MUX_INIT_INFO(EMMC, periph),
+ },
+ [CPRMAN_CLOCK_EMMC2] = {
+ .name = "emmc2",
+ .int_bits = 4,
+ .frac_bits = 8,
+ FILL_CLOCK_MUX_INIT_INFO(EMMC2, unknown),
+ },
+};
+
+#undef FILL_CLOCK_MUX_INIT_INFO
+#undef FILL_CLOCK_MUX_SRC_MAPPING_INIT_INFO
+#undef SRC_MAPPING_INFO_dsi1
+#undef SRC_MAPPING_INFO_dsi0
+#undef SRC_MAPPING_INFO_periph
+#undef SRC_MAPPING_INFO_core
+#undef SRC_MAPPING_INFO_xosc
+#undef SRC_MAPPING_INFO_unknown
+
+static inline void set_clock_mux_init_info(BCM2835CprmanState *s,
+ CprmanClockMuxState *mux,
+ CprmanClockMux id)
+{
+ mux->id = id;
+ mux->reg_ctl = &s->regs[CLOCK_MUX_INIT_INFO[id].cm_offset];
+ mux->reg_div = &s->regs[CLOCK_MUX_INIT_INFO[id].cm_offset + 1];
+ mux->int_bits = CLOCK_MUX_INIT_INFO[id].int_bits;
+ mux->frac_bits = CLOCK_MUX_INIT_INFO[id].frac_bits;
+}
+
+
+/*
+ * Object reset info
+ * Those values have been dumped from a Raspberry Pi 3 Model B v1.2 using the
+ * clk debugfs interface in Linux.
+ */
+typedef struct PLLResetInfo {
+ uint32_t cm;
+ uint32_t a2w_ctrl;
+ uint32_t a2w_ana[4];
+ uint32_t a2w_frac;
+} PLLResetInfo;
+
+static const PLLResetInfo PLL_RESET_INFO[] = {
+ [CPRMAN_PLLA] = {
+ .cm = 0x0000008a,
+ .a2w_ctrl = 0x0002103a,
+ .a2w_frac = 0x00098000,
+ .a2w_ana = { 0x00000000, 0x00144000, 0x00000000, 0x00000100 }
+ },
+
+ [CPRMAN_PLLC] = {
+ .cm = 0x00000228,
+ .a2w_ctrl = 0x0002103e,
+ .a2w_frac = 0x00080000,
+ .a2w_ana = { 0x00000000, 0x00144000, 0x00000000, 0x00000100 }
+ },
+
+ [CPRMAN_PLLD] = {
+ .cm = 0x0000020a,
+ .a2w_ctrl = 0x00021034,
+ .a2w_frac = 0x00015556,
+ .a2w_ana = { 0x00000000, 0x00144000, 0x00000000, 0x00000100 }
+ },
+
+ [CPRMAN_PLLH] = {
+ .cm = 0x00000000,
+ .a2w_ctrl = 0x0002102d,
+ .a2w_frac = 0x00000000,
+ .a2w_ana = { 0x00900000, 0x0000000c, 0x00000000, 0x00000000 }
+ },
+
+ [CPRMAN_PLLB] = {
+ /* unknown */
+ .cm = 0x00000000,
+ .a2w_ctrl = 0x00000000,
+ .a2w_frac = 0x00000000,
+ .a2w_ana = { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }
+ }
+};
+
+typedef struct PLLChannelResetInfo {
+ /*
+ * Even though a PLL channel has a CM register, it shares it with its
+ * parent PLL. The parent already takes care of the reset value.
+ */
+ uint32_t a2w_ctrl;
+} PLLChannelResetInfo;
+
+static const PLLChannelResetInfo PLL_CHANNEL_RESET_INFO[] = {
+ [CPRMAN_PLLA_CHANNEL_DSI0] = { .a2w_ctrl = 0x00000100 },
+ [CPRMAN_PLLA_CHANNEL_CORE] = { .a2w_ctrl = 0x00000003 },
+ [CPRMAN_PLLA_CHANNEL_PER] = { .a2w_ctrl = 0x00000000 }, /* unknown */
+ [CPRMAN_PLLA_CHANNEL_CCP2] = { .a2w_ctrl = 0x00000100 },
+
+ [CPRMAN_PLLC_CHANNEL_CORE2] = { .a2w_ctrl = 0x00000100 },
+ [CPRMAN_PLLC_CHANNEL_CORE1] = { .a2w_ctrl = 0x00000100 },
+ [CPRMAN_PLLC_CHANNEL_PER] = { .a2w_ctrl = 0x00000002 },
+ [CPRMAN_PLLC_CHANNEL_CORE0] = { .a2w_ctrl = 0x00000002 },
+
+ [CPRMAN_PLLD_CHANNEL_DSI0] = { .a2w_ctrl = 0x00000100 },
+ [CPRMAN_PLLD_CHANNEL_CORE] = { .a2w_ctrl = 0x00000004 },
+ [CPRMAN_PLLD_CHANNEL_PER] = { .a2w_ctrl = 0x00000004 },
+ [CPRMAN_PLLD_CHANNEL_DSI1] = { .a2w_ctrl = 0x00000100 },
+
+ [CPRMAN_PLLH_CHANNEL_AUX] = { .a2w_ctrl = 0x00000004 },
+ [CPRMAN_PLLH_CHANNEL_RCAL] = { .a2w_ctrl = 0x00000000 },
+ [CPRMAN_PLLH_CHANNEL_PIX] = { .a2w_ctrl = 0x00000000 },
+
+ [CPRMAN_PLLB_CHANNEL_ARM] = { .a2w_ctrl = 0x00000000 }, /* unknown */
+};
+
+typedef struct ClockMuxResetInfo {
+ uint32_t cm_ctl;
+ uint32_t cm_div;
+} ClockMuxResetInfo;
+
+static const ClockMuxResetInfo CLOCK_MUX_RESET_INFO[] = {
+ [CPRMAN_CLOCK_GNRIC] = {
+ .cm_ctl = 0, /* unknown */
+ .cm_div = 0
+ },
+
+ [CPRMAN_CLOCK_VPU] = {
+ .cm_ctl = 0x00000245,
+ .cm_div = 0x00003000,
+ },
+
+ [CPRMAN_CLOCK_SYS] = {
+ .cm_ctl = 0, /* unknown */
+ .cm_div = 0
+ },
+
+ [CPRMAN_CLOCK_PERIA] = {
+ .cm_ctl = 0, /* unknown */
+ .cm_div = 0
+ },
+
+ [CPRMAN_CLOCK_PERII] = {
+ .cm_ctl = 0, /* unknown */
+ .cm_div = 0
+ },
+
+ [CPRMAN_CLOCK_H264] = {
+ .cm_ctl = 0x00000244,
+ .cm_div = 0x00003000,
+ },
+
+ [CPRMAN_CLOCK_ISP] = {
+ .cm_ctl = 0x00000244,
+ .cm_div = 0x00003000,
+ },
+
+ [CPRMAN_CLOCK_V3D] = {
+ .cm_ctl = 0, /* unknown */
+ .cm_div = 0
+ },
+
+ [CPRMAN_CLOCK_CAM0] = {
+ .cm_ctl = 0x00000000,
+ .cm_div = 0x00000000,
+ },
+
+ [CPRMAN_CLOCK_CAM1] = {
+ .cm_ctl = 0x00000000,
+ .cm_div = 0x00000000,
+ },
+
+ [CPRMAN_CLOCK_CCP2] = {
+ .cm_ctl = 0, /* unknown */
+ .cm_div = 0
+ },
+
+ [CPRMAN_CLOCK_DSI0E] = {
+ .cm_ctl = 0x00000000,
+ .cm_div = 0x00000000,
+ },
+
+ [CPRMAN_CLOCK_DSI0P] = {
+ .cm_ctl = 0x00000000,
+ .cm_div = 0x00000000,
+ },
+
+ [CPRMAN_CLOCK_DPI] = {
+ .cm_ctl = 0x00000000,
+ .cm_div = 0x00000000,
+ },
+
+ [CPRMAN_CLOCK_GP0] = {
+ .cm_ctl = 0x00000200,
+ .cm_div = 0x00000000,
+ },
+
+ [CPRMAN_CLOCK_GP1] = {
+ .cm_ctl = 0x00000096,
+ .cm_div = 0x00014000,
+ },
+
+ [CPRMAN_CLOCK_GP2] = {
+ .cm_ctl = 0x00000291,
+ .cm_div = 0x00249f00,
+ },
+
+ [CPRMAN_CLOCK_HSM] = {
+ .cm_ctl = 0x00000000,
+ .cm_div = 0x00000000,
+ },
+
+ [CPRMAN_CLOCK_OTP] = {
+ .cm_ctl = 0x00000091,
+ .cm_div = 0x00004000,
+ },
+
+ [CPRMAN_CLOCK_PCM] = {
+ .cm_ctl = 0x00000200,
+ .cm_div = 0x00000000,
+ },
+
+ [CPRMAN_CLOCK_PWM] = {
+ .cm_ctl = 0x00000200,
+ .cm_div = 0x00000000,
+ },
+
+ [CPRMAN_CLOCK_SLIM] = {
+ .cm_ctl = 0x00000200,
+ .cm_div = 0x00000000,
+ },
+
+ [CPRMAN_CLOCK_SMI] = {
+ .cm_ctl = 0x00000000,
+ .cm_div = 0x00000000,
+ },
+
+ [CPRMAN_CLOCK_TEC] = {
+ .cm_ctl = 0x00000000,
+ .cm_div = 0x00000000,
+ },
+
+ [CPRMAN_CLOCK_TD0] = {
+ .cm_ctl = 0, /* unknown */
+ .cm_div = 0
+ },
+
+ [CPRMAN_CLOCK_TD1] = {
+ .cm_ctl = 0, /* unknown */
+ .cm_div = 0
+ },
+
+ [CPRMAN_CLOCK_TSENS] = {
+ .cm_ctl = 0x00000091,
+ .cm_div = 0x0000a000,
+ },
+
+ [CPRMAN_CLOCK_TIMER] = {
+ .cm_ctl = 0x00000291,
+ .cm_div = 0x00013333,
+ },
+
+ [CPRMAN_CLOCK_UART] = {
+ .cm_ctl = 0x00000296,
+ .cm_div = 0x0000a6ab,
+ },
+
+ [CPRMAN_CLOCK_VEC] = {
+ .cm_ctl = 0x00000097,
+ .cm_div = 0x00002000,
+ },
+
+ [CPRMAN_CLOCK_PULSE] = {
+ .cm_ctl = 0, /* unknown */
+ .cm_div = 0
+ },
+
+ [CPRMAN_CLOCK_SDC] = {
+ .cm_ctl = 0x00004006,
+ .cm_div = 0x00003000,
+ },
+
+ [CPRMAN_CLOCK_ARM] = {
+ .cm_ctl = 0, /* unknown */
+ .cm_div = 0
+ },
+
+ [CPRMAN_CLOCK_AVEO] = {
+ .cm_ctl = 0x00000000,
+ .cm_div = 0x00000000,
+ },
+
+ [CPRMAN_CLOCK_EMMC] = {
+ .cm_ctl = 0x00000295,
+ .cm_div = 0x00006000,
+ },
+
+ [CPRMAN_CLOCK_EMMC2] = {
+ .cm_ctl = 0, /* unknown */
+ .cm_div = 0
+ },
+};
+
+#endif
diff --git a/include/hw/misc/bcm2835_mbox.h b/include/hw/misc/bcm2835_mbox.h
index 57f95cc35e..ade27af25d 100644
--- a/include/hw/misc/bcm2835_mbox.h
+++ b/include/hw/misc/bcm2835_mbox.h
@@ -10,10 +10,10 @@
#include "bcm2835_mbox_defs.h"
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_BCM2835_MBOX "bcm2835-mbox"
-#define BCM2835_MBOX(obj) \
- OBJECT_CHECK(BCM2835MboxState, (obj), TYPE_BCM2835_MBOX)
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835MboxState, BCM2835_MBOX)
typedef struct {
uint32_t reg[MBOX_SIZE];
@@ -22,7 +22,7 @@ typedef struct {
uint32_t config;
} BCM2835Mbox;
-typedef struct {
+struct BCM2835MboxState {
/*< private >*/
SysBusDevice busdev;
/*< public >*/
@@ -34,6 +34,6 @@ typedef struct {
bool mbox_irq_disabled;
bool available[MBOX_CHAN_COUNT];
BCM2835Mbox mbox[2];
-} BCM2835MboxState;
+};
#endif
diff --git a/include/hw/misc/bcm2835_mphi.h b/include/hw/misc/bcm2835_mphi.h
index e084314d0f..751363f496 100644
--- a/include/hw/misc/bcm2835_mphi.h
+++ b/include/hw/misc/bcm2835_mphi.h
@@ -19,6 +19,7 @@
#include "hw/irq.h"
#include "hw/sysbus.h"
+#include "qom/object.h"
#define MPHI_MMIO_SIZE 0x1000
@@ -38,7 +39,6 @@ struct BCM2835MphiState {
#define TYPE_BCM2835_MPHI "bcm2835-mphi"
-#define BCM2835_MPHI(obj) \
- OBJECT_CHECK(BCM2835MphiState, (obj), TYPE_BCM2835_MPHI)
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835MphiState, BCM2835_MPHI)
#endif
diff --git a/include/hw/misc/bcm2835_powermgt.h b/include/hw/misc/bcm2835_powermgt.h
new file mode 100644
index 0000000000..303b9a6f68
--- /dev/null
+++ b/include/hw/misc/bcm2835_powermgt.h
@@ -0,0 +1,29 @@
+/*
+ * BCM2835 Power Management emulation
+ *
+ * Copyright (C) 2017 Marcin Chojnacki <marcinch7@gmail.com>
+ * Copyright (C) 2021 Nolan Leake <nolan@sigbus.net>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef BCM2835_POWERMGT_H
+#define BCM2835_POWERMGT_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_BCM2835_POWERMGT "bcm2835-powermgt"
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835PowerMgtState, BCM2835_POWERMGT)
+
+struct BCM2835PowerMgtState {
+ SysBusDevice busdev;
+ MemoryRegion iomem;
+
+ uint32_t rstc;
+ uint32_t rsts;
+ uint32_t wdog;
+};
+
+#endif
diff --git a/include/hw/misc/bcm2835_property.h b/include/hw/misc/bcm2835_property.h
index b321f22499..ba8896610c 100644
--- a/include/hw/misc/bcm2835_property.h
+++ b/include/hw/misc/bcm2835_property.h
@@ -11,12 +11,12 @@
#include "hw/sysbus.h"
#include "net/net.h"
#include "hw/display/bcm2835_fb.h"
+#include "qom/object.h"
#define TYPE_BCM2835_PROPERTY "bcm2835-property"
-#define BCM2835_PROPERTY(obj) \
- OBJECT_CHECK(BCM2835PropertyState, (obj), TYPE_BCM2835_PROPERTY)
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835PropertyState, BCM2835_PROPERTY)
-typedef struct {
+struct BCM2835PropertyState {
/*< private >*/
SysBusDevice busdev;
/*< public >*/
@@ -30,7 +30,8 @@ typedef struct {
MACAddr macaddr;
uint32_t board_rev;
uint32_t addr;
+ char *command_line;
bool pending;
-} BCM2835PropertyState;
+};
#endif
diff --git a/include/hw/misc/bcm2835_rng.h b/include/hw/misc/bcm2835_rng.h
index 41a531bce7..7c1fb3ef40 100644
--- a/include/hw/misc/bcm2835_rng.h
+++ b/include/hw/misc/bcm2835_rng.h
@@ -11,17 +11,17 @@
#define BCM2835_RNG_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_BCM2835_RNG "bcm2835-rng"
-#define BCM2835_RNG(obj) \
- OBJECT_CHECK(BCM2835RngState, (obj), TYPE_BCM2835_RNG)
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835RngState, BCM2835_RNG)
-typedef struct {
+struct BCM2835RngState {
SysBusDevice busdev;
MemoryRegion iomem;
uint32_t rng_ctrl;
uint32_t rng_status;
-} BCM2835RngState;
+};
#endif
diff --git a/include/hw/misc/bcm2835_thermal.h b/include/hw/misc/bcm2835_thermal.h
index c3651b27ec..f90f9e487c 100644
--- a/include/hw/misc/bcm2835_thermal.h
+++ b/include/hw/misc/bcm2835_thermal.h
@@ -10,18 +10,18 @@
#define HW_MISC_BCM2835_THERMAL_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_BCM2835_THERMAL "bcm2835-thermal"
-#define BCM2835_THERMAL(obj) \
- OBJECT_CHECK(Bcm2835ThermalState, (obj), TYPE_BCM2835_THERMAL)
+OBJECT_DECLARE_SIMPLE_TYPE(Bcm2835ThermalState, BCM2835_THERMAL)
-typedef struct {
+struct Bcm2835ThermalState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
MemoryRegion iomem;
uint32_t ctl;
-} Bcm2835ThermalState;
+};
#endif
diff --git a/include/hw/misc/djmemc.h b/include/hw/misc/djmemc.h
new file mode 100644
index 0000000000..82d4e4a2fe
--- /dev/null
+++ b/include/hw/misc/djmemc.h
@@ -0,0 +1,30 @@
+/*
+ * djMEMC, macintosh memory and interrupt controller
+ * (Quadra 610/650/800 & Centris 610/650)
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_MISC_DJMEMC_H
+#define HW_MISC_DJMEMC_H
+
+#include "hw/sysbus.h"
+
+#define DJMEMC_SIZE 0x2000
+#define DJMEMC_NUM_REGS (0x38 / sizeof(uint32_t))
+
+#define DJMEMC_MAXBANKS 10
+
+struct DJMEMCState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion mem_regs;
+
+ /* Memory controller */
+ uint32_t regs[DJMEMC_NUM_REGS];
+};
+
+#define TYPE_DJMEMC "djMEMC"
+OBJECT_DECLARE_SIMPLE_TYPE(DJMEMCState, DJMEMC);
+
+#endif
diff --git a/include/hw/misc/grlib_ahb_apb_pnp.h b/include/hw/misc/grlib_ahb_apb_pnp.h
index a0f6dcfda7..bab0b5f47f 100644
--- a/include/hw/misc/grlib_ahb_apb_pnp.h
+++ b/include/hw/misc/grlib_ahb_apb_pnp.h
@@ -23,16 +23,13 @@
#ifndef GRLIB_AHB_APB_PNP_H
#define GRLIB_AHB_APB_PNP_H
+#include "qom/object.h"
-#define TYPE_GRLIB_AHB_PNP "grlib,ahbpnp"
-#define GRLIB_AHB_PNP(obj) \
- OBJECT_CHECK(AHBPnp, (obj), TYPE_GRLIB_AHB_PNP)
-typedef struct AHBPnp AHBPnp;
+#define TYPE_GRLIB_AHB_PNP "grlib-ahbpnp"
+OBJECT_DECLARE_SIMPLE_TYPE(AHBPnp, GRLIB_AHB_PNP)
-#define TYPE_GRLIB_APB_PNP "grlib,apbpnp"
-#define GRLIB_APB_PNP(obj) \
- OBJECT_CHECK(APBPnp, (obj), TYPE_GRLIB_APB_PNP)
-typedef struct APBPnp APBPnp;
+#define TYPE_GRLIB_APB_PNP "grlib-apbpnp"
+OBJECT_DECLARE_SIMPLE_TYPE(APBPnp, GRLIB_APB_PNP)
void grlib_ahb_pnp_add_entry(AHBPnp *dev, uint32_t address, uint32_t mask,
uint8_t vendor, uint16_t device, int slave,
diff --git a/include/hw/misc/imx25_ccm.h b/include/hw/misc/imx25_ccm.h
index 296321c612..c3b89018c6 100644
--- a/include/hw/misc/imx25_ccm.h
+++ b/include/hw/misc/imx25_ccm.h
@@ -12,6 +12,7 @@
#define IMX25_CCM_H
#include "hw/misc/imx_ccm.h"
+#include "qom/object.h"
#define IMX25_CCM_MPCTL_REG 0
#define IMX25_CCM_UPCTL_REG 1
@@ -63,9 +64,9 @@
CCTL_##name##_SHIFT)
#define TYPE_IMX25_CCM "imx25.ccm"
-#define IMX25_CCM(obj) OBJECT_CHECK(IMX25CCMState, (obj), TYPE_IMX25_CCM)
+OBJECT_DECLARE_SIMPLE_TYPE(IMX25CCMState, IMX25_CCM)
-typedef struct IMX25CCMState {
+struct IMX25CCMState {
/* <private> */
IMXCCMState parent_obj;
@@ -74,6 +75,6 @@ typedef struct IMX25CCMState {
uint32_t reg[IMX25_CCM_MAX_REG];
-} IMX25CCMState;
+};
#endif /* IMX25_CCM_H */
diff --git a/include/hw/misc/imx31_ccm.h b/include/hw/misc/imx31_ccm.h
index c376fad14c..18e08ee84f 100644
--- a/include/hw/misc/imx31_ccm.h
+++ b/include/hw/misc/imx31_ccm.h
@@ -12,6 +12,7 @@
#define IMX31_CCM_H
#include "hw/misc/imx_ccm.h"
+#include "qom/object.h"
#define IMX31_CCM_CCMR_REG 0
#define IMX31_CCM_PDR0_REG 1
@@ -72,9 +73,9 @@
PDR0_##name##_PODF_SHIFT)
#define TYPE_IMX31_CCM "imx31.ccm"
-#define IMX31_CCM(obj) OBJECT_CHECK(IMX31CCMState, (obj), TYPE_IMX31_CCM)
+OBJECT_DECLARE_SIMPLE_TYPE(IMX31CCMState, IMX31_CCM)
-typedef struct IMX31CCMState {
+struct IMX31CCMState {
/* <private> */
IMXCCMState parent_obj;
@@ -83,6 +84,6 @@ typedef struct IMX31CCMState {
uint32_t reg[IMX31_CCM_MAX_REG];
-} IMX31CCMState;
+};
#endif /* IMX31_CCM_H */
diff --git a/include/hw/misc/imx6_ccm.h b/include/hw/misc/imx6_ccm.h
index 80505809b4..ccf46d7353 100644
--- a/include/hw/misc/imx6_ccm.h
+++ b/include/hw/misc/imx6_ccm.h
@@ -13,6 +13,7 @@
#include "hw/misc/imx_ccm.h"
#include "qemu/bitops.h"
+#include "qom/object.h"
#define CCM_CCR 0
#define CCM_CCDR 1
@@ -178,9 +179,9 @@
#define EXTRACT(value, name) extract32(value, name##_SHIFT, name##_LENGTH)
#define TYPE_IMX6_CCM "imx6.ccm"
-#define IMX6_CCM(obj) OBJECT_CHECK(IMX6CCMState, (obj), TYPE_IMX6_CCM)
+OBJECT_DECLARE_SIMPLE_TYPE(IMX6CCMState, IMX6_CCM)
-typedef struct IMX6CCMState {
+struct IMX6CCMState {
/* <private> */
IMXCCMState parent_obj;
@@ -192,6 +193,6 @@ typedef struct IMX6CCMState {
uint32_t ccm[CCM_MAX];
uint32_t analog[CCM_ANALOG_MAX];
-} IMX6CCMState;
+};
#endif /* IMX6_CCM_H */
diff --git a/include/hw/misc/imx6_src.h b/include/hw/misc/imx6_src.h
index eb3640732e..f380da3810 100644
--- a/include/hw/misc/imx6_src.h
+++ b/include/hw/misc/imx6_src.h
@@ -13,6 +13,7 @@
#include "hw/sysbus.h"
#include "qemu/bitops.h"
+#include "qom/object.h"
#define SRC_SCR 0
#define SRC_SBMR1 1
@@ -57,9 +58,9 @@
#define EXTRACT(value, name) extract32(value, name##_SHIFT, name##_LENGTH)
#define TYPE_IMX6_SRC "imx6.src"
-#define IMX6_SRC(obj) OBJECT_CHECK(IMX6SRCState, (obj), TYPE_IMX6_SRC)
+OBJECT_DECLARE_SIMPLE_TYPE(IMX6SRCState, IMX6_SRC)
-typedef struct IMX6SRCState {
+struct IMX6SRCState {
/* <private> */
SysBusDevice parent_obj;
@@ -68,6 +69,6 @@ typedef struct IMX6SRCState {
uint32_t regs[SRC_MAX];
-} IMX6SRCState;
+};
#endif /* IMX6_SRC_H */
diff --git a/include/hw/misc/imx6ul_ccm.h b/include/hw/misc/imx6ul_ccm.h
index 377ddca244..edb5f784d5 100644
--- a/include/hw/misc/imx6ul_ccm.h
+++ b/include/hw/misc/imx6ul_ccm.h
@@ -12,6 +12,7 @@
#include "hw/misc/imx_ccm.h"
#include "qemu/bitops.h"
+#include "qom/object.h"
#define CCM_CCR 0
#define CCM_CCDR 1
@@ -207,9 +208,9 @@
#define CCM_ANALOG_PLL_LOCK (1 << 31);
#define TYPE_IMX6UL_CCM "imx6ul.ccm"
-#define IMX6UL_CCM(obj) OBJECT_CHECK(IMX6ULCCMState, (obj), TYPE_IMX6UL_CCM)
+OBJECT_DECLARE_SIMPLE_TYPE(IMX6ULCCMState, IMX6UL_CCM)
-typedef struct IMX6ULCCMState {
+struct IMX6ULCCMState {
/* <private> */
IMXCCMState parent_obj;
@@ -221,6 +222,6 @@ typedef struct IMX6ULCCMState {
uint32_t ccm[CCM_MAX];
uint32_t analog[CCM_ANALOG_MAX];
-} IMX6ULCCMState;
+};
#endif /* IMX6UL_CCM_H */
diff --git a/include/hw/misc/imx7_ccm.h b/include/hw/misc/imx7_ccm.h
index 9538f37d98..dcaebfb4ef 100644
--- a/include/hw/misc/imx7_ccm.h
+++ b/include/hw/misc/imx7_ccm.h
@@ -14,6 +14,7 @@
#include "hw/misc/imx_ccm.h"
#include "qemu/bitops.h"
+#include "qom/object.h"
enum IMX7AnalogRegisters {
ANALOG_PLL_ARM,
@@ -104,9 +105,9 @@ enum IMX7PMURegisters {
};
#define TYPE_IMX7_CCM "imx7.ccm"
-#define IMX7_CCM(obj) OBJECT_CHECK(IMX7CCMState, (obj), TYPE_IMX7_CCM)
+OBJECT_DECLARE_SIMPLE_TYPE(IMX7CCMState, IMX7_CCM)
-typedef struct IMX7CCMState {
+struct IMX7CCMState {
/* <private> */
IMXCCMState parent_obj;
@@ -114,13 +115,13 @@ typedef struct IMX7CCMState {
MemoryRegion iomem;
uint32_t ccm[CCM_MAX];
-} IMX7CCMState;
+};
#define TYPE_IMX7_ANALOG "imx7.analog"
-#define IMX7_ANALOG(obj) OBJECT_CHECK(IMX7AnalogState, (obj), TYPE_IMX7_ANALOG)
+OBJECT_DECLARE_SIMPLE_TYPE(IMX7AnalogState, IMX7_ANALOG)
-typedef struct IMX7AnalogState {
+struct IMX7AnalogState {
/* <private> */
IMXCCMState parent_obj;
@@ -134,6 +135,6 @@ typedef struct IMX7AnalogState {
uint32_t analog[ANALOG_MAX];
uint32_t pmu[PMU_MAX];
-} IMX7AnalogState;
+};
#endif /* IMX7_CCM_H */
diff --git a/include/hw/misc/imx7_gpr.h b/include/hw/misc/imx7_gpr.h
index e19373d274..df364bd8f0 100644
--- a/include/hw/misc/imx7_gpr.h
+++ b/include/hw/misc/imx7_gpr.h
@@ -14,15 +14,16 @@
#include "qemu/bitops.h"
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_IMX7_GPR "imx7.gpr"
-#define IMX7_GPR(obj) OBJECT_CHECK(IMX7GPRState, (obj), TYPE_IMX7_GPR)
+OBJECT_DECLARE_SIMPLE_TYPE(IMX7GPRState, IMX7_GPR)
-typedef struct IMX7GPRState {
+struct IMX7GPRState {
/* <private> */
SysBusDevice parent_obj;
MemoryRegion mmio;
-} IMX7GPRState;
+};
#endif /* IMX7_GPR_H */
diff --git a/include/hw/misc/imx7_snvs.h b/include/hw/misc/imx7_snvs.h
index 255f8f26f9..1272076086 100644
--- a/include/hw/misc/imx7_snvs.h
+++ b/include/hw/misc/imx7_snvs.h
@@ -14,22 +14,28 @@
#include "qemu/bitops.h"
#include "hw/sysbus.h"
+#include "qom/object.h"
enum IMX7SNVSRegisters {
SNVS_LPCR = 0x38,
SNVS_LPCR_TOP = BIT(6),
- SNVS_LPCR_DP_EN = BIT(5)
+ SNVS_LPCR_DP_EN = BIT(5),
+ SNVS_LPSRTCMR = 0x050, /* Secure Real Time Counter MSB Register */
+ SNVS_LPSRTCLR = 0x054, /* Secure Real Time Counter LSB Register */
};
#define TYPE_IMX7_SNVS "imx7.snvs"
-#define IMX7_SNVS(obj) OBJECT_CHECK(IMX7SNVSState, (obj), TYPE_IMX7_SNVS)
+OBJECT_DECLARE_SIMPLE_TYPE(IMX7SNVSState, IMX7_SNVS)
-typedef struct IMX7SNVSState {
+struct IMX7SNVSState {
/* <private> */
SysBusDevice parent_obj;
MemoryRegion mmio;
-} IMX7SNVSState;
+
+ uint64_t tick_offset;
+ uint64_t lpcr;
+};
#endif /* IMX7_SNVS_H */
diff --git a/include/hw/misc/imx7_src.h b/include/hw/misc/imx7_src.h
new file mode 100644
index 0000000000..b4b97dcb1c
--- /dev/null
+++ b/include/hw/misc/imx7_src.h
@@ -0,0 +1,66 @@
+/*
+ * IMX7 System Reset Controller
+ *
+ * Copyright (C) 2023 Jean-Christophe Dubois <jcd@tribudubois.net>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef IMX7_SRC_H
+#define IMX7_SRC_H
+
+#include "hw/sysbus.h"
+#include "qemu/bitops.h"
+#include "qom/object.h"
+
+#define SRC_SCR 0
+#define SRC_A7RCR0 1
+#define SRC_A7RCR1 2
+#define SRC_M4RCR 3
+#define SRC_ERCR 5
+#define SRC_HSICPHY_RCR 7
+#define SRC_USBOPHY1_RCR 8
+#define SRC_USBOPHY2_RCR 9
+#define SRC_MPIPHY_RCR 10
+#define SRC_PCIEPHY_RCR 11
+#define SRC_SBMR1 22
+#define SRC_SRSR 23
+#define SRC_SISR 26
+#define SRC_SIMR 27
+#define SRC_SBMR2 28
+#define SRC_GPR1 29
+#define SRC_GPR2 30
+#define SRC_GPR3 31
+#define SRC_GPR4 32
+#define SRC_GPR5 33
+#define SRC_GPR6 34
+#define SRC_GPR7 35
+#define SRC_GPR8 36
+#define SRC_GPR9 37
+#define SRC_GPR10 38
+#define SRC_MAX 39
+
+/* SRC_A7SCR1 */
+#define R_CORE1_ENABLE_SHIFT 1
+#define R_CORE1_ENABLE_LENGTH 1
+/* SRC_A7SCR0 */
+#define R_CORE1_RST_SHIFT 5
+#define R_CORE1_RST_LENGTH 1
+#define R_CORE0_RST_SHIFT 4
+#define R_CORE0_RST_LENGTH 1
+
+#define TYPE_IMX7_SRC "imx7.src"
+OBJECT_DECLARE_SIMPLE_TYPE(IMX7SRCState, IMX7_SRC)
+
+struct IMX7SRCState {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /* <public> */
+ MemoryRegion iomem;
+
+ uint32_t regs[SRC_MAX];
+};
+
+#endif /* IMX7_SRC_H */
diff --git a/include/hw/misc/imx_ccm.h b/include/hw/misc/imx_ccm.h
index 33cbc09952..7e5678e972 100644
--- a/include/hw/misc/imx_ccm.h
+++ b/include/hw/misc/imx_ccm.h
@@ -12,6 +12,7 @@
#define IMX_CCM_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define CKIL_FREQ 32768 /* nominal 32khz clock */
@@ -27,20 +28,15 @@
#define PLL_MFN(x) (((x) & 0x3ff) << 0)
#define TYPE_IMX_CCM "imx.ccm"
-#define IMX_CCM(obj) \
- OBJECT_CHECK(IMXCCMState, (obj), TYPE_IMX_CCM)
-#define IMX_CCM_CLASS(klass) \
- OBJECT_CLASS_CHECK(IMXCCMClass, (klass), TYPE_IMX_CCM)
-#define IMX_GET_CLASS(obj) \
- OBJECT_GET_CLASS(IMXCCMClass, (obj), TYPE_IMX_CCM)
+OBJECT_DECLARE_TYPE(IMXCCMState, IMXCCMClass, IMX_CCM)
-typedef struct IMXCCMState {
+struct IMXCCMState {
/* <private> */
SysBusDevice parent_obj;
/* <public> */
-} IMXCCMState;
+};
typedef enum {
CLK_NONE,
@@ -52,13 +48,13 @@ typedef enum {
CLK_HIGH,
} IMXClk;
-typedef struct IMXCCMClass {
+struct IMXCCMClass {
/* <private> */
SysBusDeviceClass parent_class;
/* <public> */
uint32_t (*get_clock_frequency)(IMXCCMState *s, IMXClk clk);
-} IMXCCMClass;
+};
uint32_t imx_ccm_calc_pll(uint32_t pllreg, uint32_t base_freq);
diff --git a/include/hw/misc/imx_rngc.h b/include/hw/misc/imx_rngc.h
index f0d2b44d4f..34ad699225 100644
--- a/include/hw/misc/imx_rngc.h
+++ b/include/hw/misc/imx_rngc.h
@@ -11,11 +11,12 @@
#define IMX_RNGC_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_IMX_RNGC "imx.rngc"
-#define IMX_RNGC(obj) OBJECT_CHECK(IMXRNGCState, (obj), TYPE_IMX_RNGC)
+OBJECT_DECLARE_SIMPLE_TYPE(IMXRNGCState, IMX_RNGC)
-typedef struct IMXRNGCState {
+struct IMXRNGCState {
/*< private >*/
SysBusDevice parent_obj;
@@ -30,6 +31,6 @@ typedef struct IMXRNGCState {
QEMUBH *self_test_bh;
QEMUBH *seed_bh;
qemu_irq irq;
-} IMXRNGCState;
+};
#endif /* IMX_RNGC_H */
diff --git a/include/hw/misc/iosb.h b/include/hw/misc/iosb.h
new file mode 100644
index 0000000000..377f8ca7e2
--- /dev/null
+++ b/include/hw/misc/iosb.h
@@ -0,0 +1,25 @@
+/*
+ * QEMU IOSB emulation
+ *
+ * Copyright (c) 2019 Laurent Vivier
+ * Copyright (c) 2022 Mark Cave-Ayland
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_MEM_IOSB_H
+#define HW_MEM_IOSB_H
+
+#define IOSB_REGS 7
+
+struct IOSBState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion mem_regs;
+ uint32_t regs[IOSB_REGS];
+};
+
+#define TYPE_IOSB "IOSB"
+OBJECT_DECLARE_SIMPLE_TYPE(IOSBState, IOSB);
+
+#endif
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
index bcb0437be5..79a3628320 100644
--- a/include/hw/misc/iotkit-secctl.h
+++ b/include/hw/misc/iotkit-secctl.h
@@ -11,7 +11,7 @@
/* This is a model of the security controller which is part of the
* Arm IoT Kit and documented in
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
+ * https://developer.arm.com/documentation/ecm0601256/latest
*
* QEMU interface:
* + sysbus MMIO region 0 is the "secure privilege control block" registers
@@ -56,9 +56,10 @@
#define IOTKIT_SECCTL_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_IOTKIT_SECCTL "iotkit-secctl"
-#define IOTKIT_SECCTL(obj) OBJECT_CHECK(IoTKitSecCtl, (obj), TYPE_IOTKIT_SECCTL)
+OBJECT_DECLARE_SIMPLE_TYPE(IoTKitSecCtl, IOTKIT_SECCTL)
#define IOTS_APB_PPC0_NUM_PORTS 3
#define IOTS_APB_PPC1_NUM_PORTS 1
@@ -70,7 +71,6 @@
#define IOTS_NUM_MPC 4
#define IOTS_NUM_EXP_MSC 16
-typedef struct IoTKitSecCtl IoTKitSecCtl;
/* State and IRQ lines relating to a PPC. For the
* PPCs in the IoTKit not all the IRQ lines are used.
@@ -120,6 +120,8 @@ struct IoTKitSecCtl {
IoTKitSecCtlPPC apb[IOTS_NUM_APB_PPC];
IoTKitSecCtlPPC apbexp[IOTS_NUM_APB_EXP_PPC];
IoTKitSecCtlPPC ahbexp[IOTS_NUM_APB_EXP_PPC];
+
+ uint32_t sse_version;
};
#endif
diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
index 601c8ecc0d..481e27f4db 100644
--- a/include/hw/misc/iotkit-sysctl.h
+++ b/include/hw/misc/iotkit-sysctl.h
@@ -12,14 +12,13 @@
/*
* This is a model of the "system control element" which is part of the
* Arm IoTKit and documented in
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
+ * https://developer.arm.com/documentation/ecm0601256/latest
* Specifically, it implements the "system information block" and
* "system control register" blocks.
*
* QEMU interface:
- * + QOM property "SYS_VERSION": value of the SYS_VERSION register of the
- * system information block of the SSE
- * (used to identify whether to provide SSE-200-only registers)
+ * + QOM property "sse-version": indicates which SSE version this is part of
+ * (used to identify whether to provide SSE-200-only registers, etc)
* + sysbus MMIO region 0: the system information register bank
* + sysbus MMIO region 1: the system control register bank
*/
@@ -28,12 +27,12 @@
#define HW_MISC_IOTKIT_SYSCTL_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_IOTKIT_SYSCTL "iotkit-sysctl"
-#define IOTKIT_SYSCTL(obj) OBJECT_CHECK(IoTKitSysCtl, (obj), \
- TYPE_IOTKIT_SYSCTL)
+OBJECT_DECLARE_SIMPLE_TYPE(IoTKitSysCtl, IOTKIT_SYSCTL)
-typedef struct IoTKitSysCtl {
+struct IoTKitSysCtl {
/*< private >*/
SysBusDevice parent_obj;
@@ -54,19 +53,21 @@ typedef struct IoTKitSysCtl {
uint32_t initsvtor1;
uint32_t nmi_enable;
uint32_t ewctrl;
+ uint32_t pwrctrl;
uint32_t pdcm_pd_sys_sense;
uint32_t pdcm_pd_sram0_sense;
uint32_t pdcm_pd_sram1_sense;
uint32_t pdcm_pd_sram2_sense;
uint32_t pdcm_pd_sram3_sense;
+ uint32_t pdcm_pd_cpu0_sense;
+ uint32_t pdcm_pd_vmr0_sense;
+ uint32_t pdcm_pd_vmr1_sense;
/* Properties */
- uint32_t sys_version;
+ uint32_t sse_version;
uint32_t cpuwait_rst;
uint32_t initsvtor0_rst;
uint32_t initsvtor1_rst;
-
- bool is_sse200;
-} IoTKitSysCtl;
+};
#endif
diff --git a/include/hw/misc/iotkit-sysinfo.h b/include/hw/misc/iotkit-sysinfo.h
index d84eb203b9..91c23f90d2 100644
--- a/include/hw/misc/iotkit-sysinfo.h
+++ b/include/hw/misc/iotkit-sysinfo.h
@@ -12,7 +12,7 @@
/*
* This is a model of the "system information block" which is part of the
* Arm IoTKit and documented in
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
+ * https://developer.arm.com/documentation/ecm0601256/latest
* QEMU interface:
* + QOM property "SYS_VERSION": value to use for SYS_VERSION register
* + QOM property "SYS_CONFIG": value to use for SYS_CONFIG register
@@ -23,12 +23,12 @@
#define HW_MISC_IOTKIT_SYSINFO_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_IOTKIT_SYSINFO "iotkit-sysinfo"
-#define IOTKIT_SYSINFO(obj) OBJECT_CHECK(IoTKitSysInfo, (obj), \
- TYPE_IOTKIT_SYSINFO)
+OBJECT_DECLARE_SIMPLE_TYPE(IoTKitSysInfo, IOTKIT_SYSINFO)
-typedef struct IoTKitSysInfo {
+struct IoTKitSysInfo {
/*< private >*/
SysBusDevice parent_obj;
@@ -38,6 +38,8 @@ typedef struct IoTKitSysInfo {
/* Properties */
uint32_t sys_version;
uint32_t sys_config;
-} IoTKitSysInfo;
+ uint32_t sse_version;
+ uint32_t iidr;
+};
#endif
diff --git a/include/hw/misc/lasi.h b/include/hw/misc/lasi.h
new file mode 100644
index 0000000000..f01c0f680a
--- /dev/null
+++ b/include/hw/misc/lasi.h
@@ -0,0 +1,79 @@
+/*
+ * HP-PARISC Lasi chipset emulation.
+ *
+ * (C) 2019 by Helge Deller <deller@gmx.de>
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ *
+ * Documentation available at:
+ * https://parisc.wiki.kernel.org/images-parisc/7/79/Lasi_ers.pdf
+ */
+
+#ifndef LASI_H
+#define LASI_H
+
+#include "exec/address-spaces.h"
+#include "hw/pci/pci_host.h"
+#include "hw/boards.h"
+
+#define TYPE_LASI_CHIP "lasi-chip"
+OBJECT_DECLARE_SIMPLE_TYPE(LasiState, LASI_CHIP)
+
+#define LASI_IRR 0x00 /* RO */
+#define LASI_IMR 0x04
+#define LASI_IPR 0x08
+#define LASI_ICR 0x0c
+#define LASI_IAR 0x10
+
+#define LASI_LPT 0x02000
+#define LASI_AUDIO 0x04000
+#define LASI_UART 0x05000
+#define LASI_LAN 0x07000
+#define LASI_RTC 0x09000
+#define LASI_FDC 0x0A000
+
+#define LASI_PCR 0x0C000 /* LASI Power Control register */
+#define LASI_ERRLOG 0x0C004 /* LASI Error Logging register */
+#define LASI_VER 0x0C008 /* LASI Version Control register */
+#define LASI_IORESET 0x0C00C /* LASI I/O Reset register */
+#define LASI_AMR 0x0C010 /* LASI Arbitration Mask register */
+#define LASI_IO_CONF 0x7FFFE /* LASI primary configuration register */
+#define LASI_IO_CONF2 0x7FFFF /* LASI secondary configuration register */
+
+#define LASI_BIT(x) (1ul << (x))
+#define LASI_IRQ_BITS (LASI_BIT(5) | LASI_BIT(7) | LASI_BIT(8) | LASI_BIT(9) \
+ | LASI_BIT(13) | LASI_BIT(14) | LASI_BIT(16) | LASI_BIT(17) \
+ | LASI_BIT(18) | LASI_BIT(19) | LASI_BIT(20) | LASI_BIT(21) \
+ | LASI_BIT(26))
+
+#define ICR_BUS_ERROR_BIT LASI_BIT(8) /* bit 8 in ICR */
+#define ICR_TOC_BIT LASI_BIT(1) /* bit 1 in ICR */
+
+#define LASI_IRQS 27
+
+#define LASI_IRQ_HPA 14
+#define LASI_IRQ_UART_HPA 5
+#define LASI_IRQ_LPT_HPA 7
+#define LASI_IRQ_LAN_HPA 8
+#define LASI_IRQ_SCSI_HPA 9
+#define LASI_IRQ_AUDIO_HPA 13
+#define LASI_IRQ_PS2KBD_HPA 26
+#define LASI_IRQ_PS2MOU_HPA 26
+
+struct LasiState {
+ PCIHostState parent_obj;
+
+ uint32_t irr;
+ uint32_t imr;
+ uint32_t ipr;
+ uint32_t icr;
+ uint32_t iar;
+
+ uint32_t errlog;
+ uint32_t amr;
+ uint32_t rtc_ref;
+
+ MemoryRegion this_mem;
+};
+
+#endif
diff --git a/include/hw/misc/led.h b/include/hw/misc/led.h
new file mode 100644
index 0000000000..29c0879570
--- /dev/null
+++ b/include/hw/misc/led.h
@@ -0,0 +1,98 @@
+/*
+ * QEMU single LED device
+ *
+ * Copyright (C) 2020 Philippe Mathieu-Daudé <f4bug@amsat.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef HW_MISC_LED_H
+#define HW_MISC_LED_H
+
+#include "qom/object.h"
+#include "hw/qdev-core.h"
+
+#define TYPE_LED "led"
+
+/**
+ * LEDColor: Color of a LED
+ *
+ * This set is restricted to physically available LED colors.
+ *
+ * LED colors from 'Table 1. Product performance of LUXEON Rebel Color
+ * Line' of the 'DS68 LUXEON Rebel Color Line' datasheet available at:
+ * https://www.lumileds.com/products/color-leds/luxeon-rebel-color/
+ */
+typedef enum { /* Coarse wavelength range */
+ LED_COLOR_VIOLET, /* 425 nm */
+ LED_COLOR_BLUE, /* 475 nm */
+ LED_COLOR_CYAN, /* 500 nm */
+ LED_COLOR_GREEN, /* 535 nm */
+ LED_COLOR_YELLOW, /* 567 nm */
+ LED_COLOR_AMBER, /* 590 nm */
+ LED_COLOR_ORANGE, /* 615 nm */
+ LED_COLOR_RED, /* 630 nm */
+} LEDColor;
+
+struct LEDState {
+ /* Private */
+ DeviceState parent_obj;
+ /* Public */
+
+ uint8_t intensity_percent;
+ qemu_irq irq;
+
+ /* Properties */
+ char *description;
+ char *color;
+ /*
+ * Determines whether a GPIO is using a positive (active-high)
+ * logic (when used with GPIO, the intensity at reset is related
+ * to the GPIO polarity).
+ */
+ bool gpio_active_high;
+};
+typedef struct LEDState LEDState;
+DECLARE_INSTANCE_CHECKER(LEDState, LED, TYPE_LED)
+
+/**
+ * led_set_intensity: Set the intensity of a LED device
+ * @s: the LED object
+ * @intensity_percent: intensity as percentage in range 0 to 100.
+ */
+void led_set_intensity(LEDState *s, unsigned intensity_percent);
+
+/**
+ * led_get_intensity:
+ * @s: the LED object
+ *
+ * Returns: The LED intensity as percentage in range 0 to 100.
+ */
+unsigned led_get_intensity(LEDState *s);
+
+/**
+ * led_set_state: Set the state of a LED device
+ * @s: the LED object
+ * @is_emitting: boolean indicating whether the LED is emitting
+ *
+ * This utility is meant for LED connected to GPIO.
+ */
+void led_set_state(LEDState *s, bool is_emitting);
+
+/**
+ * led_create_simple: Create and realize a LED device
+ * @parentobj: the parent object
+ * @gpio_polarity: GPIO polarity
+ * @color: color of the LED
+ * @description: description of the LED (optional)
+ *
+ * Create the device state structure, initialize it, and
+ * drop the reference to it (the device is realized).
+ *
+ * Returns: The newly allocated and instantiated LED object.
+ */
+LEDState *led_create_simple(Object *parentobj,
+ GpioPolarity gpio_polarity,
+ LEDColor color,
+ const char *description);
+
+#endif /* HW_MISC_LED_H */
diff --git a/include/hw/misc/mac_via.h b/include/hw/misc/mac_via.h
index 0be05d649b..63cdcf7c69 100644
--- a/include/hw/misc/mac_via.h
+++ b/include/hw/misc/mac_via.h
@@ -12,87 +12,43 @@
#include "exec/memory.h"
#include "hw/sysbus.h"
#include "hw/misc/mos6522.h"
+#include "hw/input/adb.h"
+#include "qom/object.h"
-/* VIA 1 */
-#define VIA1_IRQ_ONE_SECOND_BIT 0
-#define VIA1_IRQ_VBLANK_BIT 1
-#define VIA1_IRQ_ADB_READY_BIT 2
-#define VIA1_IRQ_ADB_DATA_BIT 3
-#define VIA1_IRQ_ADB_CLOCK_BIT 4
+#define VIA_SIZE 0x2000
-#define VIA1_IRQ_NB 8
+/* VIA 1 */
+#define VIA1_IRQ_ONE_SECOND_BIT CA2_INT_BIT
+#define VIA1_IRQ_60HZ_BIT CA1_INT_BIT
+#define VIA1_IRQ_ADB_READY_BIT SR_INT_BIT
+#define VIA1_IRQ_ADB_DATA_BIT CB2_INT_BIT
+#define VIA1_IRQ_ADB_CLOCK_BIT CB1_INT_BIT
-#define VIA1_IRQ_ONE_SECOND (1 << VIA1_IRQ_ONE_SECOND_BIT)
-#define VIA1_IRQ_VBLANK (1 << VIA1_IRQ_VBLANK_BIT)
-#define VIA1_IRQ_ADB_READY (1 << VIA1_IRQ_ADB_READY_BIT)
-#define VIA1_IRQ_ADB_DATA (1 << VIA1_IRQ_ADB_DATA_BIT)
-#define VIA1_IRQ_ADB_CLOCK (1 << VIA1_IRQ_ADB_CLOCK_BIT)
+#define VIA1_IRQ_ONE_SECOND BIT(VIA1_IRQ_ONE_SECOND_BIT)
+#define VIA1_IRQ_60HZ BIT(VIA1_IRQ_60HZ_BIT)
+#define VIA1_IRQ_ADB_READY BIT(VIA1_IRQ_ADB_READY_BIT)
+#define VIA1_IRQ_ADB_DATA BIT(VIA1_IRQ_ADB_DATA_BIT)
+#define VIA1_IRQ_ADB_CLOCK BIT(VIA1_IRQ_ADB_CLOCK_BIT)
#define TYPE_MOS6522_Q800_VIA1 "mos6522-q800-via1"
-#define MOS6522_Q800_VIA1(obj) OBJECT_CHECK(MOS6522Q800VIA1State, (obj), \
- TYPE_MOS6522_Q800_VIA1)
+OBJECT_DECLARE_SIMPLE_TYPE(MOS6522Q800VIA1State, MOS6522_Q800_VIA1)
-typedef struct MOS6522Q800VIA1State {
+struct MOS6522Q800VIA1State {
/*< private >*/
MOS6522State parent_obj;
- qemu_irq irqs[VIA1_IRQ_NB];
- uint8_t last_b;
- uint8_t PRAM[256];
-
- /* external timers */
- QEMUTimer *one_second_timer;
- int64_t next_second;
- QEMUTimer *VBL_timer;
- int64_t next_VBL;
-} MOS6522Q800VIA1State;
-
-
-/* VIA 2 */
-#define VIA2_IRQ_SCSI_DATA_BIT 0
-#define VIA2_IRQ_SLOT_BIT 1
-#define VIA2_IRQ_UNUSED_BIT 2
-#define VIA2_IRQ_SCSI_BIT 3
-#define VIA2_IRQ_ASC_BIT 4
+ MemoryRegion via_mem;
-#define VIA2_IRQ_NB 8
-
-#define VIA2_IRQ_SCSI_DATA (1 << VIA2_IRQ_SCSI_DATA_BIT)
-#define VIA2_IRQ_SLOT (1 << VIA2_IRQ_SLOT_BIT)
-#define VIA2_IRQ_UNUSED (1 << VIA2_IRQ_SCSI_BIT)
-#define VIA2_IRQ_SCSI (1 << VIA2_IRQ_UNUSED_BIT)
-#define VIA2_IRQ_ASC (1 << VIA2_IRQ_ASC_BIT)
-
-#define TYPE_MOS6522_Q800_VIA2 "mos6522-q800-via2"
-#define MOS6522_Q800_VIA2(obj) OBJECT_CHECK(MOS6522Q800VIA2State, (obj), \
- TYPE_MOS6522_Q800_VIA2)
-
-typedef struct MOS6522Q800VIA2State {
- /*< private >*/
- MOS6522State parent_obj;
-} MOS6522Q800VIA2State;
-
-
-#define TYPE_MAC_VIA "mac_via"
-#define MAC_VIA(obj) OBJECT_CHECK(MacVIAState, (obj), TYPE_MAC_VIA)
-
-typedef struct MacVIAState {
- SysBusDevice busdev;
+ qemu_irq auxmode_irq;
+ uint8_t last_b;
+ /* RTC */
+ uint8_t PRAM[256];
+ BlockBackend *blk;
VMChangeStateEntry *vmstate;
- /* MMIO */
- MemoryRegion mmio;
- MemoryRegion via1mem;
- MemoryRegion via2mem;
-
- /* VIAs */
- MOS6522Q800VIA1State mos6522_via1;
- MOS6522Q800VIA2State mos6522_via2;
-
- /* RTC */
uint32_t tick_offset;
uint8_t data_out;
@@ -102,7 +58,6 @@ typedef struct MacVIAState {
uint8_t cmd;
int wprotect;
int alt;
- BlockBackend *blk;
/* ADB */
ADBBusState adb_bus;
@@ -113,6 +68,48 @@ typedef struct MacVIAState {
uint8_t adb_data_in[128];
uint8_t adb_data_out[16];
uint8_t adb_autopoll_cmd;
-} MacVIAState;
+
+ /* external timers */
+ QEMUTimer *one_second_timer;
+ int64_t next_second;
+ QEMUTimer *sixty_hz_timer;
+ int64_t next_sixty_hz;
+
+ /* SETUPTIMEK hack */
+ int timer_hack_state;
+};
+
+
+/* VIA 2 */
+#define VIA2_IRQ_SCSI_DATA_BIT CA2_INT_BIT
+#define VIA2_IRQ_NUBUS_BIT CA1_INT_BIT
+#define VIA2_IRQ_SCSI_BIT CB2_INT_BIT
+#define VIA2_IRQ_ASC_BIT CB1_INT_BIT
+
+#define VIA2_IRQ_SCSI_DATA BIT(VIA2_IRQ_SCSI_DATA_BIT)
+#define VIA2_IRQ_NUBUS BIT(VIA2_IRQ_NUBUS_BIT)
+#define VIA2_IRQ_UNUSED BIT(VIA2_IRQ_SCSI_BIT)
+#define VIA2_IRQ_SCSI BIT(VIA2_IRQ_UNUSED_BIT)
+#define VIA2_IRQ_ASC BIT(VIA2_IRQ_ASC_BIT)
+
+#define VIA2_NUBUS_IRQ_NB 7
+
+#define VIA2_NUBUS_IRQ_9 0
+#define VIA2_NUBUS_IRQ_A 1
+#define VIA2_NUBUS_IRQ_B 2
+#define VIA2_NUBUS_IRQ_C 3
+#define VIA2_NUBUS_IRQ_D 4
+#define VIA2_NUBUS_IRQ_E 5
+#define VIA2_NUBUS_IRQ_INTVIDEO 6
+
+#define TYPE_MOS6522_Q800_VIA2 "mos6522-q800-via2"
+OBJECT_DECLARE_SIMPLE_TYPE(MOS6522Q800VIA2State, MOS6522_Q800_VIA2)
+
+struct MOS6522Q800VIA2State {
+ /*< private >*/
+ MOS6522State parent_obj;
+
+ MemoryRegion via_mem;
+};
#endif
diff --git a/include/hw/misc/macio/cuda.h b/include/hw/misc/macio/cuda.h
index a8cf0be1ec..8a6678c749 100644
--- a/include/hw/misc/macio/cuda.h
+++ b/include/hw/misc/macio/cuda.h
@@ -26,7 +26,9 @@
#ifndef CUDA_H
#define CUDA_H
+#include "hw/input/adb.h"
#include "hw/misc/mos6522.h"
+#include "qom/object.h"
/* CUDA commands (2nd byte) */
#define CUDA_WARM_START 0x0
@@ -58,20 +60,19 @@
/* MOS6522 CUDA */
-typedef struct MOS6522CUDAState {
+struct MOS6522CUDAState {
/*< private >*/
MOS6522State parent_obj;
-} MOS6522CUDAState;
+};
#define TYPE_MOS6522_CUDA "mos6522-cuda"
-#define MOS6522_CUDA(obj) OBJECT_CHECK(MOS6522CUDAState, (obj), \
- TYPE_MOS6522_CUDA)
+OBJECT_DECLARE_SIMPLE_TYPE(MOS6522CUDAState, MOS6522_CUDA)
/* Cuda */
#define TYPE_CUDA "cuda"
-#define CUDA(obj) OBJECT_CHECK(CUDAState, (obj), TYPE_CUDA)
+OBJECT_DECLARE_SIMPLE_TYPE(CUDAState, CUDA)
-typedef struct CUDAState {
+struct CUDAState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -97,6 +98,6 @@ typedef struct CUDAState {
qemu_irq irq;
uint8_t data_in[128];
uint8_t data_out[16];
-} CUDAState;
+};
#endif /* CUDA_H */
diff --git a/include/hw/misc/macio/gpio.h b/include/hw/misc/macio/gpio.h
index 24a4364b39..7d2aa886c2 100644
--- a/include/hw/misc/macio/gpio.h
+++ b/include/hw/misc/macio/gpio.h
@@ -28,22 +28,21 @@
#include "hw/ppc/openpic.h"
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_MACIO_GPIO "macio-gpio"
-#define MACIO_GPIO(obj) OBJECT_CHECK(MacIOGPIOState, (obj), TYPE_MACIO_GPIO)
+OBJECT_DECLARE_SIMPLE_TYPE(MacIOGPIOState, MACIO_GPIO)
-typedef struct MacIOGPIOState {
+struct MacIOGPIOState {
/*< private >*/
SysBusDevice parent;
/*< public >*/
- OpenPICState *pic;
-
MemoryRegion gpiomem;
qemu_irq gpio_extirqs[10];
uint8_t gpio_levels[8];
uint8_t gpio_regs[36]; /* XXX Check count */
-} MacIOGPIOState;
+};
void macio_set_gpio(MacIOGPIOState *s, uint32_t gpio, bool state);
diff --git a/include/hw/misc/macio/macio.h b/include/hw/misc/macio/macio.h
index 87335a991c..2b54da6b31 100644
--- a/include/hw/misc/macio/macio.h
+++ b/include/hw/misc/macio/macio.h
@@ -27,30 +27,52 @@
#define MACIO_H
#include "hw/char/escc.h"
-#include "hw/pci/pci.h"
-#include "hw/ide/internal.h"
+#include "hw/pci/pci_device.h"
+#include "hw/ide/ide-bus.h"
#include "hw/intc/heathrow_pic.h"
#include "hw/misc/macio/cuda.h"
#include "hw/misc/macio/gpio.h"
#include "hw/misc/macio/pmu.h"
-#include "hw/ppc/mac.h"
+#include "hw/nvram/mac_nvram.h"
#include "hw/ppc/mac_dbdma.h"
#include "hw/ppc/openpic.h"
+#include "qom/object.h"
+
+/* Old World IRQs */
+#define OLDWORLD_CUDA_IRQ 0x12
+#define OLDWORLD_ESCCB_IRQ 0x10
+#define OLDWORLD_ESCCA_IRQ 0xf
+#define OLDWORLD_IDE0_IRQ 0xd
+#define OLDWORLD_IDE0_DMA_IRQ 0x2
+#define OLDWORLD_IDE1_IRQ 0xe
+#define OLDWORLD_IDE1_DMA_IRQ 0x3
+
+/* New World IRQs */
+#define NEWWORLD_CUDA_IRQ 0x19
+#define NEWWORLD_PMU_IRQ 0x19
+#define NEWWORLD_ESCCB_IRQ 0x24
+#define NEWWORLD_ESCCA_IRQ 0x25
+#define NEWWORLD_IDE0_IRQ 0xd
+#define NEWWORLD_IDE0_DMA_IRQ 0x2
+#define NEWWORLD_IDE1_IRQ 0xe
+#define NEWWORLD_IDE1_DMA_IRQ 0x3
+#define NEWWORLD_EXTING_GPIO1 0x2f
+#define NEWWORLD_EXTING_GPIO9 0x37
/* MacIO virtual bus */
#define TYPE_MACIO_BUS "macio-bus"
-#define MACIO_BUS(obj) OBJECT_CHECK(MacIOBusState, (obj), TYPE_MACIO_BUS)
+OBJECT_DECLARE_SIMPLE_TYPE(MacIOBusState, MACIO_BUS)
-typedef struct MacIOBusState {
+struct MacIOBusState {
/*< private >*/
BusState parent_obj;
-} MacIOBusState;
+};
/* MacIO IDE */
#define TYPE_MACIO_IDE "macio-ide"
-#define MACIO_IDE(obj) OBJECT_CHECK(MACIOIDEState, (obj), TYPE_MACIO_IDE)
+OBJECT_DECLARE_SIMPLE_TYPE(MACIOIDEState, MACIO_IDE)
-typedef struct MACIOIDEState {
+struct MACIOIDEState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -68,15 +90,15 @@ typedef struct MACIOIDEState {
bool dma_active;
uint32_t timing_reg;
uint32_t irq_reg;
-} MACIOIDEState;
+};
void macio_ide_init_drives(MACIOIDEState *ide, DriveInfo **hd_table);
void macio_ide_register_dma(MACIOIDEState *ide);
#define TYPE_MACIO "macio"
-#define MACIO(obj) OBJECT_CHECK(MacIOState, (obj), TYPE_MACIO)
+OBJECT_DECLARE_SIMPLE_TYPE(MacIOState, MACIO)
-typedef struct MacIOState {
+struct MacIOState {
/*< private >*/
PCIDevice parent;
/*< public >*/
@@ -88,37 +110,35 @@ typedef struct MacIOState {
DBDMAState dbdma;
ESCCState escc;
uint64_t frequency;
-} MacIOState;
+};
#define TYPE_OLDWORLD_MACIO "macio-oldworld"
-#define OLDWORLD_MACIO(obj) \
- OBJECT_CHECK(OldWorldMacIOState, (obj), TYPE_OLDWORLD_MACIO)
+OBJECT_DECLARE_SIMPLE_TYPE(OldWorldMacIOState, OLDWORLD_MACIO)
-typedef struct OldWorldMacIOState {
+struct OldWorldMacIOState {
/*< private >*/
MacIOState parent_obj;
/*< public >*/
- HeathrowState *pic;
+ HeathrowState pic;
MacIONVRAMState nvram;
MACIOIDEState ide[2];
-} OldWorldMacIOState;
+};
#define TYPE_NEWWORLD_MACIO "macio-newworld"
-#define NEWWORLD_MACIO(obj) \
- OBJECT_CHECK(NewWorldMacIOState, (obj), TYPE_NEWWORLD_MACIO)
+OBJECT_DECLARE_SIMPLE_TYPE(NewWorldMacIOState, NEWWORLD_MACIO)
-typedef struct NewWorldMacIOState {
+struct NewWorldMacIOState {
/*< private >*/
MacIOState parent_obj;
/*< public >*/
bool has_pmu;
bool has_adb;
- OpenPICState *pic;
+ OpenPICState pic;
MACIOIDEState ide[2];
MacIOGPIOState gpio;
-} NewWorldMacIOState;
+};
#endif /* MACIO_H */
diff --git a/include/hw/misc/macio/pmu.h b/include/hw/misc/macio/pmu.h
index 72f75612b6..ceb12082ae 100644
--- a/include/hw/misc/macio/pmu.h
+++ b/include/hw/misc/macio/pmu.h
@@ -10,8 +10,10 @@
#ifndef PMU_H
#define PMU_H
+#include "hw/input/adb.h"
#include "hw/misc/mos6522.h"
#include "hw/misc/macio/gpio.h"
+#include "qom/object.h"
/*
* PMU commands
@@ -74,7 +76,7 @@
#define PMU_INT_WAITING_CHARGER 0x01 /* ??? */
#define PMU_INT_AUTO_SRQ_POLL 0x02 /* ??? */
-/* Bits in the environement message (either obtained via PMU_GET_COVER,
+/* Bits in the environment message (either obtained via PMU_GET_COVER,
* or via PMU_INT_ENVIRONMENT on core99 */
#define PMU_ENV_LID_CLOSED 0x01 /* The lid is closed */
@@ -173,28 +175,25 @@ typedef enum {
} PMUCmdState;
/* MOS6522 PMU */
-typedef struct MOS6522PMUState {
+struct MOS6522PMUState {
/*< private >*/
MOS6522State parent_obj;
-} MOS6522PMUState;
+};
#define TYPE_MOS6522_PMU "mos6522-pmu"
-#define MOS6522_PMU(obj) OBJECT_CHECK(MOS6522PMUState, (obj), \
- TYPE_MOS6522_PMU)
+OBJECT_DECLARE_SIMPLE_TYPE(MOS6522PMUState, MOS6522_PMU)
/**
* PMUState:
* @last_b: last value of B register
*/
-typedef struct PMUState {
+struct PMUState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
MemoryRegion mem;
uint64_t frequency;
- qemu_irq via_irq;
- bool via_irq_state;
/* PMU state */
MOS6522PMUState mos6522_pmu;
@@ -228,9 +227,9 @@ typedef struct PMUState {
/* GPIO */
MacIOGPIOState *gpio;
-} PMUState;
+};
#define TYPE_VIA_PMU "via-pmu"
-#define VIA_PMU(obj) OBJECT_CHECK(PMUState, (obj), TYPE_VIA_PMU)
+OBJECT_DECLARE_SIMPLE_TYPE(PMUState, VIA_PMU)
#endif /* PMU_H */
diff --git a/include/hw/misc/mchp_pfsoc_dmc.h b/include/hw/misc/mchp_pfsoc_dmc.h
new file mode 100644
index 0000000000..3bc1581e0f
--- /dev/null
+++ b/include/hw/misc/mchp_pfsoc_dmc.h
@@ -0,0 +1,58 @@
+/*
+ * Microchip PolarFire SoC DDR Memory Controller module emulation
+ *
+ * Copyright (c) 2020 Wind River Systems, Inc.
+ *
+ * Author:
+ * Bin Meng <bin.meng@windriver.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MCHP_PFSOC_DMC_H
+#define MCHP_PFSOC_DMC_H
+
+#include "hw/sysbus.h"
+
+/* DDR SGMII PHY module */
+
+#define MCHP_PFSOC_DDR_SGMII_PHY_REG_SIZE 0x1000
+
+typedef struct MchpPfSoCDdrSgmiiPhyState {
+ SysBusDevice parent;
+ MemoryRegion sgmii_phy;
+} MchpPfSoCDdrSgmiiPhyState;
+
+#define TYPE_MCHP_PFSOC_DDR_SGMII_PHY "mchp.pfsoc.ddr_sgmii_phy"
+
+#define MCHP_PFSOC_DDR_SGMII_PHY(obj) \
+ OBJECT_CHECK(MchpPfSoCDdrSgmiiPhyState, (obj), \
+ TYPE_MCHP_PFSOC_DDR_SGMII_PHY)
+
+/* DDR CFG module */
+
+#define MCHP_PFSOC_DDR_CFG_REG_SIZE 0x40000
+
+typedef struct MchpPfSoCDdrCfgState {
+ SysBusDevice parent;
+ MemoryRegion cfg;
+} MchpPfSoCDdrCfgState;
+
+#define TYPE_MCHP_PFSOC_DDR_CFG "mchp.pfsoc.ddr_cfg"
+
+#define MCHP_PFSOC_DDR_CFG(obj) \
+ OBJECT_CHECK(MchpPfSoCDdrCfgState, (obj), \
+ TYPE_MCHP_PFSOC_DDR_CFG)
+
+#endif /* MCHP_PFSOC_DMC_H */
diff --git a/include/hw/misc/mchp_pfsoc_ioscb.h b/include/hw/misc/mchp_pfsoc_ioscb.h
new file mode 100644
index 0000000000..3fd3e74966
--- /dev/null
+++ b/include/hw/misc/mchp_pfsoc_ioscb.h
@@ -0,0 +1,56 @@
+/*
+ * Microchip PolarFire SoC IOSCB module emulation
+ *
+ * Copyright (c) 2020 Wind River Systems, Inc.
+ *
+ * Author:
+ * Bin Meng <bin.meng@windriver.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MCHP_PFSOC_IOSCB_H
+#define MCHP_PFSOC_IOSCB_H
+
+#include "hw/sysbus.h"
+
+typedef struct MchpPfSoCIoscbState {
+ SysBusDevice parent;
+ MemoryRegion container;
+ MemoryRegion lane01;
+ MemoryRegion lane23;
+ MemoryRegion ctrl;
+ MemoryRegion qspixip;
+ MemoryRegion mailbox;
+ MemoryRegion cfg;
+ MemoryRegion ccc;
+ MemoryRegion pll_mss;
+ MemoryRegion cfm_mss;
+ MemoryRegion pll_ddr;
+ MemoryRegion bc_ddr;
+ MemoryRegion io_calib_ddr;
+ MemoryRegion pll_sgmii;
+ MemoryRegion dll_sgmii;
+ MemoryRegion cfm_sgmii;
+ MemoryRegion bc_sgmii;
+ MemoryRegion io_calib_sgmii;
+ qemu_irq irq;
+} MchpPfSoCIoscbState;
+
+#define TYPE_MCHP_PFSOC_IOSCB "mchp.pfsoc.ioscb"
+
+#define MCHP_PFSOC_IOSCB(obj) \
+ OBJECT_CHECK(MchpPfSoCIoscbState, (obj), TYPE_MCHP_PFSOC_IOSCB)
+
+#endif /* MCHP_PFSOC_IOSCB_H */
diff --git a/include/hw/misc/mchp_pfsoc_sysreg.h b/include/hw/misc/mchp_pfsoc_sysreg.h
new file mode 100644
index 0000000000..c2232bd28d
--- /dev/null
+++ b/include/hw/misc/mchp_pfsoc_sysreg.h
@@ -0,0 +1,42 @@
+/*
+ * Microchip PolarFire SoC SYSREG module emulation
+ *
+ * Copyright (c) 2020 Wind River Systems, Inc.
+ *
+ * Author:
+ * Bin Meng <bin.meng@windriver.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MCHP_PFSOC_SYSREG_H
+#define MCHP_PFSOC_SYSREG_H
+
+#include "hw/sysbus.h"
+
+#define MCHP_PFSOC_SYSREG_REG_SIZE 0x2000
+
+typedef struct MchpPfSoCSysregState {
+ SysBusDevice parent;
+ MemoryRegion sysreg;
+ qemu_irq irq;
+} MchpPfSoCSysregState;
+
+#define TYPE_MCHP_PFSOC_SYSREG "mchp.pfsoc.sysreg"
+
+#define MCHP_PFSOC_SYSREG(obj) \
+ OBJECT_CHECK(MchpPfSoCSysregState, (obj), \
+ TYPE_MCHP_PFSOC_SYSREG)
+
+#endif /* MCHP_PFSOC_SYSREG_H */
diff --git a/include/hw/misc/mips_cmgcr.h b/include/hw/misc/mips_cmgcr.h
index 3e6e223273..db4bf5f449 100644
--- a/include/hw/misc/mips_cmgcr.h
+++ b/include/hw/misc/mips_cmgcr.h
@@ -11,9 +11,10 @@
#define MIPS_CMGCR_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_MIPS_GCR "mips-gcr"
-#define MIPS_GCR(obj) OBJECT_CHECK(MIPSGCRState, (obj), TYPE_MIPS_GCR)
+OBJECT_DECLARE_SIMPLE_TYPE(MIPSGCRState, MIPS_GCR)
#define GCR_BASE_ADDR 0x1fbf8000ULL
#define GCR_ADDRSPACE_SZ 0x8000
@@ -70,12 +71,11 @@ struct MIPSGCRVPState {
uint64_t reset_base;
};
-typedef struct MIPSGCRState MIPSGCRState;
struct MIPSGCRState {
SysBusDevice parent_obj;
int32_t gcr_rev;
- int32_t num_vps;
+ uint32_t num_vps;
hwaddr gcr_base;
MemoryRegion iomem;
MemoryRegion *cpc_mr;
diff --git a/include/hw/misc/mips_cpc.h b/include/hw/misc/mips_cpc.h
index 3f670578b0..fcafbd5e00 100644
--- a/include/hw/misc/mips_cpc.h
+++ b/include/hw/misc/mips_cpc.h
@@ -6,7 +6,7 @@
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -21,6 +21,7 @@
#define MIPS_CPC_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define CPC_ADDRSPACE_SZ 0x6000
@@ -34,9 +35,9 @@
#define CPC_VP_RUNNING_OFS 0x30
#define TYPE_MIPS_CPC "mips-cpc"
-#define MIPS_CPC(obj) OBJECT_CHECK(MIPSCPCState, (obj), TYPE_MIPS_CPC)
+OBJECT_DECLARE_SIMPLE_TYPE(MIPSCPCState, MIPS_CPC)
-typedef struct MIPSCPCState {
+struct MIPSCPCState {
SysBusDevice parent_obj;
uint32_t num_vp;
@@ -44,6 +45,6 @@ typedef struct MIPSCPCState {
MemoryRegion mr;
uint64_t vp_running; /* Indicates which VPs are in the run state */
-} MIPSCPCState;
+};
#endif /* MIPS_CPC_H */
diff --git a/include/hw/misc/mips_itu.h b/include/hw/misc/mips_itu.h
index c44e7672b6..27c9a1090d 100644
--- a/include/hw/misc/mips_itu.h
+++ b/include/hw/misc/mips_itu.h
@@ -6,7 +6,7 @@
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -21,9 +21,10 @@
#define MIPS_ITU_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_MIPS_ITU "mips-itu"
-#define MIPS_ITU(obj) OBJECT_CHECK(MIPSITUState, (obj), TYPE_MIPS_ITU)
+OBJECT_DECLARE_SIMPLE_TYPE(MIPSITUState, MIPS_ITU)
#define ITC_CELL_DEPTH_SHIFT 2
#define ITC_CELL_DEPTH (1u << ITC_CELL_DEPTH_SHIFT)
@@ -51,13 +52,13 @@ typedef struct ITCStorageCell {
#define ITC_ADDRESSMAP_NUM 2
-typedef struct MIPSITUState {
+struct MIPSITUState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
- int32_t num_fifo;
- int32_t num_semaphores;
+ uint32_t num_fifo;
+ uint32_t num_semaphores;
/* ITC Storage */
ITCStorageCell *cell;
@@ -69,12 +70,7 @@ typedef struct MIPSITUState {
/* ITU Control Register */
uint64_t icr0;
-
- /* SAAR */
- bool saar_present;
- void *saar;
-
-} MIPSITUState;
+};
/* Get ITC Configuration Tag memory region. */
MemoryRegion *mips_itu_get_tag_region(MIPSITUState *itu);
diff --git a/include/hw/misc/mos6522.h b/include/hw/misc/mos6522.h
index 97384c6e02..fba45668ab 100644
--- a/include/hw/misc/mos6522.h
+++ b/include/hw/misc/mos6522.h
@@ -27,9 +27,11 @@
#ifndef MOS6522_H
#define MOS6522_H
-#include "exec/memory.h"
+#include "exec/hwaddr.h"
#include "hw/sysbus.h"
-#include "hw/input/adb.h"
+#include "qom/object.h"
+
+#define MOS6522_NUM_REGS 16
/* Bits in ACR */
#define SR_CTRL 0x1c /* Shift register control bits */
@@ -40,18 +42,43 @@
#define IER_SET 0x80 /* set bits in IER */
#define IER_CLR 0 /* clear bits in IER */
-#define CA2_INT 0x01
-#define CA1_INT 0x02
-#define SR_INT 0x04 /* Shift register full/empty */
-#define CB2_INT 0x08
-#define CB1_INT 0x10
-#define T2_INT 0x20 /* Timer 2 interrupt */
-#define T1_INT 0x40 /* Timer 1 interrupt */
+#define CA2_INT_BIT 0
+#define CA1_INT_BIT 1
+#define SR_INT_BIT 2 /* Shift register full/empty */
+#define CB2_INT_BIT 3
+#define CB1_INT_BIT 4
+#define T2_INT_BIT 5 /* Timer 2 interrupt */
+#define T1_INT_BIT 6 /* Timer 1 interrupt */
+
+#define CA2_INT BIT(CA2_INT_BIT)
+#define CA1_INT BIT(CA1_INT_BIT)
+#define SR_INT BIT(SR_INT_BIT)
+#define CB2_INT BIT(CB2_INT_BIT)
+#define CB1_INT BIT(CB1_INT_BIT)
+#define T2_INT BIT(T2_INT_BIT)
+#define T1_INT BIT(T1_INT_BIT)
+
+#define VIA_NUM_INTS 5
/* Bits in ACR */
#define T1MODE 0xc0 /* Timer 1 mode */
#define T1MODE_CONT 0x40 /* continuous interrupts */
+/* Bits in PCR */
+#define CB2_CTRL_MASK 0xe0
+#define CB2_CTRL_SHIFT 5
+#define CB1_CTRL_MASK 0x10
+#define CB1_CTRL_SHIFT 4
+#define CA2_CTRL_MASK 0x0e
+#define CA2_CTRL_SHIFT 1
+#define CA1_CTRL_MASK 0x1
+#define CA1_CTRL_SHIFT 0
+
+#define C2_POS 0x2
+#define C2_IND 0x1
+
+#define C1_POS 0x1
+
/* VIA registers */
#define VIA_REG_B 0x00
#define VIA_REG_A 0x01
@@ -99,7 +126,7 @@ typedef struct MOS6522Timer {
* @last_b: last value of B register
* @last_acr: last value of ACR register
*/
-typedef struct MOS6522State {
+struct MOS6522State {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -120,34 +147,31 @@ typedef struct MOS6522State {
uint64_t frequency;
qemu_irq irq;
-} MOS6522State;
+ uint8_t last_irq_levels;
+};
#define TYPE_MOS6522 "mos6522"
-#define MOS6522(obj) OBJECT_CHECK(MOS6522State, (obj), TYPE_MOS6522)
+OBJECT_DECLARE_TYPE(MOS6522State, MOS6522DeviceClass, MOS6522)
-typedef struct MOS6522DeviceClass {
+struct MOS6522DeviceClass {
DeviceClass parent_class;
- DeviceReset parent_reset;
- void (*set_sr_int)(MOS6522State *dev);
+ ResettablePhases parent_phases;
void (*portB_write)(MOS6522State *dev);
void (*portA_write)(MOS6522State *dev);
- void (*update_irq)(MOS6522State *dev);
/* These are used to influence the CUDA MacOS timebase calibration */
uint64_t (*get_timer1_counter_value)(MOS6522State *dev, MOS6522Timer *ti);
uint64_t (*get_timer2_counter_value)(MOS6522State *dev, MOS6522Timer *ti);
uint64_t (*get_timer1_load_time)(MOS6522State *dev, MOS6522Timer *ti);
uint64_t (*get_timer2_load_time)(MOS6522State *dev, MOS6522Timer *ti);
-} MOS6522DeviceClass;
+};
-#define MOS6522_DEVICE_CLASS(cls) \
- OBJECT_CLASS_CHECK(MOS6522DeviceClass, (cls), TYPE_MOS6522)
-#define MOS6522_DEVICE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(MOS6522DeviceClass, (obj), TYPE_MOS6522)
extern const VMStateDescription vmstate_mos6522;
uint64_t mos6522_read(void *opaque, hwaddr addr, unsigned size);
void mos6522_write(void *opaque, hwaddr addr, uint64_t val, unsigned size);
+void hmp_info_via(Monitor *mon, const QDict *qdict);
+
#endif /* MOS6522_H */
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
index 69e265cd4b..7b8bd604de 100644
--- a/include/hw/misc/mps2-fpgaio.h
+++ b/include/hw/misc/mps2-fpgaio.h
@@ -12,7 +12,7 @@
/* This is a model of the FPGAIO register block in the AN505
* FPGA image for the MPS2 dev board; it is documented in the
* application note:
- * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
+ * https://developer.arm.com/documentation/dai0505/latest/
*
* QEMU interface:
* + sysbus MMIO region 0: the register bank
@@ -22,20 +22,29 @@
#define MPS2_FPGAIO_H
#include "hw/sysbus.h"
+#include "hw/misc/led.h"
+#include "qom/object.h"
#define TYPE_MPS2_FPGAIO "mps2-fpgaio"
-#define MPS2_FPGAIO(obj) OBJECT_CHECK(MPS2FPGAIO, (obj), TYPE_MPS2_FPGAIO)
+OBJECT_DECLARE_SIMPLE_TYPE(MPS2FPGAIO, MPS2_FPGAIO)
-typedef struct {
+#define MPS2FPGAIO_MAX_LEDS 32
+
+struct MPS2FPGAIO {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
MemoryRegion iomem;
+ LEDState *led[MPS2FPGAIO_MAX_LEDS];
+ uint32_t num_leds;
+ bool has_switches;
+ bool has_dbgctrl;
uint32_t led0;
uint32_t prescale;
uint32_t misc;
+ uint32_t dbgctrl;
/* QEMU_CLOCK_VIRTUAL time at which counter and pscntr were last synced */
int64_t pscntr_sync_ticks;
@@ -48,6 +57,6 @@ typedef struct {
/* These hold the CLOCK_VIRTUAL ns tick when the CLK1HZ/CLK100HZ was zero */
int64_t clk1hz_tick_offset;
int64_t clk100hz_tick_offset;
-} MPS2FPGAIO;
+};
#endif
diff --git a/include/hw/misc/mps2-scc.h b/include/hw/misc/mps2-scc.h
index 7045473788..8ff188c06b 100644
--- a/include/hw/misc/mps2-scc.h
+++ b/include/hw/misc/mps2-scc.h
@@ -9,26 +9,49 @@
* (at your option) any later version.
*/
+/*
+ * This is a model of the Serial Communication Controller (SCC)
+ * block found in most MPS FPGA images.
+ *
+ * QEMU interface:
+ * + sysbus MMIO region 0: the register bank
+ * + QOM property "scc-cfg4": value of the read-only CFG4 register
+ * + QOM property "scc-aid": value of the read-only SCC_AID register
+ * + QOM property "scc-id": value of the read-only SCC_ID register
+ * + QOM property "scc-cfg0": reset value of the CFG0 register
+ * + QOM property array "oscclk": reset values of the OSCCLK registers
+ * (which are accessed via the SYS_CFG channel provided by this device)
+ * + named GPIO output "remap": this tracks the value of CFG0 register
+ * bit 0. Boards where this bit controls memory remapping should
+ * connect this GPIO line to a function performing that mapping.
+ * Boards where bit 0 has no special function should leave the GPIO
+ * output disconnected.
+ */
#ifndef MPS2_SCC_H
#define MPS2_SCC_H
#include "hw/sysbus.h"
+#include "hw/misc/led.h"
+#include "qom/object.h"
#define TYPE_MPS2_SCC "mps2-scc"
-#define MPS2_SCC(obj) OBJECT_CHECK(MPS2SCC, (obj), TYPE_MPS2_SCC)
+OBJECT_DECLARE_SIMPLE_TYPE(MPS2SCC, MPS2_SCC)
-#define NUM_OSCCLK 3
-
-typedef struct {
+struct MPS2SCC {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
MemoryRegion iomem;
+ LEDState *led[8];
uint32_t cfg0;
uint32_t cfg1;
+ uint32_t cfg2;
uint32_t cfg4;
+ uint32_t cfg5;
+ uint32_t cfg6;
+ uint32_t cfg7;
uint32_t cfgdata_rtn;
uint32_t cfgdata_out;
uint32_t cfgctrl;
@@ -36,8 +59,12 @@ typedef struct {
uint32_t dll;
uint32_t aid;
uint32_t id;
- uint32_t oscclk[NUM_OSCCLK];
- uint32_t oscclk_reset[NUM_OSCCLK];
-} MPS2SCC;
+ uint32_t num_oscclk;
+ uint32_t *oscclk;
+ uint32_t *oscclk_reset;
+ uint32_t cfg0_reset;
+
+ qemu_irq remap;
+};
#endif
diff --git a/include/hw/misc/msf2-sysreg.h b/include/hw/misc/msf2-sysreg.h
index 5993f67b4e..fc1890e710 100644
--- a/include/hw/misc/msf2-sysreg.h
+++ b/include/hw/misc/msf2-sysreg.h
@@ -26,6 +26,7 @@
#define HW_MSF2_SYSREG_H
#include "hw/sysbus.h"
+#include "qom/object.h"
enum {
ESRAM_CR = 0x00 / 4,
@@ -61,9 +62,9 @@ enum {
#define MSF2_SYSREG_MMIO_SIZE 0x300
#define TYPE_MSF2_SYSREG "msf2-sysreg"
-#define MSF2_SYSREG(obj) OBJECT_CHECK(MSF2SysregState, (obj), TYPE_MSF2_SYSREG)
+OBJECT_DECLARE_SIMPLE_TYPE(MSF2SysregState, MSF2_SYSREG)
-typedef struct MSF2SysregState {
+struct MSF2SysregState {
SysBusDevice parent_obj;
MemoryRegion iomem;
@@ -72,6 +73,6 @@ typedef struct MSF2SysregState {
uint8_t apb1div;
uint32_t regs[MSF2_SYSREG_MMIO_SIZE / 4];
-} MSF2SysregState;
+};
#endif /* HW_MSF2_SYSREG_H */
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
new file mode 100644
index 0000000000..5ed4a4672b
--- /dev/null
+++ b/include/hw/misc/npcm7xx_clk.h
@@ -0,0 +1,180 @@
+/*
+ * Nuvoton NPCM7xx Clock Control Registers.
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_CLK_H
+#define NPCM7XX_CLK_H
+
+#include "exec/memory.h"
+#include "hw/clock.h"
+#include "hw/sysbus.h"
+
+/*
+ * Number of registers in our device state structure. Don't change this without
+ * incrementing the version_id in the vmstate.
+ */
+#define NPCM7XX_CLK_NR_REGS (0x70 / sizeof(uint32_t))
+
+#define NPCM7XX_WATCHDOG_RESET_GPIO_IN "npcm7xx-clk-watchdog-reset-gpio-in"
+
+/* Maximum amount of clock inputs in a SEL module. */
+#define NPCM7XX_CLK_SEL_MAX_INPUT 5
+
+/* PLLs in CLK module. */
+typedef enum NPCM7xxClockPLL {
+ NPCM7XX_CLOCK_PLL0,
+ NPCM7XX_CLOCK_PLL1,
+ NPCM7XX_CLOCK_PLL2,
+ NPCM7XX_CLOCK_PLLG,
+ NPCM7XX_CLOCK_NR_PLLS,
+} NPCM7xxClockPLL;
+
+/* SEL/MUX in CLK module. */
+typedef enum NPCM7xxClockSEL {
+ NPCM7XX_CLOCK_PIXCKSEL,
+ NPCM7XX_CLOCK_MCCKSEL,
+ NPCM7XX_CLOCK_CPUCKSEL,
+ NPCM7XX_CLOCK_CLKOUTSEL,
+ NPCM7XX_CLOCK_UARTCKSEL,
+ NPCM7XX_CLOCK_TIMCKSEL,
+ NPCM7XX_CLOCK_SDCKSEL,
+ NPCM7XX_CLOCK_GFXMSEL,
+ NPCM7XX_CLOCK_SUCKSEL,
+ NPCM7XX_CLOCK_NR_SELS,
+} NPCM7xxClockSEL;
+
+/* Dividers in CLK module. */
+typedef enum NPCM7xxClockDivider {
+ NPCM7XX_CLOCK_PLL1D2, /* PLL1/2 */
+ NPCM7XX_CLOCK_PLL2D2, /* PLL2/2 */
+ NPCM7XX_CLOCK_MC_DIVIDER,
+ NPCM7XX_CLOCK_AXI_DIVIDER,
+ NPCM7XX_CLOCK_AHB_DIVIDER,
+ NPCM7XX_CLOCK_AHB3_DIVIDER,
+ NPCM7XX_CLOCK_SPI0_DIVIDER,
+ NPCM7XX_CLOCK_SPIX_DIVIDER,
+ NPCM7XX_CLOCK_APB1_DIVIDER,
+ NPCM7XX_CLOCK_APB2_DIVIDER,
+ NPCM7XX_CLOCK_APB3_DIVIDER,
+ NPCM7XX_CLOCK_APB4_DIVIDER,
+ NPCM7XX_CLOCK_APB5_DIVIDER,
+ NPCM7XX_CLOCK_CLKOUT_DIVIDER,
+ NPCM7XX_CLOCK_UART_DIVIDER,
+ NPCM7XX_CLOCK_TIMER_DIVIDER,
+ NPCM7XX_CLOCK_ADC_DIVIDER,
+ NPCM7XX_CLOCK_MMC_DIVIDER,
+ NPCM7XX_CLOCK_SDHC_DIVIDER,
+ NPCM7XX_CLOCK_GFXM_DIVIDER, /* divide by 3 */
+ NPCM7XX_CLOCK_UTMI_DIVIDER,
+ NPCM7XX_CLOCK_NR_DIVIDERS,
+} NPCM7xxClockConverter;
+
+typedef struct NPCM7xxCLKState NPCM7xxCLKState;
+
+/**
+ * struct NPCM7xxClockPLLState - A PLL module in CLK module.
+ * @name: The name of the module.
+ * @clk: The CLK module that owns this module.
+ * @clock_in: The input clock of this module.
+ * @clock_out: The output clock of this module.
+ * @reg: The control registers for this PLL module.
+ */
+typedef struct NPCM7xxClockPLLState {
+ DeviceState parent;
+
+ const char *name;
+ NPCM7xxCLKState *clk;
+ Clock *clock_in;
+ Clock *clock_out;
+
+ int reg;
+} NPCM7xxClockPLLState;
+
+/**
+ * struct NPCM7xxClockSELState - A SEL module in CLK module.
+ * @name: The name of the module.
+ * @clk: The CLK module that owns this module.
+ * @input_size: The size of inputs of this module.
+ * @clock_in: The input clocks of this module.
+ * @clock_out: The output clocks of this module.
+ * @offset: The offset of this module in the control register.
+ * @len: The length of this module in the control register.
+ */
+typedef struct NPCM7xxClockSELState {
+ DeviceState parent;
+
+ const char *name;
+ NPCM7xxCLKState *clk;
+ uint8_t input_size;
+ Clock *clock_in[NPCM7XX_CLK_SEL_MAX_INPUT];
+ Clock *clock_out;
+
+ int offset;
+ int len;
+} NPCM7xxClockSELState;
+
+/**
+ * struct NPCM7xxClockDividerState - A Divider module in CLK module.
+ * @name: The name of the module.
+ * @clk: The CLK module that owns this module.
+ * @clock_in: The input clock of this module.
+ * @clock_out: The output clock of this module.
+ * @divide: The function the divider uses to divide the input.
+ * @reg: The index of the control register that contains the divisor.
+ * @offset: The offset of the divisor in the control register.
+ * @len: The length of the divisor in the control register.
+ * @divisor: The divisor for a constant divisor
+ */
+typedef struct NPCM7xxClockDividerState {
+ DeviceState parent;
+
+ const char *name;
+ NPCM7xxCLKState *clk;
+ Clock *clock_in;
+ Clock *clock_out;
+
+ uint32_t (*divide)(struct NPCM7xxClockDividerState *s);
+ union {
+ struct {
+ int reg;
+ int offset;
+ int len;
+ };
+ int divisor;
+ };
+} NPCM7xxClockDividerState;
+
+struct NPCM7xxCLKState {
+ SysBusDevice parent;
+
+ MemoryRegion iomem;
+
+ /* Clock converters */
+ NPCM7xxClockPLLState plls[NPCM7XX_CLOCK_NR_PLLS];
+ NPCM7xxClockSELState sels[NPCM7XX_CLOCK_NR_SELS];
+ NPCM7xxClockDividerState dividers[NPCM7XX_CLOCK_NR_DIVIDERS];
+
+ uint32_t regs[NPCM7XX_CLK_NR_REGS];
+
+ /* Time reference for SECCNT and CNTR25M, initialized by power on reset */
+ int64_t ref_ns;
+
+ /* The incoming reference clock. */
+ Clock *clkref;
+};
+
+#define TYPE_NPCM7XX_CLK "npcm7xx-clk"
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxCLKState, NPCM7XX_CLK)
+
+#endif /* NPCM7XX_CLK_H */
diff --git a/include/hw/misc/npcm7xx_gcr.h b/include/hw/misc/npcm7xx_gcr.h
new file mode 100644
index 0000000000..c0bbdda77e
--- /dev/null
+++ b/include/hw/misc/npcm7xx_gcr.h
@@ -0,0 +1,73 @@
+/*
+ * Nuvoton NPCM7xx System Global Control Registers.
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_GCR_H
+#define NPCM7XX_GCR_H
+
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+
+/*
+ * NPCM7XX PWRON STRAP bit fields
+ * 12: SPI0 powered by VSBV3 at 1.8V
+ * 11: System flash attached to BMC
+ * 10: BSP alternative pins.
+ * 9:8: Flash UART command route enabled.
+ * 7: Security enabled.
+ * 6: HI-Z state control.
+ * 5: ECC disabled.
+ * 4: Reserved
+ * 3: JTAG2 enabled.
+ * 2:0: CPU and DRAM clock frequency.
+ */
+#define NPCM7XX_PWRON_STRAP_SPI0F18 BIT(12)
+#define NPCM7XX_PWRON_STRAP_SFAB BIT(11)
+#define NPCM7XX_PWRON_STRAP_BSPA BIT(10)
+#define NPCM7XX_PWRON_STRAP_FUP(x) ((x) << 8)
+#define FUP_NORM_UART2 3
+#define FUP_PROG_UART3 2
+#define FUP_PROG_UART2 1
+#define FUP_NORM_UART3 0
+#define NPCM7XX_PWRON_STRAP_SECEN BIT(7)
+#define NPCM7XX_PWRON_STRAP_HIZ BIT(6)
+#define NPCM7XX_PWRON_STRAP_ECC BIT(5)
+#define NPCM7XX_PWRON_STRAP_RESERVE1 BIT(4)
+#define NPCM7XX_PWRON_STRAP_J2EN BIT(3)
+#define NPCM7XX_PWRON_STRAP_CKFRQ(x) (x)
+#define CKFRQ_SKIPINIT 0x000
+#define CKFRQ_DEFAULT 0x111
+
+/*
+ * Number of registers in our device state structure. Don't change this without
+ * incrementing the version_id in the vmstate.
+ */
+#define NPCM7XX_GCR_NR_REGS (0x148 / sizeof(uint32_t))
+
+struct NPCM7xxGCRState {
+ SysBusDevice parent;
+
+ MemoryRegion iomem;
+
+ uint32_t regs[NPCM7XX_GCR_NR_REGS];
+
+ uint32_t reset_pwron;
+ uint32_t reset_mdlr;
+ uint32_t reset_intcr3;
+};
+
+#define TYPE_NPCM7XX_GCR "npcm7xx-gcr"
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxGCRState, NPCM7XX_GCR)
+
+#endif /* NPCM7XX_GCR_H */
diff --git a/include/hw/misc/npcm7xx_mft.h b/include/hw/misc/npcm7xx_mft.h
new file mode 100644
index 0000000000..d6384382ce
--- /dev/null
+++ b/include/hw/misc/npcm7xx_mft.h
@@ -0,0 +1,69 @@
+/*
+ * Nuvoton NPCM7xx MFT Module
+ *
+ * Copyright 2021 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_MFT_H
+#define NPCM7XX_MFT_H
+
+#include "exec/memory.h"
+#include "hw/clock.h"
+#include "hw/irq.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+/* Max Fan input number. */
+#define NPCM7XX_MFT_MAX_FAN_INPUT 19
+
+/*
+ * Number of registers in one MFT module. Don't change this without increasing
+ * the version_id in vmstate.
+ */
+#define NPCM7XX_MFT_NR_REGS (0x20 / sizeof(uint16_t))
+
+/*
+ * The MFT can take up to 4 inputs: A0, B0, A1, B1. It can measure one A and one
+ * B simultaneously. NPCM7XX_MFT_INASEL and NPCM7XX_MFT_INBSEL are used to
+ * select which A or B input are used.
+ */
+#define NPCM7XX_MFT_FANIN_COUNT 4
+
+/**
+ * struct NPCM7xxMFTState - Multi Functional Tachometer device state.
+ * @parent: System bus device.
+ * @iomem: Memory region through which registers are accessed.
+ * @clock_in: The input clock for MFT from CLK module.
+ * @clock_{1,2}: The counter clocks for NPCM7XX_MFT_CNT{1,2}
+ * @irq: The IRQ for this MFT state.
+ * @regs: The MMIO registers.
+ * @max_rpm: The maximum rpm for fans. Order: A0, B0, A1, B1.
+ * @duty: The duty cycles for fans, relative to NPCM7XX_PWM_MAX_DUTY.
+ */
+struct NPCM7xxMFTState {
+ SysBusDevice parent;
+
+ MemoryRegion iomem;
+
+ Clock *clock_in;
+ Clock *clock_1, *clock_2;
+ qemu_irq irq;
+ uint16_t regs[NPCM7XX_MFT_NR_REGS];
+
+ uint32_t max_rpm[NPCM7XX_MFT_FANIN_COUNT];
+ uint32_t duty[NPCM7XX_MFT_FANIN_COUNT];
+};
+
+#define TYPE_NPCM7XX_MFT "npcm7xx-mft"
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxMFTState, NPCM7XX_MFT)
+
+#endif /* NPCM7XX_MFT_H */
diff --git a/include/hw/misc/npcm7xx_pwm.h b/include/hw/misc/npcm7xx_pwm.h
new file mode 100644
index 0000000000..bf953440ac
--- /dev/null
+++ b/include/hw/misc/npcm7xx_pwm.h
@@ -0,0 +1,106 @@
+/*
+ * Nuvoton NPCM7xx PWM Module
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_PWM_H
+#define NPCM7XX_PWM_H
+
+#include "hw/clock.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+
+/* Each PWM module holds 4 PWM channels. */
+#define NPCM7XX_PWM_PER_MODULE 4
+
+/*
+ * Number of registers in one pwm module. Don't change this without increasing
+ * the version_id in vmstate.
+ */
+#define NPCM7XX_PWM_NR_REGS (0x54 / sizeof(uint32_t))
+
+/*
+ * The maximum duty values. Each duty unit represents 1/NPCM7XX_PWM_MAX_DUTY
+ * cycles. For example, if NPCM7XX_PWM_MAX_DUTY=1,000,000 and a PWM has a duty
+ * value of 100,000 the duty cycle for that PWM is 10%.
+ */
+#define NPCM7XX_PWM_MAX_DUTY 1000000
+
+typedef struct NPCM7xxPWMState NPCM7xxPWMState;
+
+/**
+ * struct NPCM7xxPWM - The state of a single PWM channel.
+ * @module: The PWM module that contains this channel.
+ * @irq: GIC interrupt line to fire on expiration if enabled.
+ * @running: Whether this PWM channel is generating output.
+ * @inverted: Whether this PWM channel is inverted.
+ * @index: The index of this PWM channel.
+ * @cnr: The counter register.
+ * @cmr: The comparator register.
+ * @pdr: The data register.
+ * @pwdr: The watchdog register.
+ * @freq: The frequency of this PWM channel.
+ * @duty: The duty cycle of this PWM channel. One unit represents
+ * 1/NPCM7XX_MAX_DUTY cycles.
+ */
+typedef struct NPCM7xxPWM {
+ NPCM7xxPWMState *module;
+
+ qemu_irq irq;
+
+ bool running;
+ bool inverted;
+
+ uint8_t index;
+ uint32_t cnr;
+ uint32_t cmr;
+ uint32_t pdr;
+ uint32_t pwdr;
+
+ uint32_t freq;
+ uint32_t duty;
+} NPCM7xxPWM;
+
+/**
+ * struct NPCM7xxPWMState - Pulse Width Modulation device state.
+ * @parent: System bus device.
+ * @iomem: Memory region through which registers are accessed.
+ * @clock: The PWM clock.
+ * @pwm: The PWM channels owned by this module.
+ * @duty_gpio_out: The duty cycle of each PWM channels as a output GPIO.
+ * @ppr: The prescaler register.
+ * @csr: The clock selector register.
+ * @pcr: The control register.
+ * @pier: The interrupt enable register.
+ * @piir: The interrupt indication register.
+ */
+struct NPCM7xxPWMState {
+ SysBusDevice parent;
+
+ MemoryRegion iomem;
+
+ Clock *clock;
+ NPCM7xxPWM pwm[NPCM7XX_PWM_PER_MODULE];
+ qemu_irq duty_gpio_out[NPCM7XX_PWM_PER_MODULE];
+
+ uint32_t ppr;
+ uint32_t csr;
+ uint32_t pcr;
+ uint32_t pier;
+ uint32_t piir;
+};
+
+#define TYPE_NPCM7XX_PWM "npcm7xx-pwm"
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxPWMState, NPCM7XX_PWM)
+
+#endif /* NPCM7XX_PWM_H */
diff --git a/include/hw/misc/npcm7xx_rng.h b/include/hw/misc/npcm7xx_rng.h
new file mode 100644
index 0000000000..650375dc2c
--- /dev/null
+++ b/include/hw/misc/npcm7xx_rng.h
@@ -0,0 +1,34 @@
+/*
+ * Nuvoton NPCM7xx Random Number Generator.
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_RNG_H
+#define NPCM7XX_RNG_H
+
+#include "hw/sysbus.h"
+
+struct NPCM7xxRNGState {
+ SysBusDevice parent;
+
+ MemoryRegion iomem;
+
+ uint8_t rngcs;
+ uint8_t rngd;
+ uint8_t rngmode;
+};
+
+#define TYPE_NPCM7XX_RNG "npcm7xx-rng"
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxRNGState, NPCM7XX_RNG)
+
+#endif /* NPCM7XX_RNG_H */
diff --git a/include/hw/misc/nrf51_rng.h b/include/hw/misc/nrf51_rng.h
index b0133bf665..9aff9a76f8 100644
--- a/include/hw/misc/nrf51_rng.h
+++ b/include/hw/misc/nrf51_rng.h
@@ -36,8 +36,9 @@
#include "hw/sysbus.h"
#include "qemu/timer.h"
+#include "qom/object.h"
#define TYPE_NRF51_RNG "nrf51_soc.rng"
-#define NRF51_RNG(obj) OBJECT_CHECK(NRF51RNGState, (obj), TYPE_NRF51_RNG)
+OBJECT_DECLARE_SIMPLE_TYPE(NRF51RNGState, NRF51_RNG)
#define NRF51_RNG_SIZE 0x1000
@@ -54,7 +55,7 @@
#define NRF51_RNG_REG_CONFIG_DECEN 0
#define NRF51_RNG_REG_VALUE 0x508
-typedef struct {
+struct NRF51RNGState {
SysBusDevice parent_obj;
MemoryRegion mmio;
@@ -78,7 +79,7 @@ typedef struct {
uint32_t interrupt_enabled;
uint32_t filter_enabled;
-} NRF51RNGState;
+};
#endif /* NRF51_RNG_H */
diff --git a/include/hw/misc/pvpanic.h b/include/hw/misc/pvpanic.h
index ae0c8188ce..fab94165d0 100644
--- a/include/hw/misc/pvpanic.h
+++ b/include/hw/misc/pvpanic.h
@@ -15,19 +15,23 @@
#ifndef HW_MISC_PVPANIC_H
#define HW_MISC_PVPANIC_H
+#include "exec/memory.h"
#include "qom/object.h"
-#define TYPE_PVPANIC "pvpanic"
+#define TYPE_PVPANIC_ISA_DEVICE "pvpanic"
+#define TYPE_PVPANIC_PCI_DEVICE "pvpanic-pci"
#define PVPANIC_IOPORT_PROP "ioport"
-static inline uint16_t pvpanic_port(void)
-{
- Object *o = object_resolve_path_type("", TYPE_PVPANIC, NULL);
- if (!o) {
- return 0;
- }
- return object_property_get_uint(o, PVPANIC_IOPORT_PROP, NULL);
-}
+/*
+ * PVPanicState for any device type
+ */
+typedef struct PVPanicState PVPanicState;
+struct PVPanicState {
+ MemoryRegion mr;
+ uint8_t events;
+};
+
+void pvpanic_setup_io(PVPanicState *s, DeviceState *dev, unsigned size);
#endif
diff --git a/include/hw/misc/sifive_e_aon.h b/include/hw/misc/sifive_e_aon.h
new file mode 100644
index 0000000000..2ae1c4139c
--- /dev/null
+++ b/include/hw/misc/sifive_e_aon.h
@@ -0,0 +1,60 @@
+/*
+ * SiFive HiFive1 AON (Always On Domain) interface.
+ *
+ * Copyright (c) 2022 SiFive, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_SIFIVE_AON_H
+#define HW_SIFIVE_AON_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_SIFIVE_E_AON "riscv.sifive.e.aon"
+OBJECT_DECLARE_SIMPLE_TYPE(SiFiveEAONState, SIFIVE_E_AON)
+
+#define SIFIVE_E_AON_WDOGKEY (0x51F15E)
+#define SIFIVE_E_AON_WDOGFEED (0xD09F00D)
+#define SIFIVE_E_LFCLK_DEFAULT_FREQ (32768)
+
+enum {
+ SIFIVE_E_AON_WDT = 0x0,
+ SIFIVE_E_AON_RTC = 0x40,
+ SIFIVE_E_AON_LFROSC = 0x70,
+ SIFIVE_E_AON_BACKUP = 0x80,
+ SIFIVE_E_AON_PMU = 0x100,
+ SIFIVE_E_AON_MAX = 0x150
+};
+
+struct SiFiveEAONState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion mmio;
+
+ /*< watchdog timer >*/
+ QEMUTimer *wdog_timer;
+ qemu_irq wdog_irq;
+ uint64_t wdog_restart_time;
+ uint64_t wdogclk_freq;
+
+ uint32_t wdogcfg;
+ uint16_t wdogcmp0;
+ uint32_t wdogcount;
+ uint8_t wdogunlock;
+};
+
+#endif
diff --git a/include/hw/riscv/sifive_e_prci.h b/include/hw/misc/sifive_e_prci.h
index 698b0b451c..6aa949e910 100644
--- a/include/hw/riscv/sifive_e_prci.h
+++ b/include/hw/misc/sifive_e_prci.h
@@ -19,6 +19,8 @@
#ifndef HW_SIFIVE_E_PRCI_H
#define HW_SIFIVE_E_PRCI_H
+#include "hw/sysbus.h"
+
enum {
SIFIVE_E_PRCI_HFROSCCFG = 0x0,
SIFIVE_E_PRCI_HFXOSCCFG = 0x4,
@@ -51,10 +53,11 @@ enum {
#define TYPE_SIFIVE_E_PRCI "riscv.sifive.e.prci"
-#define SIFIVE_E_PRCI(obj) \
- OBJECT_CHECK(SiFiveEPRCIState, (obj), TYPE_SIFIVE_E_PRCI)
+typedef struct SiFiveEPRCIState SiFiveEPRCIState;
+DECLARE_INSTANCE_CHECKER(SiFiveEPRCIState, SIFIVE_E_PRCI,
+ TYPE_SIFIVE_E_PRCI)
-typedef struct SiFiveEPRCIState {
+struct SiFiveEPRCIState {
/*< private >*/
SysBusDevice parent_obj;
@@ -64,7 +67,7 @@ typedef struct SiFiveEPRCIState {
uint32_t hfxosccfg;
uint32_t pllcfg;
uint32_t plloutdiv;
-} SiFiveEPRCIState;
+};
DeviceState *sifive_e_prci_create(hwaddr addr);
diff --git a/include/hw/riscv/sifive_test.h b/include/hw/misc/sifive_test.h
index 1ec416ac1b..88a38d00c5 100644
--- a/include/hw/riscv/sifive_test.h
+++ b/include/hw/misc/sifive_test.h
@@ -20,19 +20,21 @@
#define HW_SIFIVE_TEST_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_SIFIVE_TEST "riscv.sifive.test"
-#define SIFIVE_TEST(obj) \
- OBJECT_CHECK(SiFiveTestState, (obj), TYPE_SIFIVE_TEST)
+typedef struct SiFiveTestState SiFiveTestState;
+DECLARE_INSTANCE_CHECKER(SiFiveTestState, SIFIVE_TEST,
+ TYPE_SIFIVE_TEST)
-typedef struct SiFiveTestState {
+struct SiFiveTestState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
MemoryRegion mmio;
-} SiFiveTestState;
+};
enum {
FINISHER_FAIL = 0x3333,
diff --git a/include/hw/riscv/sifive_u_otp.h b/include/hw/misc/sifive_u_otp.h
index 639297564a..170d2148f2 100644
--- a/include/hw/riscv/sifive_u_otp.h
+++ b/include/hw/misc/sifive_u_otp.h
@@ -19,6 +19,8 @@
#ifndef HW_SIFIVE_U_OTP_H
#define HW_SIFIVE_U_OTP_H
+#include "hw/sysbus.h"
+
#define SIFIVE_U_OTP_PA 0x00
#define SIFIVE_U_OTP_PAIO 0x04
#define SIFIVE_U_OTP_PAS 0x08
@@ -35,6 +37,8 @@
#define SIFIVE_U_OTP_PTRIM 0x34
#define SIFIVE_U_OTP_PWE 0x38
+#define SIFIVE_U_OTP_PWE_EN (1 << 0)
+
#define SIFIVE_U_OTP_PCE_EN (1 << 0)
#define SIFIVE_U_OTP_PDSTB_EN (1 << 0)
@@ -43,16 +47,18 @@
#define SIFIVE_U_OTP_PA_MASK 0xfff
#define SIFIVE_U_OTP_NUM_FUSES 0x1000
+#define SIFIVE_U_OTP_FUSE_WORD 4
#define SIFIVE_U_OTP_SERIAL_ADDR 0xfc
#define SIFIVE_U_OTP_REG_SIZE 0x1000
#define TYPE_SIFIVE_U_OTP "riscv.sifive.u.otp"
-#define SIFIVE_U_OTP(obj) \
- OBJECT_CHECK(SiFiveUOTPState, (obj), TYPE_SIFIVE_U_OTP)
+typedef struct SiFiveUOTPState SiFiveUOTPState;
+DECLARE_INSTANCE_CHECKER(SiFiveUOTPState, SIFIVE_U_OTP,
+ TYPE_SIFIVE_U_OTP)
-typedef struct SiFiveUOTPState {
+struct SiFiveUOTPState {
/*< private >*/
SysBusDevice parent_obj;
@@ -73,8 +79,10 @@ typedef struct SiFiveUOTPState {
uint32_t ptrim;
uint32_t pwe;
uint32_t fuse[SIFIVE_U_OTP_NUM_FUSES];
+ uint32_t fuse_wo[SIFIVE_U_OTP_NUM_FUSES];
/* config */
uint32_t serial;
-} SiFiveUOTPState;
+ BlockBackend *blk;
+};
#endif /* HW_SIFIVE_U_OTP_H */
diff --git a/include/hw/riscv/sifive_u_prci.h b/include/hw/misc/sifive_u_prci.h
index 0a531fdadc..4d2491ad46 100644
--- a/include/hw/riscv/sifive_u_prci.h
+++ b/include/hw/misc/sifive_u_prci.h
@@ -19,6 +19,8 @@
#ifndef HW_SIFIVE_U_PRCI_H
#define HW_SIFIVE_U_PRCI_H
+#include "hw/sysbus.h"
+
#define SIFIVE_U_PRCI_HFXOSCCFG 0x00
#define SIFIVE_U_PRCI_COREPLLCFG0 0x04
#define SIFIVE_U_PRCI_DDRPLLCFG0 0x0C
@@ -58,10 +60,11 @@
#define TYPE_SIFIVE_U_PRCI "riscv.sifive.u.prci"
-#define SIFIVE_U_PRCI(obj) \
- OBJECT_CHECK(SiFiveUPRCIState, (obj), TYPE_SIFIVE_U_PRCI)
+typedef struct SiFiveUPRCIState SiFiveUPRCIState;
+DECLARE_INSTANCE_CHECKER(SiFiveUPRCIState, SIFIVE_U_PRCI,
+ TYPE_SIFIVE_U_PRCI)
-typedef struct SiFiveUPRCIState {
+struct SiFiveUPRCIState {
/*< private >*/
SysBusDevice parent_obj;
@@ -76,7 +79,7 @@ typedef struct SiFiveUPRCIState {
uint32_t coreclksel;
uint32_t devicesreset;
uint32_t clkmuxstatus;
-} SiFiveUPRCIState;
+};
/*
* Clock indexes for use by Device Tree data and the PRCI driver.
diff --git a/include/hw/misc/stm32f2xx_syscfg.h b/include/hw/misc/stm32f2xx_syscfg.h
index 84e06fdecf..8595a3b31b 100644
--- a/include/hw/misc/stm32f2xx_syscfg.h
+++ b/include/hw/misc/stm32f2xx_syscfg.h
@@ -26,6 +26,7 @@
#define HW_STM32F2XX_SYSCFG_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define SYSCFG_MEMRMP 0x00
#define SYSCFG_PMC 0x04
@@ -36,10 +37,9 @@
#define SYSCFG_CMPCR 0x20
#define TYPE_STM32F2XX_SYSCFG "stm32f2xx-syscfg"
-#define STM32F2XX_SYSCFG(obj) \
- OBJECT_CHECK(STM32F2XXSyscfgState, (obj), TYPE_STM32F2XX_SYSCFG)
+OBJECT_DECLARE_SIMPLE_TYPE(STM32F2XXSyscfgState, STM32F2XX_SYSCFG)
-typedef struct {
+struct STM32F2XXSyscfgState {
/* <private> */
SysBusDevice parent_obj;
@@ -53,8 +53,6 @@ typedef struct {
uint32_t syscfg_exticr3;
uint32_t syscfg_exticr4;
uint32_t syscfg_cmpcr;
-
- qemu_irq irq;
-} STM32F2XXSyscfgState;
+};
#endif /* HW_STM32F2XX_SYSCFG_H */
diff --git a/include/hw/misc/stm32f4xx_exti.h b/include/hw/misc/stm32f4xx_exti.h
index 707036a41b..fc11c595fa 100644
--- a/include/hw/misc/stm32f4xx_exti.h
+++ b/include/hw/misc/stm32f4xx_exti.h
@@ -22,11 +22,11 @@
* THE SOFTWARE.
*/
-#ifndef HW_STM_EXTI_H
-#define HW_STM_EXTI_H
+#ifndef HW_STM32F4XX_EXTI_H
+#define HW_STM32F4XX_EXTI_H
#include "hw/sysbus.h"
-#include "hw/hw.h"
+#include "qom/object.h"
#define EXTI_IMR 0x00
#define EXTI_EMR 0x04
@@ -36,13 +36,12 @@
#define EXTI_PR 0x14
#define TYPE_STM32F4XX_EXTI "stm32f4xx-exti"
-#define STM32F4XX_EXTI(obj) \
- OBJECT_CHECK(STM32F4xxExtiState, (obj), TYPE_STM32F4XX_EXTI)
+OBJECT_DECLARE_SIMPLE_TYPE(STM32F4xxExtiState, STM32F4XX_EXTI)
#define NUM_GPIO_EVENT_IN_LINES 16
#define NUM_INTERRUPT_OUT_LINES 16
-typedef struct {
+struct STM32F4xxExtiState {
SysBusDevice parent_obj;
MemoryRegion mmio;
@@ -55,6 +54,6 @@ typedef struct {
uint32_t exti_pr;
qemu_irq irq[NUM_INTERRUPT_OUT_LINES];
-} STM32F4xxExtiState;
+};
#endif
diff --git a/include/hw/misc/stm32f4xx_syscfg.h b/include/hw/misc/stm32f4xx_syscfg.h
index c62c6629e5..9fce67f4b4 100644
--- a/include/hw/misc/stm32f4xx_syscfg.h
+++ b/include/hw/misc/stm32f4xx_syscfg.h
@@ -22,11 +22,11 @@
* THE SOFTWARE.
*/
-#ifndef HW_STM_SYSCFG_H
-#define HW_STM_SYSCFG_H
+#ifndef HW_STM32F4XX_SYSCFG_H
+#define HW_STM32F4XX_SYSCFG_H
#include "hw/sysbus.h"
-#include "hw/hw.h"
+#include "qom/object.h"
#define SYSCFG_MEMRMP 0x00
#define SYSCFG_PMC 0x04
@@ -37,12 +37,11 @@
#define SYSCFG_CMPCR 0x20
#define TYPE_STM32F4XX_SYSCFG "stm32f4xx-syscfg"
-#define STM32F4XX_SYSCFG(obj) \
- OBJECT_CHECK(STM32F4xxSyscfgState, (obj), TYPE_STM32F4XX_SYSCFG)
+OBJECT_DECLARE_SIMPLE_TYPE(STM32F4xxSyscfgState, STM32F4XX_SYSCFG)
#define SYSCFG_NUM_EXTICR 4
-typedef struct {
+struct STM32F4xxSyscfgState {
/* <private> */
SysBusDevice parent_obj;
@@ -56,6 +55,6 @@ typedef struct {
qemu_irq irq;
qemu_irq gpio_out[16];
-} STM32F4xxSyscfgState;
+};
#endif
diff --git a/include/hw/misc/stm32l4x5_exti.h b/include/hw/misc/stm32l4x5_exti.h
new file mode 100644
index 0000000000..be961d2f01
--- /dev/null
+++ b/include/hw/misc/stm32l4x5_exti.h
@@ -0,0 +1,51 @@
+/*
+ * STM32L4x5 EXTI (Extended interrupts and events controller)
+ *
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * This work is based on the stm32f4xx_exti by Alistair Francis.
+ * Original code is licensed under the MIT License:
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ */
+
+/*
+ * The reference used is the STMicroElectronics RM0351 Reference manual
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
+ */
+
+#ifndef HW_STM32L4X5_EXTI_H
+#define HW_STM32L4X5_EXTI_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_STM32L4X5_EXTI "stm32l4x5-exti"
+OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5ExtiState, STM32L4X5_EXTI)
+
+#define EXTI_NUM_INTERRUPT_OUT_LINES 40
+#define EXTI_NUM_REGISTER 2
+
+struct Stm32l4x5ExtiState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion mmio;
+
+ uint32_t imr[EXTI_NUM_REGISTER];
+ uint32_t emr[EXTI_NUM_REGISTER];
+ uint32_t rtsr[EXTI_NUM_REGISTER];
+ uint32_t ftsr[EXTI_NUM_REGISTER];
+ uint32_t swier[EXTI_NUM_REGISTER];
+ uint32_t pr[EXTI_NUM_REGISTER];
+
+ qemu_irq irq[EXTI_NUM_INTERRUPT_OUT_LINES];
+};
+
+#endif
diff --git a/include/hw/misc/stm32l4x5_rcc.h b/include/hw/misc/stm32l4x5_rcc.h
new file mode 100644
index 0000000000..0fbfba5c40
--- /dev/null
+++ b/include/hw/misc/stm32l4x5_rcc.h
@@ -0,0 +1,239 @@
+/*
+ * STM32L4X5 RCC (Reset and clock control)
+ *
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * The reference used is the STMicroElectronics RM0351 Reference manual
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
+ *
+ * Inspired by the BCM2835 CPRMAN clock manager by Luc Michel.
+ */
+
+#ifndef HW_STM32L4X5_RCC_H
+#define HW_STM32L4X5_RCC_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_STM32L4X5_RCC "stm32l4x5-rcc"
+OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5RccState, STM32L4X5_RCC)
+
+/* In the Stm32l4x5 clock tree, mux have at most 7 sources */
+#define RCC_NUM_CLOCK_MUX_SRC 7
+
+typedef enum PllCommonChannels {
+ RCC_PLL_COMMON_CHANNEL_P = 0,
+ RCC_PLL_COMMON_CHANNEL_Q = 1,
+ RCC_PLL_COMMON_CHANNEL_R = 2,
+
+ RCC_NUM_CHANNEL_PLL_OUT = 3
+} PllCommonChannels;
+
+/* NB: Prescaler are assimilated to mux with one source and one output */
+typedef enum RccClockMux {
+ /* Internal muxes that arent't exposed publicly to other peripherals */
+ RCC_CLOCK_MUX_SYSCLK,
+ RCC_CLOCK_MUX_PLL_INPUT,
+ RCC_CLOCK_MUX_HCLK,
+ RCC_CLOCK_MUX_PCLK1,
+ RCC_CLOCK_MUX_PCLK2,
+ RCC_CLOCK_MUX_HSE_OVER_32,
+ RCC_CLOCK_MUX_LCD_AND_RTC_COMMON,
+
+ /* Muxes with a publicly available output */
+ RCC_CLOCK_MUX_CORTEX_REFCLK,
+ RCC_CLOCK_MUX_USART1,
+ RCC_CLOCK_MUX_USART2,
+ RCC_CLOCK_MUX_USART3,
+ RCC_CLOCK_MUX_UART4,
+ RCC_CLOCK_MUX_UART5,
+ RCC_CLOCK_MUX_LPUART1,
+ RCC_CLOCK_MUX_I2C1,
+ RCC_CLOCK_MUX_I2C2,
+ RCC_CLOCK_MUX_I2C3,
+ RCC_CLOCK_MUX_LPTIM1,
+ RCC_CLOCK_MUX_LPTIM2,
+ RCC_CLOCK_MUX_SWPMI1,
+ RCC_CLOCK_MUX_MCO,
+ RCC_CLOCK_MUX_LSCO,
+ RCC_CLOCK_MUX_DFSDM1,
+ RCC_CLOCK_MUX_ADC,
+ RCC_CLOCK_MUX_CLK48,
+ RCC_CLOCK_MUX_SAI1,
+ RCC_CLOCK_MUX_SAI2,
+
+ /*
+ * Mux that have only one input and one output assigned to as peripheral.
+ * They could be direct lines but it is simpler
+ * to use the same logic for all outputs.
+ */
+ /* - AHB1 */
+ RCC_CLOCK_MUX_TSC,
+ RCC_CLOCK_MUX_CRC,
+ RCC_CLOCK_MUX_FLASH,
+ RCC_CLOCK_MUX_DMA2,
+ RCC_CLOCK_MUX_DMA1,
+
+ /* - AHB2 */
+ RCC_CLOCK_MUX_RNG,
+ RCC_CLOCK_MUX_AES,
+ RCC_CLOCK_MUX_OTGFS,
+ RCC_CLOCK_MUX_GPIOA,
+ RCC_CLOCK_MUX_GPIOB,
+ RCC_CLOCK_MUX_GPIOC,
+ RCC_CLOCK_MUX_GPIOD,
+ RCC_CLOCK_MUX_GPIOE,
+ RCC_CLOCK_MUX_GPIOF,
+ RCC_CLOCK_MUX_GPIOG,
+ RCC_CLOCK_MUX_GPIOH,
+
+ /* - AHB3 */
+ RCC_CLOCK_MUX_QSPI,
+ RCC_CLOCK_MUX_FMC,
+
+ /* - APB1 */
+ RCC_CLOCK_MUX_OPAMP,
+ RCC_CLOCK_MUX_DAC1,
+ RCC_CLOCK_MUX_PWR,
+ RCC_CLOCK_MUX_CAN1,
+ RCC_CLOCK_MUX_SPI3,
+ RCC_CLOCK_MUX_SPI2,
+ RCC_CLOCK_MUX_WWDG,
+ RCC_CLOCK_MUX_LCD,
+ RCC_CLOCK_MUX_TIM7,
+ RCC_CLOCK_MUX_TIM6,
+ RCC_CLOCK_MUX_TIM5,
+ RCC_CLOCK_MUX_TIM4,
+ RCC_CLOCK_MUX_TIM3,
+ RCC_CLOCK_MUX_TIM2,
+
+ /* - APB2 */
+ RCC_CLOCK_MUX_TIM17,
+ RCC_CLOCK_MUX_TIM16,
+ RCC_CLOCK_MUX_TIM15,
+ RCC_CLOCK_MUX_TIM8,
+ RCC_CLOCK_MUX_SPI1,
+ RCC_CLOCK_MUX_TIM1,
+ RCC_CLOCK_MUX_SDMMC1,
+ RCC_CLOCK_MUX_FW,
+ RCC_CLOCK_MUX_SYSCFG,
+
+ /* - BDCR */
+ RCC_CLOCK_MUX_RTC,
+
+ /* - OTHER */
+ RCC_CLOCK_MUX_CORTEX_FCLK,
+
+ RCC_NUM_CLOCK_MUX
+} RccClockMux;
+
+typedef enum RccPll {
+ RCC_PLL_PLL,
+ RCC_PLL_PLLSAI1,
+ RCC_PLL_PLLSAI2,
+
+ RCC_NUM_PLL
+} RccPll;
+
+typedef struct RccClockMuxState {
+ DeviceState parent_obj;
+
+ RccClockMux id;
+ Clock *srcs[RCC_NUM_CLOCK_MUX_SRC];
+ Clock *out;
+ bool enabled;
+ uint32_t src;
+ uint32_t multiplier;
+ uint32_t divider;
+
+ /*
+ * Used by clock srcs update callback to retrieve both the clock and the
+ * source number.
+ */
+ struct RccClockMuxState *backref[RCC_NUM_CLOCK_MUX_SRC];
+} RccClockMuxState;
+
+typedef struct RccPllState {
+ DeviceState parent_obj;
+
+ RccPll id;
+ Clock *in;
+ uint32_t vco_multiplier;
+ Clock *channels[RCC_NUM_CHANNEL_PLL_OUT];
+ /* Global pll enabled flag */
+ bool enabled;
+ /* 'enabled' refers to the runtime configuration */
+ bool channel_enabled[RCC_NUM_CHANNEL_PLL_OUT];
+ /*
+ * 'exists' refers to the physical configuration
+ * It should only be set at pll initialization.
+ * e.g. pllsai2 doesn't have a Q output.
+ */
+ bool channel_exists[RCC_NUM_CHANNEL_PLL_OUT];
+ uint32_t channel_divider[RCC_NUM_CHANNEL_PLL_OUT];
+} RccPllState;
+
+struct Stm32l4x5RccState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion mmio;
+
+ uint32_t cr;
+ uint32_t icscr;
+ uint32_t cfgr;
+ uint32_t pllcfgr;
+ uint32_t pllsai1cfgr;
+ uint32_t pllsai2cfgr;
+ uint32_t cier;
+ uint32_t cifr;
+ uint32_t ahb1rstr;
+ uint32_t ahb2rstr;
+ uint32_t ahb3rstr;
+ uint32_t apb1rstr1;
+ uint32_t apb1rstr2;
+ uint32_t apb2rstr;
+ uint32_t ahb1enr;
+ uint32_t ahb2enr;
+ uint32_t ahb3enr;
+ uint32_t apb1enr1;
+ uint32_t apb1enr2;
+ uint32_t apb2enr;
+ uint32_t ahb1smenr;
+ uint32_t ahb2smenr;
+ uint32_t ahb3smenr;
+ uint32_t apb1smenr1;
+ uint32_t apb1smenr2;
+ uint32_t apb2smenr;
+ uint32_t ccipr;
+ uint32_t bdcr;
+ uint32_t csr;
+
+ /* Clock sources */
+ Clock *gnd;
+ Clock *hsi16_rc;
+ Clock *msi_rc;
+ Clock *hse;
+ Clock *lsi_rc;
+ Clock *lse_crystal;
+ Clock *sai1_extclk;
+ Clock *sai2_extclk;
+
+ /* PLLs */
+ RccPllState plls[RCC_NUM_PLL];
+
+ /* Muxes ~= outputs */
+ RccClockMuxState clock_muxes[RCC_NUM_CLOCK_MUX];
+
+ qemu_irq irq;
+ uint64_t hse_frequency;
+ uint64_t sai1_extclk_frequency;
+ uint64_t sai2_extclk_frequency;
+};
+
+#endif /* HW_STM32L4X5_RCC_H */
diff --git a/include/hw/misc/stm32l4x5_rcc_internals.h b/include/hw/misc/stm32l4x5_rcc_internals.h
new file mode 100644
index 0000000000..ff1c834f69
--- /dev/null
+++ b/include/hw/misc/stm32l4x5_rcc_internals.h
@@ -0,0 +1,1042 @@
+/*
+ * STM32L4X5 RCC (Reset and clock control)
+ *
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * The reference used is the STMicroElectronics RM0351 Reference manual
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
+ *
+ * Inspired by the BCM2835 CPRMAN clock manager implementation by Luc Michel.
+ */
+
+#ifndef HW_STM32L4X5_RCC_INTERNALS_H
+#define HW_STM32L4X5_RCC_INTERNALS_H
+
+#include "hw/registerfields.h"
+#include "hw/misc/stm32l4x5_rcc.h"
+
+#define TYPE_RCC_CLOCK_MUX "stm32l4x5-rcc-clock-mux"
+#define TYPE_RCC_PLL "stm32l4x5-rcc-pll"
+
+OBJECT_DECLARE_SIMPLE_TYPE(RccClockMuxState, RCC_CLOCK_MUX)
+OBJECT_DECLARE_SIMPLE_TYPE(RccPllState, RCC_PLL)
+
+/* Register map */
+REG32(CR, 0x00)
+ FIELD(CR, PLLSAI2RDY, 29, 1)
+ FIELD(CR, PLLSAI2ON, 28, 1)
+ FIELD(CR, PLLSAI1RDY, 27, 1)
+ FIELD(CR, PLLSAI1ON, 26, 1)
+ FIELD(CR, PLLRDY, 25, 1)
+ FIELD(CR, PLLON, 24, 1)
+ FIELD(CR, CSSON, 19, 1)
+ FIELD(CR, HSEBYP, 18, 1)
+ FIELD(CR, HSERDY, 17, 1)
+ FIELD(CR, HSEON, 16, 1)
+ FIELD(CR, HSIASFS, 11, 1)
+ FIELD(CR, HSIRDY, 10, 1)
+ FIELD(CR, HSIKERON, 9, 1)
+ FIELD(CR, HSION, 8, 1)
+ FIELD(CR, MSIRANGE, 4, 4)
+ FIELD(CR, MSIRGSEL, 3, 1)
+ FIELD(CR, MSIPLLEN, 2, 1)
+ FIELD(CR, MSIRDY, 1, 1)
+ FIELD(CR, MSION, 0, 1)
+REG32(ICSCR, 0x04)
+ FIELD(ICSCR, HSITRIM, 24, 7)
+ FIELD(ICSCR, HSICAL, 16, 8)
+ FIELD(ICSCR, MSITRIM, 8, 8)
+ FIELD(ICSCR, MSICAL, 0, 8)
+REG32(CFGR, 0x08)
+ FIELD(CFGR, MCOPRE, 28, 3)
+ /* MCOSEL[2:0] only for STM32L475xx/476xx/486xx devices */
+ FIELD(CFGR, MCOSEL, 24, 3)
+ FIELD(CFGR, STOPWUCK, 15, 1)
+ FIELD(CFGR, PPRE2, 11, 3)
+ FIELD(CFGR, PPRE1, 8, 3)
+ FIELD(CFGR, HPRE, 4, 4)
+ FIELD(CFGR, SWS, 2, 2)
+ FIELD(CFGR, SW, 0, 2)
+REG32(PLLCFGR, 0x0C)
+ FIELD(PLLCFGR, PLLPDIV, 27, 5)
+ FIELD(PLLCFGR, PLLR, 25, 2)
+ FIELD(PLLCFGR, PLLREN, 24, 1)
+ FIELD(PLLCFGR, PLLQ, 21, 2)
+ FIELD(PLLCFGR, PLLQEN, 20, 1)
+ FIELD(PLLCFGR, PLLP, 17, 1)
+ FIELD(PLLCFGR, PLLPEN, 16, 1)
+ FIELD(PLLCFGR, PLLN, 8, 7)
+ FIELD(PLLCFGR, PLLM, 4, 3)
+ FIELD(PLLCFGR, PLLSRC, 0, 2)
+REG32(PLLSAI1CFGR, 0x10)
+ FIELD(PLLSAI1CFGR, PLLSAI1PDIV, 27, 5)
+ FIELD(PLLSAI1CFGR, PLLSAI1R, 25, 2)
+ FIELD(PLLSAI1CFGR, PLLSAI1REN, 24, 1)
+ FIELD(PLLSAI1CFGR, PLLSAI1Q, 21, 2)
+ FIELD(PLLSAI1CFGR, PLLSAI1QEN, 20, 1)
+ FIELD(PLLSAI1CFGR, PLLSAI1P, 17, 1)
+ FIELD(PLLSAI1CFGR, PLLSAI1PEN, 16, 1)
+ FIELD(PLLSAI1CFGR, PLLSAI1N, 8, 7)
+REG32(PLLSAI2CFGR, 0x14)
+ FIELD(PLLSAI2CFGR, PLLSAI2PDIV, 27, 5)
+ FIELD(PLLSAI2CFGR, PLLSAI2R, 25, 2)
+ FIELD(PLLSAI2CFGR, PLLSAI2REN, 24, 1)
+ FIELD(PLLSAI2CFGR, PLLSAI2Q, 21, 2)
+ FIELD(PLLSAI2CFGR, PLLSAI2QEN, 20, 1)
+ FIELD(PLLSAI2CFGR, PLLSAI2P, 17, 1)
+ FIELD(PLLSAI2CFGR, PLLSAI2PEN, 16, 1)
+ FIELD(PLLSAI2CFGR, PLLSAI2N, 8, 7)
+REG32(CIER, 0x18)
+ /* HSI48RDYIE: only on STM32L496xx/4A6xx devices */
+ FIELD(CIER, LSECSSIE, 9, 1)
+ FIELD(CIER, PLLSAI2RDYIE, 7, 1)
+ FIELD(CIER, PLLSAI1RDYIE, 6, 1)
+ FIELD(CIER, PLLRDYIE, 5, 1)
+ FIELD(CIER, HSERDYIE, 4, 1)
+ FIELD(CIER, HSIRDYIE, 3, 1)
+ FIELD(CIER, MSIRDYIE, 2, 1)
+ FIELD(CIER, LSERDYIE, 1, 1)
+ FIELD(CIER, LSIRDYIE, 0, 1)
+REG32(CIFR, 0x1C)
+ /* HSI48RDYF: only on STM32L496xx/4A6xx devices */
+ FIELD(CIFR, LSECSSF, 9, 1)
+ FIELD(CIFR, CSSF, 8, 1)
+ FIELD(CIFR, PLLSAI2RDYF, 7, 1)
+ FIELD(CIFR, PLLSAI1RDYF, 6, 1)
+ FIELD(CIFR, PLLRDYF, 5, 1)
+ FIELD(CIFR, HSERDYF, 4, 1)
+ FIELD(CIFR, HSIRDYF, 3, 1)
+ FIELD(CIFR, MSIRDYF, 2, 1)
+ FIELD(CIFR, LSERDYF, 1, 1)
+ FIELD(CIFR, LSIRDYF, 0, 1)
+REG32(CICR, 0x20)
+ /* HSI48RDYC: only on STM32L496xx/4A6xx devices */
+ FIELD(CICR, LSECSSC, 9, 1)
+ FIELD(CICR, CSSC, 8, 1)
+ FIELD(CICR, PLLSAI2RDYC, 7, 1)
+ FIELD(CICR, PLLSAI1RDYC, 6, 1)
+ FIELD(CICR, PLLRDYC, 5, 1)
+ FIELD(CICR, HSERDYC, 4, 1)
+ FIELD(CICR, HSIRDYC, 3, 1)
+ FIELD(CICR, MSIRDYC, 2, 1)
+ FIELD(CICR, LSERDYC, 1, 1)
+ FIELD(CICR, LSIRDYC, 0, 1)
+REG32(AHB1RSTR, 0x28)
+REG32(AHB2RSTR, 0x2C)
+REG32(AHB3RSTR, 0x30)
+REG32(APB1RSTR1, 0x38)
+REG32(APB1RSTR2, 0x3C)
+REG32(APB2RSTR, 0x40)
+REG32(AHB1ENR, 0x48)
+ /* DMA2DEN: reserved for STM32L475xx */
+ FIELD(AHB1ENR, TSCEN, 16, 1)
+ FIELD(AHB1ENR, CRCEN, 12, 1)
+ FIELD(AHB1ENR, FLASHEN, 8, 1)
+ FIELD(AHB1ENR, DMA2EN, 1, 1)
+ FIELD(AHB1ENR, DMA1EN, 0, 1)
+REG32(AHB2ENR, 0x4C)
+ FIELD(AHB2ENR, RNGEN, 18, 1)
+ /* HASHEN: reserved for STM32L475xx */
+ FIELD(AHB2ENR, AESEN, 16, 1)
+ /* DCMIEN: reserved for STM32L475xx */
+ FIELD(AHB2ENR, ADCEN, 13, 1)
+ FIELD(AHB2ENR, OTGFSEN, 12, 1)
+ /* GPIOIEN: reserved for STM32L475xx */
+ FIELD(AHB2ENR, GPIOHEN, 7, 1)
+ FIELD(AHB2ENR, GPIOGEN, 6, 1)
+ FIELD(AHB2ENR, GPIOFEN, 5, 1)
+ FIELD(AHB2ENR, GPIOEEN, 4, 1)
+ FIELD(AHB2ENR, GPIODEN, 3, 1)
+ FIELD(AHB2ENR, GPIOCEN, 2, 1)
+ FIELD(AHB2ENR, GPIOBEN, 1, 1)
+ FIELD(AHB2ENR, GPIOAEN, 0, 1)
+REG32(AHB3ENR, 0x50)
+ FIELD(AHB3ENR, QSPIEN, 8, 1)
+ FIELD(AHB3ENR, FMCEN, 0, 1)
+REG32(APB1ENR1, 0x58)
+ FIELD(APB1ENR1, LPTIM1EN, 31, 1)
+ FIELD(APB1ENR1, OPAMPEN, 30, 1)
+ FIELD(APB1ENR1, DAC1EN, 29, 1)
+ FIELD(APB1ENR1, PWREN, 28, 1)
+ FIELD(APB1ENR1, CAN2EN, 26, 1)
+ FIELD(APB1ENR1, CAN1EN, 25, 1)
+ /* CRSEN: reserved for STM32L475xx */
+ FIELD(APB1ENR1, I2C3EN, 23, 1)
+ FIELD(APB1ENR1, I2C2EN, 22, 1)
+ FIELD(APB1ENR1, I2C1EN, 21, 1)
+ FIELD(APB1ENR1, UART5EN, 20, 1)
+ FIELD(APB1ENR1, UART4EN, 19, 1)
+ FIELD(APB1ENR1, USART3EN, 18, 1)
+ FIELD(APB1ENR1, USART2EN, 17, 1)
+ FIELD(APB1ENR1, SPI3EN, 15, 1)
+ FIELD(APB1ENR1, SPI2EN, 14, 1)
+ FIELD(APB1ENR1, WWDGEN, 11, 1)
+ /* RTCAPBEN: reserved for STM32L475xx */
+ FIELD(APB1ENR1, LCDEN, 9, 1)
+ FIELD(APB1ENR1, TIM7EN, 5, 1)
+ FIELD(APB1ENR1, TIM6EN, 4, 1)
+ FIELD(APB1ENR1, TIM5EN, 3, 1)
+ FIELD(APB1ENR1, TIM4EN, 2, 1)
+ FIELD(APB1ENR1, TIM3EN, 1, 1)
+ FIELD(APB1ENR1, TIM2EN, 0, 1)
+REG32(APB1ENR2, 0x5C)
+ FIELD(APB1ENR2, LPTIM2EN, 5, 1)
+ FIELD(APB1ENR2, SWPMI1EN, 2, 1)
+ /* I2C4EN: reserved for STM32L475xx */
+ FIELD(APB1ENR2, LPUART1EN, 0, 1)
+REG32(APB2ENR, 0x60)
+ FIELD(APB2ENR, DFSDM1EN, 24, 1)
+ FIELD(APB2ENR, SAI2EN, 22, 1)
+ FIELD(APB2ENR, SAI1EN, 21, 1)
+ FIELD(APB2ENR, TIM17EN, 18, 1)
+ FIELD(APB2ENR, TIM16EN, 17, 1)
+ FIELD(APB2ENR, TIM15EN, 16, 1)
+ FIELD(APB2ENR, USART1EN, 14, 1)
+ FIELD(APB2ENR, TIM8EN, 13, 1)
+ FIELD(APB2ENR, SPI1EN, 12, 1)
+ FIELD(APB2ENR, TIM1EN, 11, 1)
+ FIELD(APB2ENR, SDMMC1EN, 10, 1)
+ FIELD(APB2ENR, FWEN, 7, 1)
+ FIELD(APB2ENR, SYSCFGEN, 0, 1)
+REG32(AHB1SMENR, 0x68)
+REG32(AHB2SMENR, 0x6C)
+REG32(AHB3SMENR, 0x70)
+REG32(APB1SMENR1, 0x78)
+REG32(APB1SMENR2, 0x7C)
+REG32(APB2SMENR, 0x80)
+REG32(CCIPR, 0x88)
+ FIELD(CCIPR, DFSDM1SEL, 31, 1)
+ FIELD(CCIPR, SWPMI1SEL, 30, 1)
+ FIELD(CCIPR, ADCSEL, 28, 2)
+ FIELD(CCIPR, CLK48SEL, 26, 2)
+ FIELD(CCIPR, SAI2SEL, 24, 2)
+ FIELD(CCIPR, SAI1SEL, 22, 2)
+ FIELD(CCIPR, LPTIM2SEL, 20, 2)
+ FIELD(CCIPR, LPTIM1SEL, 18, 2)
+ FIELD(CCIPR, I2C3SEL, 16, 2)
+ FIELD(CCIPR, I2C2SEL, 14, 2)
+ FIELD(CCIPR, I2C1SEL, 12, 2)
+ FIELD(CCIPR, LPUART1SEL, 10, 2)
+ FIELD(CCIPR, UART5SEL, 8, 2)
+ FIELD(CCIPR, UART4SEL, 6, 2)
+ FIELD(CCIPR, USART3SEL, 4, 2)
+ FIELD(CCIPR, USART2SEL, 2, 2)
+ FIELD(CCIPR, USART1SEL, 0, 2)
+REG32(BDCR, 0x90)
+ FIELD(BDCR, LSCOSEL, 25, 1)
+ FIELD(BDCR, LSCOEN, 24, 1)
+ FIELD(BDCR, BDRST, 16, 1)
+ FIELD(BDCR, RTCEN, 15, 1)
+ FIELD(BDCR, RTCSEL, 8, 2)
+ FIELD(BDCR, LSECSSD, 6, 1)
+ FIELD(BDCR, LSECSSON, 5, 1)
+ FIELD(BDCR, LSEDRV, 3, 2)
+ FIELD(BDCR, LSEBYP, 2, 1)
+ FIELD(BDCR, LSERDY, 1, 1)
+ FIELD(BDCR, LSEON, 0, 1)
+REG32(CSR, 0x94)
+ FIELD(CSR, LPWRRSTF, 31, 1)
+ FIELD(CSR, WWDGRSTF, 30, 1)
+ FIELD(CSR, IWWGRSTF, 29, 1)
+ FIELD(CSR, SFTRSTF, 28, 1)
+ FIELD(CSR, BORRSTF, 27, 1)
+ FIELD(CSR, PINRSTF, 26, 1)
+ FIELD(CSR, OBLRSTF, 25, 1)
+ FIELD(CSR, FWRSTF, 24, 1)
+ FIELD(CSR, RMVF, 23, 1)
+ FIELD(CSR, MSISRANGE, 8, 4)
+ FIELD(CSR, LSIRDY, 1, 1)
+ FIELD(CSR, LSION, 0, 1)
+/* CRRCR and CCIPR2 registers are present on L496/L4A6 devices only. */
+
+/* Read Only masks to prevent writes in unauthorized bits */
+#define CR_READ_ONLY_MASK (R_CR_PLLSAI2RDY_MASK | \
+ R_CR_PLLSAI1RDY_MASK | \
+ R_CR_PLLRDY_MASK | \
+ R_CR_HSERDY_MASK | \
+ R_CR_HSIRDY_MASK | \
+ R_CR_MSIRDY_MASK)
+#define CR_READ_SET_MASK (R_CR_CSSON_MASK | R_CR_MSIRGSEL_MASK)
+#define ICSCR_READ_ONLY_MASK (R_ICSCR_HSICAL_MASK | R_ICSCR_MSICAL_MASK)
+#define CFGR_READ_ONLY_MASK (R_CFGR_SWS_MASK)
+#define CIFR_READ_ONLY_MASK (R_CIFR_LSECSSF_MASK | \
+ R_CIFR_CSSF_MASK | \
+ R_CIFR_PLLSAI2RDYF_MASK | \
+ R_CIFR_PLLSAI1RDYF_MASK | \
+ R_CIFR_PLLRDYF_MASK | \
+ R_CIFR_HSERDYF_MASK | \
+ R_CIFR_HSIRDYF_MASK | \
+ R_CIFR_MSIRDYF_MASK | \
+ R_CIFR_LSERDYF_MASK | \
+ R_CIFR_LSIRDYF_MASK)
+#define CIFR_IRQ_MASK CIFR_READ_ONLY_MASK
+#define APB2ENR_READ_SET_MASK (R_APB2ENR_FWEN_MASK)
+#define BDCR_READ_ONLY_MASK (R_BDCR_LSECSSD_MASK | R_BDCR_LSERDY_MASK)
+#define CSR_READ_ONLY_MASK (R_CSR_LPWRRSTF_MASK | \
+ R_CSR_WWDGRSTF_MASK | \
+ R_CSR_IWWGRSTF_MASK | \
+ R_CSR_SFTRSTF_MASK | \
+ R_CSR_BORRSTF_MASK | \
+ R_CSR_PINRSTF_MASK | \
+ R_CSR_OBLRSTF_MASK | \
+ R_CSR_FWRSTF_MASK | \
+ R_CSR_LSIRDY_MASK)
+
+/* Pll Channels */
+enum PllChannels {
+ RCC_PLL_CHANNEL_PLLSAI3CLK = 0,
+ RCC_PLL_CHANNEL_PLL48M1CLK = 1,
+ RCC_PLL_CHANNEL_PLLCLK = 2,
+};
+
+enum PllSai1Channels {
+ RCC_PLLSAI1_CHANNEL_PLLSAI1CLK = 0,
+ RCC_PLLSAI1_CHANNEL_PLL48M2CLK = 1,
+ RCC_PLLSAI1_CHANNEL_PLLADC1CLK = 2,
+};
+
+enum PllSai2Channels {
+ RCC_PLLSAI2_CHANNEL_PLLSAI2CLK = 0,
+ /* No Q channel */
+ RCC_PLLSAI2_CHANNEL_PLLADC2CLK = 2,
+};
+
+typedef enum RccClockMuxSource {
+ RCC_CLOCK_MUX_SRC_GND = 0,
+ RCC_CLOCK_MUX_SRC_HSI,
+ RCC_CLOCK_MUX_SRC_HSE,
+ RCC_CLOCK_MUX_SRC_MSI,
+ RCC_CLOCK_MUX_SRC_LSI,
+ RCC_CLOCK_MUX_SRC_LSE,
+ RCC_CLOCK_MUX_SRC_SAI1_EXTCLK,
+ RCC_CLOCK_MUX_SRC_SAI2_EXTCLK,
+ RCC_CLOCK_MUX_SRC_PLL,
+ RCC_CLOCK_MUX_SRC_PLLSAI1,
+ RCC_CLOCK_MUX_SRC_PLLSAI2,
+ RCC_CLOCK_MUX_SRC_PLLSAI3,
+ RCC_CLOCK_MUX_SRC_PLL48M1,
+ RCC_CLOCK_MUX_SRC_PLL48M2,
+ RCC_CLOCK_MUX_SRC_PLLADC1,
+ RCC_CLOCK_MUX_SRC_PLLADC2,
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ RCC_CLOCK_MUX_SRC_HCLK,
+ RCC_CLOCK_MUX_SRC_PCLK1,
+ RCC_CLOCK_MUX_SRC_PCLK2,
+ RCC_CLOCK_MUX_SRC_HSE_OVER_32,
+ RCC_CLOCK_MUX_SRC_LCD_AND_RTC_COMMON,
+
+ RCC_CLOCK_MUX_SRC_NUMBER,
+} RccClockMuxSource;
+
+/* PLL init info */
+typedef struct PllInitInfo {
+ const char *name;
+
+ const char *channel_name[RCC_NUM_CHANNEL_PLL_OUT];
+ bool channel_exists[RCC_NUM_CHANNEL_PLL_OUT];
+ uint32_t default_channel_divider[RCC_NUM_CHANNEL_PLL_OUT];
+
+ RccClockMuxSource src_mapping[RCC_NUM_CLOCK_MUX_SRC];
+} PllInitInfo;
+
+static const PllInitInfo PLL_INIT_INFO[] = {
+ [RCC_PLL_PLL] = {
+ .name = "pll",
+ .channel_name = {
+ "pllsai3clk",
+ "pll48m1clk",
+ "pllclk"
+ },
+ .channel_exists = {
+ true, true, true
+ },
+ /* From PLLCFGR register documentation */
+ .default_channel_divider = {
+ 7, 2, 2
+ }
+ },
+ [RCC_PLL_PLLSAI1] = {
+ .name = "pllsai1",
+ .channel_name = {
+ "pllsai1clk",
+ "pll48m2clk",
+ "plladc1clk"
+ },
+ .channel_exists = {
+ true, true, true
+ },
+ /* From PLLSAI1CFGR register documentation */
+ .default_channel_divider = {
+ 7, 2, 2
+ }
+ },
+ [RCC_PLL_PLLSAI2] = {
+ .name = "pllsai2",
+ .channel_name = {
+ "pllsai2clk",
+ NULL,
+ "plladc2clk"
+ },
+ .channel_exists = {
+ true, false, true
+ },
+ /* From PLLSAI2CFGR register documentation */
+ .default_channel_divider = {
+ 7, 0, 2
+ }
+ }
+};
+
+static inline void set_pll_init_info(RccPllState *pll,
+ RccPll id)
+{
+ int i;
+
+ pll->id = id;
+ pll->vco_multiplier = 1;
+ for (i = 0; i < RCC_NUM_CHANNEL_PLL_OUT; i++) {
+ pll->channel_enabled[i] = false;
+ pll->channel_exists[i] = PLL_INIT_INFO[id].channel_exists[i];
+ pll->channel_divider[i] = PLL_INIT_INFO[id].default_channel_divider[i];
+ }
+}
+
+/* Clock mux init info */
+typedef struct ClockMuxInitInfo {
+ const char *name;
+
+ uint32_t multiplier;
+ uint32_t divider;
+ bool enabled;
+ /* If this is true, the clock will not be exposed outside of the device */
+ bool hidden;
+
+ RccClockMuxSource src_mapping[RCC_NUM_CLOCK_MUX_SRC];
+} ClockMuxInitInfo;
+
+#define FILL_DEFAULT_FACTOR \
+ .multiplier = 1, \
+ .divider = 1
+
+#define FILL_DEFAULT_INIT_ENABLED \
+ FILL_DEFAULT_FACTOR, \
+ .enabled = true
+
+#define FILL_DEFAULT_INIT_DISABLED \
+ FILL_DEFAULT_FACTOR, \
+ .enabled = false
+
+
+static const ClockMuxInitInfo CLOCK_MUX_INIT_INFO[] = {
+ [RCC_CLOCK_MUX_SYSCLK] = {
+ .name = "sysclk",
+ /* Same mapping as: CFGR_SW */
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_MSI,
+ RCC_CLOCK_MUX_SRC_HSI,
+ RCC_CLOCK_MUX_SRC_HSE,
+ RCC_CLOCK_MUX_SRC_PLL,
+ },
+ .hidden = true,
+ FILL_DEFAULT_INIT_ENABLED,
+ },
+ [RCC_CLOCK_MUX_PLL_INPUT] = {
+ .name = "pll-input",
+ /* Same mapping as: PLLCFGR_PLLSRC */
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_MSI,
+ RCC_CLOCK_MUX_SRC_HSI,
+ RCC_CLOCK_MUX_SRC_HSE,
+ },
+ .hidden = true,
+ FILL_DEFAULT_INIT_ENABLED,
+ },
+ [RCC_CLOCK_MUX_HCLK] = {
+ .name = "hclk",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ },
+ .hidden = true,
+ FILL_DEFAULT_INIT_ENABLED,
+ },
+ [RCC_CLOCK_MUX_PCLK1] = {
+ .name = "pclk1",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_HCLK,
+ },
+ .hidden = true,
+ FILL_DEFAULT_INIT_ENABLED,
+ },
+ [RCC_CLOCK_MUX_PCLK2] = {
+ .name = "pclk2",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_HCLK,
+ },
+ .hidden = true,
+ FILL_DEFAULT_INIT_ENABLED,
+ },
+ [RCC_CLOCK_MUX_HSE_OVER_32] = {
+ .name = "hse-divided-by-32",
+ .multiplier = 1,
+ .divider = 32,
+ .enabled = true,
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_HSE,
+ },
+ .hidden = true,
+ },
+ [RCC_CLOCK_MUX_LCD_AND_RTC_COMMON] = {
+ .name = "lcd-and-rtc-common-mux",
+ /* Same mapping as: BDCR_RTCSEL */
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_GND,
+ RCC_CLOCK_MUX_SRC_LSE,
+ RCC_CLOCK_MUX_SRC_LSI,
+ RCC_CLOCK_MUX_SRC_HSE_OVER_32,
+ },
+ .hidden = true,
+ FILL_DEFAULT_INIT_ENABLED,
+ },
+ /* From now on, muxes with a publicly available output */
+ [RCC_CLOCK_MUX_CORTEX_REFCLK] = {
+ .name = "cortex-refclk",
+ .multiplier = 1,
+ /* REFCLK is always HCLK/8 */
+ .divider = 8,
+ .enabled = true,
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_HCLK,
+ }
+ },
+ [RCC_CLOCK_MUX_USART1] = {
+ .name = "usart1",
+ /* Same mapping as: CCIPR_USART1SEL */
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK2,
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ RCC_CLOCK_MUX_SRC_HSI,
+ RCC_CLOCK_MUX_SRC_LSE,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_USART2] = {
+ .name = "usart2",
+ /* Same mapping as: CCIPR_USART2SEL */
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK1,
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ RCC_CLOCK_MUX_SRC_HSI,
+ RCC_CLOCK_MUX_SRC_LSE,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_USART3] = {
+ .name = "usart3",
+ /* Same mapping as: CCIPR_USART3SEL */
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK1,
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ RCC_CLOCK_MUX_SRC_HSI,
+ RCC_CLOCK_MUX_SRC_LSE,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_UART4] = {
+ .name = "uart4",
+ /* Same mapping as: CCIPR_UART4SEL */
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK1,
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ RCC_CLOCK_MUX_SRC_HSI,
+ RCC_CLOCK_MUX_SRC_LSE,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_UART5] = {
+ .name = "uart5",
+ /* Same mapping as: CCIPR_UART5SEL */
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK1,
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ RCC_CLOCK_MUX_SRC_HSI,
+ RCC_CLOCK_MUX_SRC_LSE,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_LPUART1] = {
+ .name = "lpuart1",
+ /* Same mapping as: CCIPR_LPUART1SEL */
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK1,
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ RCC_CLOCK_MUX_SRC_HSI,
+ RCC_CLOCK_MUX_SRC_LSE,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_I2C1] = {
+ .name = "i2c1",
+ /* Same mapping as: CCIPR_I2C1SEL */
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK1,
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ RCC_CLOCK_MUX_SRC_HSI,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_I2C2] = {
+ .name = "i2c2",
+ /* Same mapping as: CCIPR_I2C2SEL */
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK1,
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ RCC_CLOCK_MUX_SRC_HSI,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_I2C3] = {
+ .name = "i2c3",
+ /* Same mapping as: CCIPR_I2C3SEL */
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK1,
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ RCC_CLOCK_MUX_SRC_HSI,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_LPTIM1] = {
+ .name = "lptim1",
+ /* Same mapping as: CCIPR_LPTIM1SEL */
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK1,
+ RCC_CLOCK_MUX_SRC_LSI,
+ RCC_CLOCK_MUX_SRC_HSI,
+ RCC_CLOCK_MUX_SRC_LSE,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_LPTIM2] = {
+ .name = "lptim2",
+ /* Same mapping as: CCIPR_LPTIM2SEL */
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK1,
+ RCC_CLOCK_MUX_SRC_LSI,
+ RCC_CLOCK_MUX_SRC_HSI,
+ RCC_CLOCK_MUX_SRC_LSE,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_SWPMI1] = {
+ .name = "swpmi1",
+ /* Same mapping as: CCIPR_SWPMI1SEL */
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK1,
+ RCC_CLOCK_MUX_SRC_HSI,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_MCO] = {
+ .name = "mco",
+ /* Same mapping as: CFGR_MCOSEL */
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ RCC_CLOCK_MUX_SRC_MSI,
+ RCC_CLOCK_MUX_SRC_HSI,
+ RCC_CLOCK_MUX_SRC_HSE,
+ RCC_CLOCK_MUX_SRC_PLL,
+ RCC_CLOCK_MUX_SRC_LSI,
+ RCC_CLOCK_MUX_SRC_LSE,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_LSCO] = {
+ .name = "lsco",
+ /* Same mapping as: BDCR_LSCOSEL */
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_LSI,
+ RCC_CLOCK_MUX_SRC_LSE,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_DFSDM1] = {
+ .name = "dfsdm1",
+ /* Same mapping as: CCIPR_DFSDM1SEL */
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK2,
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_ADC] = {
+ .name = "adc",
+ /* Same mapping as: CCIPR_ADCSEL */
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_GND,
+ RCC_CLOCK_MUX_SRC_PLLADC1,
+ RCC_CLOCK_MUX_SRC_PLLADC2,
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_CLK48] = {
+ .name = "clk48",
+ /* Same mapping as: CCIPR_CLK48SEL */
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_GND,
+ RCC_CLOCK_MUX_SRC_PLL48M2,
+ RCC_CLOCK_MUX_SRC_PLL48M1,
+ RCC_CLOCK_MUX_SRC_MSI,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_SAI2] = {
+ .name = "sai2",
+ /* Same mapping as: CCIPR_SAI2SEL */
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PLLSAI1,
+ RCC_CLOCK_MUX_SRC_PLLSAI2,
+ RCC_CLOCK_MUX_SRC_PLLSAI3,
+ RCC_CLOCK_MUX_SRC_SAI2_EXTCLK,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_SAI1] = {
+ .name = "sai1",
+ /* Same mapping as: CCIPR_SAI1SEL */
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PLLSAI1,
+ RCC_CLOCK_MUX_SRC_PLLSAI2,
+ RCC_CLOCK_MUX_SRC_PLLSAI3,
+ RCC_CLOCK_MUX_SRC_SAI1_EXTCLK,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ /* From now on, these muxes only have one valid source */
+ [RCC_CLOCK_MUX_TSC] = {
+ .name = "tsc",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_CRC] = {
+ .name = "crc",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_FLASH] = {
+ .name = "flash",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_DMA2] = {
+ .name = "dma2",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_DMA1] = {
+ .name = "dma1",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_RNG] = {
+ .name = "rng",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_AES] = {
+ .name = "aes",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_OTGFS] = {
+ .name = "otgfs",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_GPIOA] = {
+ .name = "gpioa",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_GPIOB] = {
+ .name = "gpiob",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_GPIOC] = {
+ .name = "gpioc",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_GPIOD] = {
+ .name = "gpiod",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_GPIOE] = {
+ .name = "gpioe",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_GPIOF] = {
+ .name = "gpiof",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_GPIOG] = {
+ .name = "gpiog",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_GPIOH] = {
+ .name = "gpioh",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_QSPI] = {
+ .name = "qspi",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_FMC] = {
+ .name = "fmc",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_OPAMP] = {
+ .name = "opamp",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK1,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_DAC1] = {
+ .name = "dac1",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK1,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_PWR] = {
+ .name = "pwr",
+ /*
+ * PWREN is in the APB1ENR1 register,
+ * but PWR uses SYSCLK according to the clock tree.
+ */
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_SYSCLK,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_CAN1] = {
+ .name = "can1",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK1,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_SPI3] = {
+ .name = "spi3",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK1,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_SPI2] = {
+ .name = "spi2",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK1,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_WWDG] = {
+ .name = "wwdg",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK1,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_LCD] = {
+ .name = "lcd",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_LCD_AND_RTC_COMMON,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_TIM7] = {
+ .name = "tim7",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK1,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_TIM6] = {
+ .name = "tim6",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK1,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_TIM5] = {
+ .name = "tim5",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK1,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_TIM4] = {
+ .name = "tim4",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK1,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_TIM3] = {
+ .name = "tim3",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK1,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_TIM2] = {
+ .name = "tim2",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK1,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_TIM17] = {
+ .name = "tim17",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK2,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_TIM16] = {
+ .name = "tim16",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK2,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_TIM15] = {
+ .name = "tim15",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK2,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_TIM8] = {
+ .name = "tim8",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK2,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_SPI1] = {
+ .name = "spi1",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK2,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_TIM1] = {
+ .name = "tim1",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK2,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_SDMMC1] = {
+ .name = "sdmmc1",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK2,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_FW] = {
+ .name = "fw",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK2,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_SYSCFG] = {
+ .name = "syscfg",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_PCLK2,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_RTC] = {
+ .name = "rtc",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_LCD_AND_RTC_COMMON,
+ },
+ FILL_DEFAULT_INIT_DISABLED,
+ },
+ [RCC_CLOCK_MUX_CORTEX_FCLK] = {
+ .name = "cortex-fclk",
+ .src_mapping = {
+ RCC_CLOCK_MUX_SRC_HCLK,
+ },
+ FILL_DEFAULT_INIT_ENABLED,
+ },
+};
+
+static inline void set_clock_mux_init_info(RccClockMuxState *mux,
+ RccClockMux id)
+{
+ mux->id = id;
+ mux->multiplier = CLOCK_MUX_INIT_INFO[id].multiplier;
+ mux->divider = CLOCK_MUX_INIT_INFO[id].divider;
+ mux->enabled = CLOCK_MUX_INIT_INFO[id].enabled;
+ /*
+ * Every peripheral has the first source of their source list as
+ * as their default source.
+ */
+ mux->src = 0;
+}
+
+#endif /* HW_STM32L4X5_RCC_INTERNALS_H */
diff --git a/include/hw/misc/stm32l4x5_syscfg.h b/include/hw/misc/stm32l4x5_syscfg.h
new file mode 100644
index 0000000000..23bb564150
--- /dev/null
+++ b/include/hw/misc/stm32l4x5_syscfg.h
@@ -0,0 +1,53 @@
+/*
+ * STM32L4x5 SYSCFG (System Configuration Controller)
+ *
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * This work is based on the stm32f4xx_syscfg by Alistair Francis.
+ * Original code is licensed under the MIT License:
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ */
+
+/*
+ * The reference used is the STMicroElectronics RM0351 Reference manual
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
+ */
+
+#ifndef HW_STM32L4X5_SYSCFG_H
+#define HW_STM32L4X5_SYSCFG_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+#include "hw/gpio/stm32l4x5_gpio.h"
+
+#define TYPE_STM32L4X5_SYSCFG "stm32l4x5-syscfg"
+OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5SyscfgState, STM32L4X5_SYSCFG)
+
+#define SYSCFG_NUM_EXTICR 4
+
+struct Stm32l4x5SyscfgState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion mmio;
+
+ uint32_t memrmp;
+ uint32_t cfgr1;
+ uint32_t exticr[SYSCFG_NUM_EXTICR];
+ uint32_t scsr;
+ uint32_t cfgr2;
+ uint32_t swpr;
+ uint32_t skr;
+ uint32_t swpr2;
+
+ qemu_irq gpio_out[GPIO_NUM_PINS];
+};
+
+#endif
diff --git a/include/hw/misc/tz-mpc.h b/include/hw/misc/tz-mpc.h
index 6f15945410..74d5d822cf 100644
--- a/include/hw/misc/tz-mpc.h
+++ b/include/hw/misc/tz-mpc.h
@@ -32,15 +32,15 @@
#define TZ_MPC_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_TZ_MPC "tz-mpc"
-#define TZ_MPC(obj) OBJECT_CHECK(TZMPC, (obj), TYPE_TZ_MPC)
+OBJECT_DECLARE_SIMPLE_TYPE(TZMPC, TZ_MPC)
#define TZ_NUM_PORTS 16
#define TYPE_TZ_MPC_IOMMU_MEMORY_REGION "tz-mpc-iommu-memory-region"
-typedef struct TZMPC TZMPC;
struct TZMPC {
/*< private >*/
diff --git a/include/hw/misc/tz-msc.h b/include/hw/misc/tz-msc.h
index 116b96ae9b..77cc7f2404 100644
--- a/include/hw/misc/tz-msc.h
+++ b/include/hw/misc/tz-msc.h
@@ -52,11 +52,12 @@
#include "hw/sysbus.h"
#include "target/arm/idau.h"
+#include "qom/object.h"
#define TYPE_TZ_MSC "tz-msc"
-#define TZ_MSC(obj) OBJECT_CHECK(TZMSC, (obj), TYPE_TZ_MSC)
+OBJECT_DECLARE_SIMPLE_TYPE(TZMSC, TZ_MSC)
-typedef struct TZMSC {
+struct TZMSC {
/*< private >*/
SysBusDevice parent_obj;
@@ -74,6 +75,6 @@ typedef struct TZMSC {
AddressSpace downstream_as;
MemoryRegion upstream;
IDAUInterface *idau;
-} TZMSC;
+};
#endif
diff --git a/include/hw/misc/tz-ppc.h b/include/hw/misc/tz-ppc.h
index 080d6e2ec1..021d671b29 100644
--- a/include/hw/misc/tz-ppc.h
+++ b/include/hw/misc/tz-ppc.h
@@ -66,13 +66,13 @@
#define TZ_PPC_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_TZ_PPC "tz-ppc"
-#define TZ_PPC(obj) OBJECT_CHECK(TZPPC, (obj), TYPE_TZ_PPC)
+OBJECT_DECLARE_SIMPLE_TYPE(TZPPC, TZ_PPC)
#define TZ_NUM_PORTS 16
-typedef struct TZPPC TZPPC;
typedef struct TZPPCPort {
TZPPC *ppc;
diff --git a/include/hw/misc/unimp.h b/include/hw/misc/unimp.h
index 4c1d13c9bf..518d627dc5 100644
--- a/include/hw/misc/unimp.h
+++ b/include/hw/misc/unimp.h
@@ -11,18 +11,19 @@
#include "hw/qdev-properties.h"
#include "hw/sysbus.h"
#include "qapi/error.h"
+#include "qom/object.h"
#define TYPE_UNIMPLEMENTED_DEVICE "unimplemented-device"
-#define UNIMPLEMENTED_DEVICE(obj) \
- OBJECT_CHECK(UnimplementedDeviceState, (obj), TYPE_UNIMPLEMENTED_DEVICE)
+OBJECT_DECLARE_SIMPLE_TYPE(UnimplementedDeviceState, UNIMPLEMENTED_DEVICE)
-typedef struct {
+struct UnimplementedDeviceState {
SysBusDevice parent_obj;
MemoryRegion iomem;
+ unsigned offset_fmt_width;
char *name;
uint64_t size;
-} UnimplementedDeviceState;
+};
/**
* create_unimplemented_device: create and map a dummy device
diff --git a/include/hw/misc/virt_ctrl.h b/include/hw/misc/virt_ctrl.h
new file mode 100644
index 0000000000..81346cf017
--- /dev/null
+++ b/include/hw/misc/virt_ctrl.h
@@ -0,0 +1,24 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Virt system Controller
+ */
+
+#ifndef VIRT_CTRL_H
+#define VIRT_CTRL_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_VIRT_CTRL "virt-ctrl"
+OBJECT_DECLARE_SIMPLE_TYPE(VirtCtrlState, VIRT_CTRL)
+
+struct VirtCtrlState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ qemu_irq irq;
+
+ uint32_t irq_enabled;
+};
+
+#endif
diff --git a/include/hw/misc/vmcoreinfo.h b/include/hw/misc/vmcoreinfo.h
index d4f3d3a91c..0b7b55d400 100644
--- a/include/hw/misc/vmcoreinfo.h
+++ b/include/hw/misc/vmcoreinfo.h
@@ -14,18 +14,21 @@
#include "hw/qdev-core.h"
#include "standard-headers/linux/qemu_fw_cfg.h"
+#include "qom/object.h"
#define VMCOREINFO_DEVICE "vmcoreinfo"
-#define VMCOREINFO(obj) OBJECT_CHECK(VMCoreInfoState, (obj), VMCOREINFO_DEVICE)
+typedef struct VMCoreInfoState VMCoreInfoState;
+DECLARE_INSTANCE_CHECKER(VMCoreInfoState, VMCOREINFO,
+ VMCOREINFO_DEVICE)
typedef struct fw_cfg_vmcoreinfo FWCfgVMCoreInfo;
-typedef struct VMCoreInfoState {
- DeviceClass parent_obj;
+struct VMCoreInfoState {
+ DeviceState parent_obj;
bool has_vmcoreinfo;
FWCfgVMCoreInfo vmcoreinfo;
-} VMCoreInfoState;
+};
/* returns NULL unless there is exactly one device */
static inline VMCoreInfoState *vmcoreinfo_find(void)
diff --git a/include/hw/misc/xlnx-cfi-if.h b/include/hw/misc/xlnx-cfi-if.h
new file mode 100644
index 0000000000..f9bd12292d
--- /dev/null
+++ b/include/hw/misc/xlnx-cfi-if.h
@@ -0,0 +1,59 @@
+/*
+ * Xilinx CFI interface
+ *
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * Written by Francisco Iglesias <francisco.iglesias@amd.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef XLNX_CFI_IF_H
+#define XLNX_CFI_IF_H 1
+
+#include "qemu/help-texts.h"
+#include "hw/hw.h"
+#include "qom/object.h"
+
+#define TYPE_XLNX_CFI_IF "xlnx-cfi-if"
+typedef struct XlnxCfiIfClass XlnxCfiIfClass;
+DECLARE_CLASS_CHECKERS(XlnxCfiIfClass, XLNX_CFI_IF, TYPE_XLNX_CFI_IF)
+
+#define XLNX_CFI_IF(obj) \
+ INTERFACE_CHECK(XlnxCfiIf, (obj), TYPE_XLNX_CFI_IF)
+
+typedef enum {
+ PACKET_TYPE_CFU = 0x52,
+ PACKET_TYPE_CFRAME = 0xA1,
+} xlnx_cfi_packet_type;
+
+typedef enum {
+ CFRAME_FAR = 1,
+ CFRAME_SFR = 2,
+ CFRAME_FDRI = 4,
+ CFRAME_CMD = 6,
+} xlnx_cfi_reg_addr;
+
+typedef struct XlnxCfiPacket {
+ uint8_t reg_addr;
+ uint32_t data[4];
+} XlnxCfiPacket;
+
+typedef struct XlnxCfiIf {
+ Object Parent;
+} XlnxCfiIf;
+
+typedef struct XlnxCfiIfClass {
+ InterfaceClass parent;
+
+ void (*cfi_transfer_packet)(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt);
+} XlnxCfiIfClass;
+
+/**
+ * Transfer a XlnxCfiPacket.
+ *
+ * @cfi_if: the object implementing this interface
+ * @XlnxCfiPacket: a pointer to the XlnxCfiPacket to transfer
+ */
+void xlnx_cfi_transfer_packet(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt);
+
+#endif /* XLNX_CFI_IF_H */
diff --git a/include/hw/misc/xlnx-versal-cframe-reg.h b/include/hw/misc/xlnx-versal-cframe-reg.h
new file mode 100644
index 0000000000..83f6a07744
--- /dev/null
+++ b/include/hw/misc/xlnx-versal-cframe-reg.h
@@ -0,0 +1,303 @@
+/*
+ * QEMU model of the Configuration Frame Control module
+ *
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * Written by Francisco Iglesias <francisco.iglesias@amd.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * References:
+ * [1] Versal ACAP Technical Reference Manual,
+ * https://www.xilinx.com/support/documentation/architecture-manuals/am011-versal-acap-trm.pdf
+ *
+ * [2] Versal ACAP Register Reference,
+ * https://docs.xilinx.com/r/en-US/am012-versal-register-reference/CFRAME_REG-Module
+ */
+#ifndef HW_MISC_XLNX_VERSAL_CFRAME_REG_H
+#define HW_MISC_XLNX_VERSAL_CFRAME_REG_H
+
+#include "hw/sysbus.h"
+#include "hw/register.h"
+#include "hw/misc/xlnx-cfi-if.h"
+#include "hw/misc/xlnx-versal-cfu.h"
+#include "qemu/fifo32.h"
+
+#define TYPE_XLNX_VERSAL_CFRAME_REG "xlnx-cframe-reg"
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFrameReg, XLNX_VERSAL_CFRAME_REG)
+
+#define TYPE_XLNX_VERSAL_CFRAME_BCAST_REG "xlnx.cframe-bcast-reg"
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFrameBcastReg,
+ XLNX_VERSAL_CFRAME_BCAST_REG)
+
+/*
+ * The registers in this module are 128 bits wide but it is ok to write
+ * and read them through 4 sequential 32 bit accesses (address[3:2] = 0,
+ * 1, 2, 3).
+ */
+REG32(CRC0, 0x0)
+ FIELD(CRC, CRC, 0, 32)
+REG32(CRC1, 0x4)
+REG32(CRC2, 0x8)
+REG32(CRC3, 0xc)
+REG32(FAR0, 0x10)
+ FIELD(FAR0, SEGMENT, 23, 2)
+ FIELD(FAR0, BLOCKTYPE, 20, 3)
+ FIELD(FAR0, FRAME_ADDR, 0, 20)
+REG32(FAR1, 0x14)
+REG32(FAR2, 0x18)
+REG32(FAR3, 0x1c)
+REG32(FAR_SFR0, 0x20)
+ FIELD(FAR_SFR0, BLOCKTYPE, 20, 3)
+ FIELD(FAR_SFR0, FRAME_ADDR, 0, 20)
+REG32(FAR_SFR1, 0x24)
+REG32(FAR_SFR2, 0x28)
+REG32(FAR_SFR3, 0x2c)
+REG32(FDRI0, 0x40)
+REG32(FDRI1, 0x44)
+REG32(FDRI2, 0x48)
+REG32(FDRI3, 0x4c)
+REG32(FRCNT0, 0x50)
+ FIELD(FRCNT0, FRCNT, 0, 32)
+REG32(FRCNT1, 0x54)
+REG32(FRCNT2, 0x58)
+REG32(FRCNT3, 0x5c)
+REG32(CMD0, 0x60)
+ FIELD(CMD0, CMD, 0, 5)
+REG32(CMD1, 0x64)
+REG32(CMD2, 0x68)
+REG32(CMD3, 0x6c)
+REG32(CR_MASK0, 0x70)
+REG32(CR_MASK1, 0x74)
+REG32(CR_MASK2, 0x78)
+REG32(CR_MASK3, 0x7c)
+REG32(CTL0, 0x80)
+ FIELD(CTL, PER_FRAME_CRC, 0, 1)
+REG32(CTL1, 0x84)
+REG32(CTL2, 0x88)
+REG32(CTL3, 0x8c)
+REG32(CFRM_ISR0, 0x150)
+ FIELD(CFRM_ISR0, READ_BROADCAST_ERROR, 21, 1)
+ FIELD(CFRM_ISR0, CMD_MISSING_ERROR, 20, 1)
+ FIELD(CFRM_ISR0, RW_ROWOFF_ERROR, 19, 1)
+ FIELD(CFRM_ISR0, READ_REG_ADDR_ERROR, 18, 1)
+ FIELD(CFRM_ISR0, READ_BLK_TYPE_ERROR, 17, 1)
+ FIELD(CFRM_ISR0, READ_FRAME_ADDR_ERROR, 16, 1)
+ FIELD(CFRM_ISR0, WRITE_REG_ADDR_ERROR, 15, 1)
+ FIELD(CFRM_ISR0, WRITE_BLK_TYPE_ERROR, 13, 1)
+ FIELD(CFRM_ISR0, WRITE_FRAME_ADDR_ERROR, 12, 1)
+ FIELD(CFRM_ISR0, MFW_OVERRUN_ERROR, 11, 1)
+ FIELD(CFRM_ISR0, FAR_FIFO_UNDERFLOW, 10, 1)
+ FIELD(CFRM_ISR0, FAR_FIFO_OVERFLOW, 9, 1)
+ FIELD(CFRM_ISR0, PER_FRAME_SEQ_ERROR, 8, 1)
+ FIELD(CFRM_ISR0, CRC_ERROR, 7, 1)
+ FIELD(CFRM_ISR0, WRITE_OVERRUN_ERROR, 6, 1)
+ FIELD(CFRM_ISR0, READ_OVERRUN_ERROR, 5, 1)
+ FIELD(CFRM_ISR0, CMD_INTERRUPT_ERROR, 4, 1)
+ FIELD(CFRM_ISR0, WRITE_INTERRUPT_ERROR, 3, 1)
+ FIELD(CFRM_ISR0, READ_INTERRUPT_ERROR, 2, 1)
+ FIELD(CFRM_ISR0, SEU_CRC_ERROR, 1, 1)
+ FIELD(CFRM_ISR0, SEU_ECC_ERROR, 0, 1)
+REG32(CFRM_ISR1, 0x154)
+REG32(CFRM_ISR2, 0x158)
+REG32(CFRM_ISR3, 0x15c)
+REG32(CFRM_IMR0, 0x160)
+ FIELD(CFRM_IMR0, READ_BROADCAST_ERROR, 21, 1)
+ FIELD(CFRM_IMR0, CMD_MISSING_ERROR, 20, 1)
+ FIELD(CFRM_IMR0, RW_ROWOFF_ERROR, 19, 1)
+ FIELD(CFRM_IMR0, READ_REG_ADDR_ERROR, 18, 1)
+ FIELD(CFRM_IMR0, READ_BLK_TYPE_ERROR, 17, 1)
+ FIELD(CFRM_IMR0, READ_FRAME_ADDR_ERROR, 16, 1)
+ FIELD(CFRM_IMR0, WRITE_REG_ADDR_ERROR, 15, 1)
+ FIELD(CFRM_IMR0, WRITE_BLK_TYPE_ERROR, 13, 1)
+ FIELD(CFRM_IMR0, WRITE_FRAME_ADDR_ERROR, 12, 1)
+ FIELD(CFRM_IMR0, MFW_OVERRUN_ERROR, 11, 1)
+ FIELD(CFRM_IMR0, FAR_FIFO_UNDERFLOW, 10, 1)
+ FIELD(CFRM_IMR0, FAR_FIFO_OVERFLOW, 9, 1)
+ FIELD(CFRM_IMR0, PER_FRAME_SEQ_ERROR, 8, 1)
+ FIELD(CFRM_IMR0, CRC_ERROR, 7, 1)
+ FIELD(CFRM_IMR0, WRITE_OVERRUN_ERROR, 6, 1)
+ FIELD(CFRM_IMR0, READ_OVERRUN_ERROR, 5, 1)
+ FIELD(CFRM_IMR0, CMD_INTERRUPT_ERROR, 4, 1)
+ FIELD(CFRM_IMR0, WRITE_INTERRUPT_ERROR, 3, 1)
+ FIELD(CFRM_IMR0, READ_INTERRUPT_ERROR, 2, 1)
+ FIELD(CFRM_IMR0, SEU_CRC_ERROR, 1, 1)
+ FIELD(CFRM_IMR0, SEU_ECC_ERROR, 0, 1)
+REG32(CFRM_IMR1, 0x164)
+REG32(CFRM_IMR2, 0x168)
+REG32(CFRM_IMR3, 0x16c)
+REG32(CFRM_IER0, 0x170)
+ FIELD(CFRM_IER0, READ_BROADCAST_ERROR, 21, 1)
+ FIELD(CFRM_IER0, CMD_MISSING_ERROR, 20, 1)
+ FIELD(CFRM_IER0, RW_ROWOFF_ERROR, 19, 1)
+ FIELD(CFRM_IER0, READ_REG_ADDR_ERROR, 18, 1)
+ FIELD(CFRM_IER0, READ_BLK_TYPE_ERROR, 17, 1)
+ FIELD(CFRM_IER0, READ_FRAME_ADDR_ERROR, 16, 1)
+ FIELD(CFRM_IER0, WRITE_REG_ADDR_ERROR, 15, 1)
+ FIELD(CFRM_IER0, WRITE_BLK_TYPE_ERROR, 13, 1)
+ FIELD(CFRM_IER0, WRITE_FRAME_ADDR_ERROR, 12, 1)
+ FIELD(CFRM_IER0, MFW_OVERRUN_ERROR, 11, 1)
+ FIELD(CFRM_IER0, FAR_FIFO_UNDERFLOW, 10, 1)
+ FIELD(CFRM_IER0, FAR_FIFO_OVERFLOW, 9, 1)
+ FIELD(CFRM_IER0, PER_FRAME_SEQ_ERROR, 8, 1)
+ FIELD(CFRM_IER0, CRC_ERROR, 7, 1)
+ FIELD(CFRM_IER0, WRITE_OVERRUN_ERROR, 6, 1)
+ FIELD(CFRM_IER0, READ_OVERRUN_ERROR, 5, 1)
+ FIELD(CFRM_IER0, CMD_INTERRUPT_ERROR, 4, 1)
+ FIELD(CFRM_IER0, WRITE_INTERRUPT_ERROR, 3, 1)
+ FIELD(CFRM_IER0, READ_INTERRUPT_ERROR, 2, 1)
+ FIELD(CFRM_IER0, SEU_CRC_ERROR, 1, 1)
+ FIELD(CFRM_IER0, SEU_ECC_ERROR, 0, 1)
+REG32(CFRM_IER1, 0x174)
+REG32(CFRM_IER2, 0x178)
+REG32(CFRM_IER3, 0x17c)
+REG32(CFRM_IDR0, 0x180)
+ FIELD(CFRM_IDR0, READ_BROADCAST_ERROR, 21, 1)
+ FIELD(CFRM_IDR0, CMD_MISSING_ERROR, 20, 1)
+ FIELD(CFRM_IDR0, RW_ROWOFF_ERROR, 19, 1)
+ FIELD(CFRM_IDR0, READ_REG_ADDR_ERROR, 18, 1)
+ FIELD(CFRM_IDR0, READ_BLK_TYPE_ERROR, 17, 1)
+ FIELD(CFRM_IDR0, READ_FRAME_ADDR_ERROR, 16, 1)
+ FIELD(CFRM_IDR0, WRITE_REG_ADDR_ERROR, 15, 1)
+ FIELD(CFRM_IDR0, WRITE_BLK_TYPE_ERROR, 13, 1)
+ FIELD(CFRM_IDR0, WRITE_FRAME_ADDR_ERROR, 12, 1)
+ FIELD(CFRM_IDR0, MFW_OVERRUN_ERROR, 11, 1)
+ FIELD(CFRM_IDR0, FAR_FIFO_UNDERFLOW, 10, 1)
+ FIELD(CFRM_IDR0, FAR_FIFO_OVERFLOW, 9, 1)
+ FIELD(CFRM_IDR0, PER_FRAME_SEQ_ERROR, 8, 1)
+ FIELD(CFRM_IDR0, CRC_ERROR, 7, 1)
+ FIELD(CFRM_IDR0, WRITE_OVERRUN_ERROR, 6, 1)
+ FIELD(CFRM_IDR0, READ_OVERRUN_ERROR, 5, 1)
+ FIELD(CFRM_IDR0, CMD_INTERRUPT_ERROR, 4, 1)
+ FIELD(CFRM_IDR0, WRITE_INTERRUPT_ERROR, 3, 1)
+ FIELD(CFRM_IDR0, READ_INTERRUPT_ERROR, 2, 1)
+ FIELD(CFRM_IDR0, SEU_CRC_ERROR, 1, 1)
+ FIELD(CFRM_IDR0, SEU_ECC_ERROR, 0, 1)
+REG32(CFRM_IDR1, 0x184)
+REG32(CFRM_IDR2, 0x188)
+REG32(CFRM_IDR3, 0x18c)
+REG32(CFRM_ITR0, 0x190)
+ FIELD(CFRM_ITR0, READ_BROADCAST_ERROR, 21, 1)
+ FIELD(CFRM_ITR0, CMD_MISSING_ERROR, 20, 1)
+ FIELD(CFRM_ITR0, RW_ROWOFF_ERROR, 19, 1)
+ FIELD(CFRM_ITR0, READ_REG_ADDR_ERROR, 18, 1)
+ FIELD(CFRM_ITR0, READ_BLK_TYPE_ERROR, 17, 1)
+ FIELD(CFRM_ITR0, READ_FRAME_ADDR_ERROR, 16, 1)
+ FIELD(CFRM_ITR0, WRITE_REG_ADDR_ERROR, 15, 1)
+ FIELD(CFRM_ITR0, WRITE_BLK_TYPE_ERROR, 13, 1)
+ FIELD(CFRM_ITR0, WRITE_FRAME_ADDR_ERROR, 12, 1)
+ FIELD(CFRM_ITR0, MFW_OVERRUN_ERROR, 11, 1)
+ FIELD(CFRM_ITR0, FAR_FIFO_UNDERFLOW, 10, 1)
+ FIELD(CFRM_ITR0, FAR_FIFO_OVERFLOW, 9, 1)
+ FIELD(CFRM_ITR0, PER_FRAME_SEQ_ERROR, 8, 1)
+ FIELD(CFRM_ITR0, CRC_ERROR, 7, 1)
+ FIELD(CFRM_ITR0, WRITE_OVERRUN_ERROR, 6, 1)
+ FIELD(CFRM_ITR0, READ_OVERRUN_ERROR, 5, 1)
+ FIELD(CFRM_ITR0, CMD_INTERRUPT_ERROR, 4, 1)
+ FIELD(CFRM_ITR0, WRITE_INTERRUPT_ERROR, 3, 1)
+ FIELD(CFRM_ITR0, READ_INTERRUPT_ERROR, 2, 1)
+ FIELD(CFRM_ITR0, SEU_CRC_ERROR, 1, 1)
+ FIELD(CFRM_ITR0, SEU_ECC_ERROR, 0, 1)
+REG32(CFRM_ITR1, 0x194)
+REG32(CFRM_ITR2, 0x198)
+REG32(CFRM_ITR3, 0x19c)
+REG32(SEU_SYNDRM00, 0x1a0)
+REG32(SEU_SYNDRM01, 0x1a4)
+REG32(SEU_SYNDRM02, 0x1a8)
+REG32(SEU_SYNDRM03, 0x1ac)
+REG32(SEU_SYNDRM10, 0x1b0)
+REG32(SEU_SYNDRM11, 0x1b4)
+REG32(SEU_SYNDRM12, 0x1b8)
+REG32(SEU_SYNDRM13, 0x1bc)
+REG32(SEU_SYNDRM20, 0x1c0)
+REG32(SEU_SYNDRM21, 0x1c4)
+REG32(SEU_SYNDRM22, 0x1c8)
+REG32(SEU_SYNDRM23, 0x1cc)
+REG32(SEU_SYNDRM30, 0x1d0)
+REG32(SEU_SYNDRM31, 0x1d4)
+REG32(SEU_SYNDRM32, 0x1d8)
+REG32(SEU_SYNDRM33, 0x1dc)
+REG32(SEU_VIRTUAL_SYNDRM0, 0x1e0)
+REG32(SEU_VIRTUAL_SYNDRM1, 0x1e4)
+REG32(SEU_VIRTUAL_SYNDRM2, 0x1e8)
+REG32(SEU_VIRTUAL_SYNDRM3, 0x1ec)
+REG32(SEU_CRC0, 0x1f0)
+REG32(SEU_CRC1, 0x1f4)
+REG32(SEU_CRC2, 0x1f8)
+REG32(SEU_CRC3, 0x1fc)
+REG32(CFRAME_FAR_BOT0, 0x200)
+REG32(CFRAME_FAR_BOT1, 0x204)
+REG32(CFRAME_FAR_BOT2, 0x208)
+REG32(CFRAME_FAR_BOT3, 0x20c)
+REG32(CFRAME_FAR_TOP0, 0x210)
+REG32(CFRAME_FAR_TOP1, 0x214)
+REG32(CFRAME_FAR_TOP2, 0x218)
+REG32(CFRAME_FAR_TOP3, 0x21c)
+REG32(LAST_FRAME_BOT0, 0x220)
+ FIELD(LAST_FRAME_BOT0, BLOCKTYPE1_LAST_FRAME_LSB, 20, 12)
+ FIELD(LAST_FRAME_BOT0, BLOCKTYPE0_LAST_FRAME, 0, 20)
+REG32(LAST_FRAME_BOT1, 0x224)
+ FIELD(LAST_FRAME_BOT1, BLOCKTYPE3_LAST_FRAME_LSB, 28, 4)
+ FIELD(LAST_FRAME_BOT1, BLOCKTYPE2_LAST_FRAME, 8, 20)
+ FIELD(LAST_FRAME_BOT1, BLOCKTYPE1_LAST_FRAME_MSB, 0, 8)
+REG32(LAST_FRAME_BOT2, 0x228)
+ FIELD(LAST_FRAME_BOT2, BLOCKTYPE3_LAST_FRAME_MSB, 0, 16)
+REG32(LAST_FRAME_BOT3, 0x22c)
+REG32(LAST_FRAME_TOP0, 0x230)
+ FIELD(LAST_FRAME_TOP0, BLOCKTYPE5_LAST_FRAME_LSB, 20, 12)
+ FIELD(LAST_FRAME_TOP0, BLOCKTYPE4_LAST_FRAME, 0, 20)
+REG32(LAST_FRAME_TOP1, 0x234)
+ FIELD(LAST_FRAME_TOP1, BLOCKTYPE6_LAST_FRAME, 8, 20)
+ FIELD(LAST_FRAME_TOP1, BLOCKTYPE5_LAST_FRAME_MSB, 0, 8)
+REG32(LAST_FRAME_TOP2, 0x238)
+REG32(LAST_FRAME_TOP3, 0x23c)
+
+#define CFRAME_REG_R_MAX (R_LAST_FRAME_TOP3 + 1)
+
+#define FRAME_NUM_QWORDS 25
+#define FRAME_NUM_WORDS (FRAME_NUM_QWORDS * 4) /* 25 * 128 bits */
+
+typedef struct XlnxCFrame {
+ uint32_t data[FRAME_NUM_WORDS];
+} XlnxCFrame;
+
+struct XlnxVersalCFrameReg {
+ SysBusDevice parent_obj;
+ MemoryRegion iomem;
+ MemoryRegion iomem_fdri;
+ qemu_irq irq_cfrm_imr;
+
+ /* 128-bit wfifo. */
+ uint32_t wfifo[WFIFO_SZ];
+
+ uint32_t regs[CFRAME_REG_R_MAX];
+ RegisterInfo regs_info[CFRAME_REG_R_MAX];
+
+ bool rowon;
+ bool wcfg;
+ bool rcfg;
+
+ GTree *cframes;
+ Fifo32 new_f_data;
+
+ struct {
+ XlnxCfiIf *cfu_fdro;
+ uint32_t blktype_num_frames[7];
+ } cfg;
+ bool row_configured;
+};
+
+struct XlnxVersalCFrameBcastReg {
+ SysBusDevice parent_obj;
+ MemoryRegion iomem_reg;
+ MemoryRegion iomem_fdri;
+
+ /* 128-bit wfifo. */
+ uint32_t wfifo[WFIFO_SZ];
+
+ struct {
+ XlnxCfiIf *cframe[15];
+ } cfg;
+};
+
+#endif
diff --git a/include/hw/misc/xlnx-versal-cfu.h b/include/hw/misc/xlnx-versal-cfu.h
new file mode 100644
index 0000000000..3de3ee4923
--- /dev/null
+++ b/include/hw/misc/xlnx-versal-cfu.h
@@ -0,0 +1,258 @@
+/*
+ * QEMU model of the CFU Configuration Unit.
+ *
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * Written by Francisco Iglesias <francisco.iglesias@amd.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * References:
+ * [1] Versal ACAP Technical Reference Manual,
+ * https://www.xilinx.com/support/documentation/architecture-manuals/am011-versal-acap-trm.pdf
+ *
+ * [2] Versal ACAP Register Reference,
+ * https://docs.xilinx.com/r/en-US/am012-versal-register-reference/CFU_CSR-Module
+ */
+#ifndef HW_MISC_XLNX_VERSAL_CFU_APB_H
+#define HW_MISC_XLNX_VERSAL_CFU_APB_H
+
+#include "hw/sysbus.h"
+#include "hw/register.h"
+#include "hw/misc/xlnx-cfi-if.h"
+#include "qemu/fifo32.h"
+
+#define TYPE_XLNX_VERSAL_CFU_APB "xlnx-versal-cfu-apb"
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFUAPB, XLNX_VERSAL_CFU_APB)
+
+#define TYPE_XLNX_VERSAL_CFU_FDRO "xlnx-versal-cfu-fdro"
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFUFDRO, XLNX_VERSAL_CFU_FDRO)
+
+#define TYPE_XLNX_VERSAL_CFU_SFR "xlnx-versal-cfu-sfr"
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFUSFR, XLNX_VERSAL_CFU_SFR)
+
+REG32(CFU_ISR, 0x0)
+ FIELD(CFU_ISR, USR_GTS_EVENT, 9, 1)
+ FIELD(CFU_ISR, USR_GSR_EVENT, 8, 1)
+ FIELD(CFU_ISR, SLVERR, 7, 1)
+ FIELD(CFU_ISR, DECOMP_ERROR, 6, 1)
+ FIELD(CFU_ISR, BAD_CFI_PACKET, 5, 1)
+ FIELD(CFU_ISR, AXI_ALIGN_ERROR, 4, 1)
+ FIELD(CFU_ISR, CFI_ROW_ERROR, 3, 1)
+ FIELD(CFU_ISR, CRC32_ERROR, 2, 1)
+ FIELD(CFU_ISR, CRC8_ERROR, 1, 1)
+ FIELD(CFU_ISR, SEU_ENDOFCALIB, 0, 1)
+REG32(CFU_IMR, 0x4)
+ FIELD(CFU_IMR, USR_GTS_EVENT, 9, 1)
+ FIELD(CFU_IMR, USR_GSR_EVENT, 8, 1)
+ FIELD(CFU_IMR, SLVERR, 7, 1)
+ FIELD(CFU_IMR, DECOMP_ERROR, 6, 1)
+ FIELD(CFU_IMR, BAD_CFI_PACKET, 5, 1)
+ FIELD(CFU_IMR, AXI_ALIGN_ERROR, 4, 1)
+ FIELD(CFU_IMR, CFI_ROW_ERROR, 3, 1)
+ FIELD(CFU_IMR, CRC32_ERROR, 2, 1)
+ FIELD(CFU_IMR, CRC8_ERROR, 1, 1)
+ FIELD(CFU_IMR, SEU_ENDOFCALIB, 0, 1)
+REG32(CFU_IER, 0x8)
+ FIELD(CFU_IER, USR_GTS_EVENT, 9, 1)
+ FIELD(CFU_IER, USR_GSR_EVENT, 8, 1)
+ FIELD(CFU_IER, SLVERR, 7, 1)
+ FIELD(CFU_IER, DECOMP_ERROR, 6, 1)
+ FIELD(CFU_IER, BAD_CFI_PACKET, 5, 1)
+ FIELD(CFU_IER, AXI_ALIGN_ERROR, 4, 1)
+ FIELD(CFU_IER, CFI_ROW_ERROR, 3, 1)
+ FIELD(CFU_IER, CRC32_ERROR, 2, 1)
+ FIELD(CFU_IER, CRC8_ERROR, 1, 1)
+ FIELD(CFU_IER, SEU_ENDOFCALIB, 0, 1)
+REG32(CFU_IDR, 0xc)
+ FIELD(CFU_IDR, USR_GTS_EVENT, 9, 1)
+ FIELD(CFU_IDR, USR_GSR_EVENT, 8, 1)
+ FIELD(CFU_IDR, SLVERR, 7, 1)
+ FIELD(CFU_IDR, DECOMP_ERROR, 6, 1)
+ FIELD(CFU_IDR, BAD_CFI_PACKET, 5, 1)
+ FIELD(CFU_IDR, AXI_ALIGN_ERROR, 4, 1)
+ FIELD(CFU_IDR, CFI_ROW_ERROR, 3, 1)
+ FIELD(CFU_IDR, CRC32_ERROR, 2, 1)
+ FIELD(CFU_IDR, CRC8_ERROR, 1, 1)
+ FIELD(CFU_IDR, SEU_ENDOFCALIB, 0, 1)
+REG32(CFU_ITR, 0x10)
+ FIELD(CFU_ITR, USR_GTS_EVENT, 9, 1)
+ FIELD(CFU_ITR, USR_GSR_EVENT, 8, 1)
+ FIELD(CFU_ITR, SLVERR, 7, 1)
+ FIELD(CFU_ITR, DECOMP_ERROR, 6, 1)
+ FIELD(CFU_ITR, BAD_CFI_PACKET, 5, 1)
+ FIELD(CFU_ITR, AXI_ALIGN_ERROR, 4, 1)
+ FIELD(CFU_ITR, CFI_ROW_ERROR, 3, 1)
+ FIELD(CFU_ITR, CRC32_ERROR, 2, 1)
+ FIELD(CFU_ITR, CRC8_ERROR, 1, 1)
+ FIELD(CFU_ITR, SEU_ENDOFCALIB, 0, 1)
+REG32(CFU_PROTECT, 0x14)
+ FIELD(CFU_PROTECT, ACTIVE, 0, 1)
+REG32(CFU_FGCR, 0x18)
+ FIELD(CFU_FGCR, GCLK_CAL, 14, 1)
+ FIELD(CFU_FGCR, SC_HBC_TRIGGER, 13, 1)
+ FIELD(CFU_FGCR, GLOW, 12, 1)
+ FIELD(CFU_FGCR, GPWRDWN, 11, 1)
+ FIELD(CFU_FGCR, GCAP, 10, 1)
+ FIELD(CFU_FGCR, GSCWE, 9, 1)
+ FIELD(CFU_FGCR, GHIGH_B, 8, 1)
+ FIELD(CFU_FGCR, GMC_B, 7, 1)
+ FIELD(CFU_FGCR, GWE, 6, 1)
+ FIELD(CFU_FGCR, GRESTORE, 5, 1)
+ FIELD(CFU_FGCR, GTS_CFG_B, 4, 1)
+ FIELD(CFU_FGCR, GLUTMASK, 3, 1)
+ FIELD(CFU_FGCR, EN_GLOBS_B, 2, 1)
+ FIELD(CFU_FGCR, EOS, 1, 1)
+ FIELD(CFU_FGCR, INIT_COMPLETE, 0, 1)
+REG32(CFU_CTL, 0x1c)
+ FIELD(CFU_CTL, GSR_GSC, 15, 1)
+ FIELD(CFU_CTL, SLVERR_EN, 14, 1)
+ FIELD(CFU_CTL, CRC32_RESET, 13, 1)
+ FIELD(CFU_CTL, AXI_ERROR_EN, 12, 1)
+ FIELD(CFU_CTL, FLUSH_AXI, 11, 1)
+ FIELD(CFU_CTL, SSI_PER_SLR_PR, 10, 1)
+ FIELD(CFU_CTL, GCAP_CLK_EN, 9, 1)
+ FIELD(CFU_CTL, STATUS_SYNC_DISABLE, 8, 1)
+ FIELD(CFU_CTL, IGNORE_CFI_ERROR, 7, 1)
+ FIELD(CFU_CTL, CFRAME_DISABLE, 6, 1)
+ FIELD(CFU_CTL, QWORD_CNT_RESET, 5, 1)
+ FIELD(CFU_CTL, CRC8_DISABLE, 4, 1)
+ FIELD(CFU_CTL, CRC32_CHECK, 3, 1)
+ FIELD(CFU_CTL, DECOMPRESS, 2, 1)
+ FIELD(CFU_CTL, SEU_GO, 1, 1)
+ FIELD(CFU_CTL, CFI_LOCAL_RESET, 0, 1)
+REG32(CFU_CRAM_RW, 0x20)
+ FIELD(CFU_CRAM_RW, RFIFO_AFULL_DEPTH, 18, 9)
+ FIELD(CFU_CRAM_RW, RD_WAVE_CNT_LEFT, 12, 6)
+ FIELD(CFU_CRAM_RW, RD_WAVE_CNT, 6, 6)
+ FIELD(CFU_CRAM_RW, WR_WAVE_CNT, 0, 6)
+REG32(CFU_MASK, 0x28)
+REG32(CFU_CRC_EXPECT, 0x2c)
+REG32(CFU_CFRAME_LEFT_T0, 0x60)
+ FIELD(CFU_CFRAME_LEFT_T0, NUM, 0, 20)
+REG32(CFU_CFRAME_LEFT_T1, 0x64)
+ FIELD(CFU_CFRAME_LEFT_T1, NUM, 0, 20)
+REG32(CFU_CFRAME_LEFT_T2, 0x68)
+ FIELD(CFU_CFRAME_LEFT_T2, NUM, 0, 20)
+REG32(CFU_ROW_RANGE, 0x6c)
+ FIELD(CFU_ROW_RANGE, HALF_FSR, 5, 1)
+ FIELD(CFU_ROW_RANGE, NUM, 0, 5)
+REG32(CFU_STATUS, 0x100)
+ FIELD(CFU_STATUS, SEU_WRITE_ERROR, 30, 1)
+ FIELD(CFU_STATUS, FRCNT_ERROR, 29, 1)
+ FIELD(CFU_STATUS, RSVD_ERROR, 28, 1)
+ FIELD(CFU_STATUS, FDRO_ERROR, 27, 1)
+ FIELD(CFU_STATUS, FDRI_ERROR, 26, 1)
+ FIELD(CFU_STATUS, FDRI_READ_ERROR, 25, 1)
+ FIELD(CFU_STATUS, READ_FDRI_ERROR, 24, 1)
+ FIELD(CFU_STATUS, READ_SFR_ERROR, 23, 1)
+ FIELD(CFU_STATUS, READ_STREAM_ERROR, 22, 1)
+ FIELD(CFU_STATUS, UNKNOWN_STREAM_PKT, 21, 1)
+ FIELD(CFU_STATUS, USR_GTS, 20, 1)
+ FIELD(CFU_STATUS, USR_GSR, 19, 1)
+ FIELD(CFU_STATUS, AXI_BAD_WSTRB, 18, 1)
+ FIELD(CFU_STATUS, AXI_BAD_AR_SIZE, 17, 1)
+ FIELD(CFU_STATUS, AXI_BAD_AW_SIZE, 16, 1)
+ FIELD(CFU_STATUS, AXI_BAD_ARADDR, 15, 1)
+ FIELD(CFU_STATUS, AXI_BAD_AWADDR, 14, 1)
+ FIELD(CFU_STATUS, SCAN_CLEAR_PASS, 13, 1)
+ FIELD(CFU_STATUS, HC_SEC_ERROR, 12, 1)
+ FIELD(CFU_STATUS, GHIGH_B_ISHIGH, 11, 1)
+ FIELD(CFU_STATUS, GHIGH_B_ISLOW, 10, 1)
+ FIELD(CFU_STATUS, GMC_B_ISHIGH, 9, 1)
+ FIELD(CFU_STATUS, GMC_B_ISLOW, 8, 1)
+ FIELD(CFU_STATUS, GPWRDWN_B_ISHIGH, 7, 1)
+ FIELD(CFU_STATUS, CFI_SEU_CRC_ERROR, 6, 1)
+ FIELD(CFU_STATUS, CFI_SEU_ECC_ERROR, 5, 1)
+ FIELD(CFU_STATUS, CFI_SEU_HEARTBEAT, 4, 1)
+ FIELD(CFU_STATUS, SCAN_CLEAR_DONE, 3, 1)
+ FIELD(CFU_STATUS, HC_COMPLETE, 2, 1)
+ FIELD(CFU_STATUS, CFI_CFRAME_BUSY, 1, 1)
+ FIELD(CFU_STATUS, CFU_STREAM_BUSY, 0, 1)
+REG32(CFU_INTERNAL_STATUS, 0x104)
+ FIELD(CFU_INTERNAL_STATUS, SSI_EOS, 22, 1)
+ FIELD(CFU_INTERNAL_STATUS, SSI_GWE, 21, 1)
+ FIELD(CFU_INTERNAL_STATUS, RFIFO_EMPTY, 20, 1)
+ FIELD(CFU_INTERNAL_STATUS, RFIFO_FULL, 19, 1)
+ FIELD(CFU_INTERNAL_STATUS, SEL_SFR, 18, 1)
+ FIELD(CFU_INTERNAL_STATUS, STREAM_CFRAME, 17, 1)
+ FIELD(CFU_INTERNAL_STATUS, FDRI_PHASE, 16, 1)
+ FIELD(CFU_INTERNAL_STATUS, CFI_PIPE_EN, 15, 1)
+ FIELD(CFU_INTERNAL_STATUS, AWFIFO_DCNT, 10, 5)
+ FIELD(CFU_INTERNAL_STATUS, WFIFO_DCNT, 5, 5)
+ FIELD(CFU_INTERNAL_STATUS, REPAIR_BUSY, 4, 1)
+ FIELD(CFU_INTERNAL_STATUS, TRIMU_BUSY, 3, 1)
+ FIELD(CFU_INTERNAL_STATUS, TRIMB_BUSY, 2, 1)
+ FIELD(CFU_INTERNAL_STATUS, HCLEANR_BUSY, 1, 1)
+ FIELD(CFU_INTERNAL_STATUS, HCLEAN_BUSY, 0, 1)
+REG32(CFU_QWORD_CNT, 0x108)
+REG32(CFU_CRC_LIVE, 0x10c)
+REG32(CFU_PENDING_READ_CNT, 0x110)
+ FIELD(CFU_PENDING_READ_CNT, NUM, 0, 25)
+REG32(CFU_FDRI_CNT, 0x114)
+REG32(CFU_ECO1, 0x118)
+REG32(CFU_ECO2, 0x11c)
+
+#define R_MAX (R_CFU_ECO2 + 1)
+
+#define NUM_STREAM 2
+#define WFIFO_SZ 4
+
+struct XlnxVersalCFUAPB {
+ SysBusDevice parent_obj;
+ MemoryRegion iomem;
+ MemoryRegion iomem_stream[NUM_STREAM];
+ qemu_irq irq_cfu_imr;
+
+ /* 128-bit wfifo. */
+ uint32_t wfifo[WFIFO_SZ];
+
+ uint32_t regs[R_MAX];
+ RegisterInfo regs_info[R_MAX];
+
+ uint8_t fdri_row_addr;
+
+ struct {
+ XlnxCfiIf *cframe[15];
+ } cfg;
+};
+
+
+struct XlnxVersalCFUFDRO {
+ SysBusDevice parent_obj;
+ MemoryRegion iomem_fdro;
+
+ Fifo32 fdro_data;
+};
+
+struct XlnxVersalCFUSFR {
+ SysBusDevice parent_obj;
+ MemoryRegion iomem_sfr;
+
+ /* 128-bit wfifo. */
+ uint32_t wfifo[WFIFO_SZ];
+
+ struct {
+ XlnxVersalCFUAPB *cfu;
+ } cfg;
+};
+
+/**
+ * This is a helper function for updating a CFI data write fifo, an array of 4
+ * uint32_t and 128 bits of data that are allowed to be written through 4
+ * sequential 32 bit accesses. After the last index has been written into the
+ * write fifo (wfifo), the data is copied to and returned in a secondary fifo
+ * provided to the function (wfifo_ret), and the write fifo is cleared
+ * (zeroized).
+ *
+ * @addr: the address used when calculating the wfifo array index to update
+ * @value: the value to write into the wfifo array
+ * @wfifo: the wfifo to update
+ * @wfifo_out: will return the wfifo data when all 128 bits have been written
+ *
+ * @return: true if all 128 bits have been updated.
+ */
+bool update_wfifo(hwaddr addr, uint64_t value,
+ uint32_t *wfifo, uint32_t *wfifo_ret);
+
+#endif
diff --git a/include/hw/misc/xlnx-versal-crl.h b/include/hw/misc/xlnx-versal-crl.h
new file mode 100644
index 0000000000..dba6d3585d
--- /dev/null
+++ b/include/hw/misc/xlnx-versal-crl.h
@@ -0,0 +1,235 @@
+/*
+ * QEMU model of the Clock-Reset-LPD (CRL).
+ *
+ * Copyright (c) 2022 Xilinx Inc.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
+ */
+#ifndef HW_MISC_XLNX_VERSAL_CRL_H
+#define HW_MISC_XLNX_VERSAL_CRL_H
+
+#include "hw/sysbus.h"
+#include "hw/register.h"
+#include "target/arm/cpu-qom.h"
+
+#define TYPE_XLNX_VERSAL_CRL "xlnx-versal-crl"
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCRL, XLNX_VERSAL_CRL)
+
+REG32(ERR_CTRL, 0x0)
+ FIELD(ERR_CTRL, SLVERR_ENABLE, 0, 1)
+REG32(IR_STATUS, 0x4)
+ FIELD(IR_STATUS, ADDR_DECODE_ERR, 0, 1)
+REG32(IR_MASK, 0x8)
+ FIELD(IR_MASK, ADDR_DECODE_ERR, 0, 1)
+REG32(IR_ENABLE, 0xc)
+ FIELD(IR_ENABLE, ADDR_DECODE_ERR, 0, 1)
+REG32(IR_DISABLE, 0x10)
+ FIELD(IR_DISABLE, ADDR_DECODE_ERR, 0, 1)
+REG32(WPROT, 0x1c)
+ FIELD(WPROT, ACTIVE, 0, 1)
+REG32(PLL_CLK_OTHER_DMN, 0x20)
+ FIELD(PLL_CLK_OTHER_DMN, APLL_BYPASS, 0, 1)
+REG32(RPLL_CTRL, 0x40)
+ FIELD(RPLL_CTRL, POST_SRC, 24, 3)
+ FIELD(RPLL_CTRL, PRE_SRC, 20, 3)
+ FIELD(RPLL_CTRL, CLKOUTDIV, 16, 2)
+ FIELD(RPLL_CTRL, FBDIV, 8, 8)
+ FIELD(RPLL_CTRL, BYPASS, 3, 1)
+ FIELD(RPLL_CTRL, RESET, 0, 1)
+REG32(RPLL_CFG, 0x44)
+ FIELD(RPLL_CFG, LOCK_DLY, 25, 7)
+ FIELD(RPLL_CFG, LOCK_CNT, 13, 10)
+ FIELD(RPLL_CFG, LFHF, 10, 2)
+ FIELD(RPLL_CFG, CP, 5, 4)
+ FIELD(RPLL_CFG, RES, 0, 4)
+REG32(RPLL_FRAC_CFG, 0x48)
+ FIELD(RPLL_FRAC_CFG, ENABLED, 31, 1)
+ FIELD(RPLL_FRAC_CFG, SEED, 22, 3)
+ FIELD(RPLL_FRAC_CFG, ALGRTHM, 19, 1)
+ FIELD(RPLL_FRAC_CFG, ORDER, 18, 1)
+ FIELD(RPLL_FRAC_CFG, DATA, 0, 16)
+REG32(PLL_STATUS, 0x50)
+ FIELD(PLL_STATUS, RPLL_STABLE, 2, 1)
+ FIELD(PLL_STATUS, RPLL_LOCK, 0, 1)
+REG32(RPLL_TO_XPD_CTRL, 0x100)
+ FIELD(RPLL_TO_XPD_CTRL, CLKACT, 25, 1)
+ FIELD(RPLL_TO_XPD_CTRL, DIVISOR0, 8, 10)
+REG32(LPD_TOP_SWITCH_CTRL, 0x104)
+ FIELD(LPD_TOP_SWITCH_CTRL, CLKACT_ADMA, 26, 1)
+ FIELD(LPD_TOP_SWITCH_CTRL, CLKACT, 25, 1)
+ FIELD(LPD_TOP_SWITCH_CTRL, DIVISOR0, 8, 10)
+ FIELD(LPD_TOP_SWITCH_CTRL, SRCSEL, 0, 3)
+REG32(LPD_LSBUS_CTRL, 0x108)
+ FIELD(LPD_LSBUS_CTRL, CLKACT, 25, 1)
+ FIELD(LPD_LSBUS_CTRL, DIVISOR0, 8, 10)
+ FIELD(LPD_LSBUS_CTRL, SRCSEL, 0, 3)
+REG32(CPU_R5_CTRL, 0x10c)
+ FIELD(CPU_R5_CTRL, CLKACT_OCM2, 28, 1)
+ FIELD(CPU_R5_CTRL, CLKACT_OCM, 27, 1)
+ FIELD(CPU_R5_CTRL, CLKACT_CORE, 26, 1)
+ FIELD(CPU_R5_CTRL, CLKACT, 25, 1)
+ FIELD(CPU_R5_CTRL, DIVISOR0, 8, 10)
+ FIELD(CPU_R5_CTRL, SRCSEL, 0, 3)
+REG32(IOU_SWITCH_CTRL, 0x114)
+ FIELD(IOU_SWITCH_CTRL, CLKACT, 25, 1)
+ FIELD(IOU_SWITCH_CTRL, DIVISOR0, 8, 10)
+ FIELD(IOU_SWITCH_CTRL, SRCSEL, 0, 3)
+REG32(GEM0_REF_CTRL, 0x118)
+ FIELD(GEM0_REF_CTRL, CLKACT_RX, 27, 1)
+ FIELD(GEM0_REF_CTRL, CLKACT_TX, 26, 1)
+ FIELD(GEM0_REF_CTRL, CLKACT, 25, 1)
+ FIELD(GEM0_REF_CTRL, DIVISOR0, 8, 10)
+ FIELD(GEM0_REF_CTRL, SRCSEL, 0, 3)
+REG32(GEM1_REF_CTRL, 0x11c)
+ FIELD(GEM1_REF_CTRL, CLKACT_RX, 27, 1)
+ FIELD(GEM1_REF_CTRL, CLKACT_TX, 26, 1)
+ FIELD(GEM1_REF_CTRL, CLKACT, 25, 1)
+ FIELD(GEM1_REF_CTRL, DIVISOR0, 8, 10)
+ FIELD(GEM1_REF_CTRL, SRCSEL, 0, 3)
+REG32(GEM_TSU_REF_CTRL, 0x120)
+ FIELD(GEM_TSU_REF_CTRL, CLKACT, 25, 1)
+ FIELD(GEM_TSU_REF_CTRL, DIVISOR0, 8, 10)
+ FIELD(GEM_TSU_REF_CTRL, SRCSEL, 0, 3)
+REG32(USB0_BUS_REF_CTRL, 0x124)
+ FIELD(USB0_BUS_REF_CTRL, CLKACT, 25, 1)
+ FIELD(USB0_BUS_REF_CTRL, DIVISOR0, 8, 10)
+ FIELD(USB0_BUS_REF_CTRL, SRCSEL, 0, 3)
+REG32(UART0_REF_CTRL, 0x128)
+ FIELD(UART0_REF_CTRL, CLKACT, 25, 1)
+ FIELD(UART0_REF_CTRL, DIVISOR0, 8, 10)
+ FIELD(UART0_REF_CTRL, SRCSEL, 0, 3)
+REG32(UART1_REF_CTRL, 0x12c)
+ FIELD(UART1_REF_CTRL, CLKACT, 25, 1)
+ FIELD(UART1_REF_CTRL, DIVISOR0, 8, 10)
+ FIELD(UART1_REF_CTRL, SRCSEL, 0, 3)
+REG32(SPI0_REF_CTRL, 0x130)
+ FIELD(SPI0_REF_CTRL, CLKACT, 25, 1)
+ FIELD(SPI0_REF_CTRL, DIVISOR0, 8, 10)
+ FIELD(SPI0_REF_CTRL, SRCSEL, 0, 3)
+REG32(SPI1_REF_CTRL, 0x134)
+ FIELD(SPI1_REF_CTRL, CLKACT, 25, 1)
+ FIELD(SPI1_REF_CTRL, DIVISOR0, 8, 10)
+ FIELD(SPI1_REF_CTRL, SRCSEL, 0, 3)
+REG32(CAN0_REF_CTRL, 0x138)
+ FIELD(CAN0_REF_CTRL, CLKACT, 25, 1)
+ FIELD(CAN0_REF_CTRL, DIVISOR0, 8, 10)
+ FIELD(CAN0_REF_CTRL, SRCSEL, 0, 3)
+REG32(CAN1_REF_CTRL, 0x13c)
+ FIELD(CAN1_REF_CTRL, CLKACT, 25, 1)
+ FIELD(CAN1_REF_CTRL, DIVISOR0, 8, 10)
+ FIELD(CAN1_REF_CTRL, SRCSEL, 0, 3)
+REG32(I2C0_REF_CTRL, 0x140)
+ FIELD(I2C0_REF_CTRL, CLKACT, 25, 1)
+ FIELD(I2C0_REF_CTRL, DIVISOR0, 8, 10)
+ FIELD(I2C0_REF_CTRL, SRCSEL, 0, 3)
+REG32(I2C1_REF_CTRL, 0x144)
+ FIELD(I2C1_REF_CTRL, CLKACT, 25, 1)
+ FIELD(I2C1_REF_CTRL, DIVISOR0, 8, 10)
+ FIELD(I2C1_REF_CTRL, SRCSEL, 0, 3)
+REG32(DBG_LPD_CTRL, 0x148)
+ FIELD(DBG_LPD_CTRL, CLKACT, 25, 1)
+ FIELD(DBG_LPD_CTRL, DIVISOR0, 8, 10)
+ FIELD(DBG_LPD_CTRL, SRCSEL, 0, 3)
+REG32(TIMESTAMP_REF_CTRL, 0x14c)
+ FIELD(TIMESTAMP_REF_CTRL, CLKACT, 25, 1)
+ FIELD(TIMESTAMP_REF_CTRL, DIVISOR0, 8, 10)
+ FIELD(TIMESTAMP_REF_CTRL, SRCSEL, 0, 3)
+REG32(CRL_SAFETY_CHK, 0x150)
+REG32(PSM_REF_CTRL, 0x154)
+ FIELD(PSM_REF_CTRL, DIVISOR0, 8, 10)
+ FIELD(PSM_REF_CTRL, SRCSEL, 0, 3)
+REG32(DBG_TSTMP_CTRL, 0x158)
+ FIELD(DBG_TSTMP_CTRL, CLKACT, 25, 1)
+ FIELD(DBG_TSTMP_CTRL, DIVISOR0, 8, 10)
+ FIELD(DBG_TSTMP_CTRL, SRCSEL, 0, 3)
+REG32(CPM_TOPSW_REF_CTRL, 0x15c)
+ FIELD(CPM_TOPSW_REF_CTRL, CLKACT, 25, 1)
+ FIELD(CPM_TOPSW_REF_CTRL, DIVISOR0, 8, 10)
+ FIELD(CPM_TOPSW_REF_CTRL, SRCSEL, 0, 3)
+REG32(USB3_DUAL_REF_CTRL, 0x160)
+ FIELD(USB3_DUAL_REF_CTRL, CLKACT, 25, 1)
+ FIELD(USB3_DUAL_REF_CTRL, DIVISOR0, 8, 10)
+ FIELD(USB3_DUAL_REF_CTRL, SRCSEL, 0, 3)
+REG32(RST_CPU_R5, 0x300)
+ FIELD(RST_CPU_R5, RESET_PGE, 4, 1)
+ FIELD(RST_CPU_R5, RESET_AMBA, 2, 1)
+ FIELD(RST_CPU_R5, RESET_CPU1, 1, 1)
+ FIELD(RST_CPU_R5, RESET_CPU0, 0, 1)
+REG32(RST_ADMA, 0x304)
+ FIELD(RST_ADMA, RESET, 0, 1)
+REG32(RST_GEM0, 0x308)
+ FIELD(RST_GEM0, RESET, 0, 1)
+REG32(RST_GEM1, 0x30c)
+ FIELD(RST_GEM1, RESET, 0, 1)
+REG32(RST_SPARE, 0x310)
+ FIELD(RST_SPARE, RESET, 0, 1)
+REG32(RST_USB0, 0x314)
+ FIELD(RST_USB0, RESET, 0, 1)
+REG32(RST_UART0, 0x318)
+ FIELD(RST_UART0, RESET, 0, 1)
+REG32(RST_UART1, 0x31c)
+ FIELD(RST_UART1, RESET, 0, 1)
+REG32(RST_SPI0, 0x320)
+ FIELD(RST_SPI0, RESET, 0, 1)
+REG32(RST_SPI1, 0x324)
+ FIELD(RST_SPI1, RESET, 0, 1)
+REG32(RST_CAN0, 0x328)
+ FIELD(RST_CAN0, RESET, 0, 1)
+REG32(RST_CAN1, 0x32c)
+ FIELD(RST_CAN1, RESET, 0, 1)
+REG32(RST_I2C0, 0x330)
+ FIELD(RST_I2C0, RESET, 0, 1)
+REG32(RST_I2C1, 0x334)
+ FIELD(RST_I2C1, RESET, 0, 1)
+REG32(RST_DBG_LPD, 0x338)
+ FIELD(RST_DBG_LPD, RPU_DBG1_RESET, 5, 1)
+ FIELD(RST_DBG_LPD, RPU_DBG0_RESET, 4, 1)
+ FIELD(RST_DBG_LPD, RESET_HSDP, 1, 1)
+ FIELD(RST_DBG_LPD, RESET, 0, 1)
+REG32(RST_GPIO, 0x33c)
+ FIELD(RST_GPIO, RESET, 0, 1)
+REG32(RST_TTC, 0x344)
+ FIELD(RST_TTC, TTC3_RESET, 3, 1)
+ FIELD(RST_TTC, TTC2_RESET, 2, 1)
+ FIELD(RST_TTC, TTC1_RESET, 1, 1)
+ FIELD(RST_TTC, TTC0_RESET, 0, 1)
+REG32(RST_TIMESTAMP, 0x348)
+ FIELD(RST_TIMESTAMP, RESET, 0, 1)
+REG32(RST_SWDT, 0x34c)
+ FIELD(RST_SWDT, RESET, 0, 1)
+REG32(RST_OCM, 0x350)
+ FIELD(RST_OCM, RESET, 0, 1)
+REG32(RST_IPI, 0x354)
+ FIELD(RST_IPI, RESET, 0, 1)
+REG32(RST_SYSMON, 0x358)
+ FIELD(RST_SYSMON, SEQ_RST, 1, 1)
+ FIELD(RST_SYSMON, CFG_RST, 0, 1)
+REG32(RST_FPD, 0x360)
+ FIELD(RST_FPD, SRST, 1, 1)
+ FIELD(RST_FPD, POR, 0, 1)
+REG32(PSM_RST_MODE, 0x370)
+ FIELD(PSM_RST_MODE, WAKEUP, 2, 1)
+ FIELD(PSM_RST_MODE, RST_MODE, 0, 2)
+
+#define CRL_R_MAX (R_PSM_RST_MODE + 1)
+
+#define RPU_MAX_CPU 2
+
+struct XlnxVersalCRL {
+ SysBusDevice parent_obj;
+ qemu_irq irq;
+
+ struct {
+ ARMCPU *cpu_r5[RPU_MAX_CPU];
+ DeviceState *adma[8];
+ DeviceState *uart[2];
+ DeviceState *gem[2];
+ DeviceState *usb;
+ } cfg;
+
+ RegisterInfoArray *reg_array;
+ uint32_t regs[CRL_R_MAX];
+ RegisterInfo regs_info[CRL_R_MAX];
+};
+#endif
diff --git a/include/hw/misc/xlnx-versal-pmc-iou-slcr.h b/include/hw/misc/xlnx-versal-pmc-iou-slcr.h
new file mode 100644
index 0000000000..0c4a4fd66d
--- /dev/null
+++ b/include/hw/misc/xlnx-versal-pmc-iou-slcr.h
@@ -0,0 +1,79 @@
+/*
+ * Header file for the Xilinx Versal's PMC IOU SLCR
+ *
+ * Copyright (C) 2021 Xilinx Inc
+ * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
+ *
+ * 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.
+ */
+
+/*
+ * This is a model of Xilinx Versal's PMC I/O Peripheral Control and Status
+ * module documented in Versal's Technical Reference manual [1] and the Versal
+ * ACAP Register reference [2].
+ *
+ * References:
+ *
+ * [1] Versal ACAP Technical Reference Manual,
+ * https://www.xilinx.com/support/documentation/architecture-manuals/am011-versal-acap-trm.pdf
+ *
+ * [2] Versal ACAP Register Reference,
+ * https://docs.xilinx.com/r/en-US/am012-versal-register-reference/PMC_IOP_SLCR-Module
+ *
+ * QEMU interface:
+ * + sysbus MMIO region 0: MemoryRegion for the device's registers
+ * + sysbus IRQ 0: PMC (AXI and APB) parity error interrupt detected by the PMC
+ * I/O peripherals.
+ * + sysbus IRQ 1: Device interrupt.
+ * + Named GPIO output "sd-emmc-sel[0]": Enables 0: SD mode or 1: eMMC mode on
+ * SD/eMMC controller 0.
+ * + Named GPIO output "sd-emmc-sel[1]": Enables 0: SD mode or 1: eMMC mode on
+ * SD/eMMC controller 1.
+ * + Named GPIO output "qspi-ospi-mux-sel": Selects 0: QSPI linear region or 1:
+ * OSPI linear region.
+ * + Named GPIO output "ospi-mux-sel": Selects 0: OSPI Indirect access mode or
+ * 1: OSPI direct access mode.
+ */
+
+#ifndef XLNX_VERSAL_PMC_IOU_SLCR_H
+#define XLNX_VERSAL_PMC_IOU_SLCR_H
+
+#include "hw/sysbus.h"
+#include "hw/register.h"
+
+#define TYPE_XILINX_VERSAL_PMC_IOU_SLCR "xlnx.versal-pmc-iou-slcr"
+
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalPmcIouSlcr, XILINX_VERSAL_PMC_IOU_SLCR)
+
+#define XILINX_VERSAL_PMC_IOU_SLCR_R_MAX (0x828 / 4 + 1)
+
+struct XlnxVersalPmcIouSlcr {
+ SysBusDevice parent_obj;
+ MemoryRegion iomem;
+ qemu_irq irq_parity_imr;
+ qemu_irq irq_imr;
+ qemu_irq sd_emmc_sel[2];
+ qemu_irq qspi_ospi_mux_sel;
+ qemu_irq ospi_mux_sel;
+
+ uint32_t regs[XILINX_VERSAL_PMC_IOU_SLCR_R_MAX];
+ RegisterInfo regs_info[XILINX_VERSAL_PMC_IOU_SLCR_R_MAX];
+};
+
+#endif /* XLNX_VERSAL_PMC_IOU_SLCR_H */
diff --git a/include/hw/misc/xlnx-versal-trng.h b/include/hw/misc/xlnx-versal-trng.h
new file mode 100644
index 0000000000..0bcef8a613
--- /dev/null
+++ b/include/hw/misc/xlnx-versal-trng.h
@@ -0,0 +1,58 @@
+/*
+ * Non-crypto strength model of the True Random Number Generator
+ * in the AMD/Xilinx Versal device family.
+ *
+ * Copyright (c) 2017-2020 Xilinx Inc.
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ *
+ * 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.
+ */
+#ifndef XLNX_VERSAL_TRNG_H
+#define XLNX_VERSAL_TRNG_H
+
+#include "hw/irq.h"
+#include "hw/sysbus.h"
+#include "hw/register.h"
+
+#define TYPE_XLNX_VERSAL_TRNG "xlnx.versal-trng"
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalTRng, XLNX_VERSAL_TRNG);
+
+#define RMAX_XLNX_VERSAL_TRNG ((0xf0 / 4) + 1)
+
+typedef struct XlnxVersalTRng {
+ SysBusDevice parent_obj;
+ qemu_irq irq;
+ GRand *prng;
+
+ uint32_t hw_version;
+ uint32_t forced_faults;
+
+ uint32_t rand_count;
+ uint64_t rand_reseed;
+
+ uint64_t forced_prng_seed;
+ uint64_t forced_prng_count;
+ uint64_t tst_seed[2];
+
+ uint32_t regs[RMAX_XLNX_VERSAL_TRNG];
+ RegisterInfo regs_info[RMAX_XLNX_VERSAL_TRNG];
+} XlnxVersalTRng;
+
+#undef RMAX_XLNX_VERSAL_TRNG
+#endif
diff --git a/include/hw/misc/xlnx-versal-xramc.h b/include/hw/misc/xlnx-versal-xramc.h
new file mode 100644
index 0000000000..d3d1862676
--- /dev/null
+++ b/include/hw/misc/xlnx-versal-xramc.h
@@ -0,0 +1,97 @@
+/*
+ * QEMU model of the Xilinx XRAM Controller.
+ *
+ * Copyright (c) 2021 Xilinx Inc.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
+ */
+
+#ifndef XLNX_VERSAL_XRAMC_H
+#define XLNX_VERSAL_XRAMC_H
+
+#include "hw/sysbus.h"
+#include "hw/register.h"
+
+#define TYPE_XLNX_XRAM_CTRL "xlnx.versal-xramc"
+
+#define XLNX_XRAM_CTRL(obj) \
+ OBJECT_CHECK(XlnxXramCtrl, (obj), TYPE_XLNX_XRAM_CTRL)
+
+REG32(XRAM_ERR_CTRL, 0x0)
+ FIELD(XRAM_ERR_CTRL, UE_RES, 3, 1)
+ FIELD(XRAM_ERR_CTRL, PWR_ERR_RES, 2, 1)
+ FIELD(XRAM_ERR_CTRL, PZ_ERR_RES, 1, 1)
+ FIELD(XRAM_ERR_CTRL, APB_ERR_RES, 0, 1)
+REG32(XRAM_ISR, 0x4)
+ FIELD(XRAM_ISR, INV_APB, 0, 1)
+REG32(XRAM_IMR, 0x8)
+ FIELD(XRAM_IMR, INV_APB, 0, 1)
+REG32(XRAM_IEN, 0xc)
+ FIELD(XRAM_IEN, INV_APB, 0, 1)
+REG32(XRAM_IDS, 0x10)
+ FIELD(XRAM_IDS, INV_APB, 0, 1)
+REG32(XRAM_ECC_CNTL, 0x14)
+ FIELD(XRAM_ECC_CNTL, FI_MODE, 2, 1)
+ FIELD(XRAM_ECC_CNTL, DET_ONLY, 1, 1)
+ FIELD(XRAM_ECC_CNTL, ECC_ON_OFF, 0, 1)
+REG32(XRAM_CLR_EXE, 0x18)
+ FIELD(XRAM_CLR_EXE, MON_7, 7, 1)
+ FIELD(XRAM_CLR_EXE, MON_6, 6, 1)
+ FIELD(XRAM_CLR_EXE, MON_5, 5, 1)
+ FIELD(XRAM_CLR_EXE, MON_4, 4, 1)
+ FIELD(XRAM_CLR_EXE, MON_3, 3, 1)
+ FIELD(XRAM_CLR_EXE, MON_2, 2, 1)
+ FIELD(XRAM_CLR_EXE, MON_1, 1, 1)
+ FIELD(XRAM_CLR_EXE, MON_0, 0, 1)
+REG32(XRAM_CE_FFA, 0x1c)
+ FIELD(XRAM_CE_FFA, ADDR, 0, 20)
+REG32(XRAM_CE_FFD0, 0x20)
+REG32(XRAM_CE_FFD1, 0x24)
+REG32(XRAM_CE_FFD2, 0x28)
+REG32(XRAM_CE_FFD3, 0x2c)
+REG32(XRAM_CE_FFE, 0x30)
+ FIELD(XRAM_CE_FFE, SYNDROME, 0, 16)
+REG32(XRAM_UE_FFA, 0x34)
+ FIELD(XRAM_UE_FFA, ADDR, 0, 20)
+REG32(XRAM_UE_FFD0, 0x38)
+REG32(XRAM_UE_FFD1, 0x3c)
+REG32(XRAM_UE_FFD2, 0x40)
+REG32(XRAM_UE_FFD3, 0x44)
+REG32(XRAM_UE_FFE, 0x48)
+ FIELD(XRAM_UE_FFE, SYNDROME, 0, 16)
+REG32(XRAM_FI_D0, 0x4c)
+REG32(XRAM_FI_D1, 0x50)
+REG32(XRAM_FI_D2, 0x54)
+REG32(XRAM_FI_D3, 0x58)
+REG32(XRAM_FI_SY, 0x5c)
+ FIELD(XRAM_FI_SY, DATA, 0, 16)
+REG32(XRAM_RMW_UE_FFA, 0x70)
+ FIELD(XRAM_RMW_UE_FFA, ADDR, 0, 20)
+REG32(XRAM_FI_CNTR, 0x74)
+ FIELD(XRAM_FI_CNTR, COUNT, 0, 24)
+REG32(XRAM_IMP, 0x80)
+ FIELD(XRAM_IMP, SIZE, 0, 4)
+REG32(XRAM_PRDY_DBG, 0x84)
+ FIELD(XRAM_PRDY_DBG, ISLAND3, 12, 4)
+ FIELD(XRAM_PRDY_DBG, ISLAND2, 8, 4)
+ FIELD(XRAM_PRDY_DBG, ISLAND1, 4, 4)
+ FIELD(XRAM_PRDY_DBG, ISLAND0, 0, 4)
+REG32(XRAM_SAFETY_CHK, 0xff8)
+
+#define XRAM_CTRL_R_MAX (R_XRAM_SAFETY_CHK + 1)
+
+typedef struct XlnxXramCtrl {
+ SysBusDevice parent_obj;
+ MemoryRegion ram;
+ qemu_irq irq;
+
+ struct {
+ uint64_t size;
+ unsigned int encoded_size;
+ } cfg;
+
+ RegisterInfoArray *reg_array;
+ uint32_t regs[XRAM_CTRL_R_MAX];
+ RegisterInfo regs_info[XRAM_CTRL_R_MAX];
+} XlnxXramCtrl;
+#endif
diff --git a/include/hw/misc/xlnx-zynqmp-apu-ctrl.h b/include/hw/misc/xlnx-zynqmp-apu-ctrl.h
new file mode 100644
index 0000000000..c3bf3c1583
--- /dev/null
+++ b/include/hw/misc/xlnx-zynqmp-apu-ctrl.h
@@ -0,0 +1,93 @@
+/*
+ * QEMU model of ZynqMP APU Control.
+ *
+ * Copyright (c) 2013-2022 Xilinx Inc
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Written by Peter Crosthwaite <peter.crosthwaite@xilinx.com> and
+ * Edgar E. Iglesias <edgar.iglesias@xilinx.com>
+ *
+ */
+#ifndef HW_MISC_XLNX_ZYNQMP_APU_CTRL_H
+#define HW_MISC_XLNX_ZYNQMP_APU_CTRL_H
+
+#include "hw/sysbus.h"
+#include "hw/register.h"
+#include "target/arm/cpu-qom.h"
+
+#define TYPE_XLNX_ZYNQMP_APU_CTRL "xlnx.apu-ctrl"
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPAPUCtrl, XLNX_ZYNQMP_APU_CTRL)
+
+REG32(APU_ERR_CTRL, 0x0)
+ FIELD(APU_ERR_CTRL, PSLVERR, 0, 1)
+REG32(ISR, 0x10)
+ FIELD(ISR, INV_APB, 0, 1)
+REG32(IMR, 0x14)
+ FIELD(IMR, INV_APB, 0, 1)
+REG32(IEN, 0x18)
+ FIELD(IEN, INV_APB, 0, 1)
+REG32(IDS, 0x1c)
+ FIELD(IDS, INV_APB, 0, 1)
+REG32(CONFIG_0, 0x20)
+ FIELD(CONFIG_0, CFGTE, 24, 4)
+ FIELD(CONFIG_0, CFGEND, 16, 4)
+ FIELD(CONFIG_0, VINITHI, 8, 4)
+ FIELD(CONFIG_0, AA64NAA32, 0, 4)
+REG32(CONFIG_1, 0x24)
+ FIELD(CONFIG_1, L2RSTDISABLE, 29, 1)
+ FIELD(CONFIG_1, L1RSTDISABLE, 28, 1)
+ FIELD(CONFIG_1, CP15DISABLE, 0, 4)
+REG32(RVBARADDR0L, 0x40)
+ FIELD(RVBARADDR0L, ADDR, 2, 30)
+REG32(RVBARADDR0H, 0x44)
+ FIELD(RVBARADDR0H, ADDR, 0, 8)
+REG32(RVBARADDR1L, 0x48)
+ FIELD(RVBARADDR1L, ADDR, 2, 30)
+REG32(RVBARADDR1H, 0x4c)
+ FIELD(RVBARADDR1H, ADDR, 0, 8)
+REG32(RVBARADDR2L, 0x50)
+ FIELD(RVBARADDR2L, ADDR, 2, 30)
+REG32(RVBARADDR2H, 0x54)
+ FIELD(RVBARADDR2H, ADDR, 0, 8)
+REG32(RVBARADDR3L, 0x58)
+ FIELD(RVBARADDR3L, ADDR, 2, 30)
+REG32(RVBARADDR3H, 0x5c)
+ FIELD(RVBARADDR3H, ADDR, 0, 8)
+REG32(ACE_CTRL, 0x60)
+ FIELD(ACE_CTRL, AWQOS, 16, 4)
+ FIELD(ACE_CTRL, ARQOS, 0, 4)
+REG32(SNOOP_CTRL, 0x80)
+ FIELD(SNOOP_CTRL, ACE_INACT, 4, 1)
+ FIELD(SNOOP_CTRL, ACP_INACT, 0, 1)
+REG32(PWRCTL, 0x90)
+ FIELD(PWRCTL, CLREXMONREQ, 17, 1)
+ FIELD(PWRCTL, L2FLUSHREQ, 16, 1)
+ FIELD(PWRCTL, CPUPWRDWNREQ, 0, 4)
+REG32(PWRSTAT, 0x94)
+ FIELD(PWRSTAT, CLREXMONACK, 17, 1)
+ FIELD(PWRSTAT, L2FLUSHDONE, 16, 1)
+ FIELD(PWRSTAT, DBGNOPWRDWN, 0, 4)
+
+#define APU_R_MAX ((R_PWRSTAT) + 1)
+
+#define APU_MAX_CPU 4
+
+struct XlnxZynqMPAPUCtrl {
+ SysBusDevice busdev;
+
+ ARMCPU *cpus[APU_MAX_CPU];
+ /* WFIs towards PMU. */
+ qemu_irq wfi_out[4];
+ /* CPU Power status towards INTC Redirect. */
+ qemu_irq cpu_power_status[4];
+ qemu_irq irq_imr;
+
+ uint8_t cpu_pwrdwn_req;
+ uint8_t cpu_in_wfi;
+
+ RegisterInfoArray *reg_array;
+ uint32_t regs[APU_R_MAX];
+ RegisterInfo regs_info[APU_R_MAX];
+};
+
+#endif
diff --git a/include/hw/misc/xlnx-zynqmp-crf.h b/include/hw/misc/xlnx-zynqmp-crf.h
new file mode 100644
index 0000000000..02ef0bdeee
--- /dev/null
+++ b/include/hw/misc/xlnx-zynqmp-crf.h
@@ -0,0 +1,211 @@
+/*
+ * QEMU model of the CRF - Clock Reset FPD.
+ *
+ * Copyright (c) 2022 Xilinx Inc.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
+ */
+#ifndef HW_MISC_XLNX_ZYNQMP_CRF_H
+#define HW_MISC_XLNX_ZYNQMP_CRF_H
+
+#include "hw/sysbus.h"
+#include "hw/register.h"
+
+#define TYPE_XLNX_ZYNQMP_CRF "xlnx.zynqmp_crf"
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPCRF, XLNX_ZYNQMP_CRF)
+
+REG32(ERR_CTRL, 0x0)
+ FIELD(ERR_CTRL, SLVERR_ENABLE, 0, 1)
+REG32(IR_STATUS, 0x4)
+ FIELD(IR_STATUS, ADDR_DECODE_ERR, 0, 1)
+REG32(IR_MASK, 0x8)
+ FIELD(IR_MASK, ADDR_DECODE_ERR, 0, 1)
+REG32(IR_ENABLE, 0xc)
+ FIELD(IR_ENABLE, ADDR_DECODE_ERR, 0, 1)
+REG32(IR_DISABLE, 0x10)
+ FIELD(IR_DISABLE, ADDR_DECODE_ERR, 0, 1)
+REG32(CRF_WPROT, 0x1c)
+ FIELD(CRF_WPROT, ACTIVE, 0, 1)
+REG32(APLL_CTRL, 0x20)
+ FIELD(APLL_CTRL, POST_SRC, 24, 3)
+ FIELD(APLL_CTRL, PRE_SRC, 20, 3)
+ FIELD(APLL_CTRL, CLKOUTDIV, 17, 1)
+ FIELD(APLL_CTRL, DIV2, 16, 1)
+ FIELD(APLL_CTRL, FBDIV, 8, 7)
+ FIELD(APLL_CTRL, BYPASS, 3, 1)
+ FIELD(APLL_CTRL, RESET, 0, 1)
+REG32(APLL_CFG, 0x24)
+ FIELD(APLL_CFG, LOCK_DLY, 25, 7)
+ FIELD(APLL_CFG, LOCK_CNT, 13, 10)
+ FIELD(APLL_CFG, LFHF, 10, 2)
+ FIELD(APLL_CFG, CP, 5, 4)
+ FIELD(APLL_CFG, RES, 0, 4)
+REG32(APLL_FRAC_CFG, 0x28)
+ FIELD(APLL_FRAC_CFG, ENABLED, 31, 1)
+ FIELD(APLL_FRAC_CFG, SEED, 22, 3)
+ FIELD(APLL_FRAC_CFG, ALGRTHM, 19, 1)
+ FIELD(APLL_FRAC_CFG, ORDER, 18, 1)
+ FIELD(APLL_FRAC_CFG, DATA, 0, 16)
+REG32(DPLL_CTRL, 0x2c)
+ FIELD(DPLL_CTRL, POST_SRC, 24, 3)
+ FIELD(DPLL_CTRL, PRE_SRC, 20, 3)
+ FIELD(DPLL_CTRL, CLKOUTDIV, 17, 1)
+ FIELD(DPLL_CTRL, DIV2, 16, 1)
+ FIELD(DPLL_CTRL, FBDIV, 8, 7)
+ FIELD(DPLL_CTRL, BYPASS, 3, 1)
+ FIELD(DPLL_CTRL, RESET, 0, 1)
+REG32(DPLL_CFG, 0x30)
+ FIELD(DPLL_CFG, LOCK_DLY, 25, 7)
+ FIELD(DPLL_CFG, LOCK_CNT, 13, 10)
+ FIELD(DPLL_CFG, LFHF, 10, 2)
+ FIELD(DPLL_CFG, CP, 5, 4)
+ FIELD(DPLL_CFG, RES, 0, 4)
+REG32(DPLL_FRAC_CFG, 0x34)
+ FIELD(DPLL_FRAC_CFG, ENABLED, 31, 1)
+ FIELD(DPLL_FRAC_CFG, SEED, 22, 3)
+ FIELD(DPLL_FRAC_CFG, ALGRTHM, 19, 1)
+ FIELD(DPLL_FRAC_CFG, ORDER, 18, 1)
+ FIELD(DPLL_FRAC_CFG, DATA, 0, 16)
+REG32(VPLL_CTRL, 0x38)
+ FIELD(VPLL_CTRL, POST_SRC, 24, 3)
+ FIELD(VPLL_CTRL, PRE_SRC, 20, 3)
+ FIELD(VPLL_CTRL, CLKOUTDIV, 17, 1)
+ FIELD(VPLL_CTRL, DIV2, 16, 1)
+ FIELD(VPLL_CTRL, FBDIV, 8, 7)
+ FIELD(VPLL_CTRL, BYPASS, 3, 1)
+ FIELD(VPLL_CTRL, RESET, 0, 1)
+REG32(VPLL_CFG, 0x3c)
+ FIELD(VPLL_CFG, LOCK_DLY, 25, 7)
+ FIELD(VPLL_CFG, LOCK_CNT, 13, 10)
+ FIELD(VPLL_CFG, LFHF, 10, 2)
+ FIELD(VPLL_CFG, CP, 5, 4)
+ FIELD(VPLL_CFG, RES, 0, 4)
+REG32(VPLL_FRAC_CFG, 0x40)
+ FIELD(VPLL_FRAC_CFG, ENABLED, 31, 1)
+ FIELD(VPLL_FRAC_CFG, SEED, 22, 3)
+ FIELD(VPLL_FRAC_CFG, ALGRTHM, 19, 1)
+ FIELD(VPLL_FRAC_CFG, ORDER, 18, 1)
+ FIELD(VPLL_FRAC_CFG, DATA, 0, 16)
+REG32(PLL_STATUS, 0x44)
+ FIELD(PLL_STATUS, VPLL_STABLE, 5, 1)
+ FIELD(PLL_STATUS, DPLL_STABLE, 4, 1)
+ FIELD(PLL_STATUS, APLL_STABLE, 3, 1)
+ FIELD(PLL_STATUS, VPLL_LOCK, 2, 1)
+ FIELD(PLL_STATUS, DPLL_LOCK, 1, 1)
+ FIELD(PLL_STATUS, APLL_LOCK, 0, 1)
+REG32(APLL_TO_LPD_CTRL, 0x48)
+ FIELD(APLL_TO_LPD_CTRL, DIVISOR0, 8, 6)
+REG32(DPLL_TO_LPD_CTRL, 0x4c)
+ FIELD(DPLL_TO_LPD_CTRL, DIVISOR0, 8, 6)
+REG32(VPLL_TO_LPD_CTRL, 0x50)
+ FIELD(VPLL_TO_LPD_CTRL, DIVISOR0, 8, 6)
+REG32(ACPU_CTRL, 0x60)
+ FIELD(ACPU_CTRL, CLKACT_HALF, 25, 1)
+ FIELD(ACPU_CTRL, CLKACT_FULL, 24, 1)
+ FIELD(ACPU_CTRL, DIVISOR0, 8, 6)
+ FIELD(ACPU_CTRL, SRCSEL, 0, 3)
+REG32(DBG_TRACE_CTRL, 0x64)
+ FIELD(DBG_TRACE_CTRL, CLKACT, 24, 1)
+ FIELD(DBG_TRACE_CTRL, DIVISOR0, 8, 6)
+ FIELD(DBG_TRACE_CTRL, SRCSEL, 0, 3)
+REG32(DBG_FPD_CTRL, 0x68)
+ FIELD(DBG_FPD_CTRL, CLKACT, 24, 1)
+ FIELD(DBG_FPD_CTRL, DIVISOR0, 8, 6)
+ FIELD(DBG_FPD_CTRL, SRCSEL, 0, 3)
+REG32(DP_VIDEO_REF_CTRL, 0x70)
+ FIELD(DP_VIDEO_REF_CTRL, CLKACT, 24, 1)
+ FIELD(DP_VIDEO_REF_CTRL, DIVISOR1, 16, 6)
+ FIELD(DP_VIDEO_REF_CTRL, DIVISOR0, 8, 6)
+ FIELD(DP_VIDEO_REF_CTRL, SRCSEL, 0, 3)
+REG32(DP_AUDIO_REF_CTRL, 0x74)
+ FIELD(DP_AUDIO_REF_CTRL, CLKACT, 24, 1)
+ FIELD(DP_AUDIO_REF_CTRL, DIVISOR1, 16, 6)
+ FIELD(DP_AUDIO_REF_CTRL, DIVISOR0, 8, 6)
+ FIELD(DP_AUDIO_REF_CTRL, SRCSEL, 0, 3)
+REG32(DP_STC_REF_CTRL, 0x7c)
+ FIELD(DP_STC_REF_CTRL, CLKACT, 24, 1)
+ FIELD(DP_STC_REF_CTRL, DIVISOR1, 16, 6)
+ FIELD(DP_STC_REF_CTRL, DIVISOR0, 8, 6)
+ FIELD(DP_STC_REF_CTRL, SRCSEL, 0, 3)
+REG32(DDR_CTRL, 0x80)
+ FIELD(DDR_CTRL, CLKACT, 24, 1)
+ FIELD(DDR_CTRL, DIVISOR0, 8, 6)
+ FIELD(DDR_CTRL, SRCSEL, 0, 3)
+REG32(GPU_REF_CTRL, 0x84)
+ FIELD(GPU_REF_CTRL, PP1_CLKACT, 26, 1)
+ FIELD(GPU_REF_CTRL, PP0_CLKACT, 25, 1)
+ FIELD(GPU_REF_CTRL, CLKACT, 24, 1)
+ FIELD(GPU_REF_CTRL, DIVISOR0, 8, 6)
+ FIELD(GPU_REF_CTRL, SRCSEL, 0, 3)
+REG32(SATA_REF_CTRL, 0xa0)
+ FIELD(SATA_REF_CTRL, CLKACT, 24, 1)
+ FIELD(SATA_REF_CTRL, DIVISOR0, 8, 6)
+ FIELD(SATA_REF_CTRL, SRCSEL, 0, 3)
+REG32(PCIE_REF_CTRL, 0xb4)
+ FIELD(PCIE_REF_CTRL, CLKACT, 24, 1)
+ FIELD(PCIE_REF_CTRL, DIVISOR0, 8, 6)
+ FIELD(PCIE_REF_CTRL, SRCSEL, 0, 3)
+REG32(GDMA_REF_CTRL, 0xb8)
+ FIELD(GDMA_REF_CTRL, CLKACT, 24, 1)
+ FIELD(GDMA_REF_CTRL, DIVISOR0, 8, 6)
+ FIELD(GDMA_REF_CTRL, SRCSEL, 0, 3)
+REG32(DPDMA_REF_CTRL, 0xbc)
+ FIELD(DPDMA_REF_CTRL, CLKACT, 24, 1)
+ FIELD(DPDMA_REF_CTRL, DIVISOR0, 8, 6)
+ FIELD(DPDMA_REF_CTRL, SRCSEL, 0, 3)
+REG32(TOPSW_MAIN_CTRL, 0xc0)
+ FIELD(TOPSW_MAIN_CTRL, CLKACT, 24, 1)
+ FIELD(TOPSW_MAIN_CTRL, DIVISOR0, 8, 6)
+ FIELD(TOPSW_MAIN_CTRL, SRCSEL, 0, 3)
+REG32(TOPSW_LSBUS_CTRL, 0xc4)
+ FIELD(TOPSW_LSBUS_CTRL, CLKACT, 24, 1)
+ FIELD(TOPSW_LSBUS_CTRL, DIVISOR0, 8, 6)
+ FIELD(TOPSW_LSBUS_CTRL, SRCSEL, 0, 3)
+REG32(DBG_TSTMP_CTRL, 0xf8)
+ FIELD(DBG_TSTMP_CTRL, DIVISOR0, 8, 6)
+ FIELD(DBG_TSTMP_CTRL, SRCSEL, 0, 3)
+REG32(RST_FPD_TOP, 0x100)
+ FIELD(RST_FPD_TOP, PCIE_CFG_RESET, 19, 1)
+ FIELD(RST_FPD_TOP, PCIE_BRIDGE_RESET, 18, 1)
+ FIELD(RST_FPD_TOP, PCIE_CTRL_RESET, 17, 1)
+ FIELD(RST_FPD_TOP, DP_RESET, 16, 1)
+ FIELD(RST_FPD_TOP, SWDT_RESET, 15, 1)
+ FIELD(RST_FPD_TOP, AFI_FM5_RESET, 12, 1)
+ FIELD(RST_FPD_TOP, AFI_FM4_RESET, 11, 1)
+ FIELD(RST_FPD_TOP, AFI_FM3_RESET, 10, 1)
+ FIELD(RST_FPD_TOP, AFI_FM2_RESET, 9, 1)
+ FIELD(RST_FPD_TOP, AFI_FM1_RESET, 8, 1)
+ FIELD(RST_FPD_TOP, AFI_FM0_RESET, 7, 1)
+ FIELD(RST_FPD_TOP, GDMA_RESET, 6, 1)
+ FIELD(RST_FPD_TOP, GPU_PP1_RESET, 5, 1)
+ FIELD(RST_FPD_TOP, GPU_PP0_RESET, 4, 1)
+ FIELD(RST_FPD_TOP, GPU_RESET, 3, 1)
+ FIELD(RST_FPD_TOP, GT_RESET, 2, 1)
+ FIELD(RST_FPD_TOP, SATA_RESET, 1, 1)
+REG32(RST_FPD_APU, 0x104)
+ FIELD(RST_FPD_APU, ACPU3_PWRON_RESET, 13, 1)
+ FIELD(RST_FPD_APU, ACPU2_PWRON_RESET, 12, 1)
+ FIELD(RST_FPD_APU, ACPU1_PWRON_RESET, 11, 1)
+ FIELD(RST_FPD_APU, ACPU0_PWRON_RESET, 10, 1)
+ FIELD(RST_FPD_APU, APU_L2_RESET, 8, 1)
+ FIELD(RST_FPD_APU, ACPU3_RESET, 3, 1)
+ FIELD(RST_FPD_APU, ACPU2_RESET, 2, 1)
+ FIELD(RST_FPD_APU, ACPU1_RESET, 1, 1)
+ FIELD(RST_FPD_APU, ACPU0_RESET, 0, 1)
+REG32(RST_DDR_SS, 0x108)
+ FIELD(RST_DDR_SS, DDR_RESET, 3, 1)
+ FIELD(RST_DDR_SS, APM_RESET, 2, 1)
+
+#define CRF_R_MAX (R_RST_DDR_SS + 1)
+
+struct XlnxZynqMPCRF {
+ SysBusDevice parent_obj;
+ MemoryRegion iomem;
+ qemu_irq irq_ir;
+
+ RegisterInfoArray *reg_array;
+ uint32_t regs[CRF_R_MAX];
+ RegisterInfo regs_info[CRF_R_MAX];
+};
+
+#endif
diff --git a/include/hw/net/allwinner-sun8i-emac.h b/include/hw/net/allwinner-sun8i-emac.h
index eda034e96b..185895f4e1 100644
--- a/include/hw/net/allwinner-sun8i-emac.h
+++ b/include/hw/net/allwinner-sun8i-emac.h
@@ -30,15 +30,14 @@
*/
#define TYPE_AW_SUN8I_EMAC "allwinner-sun8i-emac"
-#define AW_SUN8I_EMAC(obj) \
- OBJECT_CHECK(AwSun8iEmacState, (obj), TYPE_AW_SUN8I_EMAC)
+OBJECT_DECLARE_SIMPLE_TYPE(AwSun8iEmacState, AW_SUN8I_EMAC)
/** @} */
/**
* Allwinner Sun8i EMAC object instance state
*/
-typedef struct AwSun8iEmacState {
+struct AwSun8iEmacState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -49,6 +48,12 @@ typedef struct AwSun8iEmacState {
/** Interrupt output signal to notify CPU */
qemu_irq irq;
+ /** Memory region where DMA transfers are done */
+ MemoryRegion *dma_mr;
+
+ /** Address space used internally for DMA transfers */
+ AddressSpace dma_as;
+
/** Generic Network Interface Controller (NIC) for networking API */
NICState *nic;
@@ -94,6 +99,6 @@ typedef struct AwSun8iEmacState {
/** @} */
-} AwSun8iEmacState;
+};
-#endif /* HW_NET_ALLWINNER_SUN8I_H */
+#endif /* HW_NET_ALLWINNER_SUN8I_EMAC_H */
diff --git a/include/hw/net/allwinner_emac.h b/include/hw/net/allwinner_emac.h
index 5013207d15..534e748982 100644
--- a/include/hw/net/allwinner_emac.h
+++ b/include/hw/net/allwinner_emac.h
@@ -28,9 +28,10 @@
#include "qemu/fifo8.h"
#include "hw/net/mii.h"
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_AW_EMAC "allwinner-emac"
-#define AW_EMAC(obj) OBJECT_CHECK(AwEmacState, (obj), TYPE_AW_EMAC)
+OBJECT_DECLARE_SIMPLE_TYPE(AwEmacState, AW_EMAC)
/*
* Allwinner EMAC register list
@@ -144,7 +145,7 @@ typedef struct RTL8201CPState {
uint16_t anlpar;
} RTL8201CPState;
-typedef struct AwEmacState {
+struct AwEmacState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -171,6 +172,6 @@ typedef struct AwEmacState {
Fifo8 tx_fifo[NUM_TX_FIFOS];
uint32_t tx_length[NUM_TX_FIFOS];
uint32_t tx_channel;
-} AwEmacState;
+};
#endif
diff --git a/include/hw/net/cadence_gem.h b/include/hw/net/cadence_gem.h
index 54e646ff79..91ebb5c8ae 100644
--- a/include/hw/net/cadence_gem.h
+++ b/include/hw/net/cadence_gem.h
@@ -24,9 +24,10 @@
#ifndef CADENCE_GEM_H
#define CADENCE_GEM_H
+#include "qom/object.h"
#define TYPE_CADENCE_GEM "cadence_gem"
-#define CADENCE_GEM(obj) OBJECT_CHECK(CadenceGEMState, (obj), TYPE_CADENCE_GEM)
+OBJECT_DECLARE_SIMPLE_TYPE(CadenceGEMState, CADENCE_GEM)
#include "net/net.h"
#include "hw/sysbus.h"
@@ -43,7 +44,7 @@
#define MAX_JUMBO_FRAME_SIZE_MASK 0x3FFF
#define MAX_FRAME_SIZE MAX_JUMBO_FRAME_SIZE_MASK
-typedef struct CadenceGEMState {
+struct CadenceGEMState {
/*< private >*/
SysBusDevice parent_obj;
@@ -73,6 +74,8 @@ typedef struct CadenceGEMState {
/* Mask of register bits which are write 1 to clear */
uint32_t regs_w1c[CADENCE_GEM_MAXREG];
+ /* PHY address */
+ uint8_t phy_addr;
/* PHY registers backing store */
uint16_t phy_regs[32];
@@ -89,6 +92,6 @@ typedef struct CadenceGEMState {
uint32_t rx_desc[MAX_PRIORITY_QUEUES][DESC_MAX_NUM_WORDS];
bool sar_active[4];
-} CadenceGEMState;
+};
#endif
diff --git a/include/hw/net/dp8393x.h b/include/hw/net/dp8393x.h
new file mode 100644
index 0000000000..4a3f7478be
--- /dev/null
+++ b/include/hw/net/dp8393x.h
@@ -0,0 +1,60 @@
+/*
+ * QEMU NS SONIC DP8393x netcard
+ *
+ * Copyright (c) 2008-2009 Herve Poussineau
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_NET_DP8393X_H
+#define HW_NET_DP8393X_H
+
+#include "hw/sysbus.h"
+#include "net/net.h"
+#include "exec/memory.h"
+
+#define SONIC_REG_COUNT 0x40
+
+#define TYPE_DP8393X "dp8393x"
+OBJECT_DECLARE_SIMPLE_TYPE(dp8393xState, DP8393X)
+
+struct dp8393xState {
+ SysBusDevice parent_obj;
+
+ /* Hardware */
+ uint8_t it_shift;
+ bool big_endian;
+ bool last_rba_is_full;
+ qemu_irq irq;
+ int irq_level;
+ QEMUTimer *watchdog;
+ int64_t wt_last_update;
+ NICConf conf;
+ NICState *nic;
+ MemoryRegion mmio;
+
+ /* Registers */
+ uint16_t cam[16][3];
+ uint16_t regs[SONIC_REG_COUNT];
+
+ /* Temporaries */
+ uint8_t tx_buffer[0x10000];
+ int loopback_packet;
+
+ /* Memory access */
+ MemoryRegion *dma_mr;
+ AddressSpace as;
+};
+
+#endif
diff --git a/include/hw/net/ftgmac100.h b/include/hw/net/ftgmac100.h
index ab37e7b2b8..765d1538a4 100644
--- a/include/hw/net/ftgmac100.h
+++ b/include/hw/net/ftgmac100.h
@@ -9,9 +9,10 @@
#ifndef FTGMAC100_H
#define FTGMAC100_H
+#include "qom/object.h"
#define TYPE_FTGMAC100 "ftgmac100"
-#define FTGMAC100(obj) OBJECT_CHECK(FTGMAC100State, (obj), TYPE_FTGMAC100)
+OBJECT_DECLARE_SIMPLE_TYPE(FTGMAC100State, FTGMAC100)
#include "hw/sysbus.h"
#include "net/net.h"
@@ -21,7 +22,7 @@
*/
#define FTGMAC100_MAX_FRAME_SIZE 9220
-typedef struct FTGMAC100State {
+struct FTGMAC100State {
/*< private >*/
SysBusDevice parent_obj;
@@ -64,15 +65,15 @@ typedef struct FTGMAC100State {
bool aspeed;
uint32_t txdes0_edotr;
uint32_t rxdes0_edorr;
-} FTGMAC100State;
+};
#define TYPE_ASPEED_MII "aspeed-mmi"
-#define ASPEED_MII(obj) OBJECT_CHECK(AspeedMiiState, (obj), TYPE_ASPEED_MII)
+OBJECT_DECLARE_SIMPLE_TYPE(AspeedMiiState, ASPEED_MII)
/*
* AST2600 MII controller
*/
-typedef struct AspeedMiiState {
+struct AspeedMiiState {
/*< private >*/
SysBusDevice parent_obj;
@@ -81,6 +82,6 @@ typedef struct AspeedMiiState {
MemoryRegion iomem;
uint32_t phycr;
uint32_t phydata;
-} AspeedMiiState;
+};
#endif
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
index 9f03034b89..2d13290c78 100644
--- a/include/hw/net/imx_fec.h
+++ b/include/hw/net/imx_fec.h
@@ -23,9 +23,10 @@
#ifndef IMX_FEC_H
#define IMX_FEC_H
+#include "qom/object.h"
#define TYPE_IMX_FEC "imx.fec"
-#define IMX_FEC(obj) OBJECT_CHECK(IMXFECState, (obj), TYPE_IMX_FEC)
+OBJECT_DECLARE_SIMPLE_TYPE(IMXFECState, IMX_FEC)
#define TYPE_IMX_ENET "imx.enet"
@@ -247,7 +248,7 @@ typedef struct {
#define FSL_IMX25_FEC_SIZE 0x4000
-typedef struct IMXFECState {
+struct IMXFECState {
/*< private >*/
SysBusDevice parent_obj;
@@ -269,11 +270,13 @@ typedef struct IMXFECState {
uint32_t phy_int;
uint32_t phy_int_mask;
uint32_t phy_num;
+ bool phy_connected;
+ struct IMXFECState *phy_consumer;
bool is_fec;
/* Buffer used to assemble a Tx frame */
uint8_t frame[ENET_MAX_FRAME_SIZE];
-} IMXFECState;
+};
#endif
diff --git a/include/hw/net/lan9118.h b/include/hw/net/lan9118.h
index 3d0c67f339..4bf9da7a63 100644
--- a/include/hw/net/lan9118.h
+++ b/include/hw/net/lan9118.h
@@ -15,6 +15,6 @@
#define TYPE_LAN9118 "lan9118"
-void lan9118_init(NICInfo *, uint32_t, qemu_irq);
+void lan9118_init(uint32_t, qemu_irq);
#endif
diff --git a/include/hw/net/lance.h b/include/hw/net/lance.h
index 0357f5f65c..f645d6af67 100644
--- a/include/hw/net/lance.h
+++ b/include/hw/net/lance.h
@@ -32,15 +32,17 @@
#include "net/net.h"
#include "hw/net/pcnet.h"
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_LANCE "lance"
-#define SYSBUS_PCNET(obj) \
- OBJECT_CHECK(SysBusPCNetState, (obj), TYPE_LANCE)
+typedef struct SysBusPCNetState SysBusPCNetState;
+DECLARE_INSTANCE_CHECKER(SysBusPCNetState, SYSBUS_PCNET,
+ TYPE_LANCE)
-typedef struct {
+struct SysBusPCNetState {
SysBusDevice parent_obj;
PCNetState state;
-} SysBusPCNetState;
+};
#endif
diff --git a/include/hw/net/lasi_82596.h b/include/hw/net/lasi_82596.h
index e76ef8308e..439356ec19 100644
--- a/include/hw/net/lasi_82596.h
+++ b/include/hw/net/lasi_82596.h
@@ -10,20 +10,22 @@
#include "net/net.h"
#include "hw/net/i82596.h"
+#include "hw/sysbus.h"
#define TYPE_LASI_82596 "lasi_82596"
-#define SYSBUS_I82596(obj) \
- OBJECT_CHECK(SysBusI82596State, (obj), TYPE_LASI_82596)
+typedef struct SysBusI82596State SysBusI82596State;
+DECLARE_INSTANCE_CHECKER(SysBusI82596State, SYSBUS_I82596,
+ TYPE_LASI_82596)
-typedef struct {
+struct SysBusI82596State {
SysBusDevice parent_obj;
I82596State state;
uint16_t last_val;
int val_index:1;
-} SysBusI82596State;
+};
-SysBusI82596State *lasi_82596_init(MemoryRegion *addr_space,
- hwaddr hpa, qemu_irq irq);
+SysBusI82596State *lasi_82596_init(MemoryRegion *addr_space, hwaddr hpa,
+ qemu_irq irq, gboolean match_default);
#endif
diff --git a/include/hw/net/mii.h b/include/hw/net/mii.h
index 4ae4dcce7e..f7feddac9b 100644
--- a/include/hw/net/mii.h
+++ b/include/hw/net/mii.h
@@ -55,6 +55,7 @@
#define MII_BMCR_CTST (1 << 7) /* Collision test */
#define MII_BMCR_SPEED1000 (1 << 6) /* MSB of Speed (1000) */
+#define MII_BMSR_100T4 (1 << 15) /* Can do 100mbps T4 */
#define MII_BMSR_100TX_FD (1 << 14) /* Can do 100mbps, full-duplex */
#define MII_BMSR_100TX_HD (1 << 13) /* Can do 100mbps, half-duplex */
#define MII_BMSR_10T_FD (1 << 12) /* Can do 10mbps, full-duplex */
@@ -70,7 +71,7 @@
#define MII_BMSR_JABBER (1 << 1) /* Jabber detected */
#define MII_BMSR_EXTCAP (1 << 0) /* Ext-reg capability */
-#define MII_ANAR_PAUSE_ASYM (1 << 11) /* Try for asymetric pause */
+#define MII_ANAR_PAUSE_ASYM (1 << 11) /* Try for asymmetric pause */
#define MII_ANAR_PAUSE (1 << 10) /* Try for pause */
#define MII_ANAR_TXFD (1 << 8)
#define MII_ANAR_TX (1 << 7)
@@ -81,20 +82,31 @@
#define MII_ANLPAR_ACK (1 << 14)
#define MII_ANLPAR_PAUSEASY (1 << 11) /* can pause asymmetrically */
#define MII_ANLPAR_PAUSE (1 << 10) /* can pause */
+#define MII_ANLPAR_T4 (1 << 9)
#define MII_ANLPAR_TXFD (1 << 8)
#define MII_ANLPAR_TX (1 << 7)
#define MII_ANLPAR_10FD (1 << 6)
#define MII_ANLPAR_10 (1 << 5)
#define MII_ANLPAR_CSMACD (1 << 0)
-#define MII_ANER_NWAY (1 << 0) /* Can do N-way auto-nego */
+#define MII_ANER_NP (1 << 2) /* Next Page Able */
+#define MII_ANER_NWAY (1 << 0) /* Can do N-way auto-nego */
+#define MII_ANNP_MP (1 << 13) /* Message Page */
+
+#define MII_CTRL1000_MASTER (1 << 11) /* MASTER-SLAVE Manual Configuration Value */
+#define MII_CTRL1000_PORT (1 << 10) /* T2_Repeater/DTE bit */
#define MII_CTRL1000_FULL (1 << 9) /* 1000BASE-T full duplex */
#define MII_CTRL1000_HALF (1 << 8) /* 1000BASE-T half duplex */
+#define MII_STAT1000_LOK (1 << 13) /* Local Receiver Status */
+#define MII_STAT1000_ROK (1 << 12) /* Remote Receiver Status */
#define MII_STAT1000_FULL (1 << 11) /* 1000BASE-T full duplex */
#define MII_STAT1000_HALF (1 << 10) /* 1000BASE-T half duplex */
+#define MII_EXTSTAT_1000T_FD (1 << 13) /* 1000BASE-T Full Duplex */
+#define MII_EXTSTAT_1000T_HD (1 << 12) /* 1000BASE-T Half Duplex */
+
/* List of vendor identifiers */
/* RealTek 8201 */
#define RTL8201CP_PHYID1 0x0000
diff --git a/include/hw/net/msf2-emac.h b/include/hw/net/msf2-emac.h
index 37966d3a81..846ba6e6dc 100644
--- a/include/hw/net/msf2-emac.h
+++ b/include/hw/net/msf2-emac.h
@@ -26,15 +26,15 @@
#include "exec/memory.h"
#include "net/net.h"
#include "net/eth.h"
+#include "qom/object.h"
#define TYPE_MSS_EMAC "msf2-emac"
-#define MSS_EMAC(obj) \
- OBJECT_CHECK(MSF2EmacState, (obj), TYPE_MSS_EMAC)
+OBJECT_DECLARE_SIMPLE_TYPE(MSF2EmacState, MSS_EMAC)
#define R_MAX (0x1a0 / 4)
#define PHY_MAX_REGS 32
-typedef struct MSF2EmacState {
+struct MSF2EmacState {
SysBusDevice parent;
MemoryRegion mmio;
@@ -50,4 +50,4 @@ typedef struct MSF2EmacState {
uint16_t phy_regs[PHY_MAX_REGS];
uint32_t regs[R_MAX];
-} MSF2EmacState;
+};
diff --git a/include/hw/net/mv88w8618_eth.h b/include/hw/net/mv88w8618_eth.h
new file mode 100644
index 0000000000..41074940ec
--- /dev/null
+++ b/include/hw/net/mv88w8618_eth.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Marvell MV88W8618 / Freecom MusicPal emulation.
+ *
+ * Copyright (c) 2008-2021 QEMU contributors
+ */
+
+#ifndef HW_NET_MV88W8618_ETH_H
+#define HW_NET_MV88W8618_ETH_H
+
+#define TYPE_MV88W8618_ETH "mv88w8618_eth"
+
+#endif
diff --git a/include/hw/net/ne2000-isa.h b/include/hw/net/ne2000-isa.h
index af59ee0b02..73bae10ad1 100644
--- a/include/hw/net/ne2000-isa.h
+++ b/include/hw/net/ne2000-isa.h
@@ -22,8 +22,6 @@ static inline ISADevice *isa_ne2000_init(ISABus *bus, int base, int irq,
{
ISADevice *d;
- qemu_check_nic_model(nd, "ne2k_isa");
-
d = isa_try_new(TYPE_ISA_NE2000);
if (d) {
DeviceState *dev = DEVICE(d);
diff --git a/include/hw/net/npcm7xx_emc.h b/include/hw/net/npcm7xx_emc.h
new file mode 100644
index 0000000000..b789007160
--- /dev/null
+++ b/include/hw/net/npcm7xx_emc.h
@@ -0,0 +1,283 @@
+/*
+ * Nuvoton NPCM7xx EMC Module
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef NPCM7XX_EMC_H
+#define NPCM7XX_EMC_H
+
+#include "hw/irq.h"
+#include "hw/sysbus.h"
+#include "net/net.h"
+
+/* 32-bit register indices. */
+enum NPCM7xxPWMRegister {
+ /* Control registers. */
+ REG_CAMCMR,
+ REG_CAMEN,
+
+ /* There are 16 CAMn[ML] registers. */
+ REG_CAMM_BASE,
+ REG_CAML_BASE,
+ REG_CAMML_LAST = 0x21,
+
+ REG_TXDLSA = 0x22,
+ REG_RXDLSA,
+ REG_MCMDR,
+ REG_MIID,
+ REG_MIIDA,
+ REG_FFTCR,
+ REG_TSDR,
+ REG_RSDR,
+ REG_DMARFC,
+ REG_MIEN,
+
+ /* Status registers. */
+ REG_MISTA,
+ REG_MGSTA,
+ REG_MPCNT,
+ REG_MRPC,
+ REG_MRPCC,
+ REG_MREPC,
+ REG_DMARFS,
+ REG_CTXDSA,
+ REG_CTXBSA,
+ REG_CRXDSA,
+ REG_CRXBSA,
+
+ NPCM7XX_NUM_EMC_REGS,
+};
+
+/* REG_CAMCMR fields */
+/* Enable CAM Compare */
+#define REG_CAMCMR_ECMP (1 << 4)
+/* Complement CAM Compare */
+#define REG_CAMCMR_CCAM (1 << 3)
+/* Accept Broadcast Packet */
+#define REG_CAMCMR_ABP (1 << 2)
+/* Accept Multicast Packet */
+#define REG_CAMCMR_AMP (1 << 1)
+/* Accept Unicast Packet */
+#define REG_CAMCMR_AUP (1 << 0)
+
+/* REG_MCMDR fields */
+/* Software Reset */
+#define REG_MCMDR_SWR (1 << 24)
+/* Internal Loopback Select */
+#define REG_MCMDR_LBK (1 << 21)
+/* Operation Mode Select */
+#define REG_MCMDR_OPMOD (1 << 20)
+/* Enable MDC Clock Generation */
+#define REG_MCMDR_ENMDC (1 << 19)
+/* Full-Duplex Mode Select */
+#define REG_MCMDR_FDUP (1 << 18)
+/* Enable SQE Checking */
+#define REG_MCMDR_ENSEQ (1 << 17)
+/* Send PAUSE Frame */
+#define REG_MCMDR_SDPZ (1 << 16)
+/* No Defer */
+#define REG_MCMDR_NDEF (1 << 9)
+/* Frame Transmission On */
+#define REG_MCMDR_TXON (1 << 8)
+/* Strip CRC Checksum */
+#define REG_MCMDR_SPCRC (1 << 5)
+/* Accept CRC Error Packet */
+#define REG_MCMDR_AEP (1 << 4)
+/* Accept Control Packet */
+#define REG_MCMDR_ACP (1 << 3)
+/* Accept Runt Packet */
+#define REG_MCMDR_ARP (1 << 2)
+/* Accept Long Packet */
+#define REG_MCMDR_ALP (1 << 1)
+/* Frame Reception On */
+#define REG_MCMDR_RXON (1 << 0)
+
+/* REG_MIEN fields */
+/* Enable Transmit Descriptor Unavailable Interrupt */
+#define REG_MIEN_ENTDU (1 << 23)
+/* Enable Transmit Completion Interrupt */
+#define REG_MIEN_ENTXCP (1 << 18)
+/* Enable Transmit Interrupt */
+#define REG_MIEN_ENTXINTR (1 << 16)
+/* Enable Receive Descriptor Unavailable Interrupt */
+#define REG_MIEN_ENRDU (1 << 10)
+/* Enable Receive Good Interrupt */
+#define REG_MIEN_ENRXGD (1 << 4)
+/* Enable Receive Interrupt */
+#define REG_MIEN_ENRXINTR (1 << 0)
+
+/* REG_MISTA fields */
+/* TODO: Add error fields and support simulated errors? */
+/* Transmit Bus Error Interrupt */
+#define REG_MISTA_TXBERR (1 << 24)
+/* Transmit Descriptor Unavailable Interrupt */
+#define REG_MISTA_TDU (1 << 23)
+/* Transmit Completion Interrupt */
+#define REG_MISTA_TXCP (1 << 18)
+/* Transmit Interrupt */
+#define REG_MISTA_TXINTR (1 << 16)
+/* Receive Bus Error Interrupt */
+#define REG_MISTA_RXBERR (1 << 11)
+/* Receive Descriptor Unavailable Interrupt */
+#define REG_MISTA_RDU (1 << 10)
+/* DMA Early Notification Interrupt */
+#define REG_MISTA_DENI (1 << 9)
+/* Maximum Frame Length Interrupt */
+#define REG_MISTA_DFOI (1 << 8)
+/* Receive Good Interrupt */
+#define REG_MISTA_RXGD (1 << 4)
+/* Packet Too Long Interrupt */
+#define REG_MISTA_PTLE (1 << 3)
+/* Receive Interrupt */
+#define REG_MISTA_RXINTR (1 << 0)
+
+/* REG_MGSTA fields */
+/* Transmission Halted */
+#define REG_MGSTA_TXHA (1 << 11)
+/* Receive Halted */
+#define REG_MGSTA_RXHA (1 << 11)
+
+/* REG_DMARFC fields */
+/* Maximum Receive Frame Length */
+#define REG_DMARFC_RXMS(word) extract32((word), 0, 16)
+
+/* REG MIIDA fields */
+/* Busy Bit */
+#define REG_MIIDA_BUSY (1 << 17)
+
+/* Transmit and receive descriptors */
+typedef struct NPCM7xxEMCTxDesc NPCM7xxEMCTxDesc;
+typedef struct NPCM7xxEMCRxDesc NPCM7xxEMCRxDesc;
+
+struct NPCM7xxEMCTxDesc {
+ uint32_t flags;
+ uint32_t txbsa;
+ uint32_t status_and_length;
+ uint32_t ntxdsa;
+};
+
+struct NPCM7xxEMCRxDesc {
+ uint32_t status_and_length;
+ uint32_t rxbsa;
+ uint32_t reserved;
+ uint32_t nrxdsa;
+};
+
+/* NPCM7xxEMCTxDesc.flags values */
+/* Owner: 0 = cpu, 1 = emc */
+#define TX_DESC_FLAG_OWNER_MASK (1 << 31)
+/* Transmit interrupt enable */
+#define TX_DESC_FLAG_INTEN (1 << 2)
+/* CRC append */
+#define TX_DESC_FLAG_CRCAPP (1 << 1)
+/* Padding enable */
+#define TX_DESC_FLAG_PADEN (1 << 0)
+
+/* NPCM7xxEMCTxDesc.status_and_length values */
+/* Collision count */
+#define TX_DESC_STATUS_CCNT_SHIFT 28
+#define TX_DESC_STATUS_CCNT_BITSIZE 4
+/* SQE error */
+#define TX_DESC_STATUS_SQE (1 << 26)
+/* Transmission paused */
+#define TX_DESC_STATUS_PAU (1 << 25)
+/* P transmission halted */
+#define TX_DESC_STATUS_TXHA (1 << 24)
+/* Late collision */
+#define TX_DESC_STATUS_LC (1 << 23)
+/* Transmission abort */
+#define TX_DESC_STATUS_TXABT (1 << 22)
+/* No carrier sense */
+#define TX_DESC_STATUS_NCS (1 << 21)
+/* Defer exceed */
+#define TX_DESC_STATUS_EXDEF (1 << 20)
+/* Transmission complete */
+#define TX_DESC_STATUS_TXCP (1 << 19)
+/* Transmission deferred */
+#define TX_DESC_STATUS_DEF (1 << 17)
+/* Transmit interrupt */
+#define TX_DESC_STATUS_TXINTR (1 << 16)
+
+#define TX_DESC_PKT_LEN(word) extract32((word), 0, 16)
+
+/* Transmit buffer start address */
+#define TX_DESC_TXBSA(word) ((uint32_t) (word) & ~3u)
+
+/* Next transmit descriptor start address */
+#define TX_DESC_NTXDSA(word) ((uint32_t) (word) & ~3u)
+
+/* NPCM7xxEMCRxDesc.status_and_length values */
+/* Owner: 0b00 = cpu, 0b01 = undefined, 0b10 = emc, 0b11 = undefined */
+#define RX_DESC_STATUS_OWNER_SHIFT 30
+#define RX_DESC_STATUS_OWNER_BITSIZE 2
+#define RX_DESC_STATUS_OWNER_MASK (3 << RX_DESC_STATUS_OWNER_SHIFT)
+/* Runt packet */
+#define RX_DESC_STATUS_RP (1 << 22)
+/* Alignment error */
+#define RX_DESC_STATUS_ALIE (1 << 21)
+/* Frame reception complete */
+#define RX_DESC_STATUS_RXGD (1 << 20)
+/* Packet too long */
+#define RX_DESC_STATUS_PTLE (1 << 19)
+/* CRC error */
+#define RX_DESC_STATUS_CRCE (1 << 17)
+/* Receive interrupt */
+#define RX_DESC_STATUS_RXINTR (1 << 16)
+
+#define RX_DESC_PKT_LEN(word) extract32((word), 0, 16)
+
+/* Receive buffer start address */
+#define RX_DESC_RXBSA(word) ((uint32_t) (word) & ~3u)
+
+/* Next receive descriptor start address */
+#define RX_DESC_NRXDSA(word) ((uint32_t) (word) & ~3u)
+
+/* Minimum packet length, when TX_DESC_FLAG_PADEN is set. */
+#define MIN_PACKET_LENGTH 64
+
+struct NPCM7xxEMCState {
+ /*< private >*/
+ SysBusDevice parent;
+ /*< public >*/
+
+ MemoryRegion iomem;
+
+ qemu_irq tx_irq;
+ qemu_irq rx_irq;
+
+ NICState *nic;
+ NICConf conf;
+
+ /* 0 or 1, for log messages */
+ uint8_t emc_num;
+
+ uint32_t regs[NPCM7XX_NUM_EMC_REGS];
+
+ /*
+ * tx is active. Set to true by TSDR and then switches off when out of
+ * descriptors. If the TXON bit in REG_MCMDR is off then this is off.
+ */
+ bool tx_active;
+
+ /*
+ * rx is active. Set to true by RSDR and then switches off when out of
+ * descriptors. If the RXON bit in REG_MCMDR is off then this is off.
+ */
+ bool rx_active;
+};
+
+#define TYPE_NPCM7XX_EMC "npcm7xx-emc"
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxEMCState, NPCM7XX_EMC)
+
+#endif /* NPCM7XX_EMC_H */
diff --git a/include/hw/net/npcm_gmac.h b/include/hw/net/npcm_gmac.h
new file mode 100644
index 0000000000..6340ffe92c
--- /dev/null
+++ b/include/hw/net/npcm_gmac.h
@@ -0,0 +1,343 @@
+/*
+ * Nuvoton NPCM7xx/8xx GMAC Module
+ *
+ * Copyright 2024 Google LLC
+ * Authors:
+ * Hao Wu <wuhaotsh@google.com>
+ * Nabih Estefan <nabihestefan@google.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef NPCM_GMAC_H
+#define NPCM_GMAC_H
+
+#include "hw/irq.h"
+#include "hw/sysbus.h"
+#include "net/net.h"
+
+#define NPCM_GMAC_NR_REGS (0x1060 / sizeof(uint32_t))
+
+#define NPCM_GMAC_MAX_PHYS 32
+#define NPCM_GMAC_MAX_PHY_REGS 32
+
+struct NPCMGMACRxDesc {
+ uint32_t rdes0;
+ uint32_t rdes1;
+ uint32_t rdes2;
+ uint32_t rdes3;
+};
+
+/* NPCMGMACRxDesc.flags values */
+/* RDES2 and RDES3 are buffer addresses */
+/* Owner: 0 = software, 1 = dma */
+#define RX_DESC_RDES0_OWN BIT(31)
+/* Destination Address Filter Fail */
+#define RX_DESC_RDES0_DEST_ADDR_FILT_FAIL BIT(30)
+/* Frame length */
+#define RX_DESC_RDES0_FRAME_LEN_MASK(word) extract32(word, 16, 14)
+/* Frame length Shift*/
+#define RX_DESC_RDES0_FRAME_LEN_SHIFT 16
+/* Error Summary */
+#define RX_DESC_RDES0_ERR_SUMM_MASK BIT(15)
+/* Descriptor Error */
+#define RX_DESC_RDES0_DESC_ERR_MASK BIT(14)
+/* Source Address Filter Fail */
+#define RX_DESC_RDES0_SRC_ADDR_FILT_FAIL_MASK BIT(13)
+/* Length Error */
+#define RX_DESC_RDES0_LEN_ERR_MASK BIT(12)
+/* Overflow Error */
+#define RX_DESC_RDES0_OVRFLW_ERR_MASK BIT(11)
+/* VLAN Tag */
+#define RX_DESC_RDES0_VLAN_TAG_MASK BIT(10)
+/* First Descriptor */
+#define RX_DESC_RDES0_FIRST_DESC_MASK BIT(9)
+/* Last Descriptor */
+#define RX_DESC_RDES0_LAST_DESC_MASK BIT(8)
+/* IPC Checksum Error/Giant Frame */
+#define RX_DESC_RDES0_IPC_CHKSM_ERR_GNT_FRM_MASK BIT(7)
+/* Late Collision */
+#define RX_DESC_RDES0_LT_COLL_MASK BIT(6)
+/* Frame Type */
+#define RX_DESC_RDES0_FRM_TYPE_MASK BIT(5)
+/* Receive Watchdog Timeout */
+#define RX_DESC_RDES0_REC_WTCHDG_TMT_MASK BIT(4)
+/* Receive Error */
+#define RX_DESC_RDES0_RCV_ERR_MASK BIT(3)
+/* Dribble Bit Error */
+#define RX_DESC_RDES0_DRBL_BIT_ERR_MASK BIT(2)
+/* Cyclcic Redundancy Check Error */
+#define RX_DESC_RDES0_CRC_ERR_MASK BIT(1)
+/* Rx MAC Address/Payload Checksum Error */
+#define RC_DESC_RDES0_RCE_MASK BIT(0)
+
+/* Disable Interrupt on Completion */
+#define RX_DESC_RDES1_DIS_INTR_COMP_MASK BIT(31)
+/* Receive end of ring */
+#define RX_DESC_RDES1_RC_END_RING_MASK BIT(25)
+/* Second Address Chained */
+#define RX_DESC_RDES1_SEC_ADDR_CHND_MASK BIT(24)
+/* Receive Buffer 2 Size */
+#define RX_DESC_RDES1_BFFR2_SZ_SHIFT 11
+#define RX_DESC_RDES1_BFFR2_SZ_MASK(word) extract32(word, \
+ RX_DESC_RDES1_BFFR2_SZ_SHIFT, 11)
+/* Receive Buffer 1 Size */
+#define RX_DESC_RDES1_BFFR1_SZ_MASK(word) extract32(word, 0, 11)
+
+
+struct NPCMGMACTxDesc {
+ uint32_t tdes0;
+ uint32_t tdes1;
+ uint32_t tdes2;
+ uint32_t tdes3;
+};
+
+/* NPCMGMACTxDesc.flags values */
+/* TDES2 and TDES3 are buffer addresses */
+/* Owner: 0 = software, 1 = gmac */
+#define TX_DESC_TDES0_OWN BIT(31)
+/* Tx Time Stamp Status */
+#define TX_DESC_TDES0_TTSS_MASK BIT(17)
+/* IP Header Error */
+#define TX_DESC_TDES0_IP_HEAD_ERR_MASK BIT(16)
+/* Error Summary */
+#define TX_DESC_TDES0_ERR_SUMM_MASK BIT(15)
+/* Jabber Timeout */
+#define TX_DESC_TDES0_JBBR_TMT_MASK BIT(14)
+/* Frame Flushed */
+#define TX_DESC_TDES0_FRM_FLSHD_MASK BIT(13)
+/* Payload Checksum Error */
+#define TX_DESC_TDES0_PYLD_CHKSM_ERR_MASK BIT(12)
+/* Loss of Carrier */
+#define TX_DESC_TDES0_LSS_CARR_MASK BIT(11)
+/* No Carrier */
+#define TX_DESC_TDES0_NO_CARR_MASK BIT(10)
+/* Late Collision */
+#define TX_DESC_TDES0_LATE_COLL_MASK BIT(9)
+/* Excessive Collision */
+#define TX_DESC_TDES0_EXCS_COLL_MASK BIT(8)
+/* VLAN Frame */
+#define TX_DESC_TDES0_VLAN_FRM_MASK BIT(7)
+/* Collision Count */
+#define TX_DESC_TDES0_COLL_CNT_MASK(word) extract32(word, 3, 4)
+/* Excessive Deferral */
+#define TX_DESC_TDES0_EXCS_DEF_MASK BIT(2)
+/* Underflow Error */
+#define TX_DESC_TDES0_UNDRFLW_ERR_MASK BIT(1)
+/* Deferred Bit */
+#define TX_DESC_TDES0_DFRD_BIT_MASK BIT(0)
+
+/* Interrupt of Completion */
+#define TX_DESC_TDES1_INTERR_COMP_MASK BIT(31)
+/* Last Segment */
+#define TX_DESC_TDES1_LAST_SEG_MASK BIT(30)
+/* First Segment */
+#define TX_DESC_TDES1_FIRST_SEG_MASK BIT(29)
+/* Checksum Insertion Control */
+#define TX_DESC_TDES1_CHKSM_INS_CTRL_MASK(word) extract32(word, 27, 2)
+/* Disable Cyclic Redundancy Check */
+#define TX_DESC_TDES1_DIS_CDC_MASK BIT(26)
+/* Transmit End of Ring */
+#define TX_DESC_TDES1_TX_END_RING_MASK BIT(25)
+/* Secondary Address Chained */
+#define TX_DESC_TDES1_SEC_ADDR_CHND_MASK BIT(24)
+/* Transmit Buffer 2 Size */
+#define TX_DESC_TDES1_BFFR2_SZ_MASK(word) extract32(word, 11, 11)
+/* Transmit Buffer 1 Size */
+#define TX_DESC_TDES1_BFFR1_SZ_MASK(word) extract32(word, 0, 11)
+
+typedef struct NPCMGMACState {
+ SysBusDevice parent;
+
+ MemoryRegion iomem;
+ qemu_irq irq;
+
+ NICState *nic;
+ NICConf conf;
+
+ uint32_t regs[NPCM_GMAC_NR_REGS];
+ uint16_t phy_regs[NPCM_GMAC_MAX_PHYS][NPCM_GMAC_MAX_PHY_REGS];
+} NPCMGMACState;
+
+#define TYPE_NPCM_GMAC "npcm-gmac"
+OBJECT_DECLARE_SIMPLE_TYPE(NPCMGMACState, NPCM_GMAC)
+
+/* Mask for RO bits in Status */
+#define NPCM_DMA_STATUS_RO_MASK(word) (word & 0xfffe0000)
+/* Mask for RO bits in Status */
+#define NPCM_DMA_STATUS_W1C_MASK(word) (word & 0x1e7ff)
+
+/* Transmit Process State */
+#define NPCM_DMA_STATUS_TX_PROCESS_STATE_SHIFT 20
+/* Transmit States */
+#define NPCM_DMA_STATUS_TX_STOPPED_STATE \
+ (0b000)
+#define NPCM_DMA_STATUS_TX_RUNNING_FETCHING_STATE \
+ (0b001)
+#define NPCM_DMA_STATUS_TX_RUNNING_WAITING_STATE \
+ (0b010)
+#define NPCM_DMA_STATUS_TX_RUNNING_READ_STATE \
+ (0b011)
+#define NPCM_DMA_STATUS_TX_SUSPENDED_STATE \
+ (0b110)
+#define NPCM_DMA_STATUS_TX_RUNNING_CLOSING_STATE \
+ (0b111)
+/* Transmit Process State */
+#define NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT 17
+/* Receive States */
+#define NPCM_DMA_STATUS_RX_STOPPED_STATE \
+ (0b000)
+#define NPCM_DMA_STATUS_RX_RUNNING_FETCHING_STATE \
+ (0b001)
+#define NPCM_DMA_STATUS_RX_RUNNING_WAITING_STATE \
+ (0b011)
+#define NPCM_DMA_STATUS_RX_SUSPENDED_STATE \
+ (0b100)
+#define NPCM_DMA_STATUS_RX_RUNNING_CLOSING_STATE \
+ (0b101)
+#define NPCM_DMA_STATUS_RX_RUNNING_TRANSFERRING_STATE \
+ (0b111)
+
+
+/* Early Receive Interrupt */
+#define NPCM_DMA_STATUS_ERI BIT(14)
+/* Fatal Bus Error Interrupt */
+#define NPCM_DMA_STATUS_FBI BIT(13)
+/* Early transmit Interrupt */
+#define NPCM_DMA_STATUS_ETI BIT(10)
+/* Receive Watchdog Timeout */
+#define NPCM_DMA_STATUS_RWT BIT(9)
+/* Receive Process Stopped */
+#define NPCM_DMA_STATUS_RPS BIT(8)
+/* Receive Buffer Unavailable */
+#define NPCM_DMA_STATUS_RU BIT(7)
+/* Receive Interrupt */
+#define NPCM_DMA_STATUS_RI BIT(6)
+/* Transmit Underflow */
+#define NPCM_DMA_STATUS_UNF BIT(5)
+/* Receive Overflow */
+#define NPCM_DMA_STATUS_OVF BIT(4)
+/* Transmit Jabber Timeout */
+#define NPCM_DMA_STATUS_TJT BIT(3)
+/* Transmit Buffer Unavailable */
+#define NPCM_DMA_STATUS_TU BIT(2)
+/* Transmit Process Stopped */
+#define NPCM_DMA_STATUS_TPS BIT(1)
+/* Transmit Interrupt */
+#define NPCM_DMA_STATUS_TI BIT(0)
+
+/* Normal Interrupt Summary */
+#define NPCM_DMA_STATUS_NIS BIT(16)
+/* Interrupts enabled by NIE */
+#define NPCM_DMA_STATUS_NIS_BITS (NPCM_DMA_STATUS_TI | \
+ NPCM_DMA_STATUS_TU | \
+ NPCM_DMA_STATUS_RI | \
+ NPCM_DMA_STATUS_ERI)
+/* Abnormal Interrupt Summary */
+#define NPCM_DMA_STATUS_AIS BIT(15)
+/* Interrupts enabled by AIE */
+#define NPCM_DMA_STATUS_AIS_BITS (NPCM_DMA_STATUS_TPS | \
+ NPCM_DMA_STATUS_TJT | \
+ NPCM_DMA_STATUS_OVF | \
+ NPCM_DMA_STATUS_UNF | \
+ NPCM_DMA_STATUS_RU | \
+ NPCM_DMA_STATUS_RPS | \
+ NPCM_DMA_STATUS_RWT | \
+ NPCM_DMA_STATUS_ETI | \
+ NPCM_DMA_STATUS_FBI)
+
+/* Early Receive Interrupt Enable */
+#define NPCM_DMA_INTR_ENAB_ERE BIT(14)
+/* Fatal Bus Error Interrupt Enable */
+#define NPCM_DMA_INTR_ENAB_FBE BIT(13)
+/* Early transmit Interrupt Enable */
+#define NPCM_DMA_INTR_ENAB_ETE BIT(10)
+/* Receive Watchdog Timout Enable */
+#define NPCM_DMA_INTR_ENAB_RWE BIT(9)
+/* Receive Process Stopped Enable */
+#define NPCM_DMA_INTR_ENAB_RSE BIT(8)
+/* Receive Buffer Unavailable Enable */
+#define NPCM_DMA_INTR_ENAB_RUE BIT(7)
+/* Receive Interrupt Enable */
+#define NPCM_DMA_INTR_ENAB_RIE BIT(6)
+/* Transmit Underflow Enable */
+#define NPCM_DMA_INTR_ENAB_UNE BIT(5)
+/* Receive Overflow Enable */
+#define NPCM_DMA_INTR_ENAB_OVE BIT(4)
+/* Transmit Jabber Timeout Enable */
+#define NPCM_DMA_INTR_ENAB_TJE BIT(3)
+/* Transmit Buffer Unavailable Enable */
+#define NPCM_DMA_INTR_ENAB_TUE BIT(2)
+/* Transmit Process Stopped Enable */
+#define NPCM_DMA_INTR_ENAB_TSE BIT(1)
+/* Transmit Interrupt Enable */
+#define NPCM_DMA_INTR_ENAB_TIE BIT(0)
+
+/* Normal Interrupt Summary Enable */
+#define NPCM_DMA_INTR_ENAB_NIE BIT(16)
+/* Interrupts enabled by NIE Enable */
+#define NPCM_DMA_INTR_ENAB_NIE_BITS (NPCM_DMA_INTR_ENAB_TIE | \
+ NPCM_DMA_INTR_ENAB_TUE | \
+ NPCM_DMA_INTR_ENAB_RIE | \
+ NPCM_DMA_INTR_ENAB_ERE)
+/* Abnormal Interrupt Summary Enable */
+#define NPCM_DMA_INTR_ENAB_AIE BIT(15)
+/* Interrupts enabled by AIE Enable */
+#define NPCM_DMA_INTR_ENAB_AIE_BITS (NPCM_DMA_INTR_ENAB_TSE | \
+ NPCM_DMA_INTR_ENAB_TJE | \
+ NPCM_DMA_INTR_ENAB_OVE | \
+ NPCM_DMA_INTR_ENAB_UNE | \
+ NPCM_DMA_INTR_ENAB_RUE | \
+ NPCM_DMA_INTR_ENAB_RSE | \
+ NPCM_DMA_INTR_ENAB_RWE | \
+ NPCM_DMA_INTR_ENAB_ETE | \
+ NPCM_DMA_INTR_ENAB_FBE)
+
+/* Flushing Disabled */
+#define NPCM_DMA_CONTROL_FLUSH_MASK BIT(24)
+/* Start/stop Transmit */
+#define NPCM_DMA_CONTROL_START_STOP_TX BIT(13)
+/* Start/stop Receive */
+#define NPCM_DMA_CONTROL_START_STOP_RX BIT(1)
+/* Next receive descriptor start address */
+#define NPCM_DMA_HOST_RX_DESC_MASK(word) ((uint32_t) (word) & ~3u)
+/* Next transmit descriptor start address */
+#define NPCM_DMA_HOST_TX_DESC_MASK(word) ((uint32_t) (word) & ~3u)
+
+/* Receive enable */
+#define NPCM_GMAC_MAC_CONFIG_RX_EN BIT(2)
+/* Transmit enable */
+#define NPCM_GMAC_MAC_CONFIG_TX_EN BIT(3)
+
+/* Frame Receive All */
+#define NPCM_GMAC_FRAME_FILTER_REC_ALL_MASK BIT(31)
+/* Frame HPF Filter*/
+#define NPCM_GMAC_FRAME_FILTER_HPF_MASK BIT(10)
+/* Frame SAF Filter*/
+#define NPCM_GMAC_FRAME_FILTER_SAF_MASK BIT(9)
+/* Frame SAIF Filter*/
+#define NPCM_GMAC_FRAME_FILTER_SAIF_MASK BIT(8)
+/* Frame PCF Filter*/
+#define NPCM_GMAC_FRAME_FILTER_PCF_MASK BIT(word) extract32((word), 6, 2)
+/* Frame DBF Filter*/
+#define NPCM_GMAC_FRAME_FILTER_DBF_MASK BIT(5)
+/* Frame PM Filter*/
+#define NPCM_GMAC_FRAME_FILTER_PM_MASK BIT(4)
+/* Frame DAIF Filter*/
+#define NPCM_GMAC_FRAME_FILTER_DAIF_MASK BIT(3)
+/* Frame HMC Filter*/
+#define NPCM_GMAC_FRAME_FILTER_HMC_MASK BIT(2)
+/* Frame HUC Filter*/
+#define NPCM_GMAC_FRAME_FILTER_HUC_MASK BIT(1)
+/* Frame PR Filter*/
+#define NPCM_GMAC_FRAME_FILTER_PR_MASK BIT(0)
+
+#endif /* NPCM_GMAC_H */
diff --git a/include/hw/net/smc91c111.h b/include/hw/net/smc91c111.h
index df5b11dcef..dba32a233f 100644
--- a/include/hw/net/smc91c111.h
+++ b/include/hw/net/smc91c111.h
@@ -13,6 +13,6 @@
#include "net/net.h"
-void smc91c111_init(NICInfo *, uint32_t, qemu_irq);
+void smc91c111_init(uint32_t, qemu_irq);
#endif
diff --git a/include/hw/net/xlnx-versal-canfd.h b/include/hw/net/xlnx-versal-canfd.h
new file mode 100644
index 0000000000..ad3104dd13
--- /dev/null
+++ b/include/hw/net/xlnx-versal-canfd.h
@@ -0,0 +1,87 @@
+/*
+ * QEMU model of the Xilinx Versal CANFD Controller.
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ *
+ * Written-by: Vikram Garhwal<vikram.garhwal@amd.com>
+ * Based on QEMU CANFD Device emulation implemented by Jin Yang, Deniz Eren and
+ * Pavel Pisa.
+ * 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.
+ */
+
+#ifndef HW_CANFD_XILINX_H
+#define HW_CANFD_XILINX_H
+
+#include "hw/register.h"
+#include "hw/ptimer.h"
+#include "net/can_emu.h"
+#include "hw/qdev-clock.h"
+
+#define TYPE_XILINX_CANFD "xlnx.versal-canfd"
+
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCANFDState, XILINX_CANFD)
+
+#define NUM_REGS_PER_MSG_SPACE 18 /* 1 ID + 1 DLC + 16 Data(DW0 - DW15) regs. */
+#define MAX_NUM_RX 64
+#define OFFSET_RX1_DW15 (0x4144 / 4)
+#define CANFD_TIMER_MAX 0xFFFFUL
+#define CANFD_DEFAULT_CLOCK (25 * 1000 * 1000)
+
+#define XLNX_VERSAL_CANFD_R_MAX (OFFSET_RX1_DW15 + \
+ ((MAX_NUM_RX - 1) * NUM_REGS_PER_MSG_SPACE) + 1)
+
+typedef struct XlnxVersalCANFDState {
+ SysBusDevice parent_obj;
+ MemoryRegion iomem;
+
+ qemu_irq irq_canfd_int;
+ qemu_irq irq_addr_err;
+
+ RegisterInfo reg_info[XLNX_VERSAL_CANFD_R_MAX];
+ RegisterAccessInfo *tx_regs;
+ RegisterAccessInfo *rx0_regs;
+ RegisterAccessInfo *rx1_regs;
+ RegisterAccessInfo *af_regs;
+ RegisterAccessInfo *txe_regs;
+ RegisterAccessInfo *rx_mailbox_regs;
+ RegisterAccessInfo *af_mask_regs_mailbox;
+
+ uint32_t regs[XLNX_VERSAL_CANFD_R_MAX];
+
+ ptimer_state *canfd_timer;
+
+ CanBusClientState bus_client;
+ CanBusState *canfdbus;
+
+ struct {
+ uint8_t rx0_fifo;
+ uint8_t rx1_fifo;
+ uint8_t tx_fifo;
+ bool enable_rx_fifo1;
+ uint32_t ext_clk_freq;
+ } cfg;
+
+} XlnxVersalCANFDState;
+
+typedef struct tx_ready_reg_info {
+ uint32_t can_id;
+ uint32_t reg_num;
+} tx_ready_reg_info;
+
+#endif
diff --git a/include/hw/net/xlnx-zynqmp-can.h b/include/hw/net/xlnx-zynqmp-can.h
new file mode 100644
index 0000000000..fd2aa77760
--- /dev/null
+++ b/include/hw/net/xlnx-zynqmp-can.h
@@ -0,0 +1,79 @@
+/*
+ * QEMU model of the Xilinx ZynqMP CAN controller.
+ *
+ * Copyright (c) 2020 Xilinx Inc.
+ *
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
+ *
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
+ * Pavel Pisa.
+ *
+ * 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.
+ */
+
+#ifndef XLNX_ZYNQMP_CAN_H
+#define XLNX_ZYNQMP_CAN_H
+
+#include "hw/sysbus.h"
+#include "hw/register.h"
+#include "net/can_emu.h"
+#include "net/can_host.h"
+#include "qemu/fifo32.h"
+#include "hw/ptimer.h"
+#include "hw/qdev-clock.h"
+
+#define TYPE_XLNX_ZYNQMP_CAN "xlnx.zynqmp-can"
+
+#define XLNX_ZYNQMP_CAN(obj) \
+ OBJECT_CHECK(XlnxZynqMPCANState, (obj), TYPE_XLNX_ZYNQMP_CAN)
+
+#define MAX_CAN_CTRLS 2
+#define XLNX_ZYNQMP_CAN_R_MAX (0x84 / 4)
+#define MAILBOX_CAPACITY 64
+#define CAN_TIMER_MAX 0XFFFFUL
+#define CAN_DEFAULT_CLOCK (24 * 1000 * 1000)
+
+/* Each CAN_FRAME will have 4 * 32bit size. */
+#define CAN_FRAME_SIZE 4
+#define RXFIFO_SIZE (MAILBOX_CAPACITY * CAN_FRAME_SIZE)
+
+typedef struct XlnxZynqMPCANState {
+ SysBusDevice parent_obj;
+ MemoryRegion iomem;
+
+ qemu_irq irq;
+
+ CanBusClientState bus_client;
+ CanBusState *canbus;
+
+ struct {
+ uint32_t ext_clk_freq;
+ } cfg;
+
+ RegisterInfo reg_info[XLNX_ZYNQMP_CAN_R_MAX];
+ uint32_t regs[XLNX_ZYNQMP_CAN_R_MAX];
+
+ Fifo32 rx_fifo;
+ Fifo32 tx_fifo;
+ Fifo32 txhpb_fifo;
+
+ ptimer_state *can_timer;
+} XlnxZynqMPCANState;
+
+#endif
diff --git a/include/hw/nmi.h b/include/hw/nmi.h
index fe37ce3ad8..fff41bebc6 100644
--- a/include/hw/nmi.h
+++ b/include/hw/nmi.h
@@ -26,20 +26,19 @@
#define TYPE_NMI "nmi"
-#define NMI_CLASS(klass) \
- OBJECT_CLASS_CHECK(NMIClass, (klass), TYPE_NMI)
-#define NMI_GET_CLASS(obj) \
- OBJECT_GET_CLASS(NMIClass, (obj), TYPE_NMI)
+typedef struct NMIClass NMIClass;
+DECLARE_CLASS_CHECKERS(NMIClass, NMI,
+ TYPE_NMI)
#define NMI(obj) \
INTERFACE_CHECK(NMIState, (obj), TYPE_NMI)
typedef struct NMIState NMIState;
-typedef struct NMIClass {
+struct NMIClass {
InterfaceClass parent_class;
void (*nmi_monitor_handler)(NMIState *n, int cpu_index, Error **errp);
-} NMIClass;
+};
void nmi_monitor_handle(int cpu_index, Error **errp);
diff --git a/include/hw/nubus/mac-nubus-bridge.h b/include/hw/nubus/mac-nubus-bridge.h
index ce9c789d99..be4dd83530 100644
--- a/include/hw/nubus/mac-nubus-bridge.h
+++ b/include/hw/nubus/mac-nubus-bridge.h
@@ -6,19 +6,24 @@
*
*/
-#ifndef HW_NUBUS_MAC_H
-#define HW_NUBUS_MAC_H
+#ifndef HW_NUBUS_MAC_NUBUS_BRIDGE_H
+#define HW_NUBUS_MAC_NUBUS_BRIDGE_H
#include "hw/nubus/nubus.h"
+#include "qom/object.h"
+
+#define MAC_NUBUS_FIRST_SLOT 0x9
+#define MAC_NUBUS_LAST_SLOT 0xe
+#define MAC_NUBUS_SLOT_NB (MAC_NUBUS_LAST_SLOT - MAC_NUBUS_FIRST_SLOT + 1)
#define TYPE_MAC_NUBUS_BRIDGE "mac-nubus-bridge"
-#define MAC_NUBUS_BRIDGE(obj) OBJECT_CHECK(MacNubusState, (obj), \
- TYPE_MAC_NUBUS_BRIDGE)
+OBJECT_DECLARE_SIMPLE_TYPE(MacNubusBridge, MAC_NUBUS_BRIDGE)
-typedef struct MacNubusState {
- SysBusDevice sysbus_dev;
+struct MacNubusBridge {
+ NubusBridge parent_obj;
- NubusBus *bus;
-} MacNubusState;
+ MemoryRegion super_slot_alias;
+ MemoryRegion slot_alias;
+};
#endif
diff --git a/include/hw/nubus/nubus-virtio-mmio.h b/include/hw/nubus/nubus-virtio-mmio.h
new file mode 100644
index 0000000000..de497b7f76
--- /dev/null
+++ b/include/hw/nubus/nubus-virtio-mmio.h
@@ -0,0 +1,36 @@
+/*
+ * QEMU Macintosh Nubus Virtio MMIO card
+ *
+ * Copyright (c) 2023 Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_NUBUS_VIRTIO_MMIO_H
+#define HW_NUBUS_VIRTIO_MMIO_H
+
+#include "hw/nubus/nubus.h"
+#include "qom/object.h"
+#include "hw/intc/goldfish_pic.h"
+#include "hw/virtio/virtio-mmio.h"
+
+#define TYPE_NUBUS_VIRTIO_MMIO "nubus-virtio-mmio"
+OBJECT_DECLARE_TYPE(NubusVirtioMMIO, NubusVirtioMMIODeviceClass,
+ NUBUS_VIRTIO_MMIO)
+
+struct NubusVirtioMMIODeviceClass {
+ DeviceClass parent_class;
+
+ DeviceRealize parent_realize;
+};
+
+#define NUBUS_VIRTIO_MMIO_NUM_DEVICES 32
+
+struct NubusVirtioMMIO {
+ NubusDevice parent_obj;
+
+ GoldfishPICState pic;
+ VirtIOMMIOProxy virtio_mmio[NUBUS_VIRTIO_MMIO_NUM_DEVICES];
+};
+
+#endif
diff --git a/include/hw/nubus/nubus.h b/include/hw/nubus/nubus.h
index a8634e54c5..fee79b71d1 100644
--- a/include/hw/nubus/nubus.h
+++ b/include/hw/nubus/nubus.h
@@ -10,60 +10,66 @@
#define HW_NUBUS_NUBUS_H
#include "hw/qdev-properties.h"
+#include "hw/sysbus.h"
#include "exec/address-spaces.h"
+#include "qom/object.h"
+#include "qemu/units.h"
#define NUBUS_SUPER_SLOT_SIZE 0x10000000U
-#define NUBUS_SUPER_SLOT_NB 0x9
+#define NUBUS_SUPER_SLOT_NB 0xe
+
+#define NUBUS_SLOT_BASE (NUBUS_SUPER_SLOT_SIZE * \
+ (NUBUS_SUPER_SLOT_NB + 1))
#define NUBUS_SLOT_SIZE 0x01000000
-#define NUBUS_SLOT_NB 0xF
+#define NUBUS_FIRST_SLOT 0x0
+#define NUBUS_LAST_SLOT 0xf
+#define NUBUS_SLOT_NB (NUBUS_LAST_SLOT - NUBUS_FIRST_SLOT + 1)
-#define NUBUS_FIRST_SLOT 0x9
-#define NUBUS_LAST_SLOT 0xF
+#define NUBUS_IRQS 16
#define TYPE_NUBUS_DEVICE "nubus-device"
-#define NUBUS_DEVICE(obj) \
- OBJECT_CHECK(NubusDevice, (obj), TYPE_NUBUS_DEVICE)
+OBJECT_DECLARE_SIMPLE_TYPE(NubusDevice, NUBUS_DEVICE)
#define TYPE_NUBUS_BUS "nubus-bus"
-#define NUBUS_BUS(obj) OBJECT_CHECK(NubusBus, (obj), TYPE_NUBUS_BUS)
+OBJECT_DECLARE_SIMPLE_TYPE(NubusBus, NUBUS_BUS)
#define TYPE_NUBUS_BRIDGE "nubus-bridge"
-#define NUBUS_BRIDGE(obj) OBJECT_CHECK(NubusBridge, (obj), TYPE_NUBUS_BRIDGE)
+OBJECT_DECLARE_SIMPLE_TYPE(NubusBridge, NUBUS_BRIDGE);
-typedef struct NubusBus {
+struct NubusBus {
BusState qbus;
+ AddressSpace nubus_as;
+ MemoryRegion nubus_mr;
+
MemoryRegion super_slot_io;
MemoryRegion slot_io;
- int current_slot;
-} NubusBus;
+ uint16_t slot_available_mask;
-typedef struct NubusDevice {
- DeviceState qdev;
+ qemu_irq irqs[NUBUS_IRQS];
+};
- int slot_nb;
- MemoryRegion slot_mem;
+#define NUBUS_DECL_ROM_MAX_SIZE (1 * MiB)
- /* Format Block */
+struct NubusDevice {
+ DeviceState qdev;
- MemoryRegion fblock_io;
+ int32_t slot;
+ MemoryRegion super_slot_mem;
+ MemoryRegion slot_mem;
- uint32_t rom_length;
- uint32_t rom_crc;
- uint8_t rom_rev;
- uint8_t rom_format;
- uint8_t byte_lanes;
- int32_t directory_offset;
+ char *romfile;
+ MemoryRegion decl_rom;
+};
- /* ROM */
+void nubus_set_irq(NubusDevice *nd, int level);
- MemoryRegion rom_io;
- const uint8_t *rom;
-} NubusDevice;
+struct NubusBridge {
+ SysBusDevice parent_obj;
-void nubus_register_rom(NubusDevice *dev, const uint8_t *rom, uint32_t size,
- int revision, int format, uint8_t byte_lanes);
+ NubusBus bus;
+};
#endif
diff --git a/include/hw/nvram/chrp_nvram.h b/include/hw/nvram/chrp_nvram.h
index 09941a9be4..4a0f5c21b8 100644
--- a/include/hw/nvram/chrp_nvram.h
+++ b/include/hw/nvram/chrp_nvram.h
@@ -50,7 +50,8 @@ chrp_nvram_finish_partition(ChrpNvramPartHdr *header, uint32_t size)
header->checksum = sum & 0xff;
}
-int chrp_nvram_create_system_partition(uint8_t *data, int min_len);
+/* chrp_nvram_create_system_partition() failure is fatal */
+int chrp_nvram_create_system_partition(uint8_t *data, int min_len, int max_len);
int chrp_nvram_create_free_partition(uint8_t *data, int len);
#endif
diff --git a/include/hw/nvram/eeprom_at24c.h b/include/hw/nvram/eeprom_at24c.h
new file mode 100644
index 0000000000..acb9857b2a
--- /dev/null
+++ b/include/hw/nvram/eeprom_at24c.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ */
+
+#ifndef EEPROM_AT24C_H
+#define EEPROM_AT24C_H
+
+#include "hw/i2c/i2c.h"
+
+/*
+ * Create and realize an AT24C EEPROM device on the heap.
+ * @bus: I2C bus to put it on
+ * @address: I2C address of the EEPROM slave when put on a bus
+ * @rom_size: size of the EEPROM
+ *
+ * Create the device state structure, initialize it, put it on the specified
+ * @bus, and drop the reference to it (the device is realized).
+ */
+I2CSlave *at24c_eeprom_init(I2CBus *bus, uint8_t address, uint32_t rom_size);
+
+
+/*
+ * Create and realize an AT24C EEPROM device on the heap with initial data.
+ * @bus: I2C bus to put it on
+ * @address: I2C address of the EEPROM slave when put on a bus
+ * @rom_size: size of the EEPROM
+ * @init_rom: Array of bytes to initialize EEPROM memory with
+ * @init_rom_size: Size of @init_rom, must be less than or equal to @rom_size
+ *
+ * Create the device state structure, initialize it, put it on the specified
+ * @bus, and drop the reference to it (the device is realized). Copies the data
+ * from @init_rom to the beginning of the EEPROM memory buffer.
+ */
+I2CSlave *at24c_eeprom_init_rom(I2CBus *bus, uint8_t address, uint32_t rom_size,
+ const uint8_t *init_rom, uint32_t init_rom_size);
+
+#endif
diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h
index f190c428e8..c1f81a5f13 100644
--- a/include/hw/nvram/fw_cfg.h
+++ b/include/hw/nvram/fw_cfg.h
@@ -5,24 +5,22 @@
#include "standard-headers/linux/qemu_fw_cfg.h"
#include "hw/sysbus.h"
#include "sysemu/dma.h"
+#include "qom/object.h"
#define TYPE_FW_CFG "fw_cfg"
#define TYPE_FW_CFG_IO "fw_cfg_io"
#define TYPE_FW_CFG_MEM "fw_cfg_mem"
#define TYPE_FW_CFG_DATA_GENERATOR_INTERFACE "fw_cfg-data-generator"
-#define FW_CFG(obj) OBJECT_CHECK(FWCfgState, (obj), TYPE_FW_CFG)
-#define FW_CFG_IO(obj) OBJECT_CHECK(FWCfgIoState, (obj), TYPE_FW_CFG_IO)
-#define FW_CFG_MEM(obj) OBJECT_CHECK(FWCfgMemState, (obj), TYPE_FW_CFG_MEM)
+OBJECT_DECLARE_SIMPLE_TYPE(FWCfgState, FW_CFG)
+OBJECT_DECLARE_SIMPLE_TYPE(FWCfgIoState, FW_CFG_IO)
+OBJECT_DECLARE_SIMPLE_TYPE(FWCfgMemState, FW_CFG_MEM)
-#define FW_CFG_DATA_GENERATOR_CLASS(class) \
- OBJECT_CLASS_CHECK(FWCfgDataGeneratorClass, (class), \
+typedef struct FWCfgDataGeneratorClass FWCfgDataGeneratorClass;
+DECLARE_CLASS_CHECKERS(FWCfgDataGeneratorClass, FW_CFG_DATA_GENERATOR,
TYPE_FW_CFG_DATA_GENERATOR_INTERFACE)
-#define FW_CFG_DATA_GENERATOR_GET_CLASS(obj) \
- OBJECT_GET_CLASS(FWCfgDataGeneratorClass, (obj), \
- TYPE_FW_CFG_DATA_GENERATOR_INTERFACE)
-typedef struct FWCfgDataGeneratorClass {
+struct FWCfgDataGeneratorClass {
/*< private >*/
InterfaceClass parent_class;
/*< public >*/
@@ -39,7 +37,7 @@ typedef struct FWCfgDataGeneratorClass {
* required.
*/
GByteArray *(*get_data)(Object *obj, Error **errp);
-} FWCfgDataGeneratorClass;
+};
typedef struct fw_cfg_file FWCfgFile;
@@ -310,6 +308,15 @@ void *fw_cfg_modify_file(FWCfgState *s, const char *filename, void *data,
bool fw_cfg_add_from_generator(FWCfgState *s, const char *filename,
const char *gen_id, Error **errp);
+/**
+ * fw_cfg_add_extra_pci_roots:
+ * @bus: main pci root bus to be scanned from
+ * @s: fw_cfg device being modified
+ *
+ * Add a new fw_cfg item...
+ */
+void fw_cfg_add_extra_pci_roots(PCIBus *bus, FWCfgState *s);
+
FWCfgState *fw_cfg_init_io_dma(uint32_t iobase, uint32_t dma_iobase,
AddressSpace *dma_as);
FWCfgState *fw_cfg_init_io(uint32_t iobase);
@@ -335,4 +342,25 @@ bool fw_cfg_dma_enabled(void *opaque);
*/
const char *fw_cfg_arch_key_name(uint16_t key);
+/**
+ * load_image_to_fw_cfg() - Load an image file into an fw_cfg entry identified
+ * by key.
+ * @fw_cfg: The firmware config instance to store the data in.
+ * @size_key: The firmware config key to store the size of the loaded
+ * data under, with fw_cfg_add_i32().
+ * @data_key: The firmware config key to store the loaded data under,
+ * with fw_cfg_add_bytes().
+ * @image_name: The name of the image file to load. If it is NULL, the
+ * function returns without doing anything.
+ * @try_decompress: Whether the image should be decompressed (gunzipped) before
+ * adding it to fw_cfg. If decompression fails, the image is
+ * loaded as-is.
+ *
+ * In case of failure, the function prints an error message to stderr and the
+ * process exits with status 1.
+ */
+void load_image_to_fw_cfg(FWCfgState *fw_cfg, uint16_t size_key,
+ uint16_t data_key, const char *image_name,
+ bool try_decompress);
+
#endif
diff --git a/include/hw/nvram/fw_cfg_acpi.h b/include/hw/nvram/fw_cfg_acpi.h
new file mode 100644
index 0000000000..b39eb0490f
--- /dev/null
+++ b/include/hw/nvram/fw_cfg_acpi.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * ACPI support for fw_cfg
+ *
+ */
+
+#ifndef FW_CFG_ACPI_H
+#define FW_CFG_ACPI_H
+
+#include "exec/hwaddr.h"
+
+void fw_cfg_acpi_dsdt_add(Aml *scope, const MemMapEntry *fw_cfg_memmap);
+
+#endif
diff --git a/include/hw/nvram/mac_nvram.h b/include/hw/nvram/mac_nvram.h
new file mode 100644
index 0000000000..0c4dfaeff6
--- /dev/null
+++ b/include/hw/nvram/mac_nvram.h
@@ -0,0 +1,52 @@
+/*
+ * PowerMac NVRAM emulation
+ *
+ * Copyright (c) 2004-2007 Fabrice Bellard
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * 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.
+ */
+
+#ifndef MAC_NVRAM_H
+#define MAC_NVRAM_H
+
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+
+#define MACIO_NVRAM_SIZE 0x2000
+
+#define TYPE_MACIO_NVRAM "macio-nvram"
+OBJECT_DECLARE_SIMPLE_TYPE(MacIONVRAMState, MACIO_NVRAM)
+
+struct MacIONVRAMState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ uint32_t size;
+ uint32_t it_shift;
+
+ MemoryRegion mem;
+ uint8_t *data;
+ BlockBackend *blk;
+};
+
+void pmac_format_nvram_partition(MacIONVRAMState *nvr, int len);
+
+#endif /* MAC_NVRAM_H */
diff --git a/include/hw/nvram/npcm7xx_otp.h b/include/hw/nvram/npcm7xx_otp.h
new file mode 100644
index 0000000000..ea4b5d0731
--- /dev/null
+++ b/include/hw/nvram/npcm7xx_otp.h
@@ -0,0 +1,79 @@
+/*
+ * Nuvoton NPCM7xx OTP (Fuse Array) Interface
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_OTP_H
+#define NPCM7XX_OTP_H
+
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+
+/* Each OTP module holds 8192 bits of one-time programmable storage */
+#define NPCM7XX_OTP_ARRAY_BITS (8192)
+#define NPCM7XX_OTP_ARRAY_BYTES (NPCM7XX_OTP_ARRAY_BITS / BITS_PER_BYTE)
+
+/* Fuse array offsets */
+#define NPCM7XX_FUSE_FUSTRAP (0)
+#define NPCM7XX_FUSE_CP_FUSTRAP (12)
+#define NPCM7XX_FUSE_DAC_CALIB (16)
+#define NPCM7XX_FUSE_ADC_CALIB (24)
+#define NPCM7XX_FUSE_DERIVATIVE (64)
+#define NPCM7XX_FUSE_TEST_SIG (72)
+#define NPCM7XX_FUSE_DIE_LOCATION (74)
+#define NPCM7XX_FUSE_GP1 (80)
+#define NPCM7XX_FUSE_GP2 (128)
+
+/*
+ * Number of registers in our device state structure. Don't change this without
+ * incrementing the version_id in the vmstate.
+ */
+#define NPCM7XX_OTP_NR_REGS (0x18 / sizeof(uint32_t))
+
+/**
+ * struct NPCM7xxOTPState - Device state for one OTP module.
+ * @parent: System bus device.
+ * @mmio: Memory region through which registers are accessed.
+ * @regs: Register contents.
+ * @array: OTP storage array.
+ */
+typedef struct NPCM7xxOTPState {
+ SysBusDevice parent;
+
+ MemoryRegion mmio;
+ uint32_t regs[NPCM7XX_OTP_NR_REGS];
+ uint8_t array[NPCM7XX_OTP_ARRAY_BYTES];
+} NPCM7xxOTPState;
+
+#define TYPE_NPCM7XX_OTP "npcm7xx-otp"
+#define NPCM7XX_OTP(obj) OBJECT_CHECK(NPCM7xxOTPState, (obj), TYPE_NPCM7XX_OTP)
+
+#define TYPE_NPCM7XX_KEY_STORAGE "npcm7xx-key-storage"
+#define TYPE_NPCM7XX_FUSE_ARRAY "npcm7xx-fuse-array"
+
+typedef struct NPCM7xxOTPClass NPCM7xxOTPClass;
+
+/**
+ * npcm7xx_otp_array_write - ECC encode and write data to OTP array.
+ * @s: OTP module.
+ * @data: Data to be encoded and written.
+ * @offset: Offset of first byte to be written in the OTP array.
+ * @len: Number of bytes before ECC encoding.
+ *
+ * Each nibble of data is encoded into a byte, so the number of bytes written
+ * to the array will be @len * 2.
+ */
+void npcm7xx_otp_array_write(NPCM7xxOTPState *s, const void *data,
+ unsigned int offset, unsigned int len);
+
+#endif /* NPCM7XX_OTP_H */
diff --git a/include/hw/nvram/nrf51_nvm.h b/include/hw/nvram/nrf51_nvm.h
index 3792e4a9fe..d85e788df5 100644
--- a/include/hw/nvram/nrf51_nvm.h
+++ b/include/hw/nvram/nrf51_nvm.h
@@ -23,8 +23,9 @@
#define NRF51_NVM_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_NRF51_NVM "nrf51_soc.nvm"
-#define NRF51_NVM(obj) OBJECT_CHECK(NRF51NVMState, (obj), TYPE_NRF51_NVM)
+OBJECT_DECLARE_SIMPLE_TYPE(NRF51NVMState, NRF51_NVM)
#define NRF51_UICR_FIXTURE_SIZE 64
@@ -44,7 +45,7 @@
#define NRF51_UICR_SIZE 0x100
-typedef struct NRF51NVMState {
+struct NRF51NVMState {
SysBusDevice parent_obj;
MemoryRegion mmio;
@@ -58,7 +59,7 @@ typedef struct NRF51NVMState {
uint32_t config;
-} NRF51NVMState;
+};
#endif
diff --git a/include/hw/nvram/xlnx-bbram.h b/include/hw/nvram/xlnx-bbram.h
new file mode 100644
index 0000000000..6fc13f8cc1
--- /dev/null
+++ b/include/hw/nvram/xlnx-bbram.h
@@ -0,0 +1,54 @@
+/*
+ * QEMU model of the Xilinx BBRAM Battery Backed RAM
+ *
+ * Copyright (c) 2015-2021 Xilinx Inc.
+ *
+ * Written by Edgar E. Iglesias <edgari@xilinx.com>
+ *
+ * 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.
+ */
+#ifndef XLNX_BBRAM_H
+#define XLNX_BBRAM_H
+
+#include "sysemu/block-backend.h"
+#include "hw/qdev-core.h"
+#include "hw/irq.h"
+#include "hw/sysbus.h"
+#include "hw/register.h"
+
+#define RMAX_XLNX_BBRAM ((0x4c / 4) + 1)
+
+#define TYPE_XLNX_BBRAM "xlnx.bbram-ctrl"
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxBBRam, XLNX_BBRAM);
+
+struct XlnxBBRam {
+ SysBusDevice parent_obj;
+ qemu_irq irq_bbram;
+
+ BlockBackend *blk;
+
+ uint32_t crc_zpads;
+ bool bbram8_wo;
+ bool blk_ro;
+
+ uint32_t regs[RMAX_XLNX_BBRAM];
+ RegisterInfo regs_info[RMAX_XLNX_BBRAM];
+};
+
+#endif
diff --git a/include/hw/nvram/xlnx-efuse.h b/include/hw/nvram/xlnx-efuse.h
new file mode 100644
index 0000000000..cff7924106
--- /dev/null
+++ b/include/hw/nvram/xlnx-efuse.h
@@ -0,0 +1,132 @@
+/*
+ * QEMU model of the Xilinx eFuse core
+ *
+ * Copyright (c) 2015 Xilinx Inc.
+ *
+ * Written by Edgar E. Iglesias <edgari@xilinx.com>
+ *
+ * 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.
+ */
+
+#ifndef XLNX_EFUSE_H
+#define XLNX_EFUSE_H
+
+#include "sysemu/block-backend.h"
+#include "hw/qdev-core.h"
+
+#define TYPE_XLNX_EFUSE "xlnx-efuse"
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxEFuse, XLNX_EFUSE);
+
+struct XlnxEFuse {
+ DeviceState parent_obj;
+ BlockBackend *blk;
+ bool blk_ro;
+ uint32_t *fuse32;
+
+ DeviceState *dev;
+
+ bool init_tbits;
+
+ uint8_t efuse_nr;
+ uint32_t efuse_size;
+
+ uint32_t *ro_bits;
+ uint32_t ro_bits_cnt;
+};
+
+/**
+ * xlnx_efuse_calc_crc:
+ * @data: an array of 32-bit words for which the CRC should be computed
+ * @u32_cnt: the array size in number of 32-bit words
+ * @zpads: the number of 32-bit zeros prepended to @data before computation
+ *
+ * This function is used to compute the CRC for an array of 32-bit words,
+ * using a Xilinx-specific data padding.
+ *
+ * Returns: the computed 32-bit CRC
+ */
+uint32_t xlnx_efuse_calc_crc(const uint32_t *data, unsigned u32_cnt,
+ unsigned zpads);
+
+/**
+ * xlnx_efuse_get_bit:
+ * @s: the efuse object
+ * @bit: the efuse bit-address to read the data
+ *
+ * Returns: the bit, 0 or 1, at @bit of object @s
+ */
+bool xlnx_efuse_get_bit(XlnxEFuse *s, unsigned int bit);
+
+/**
+ * xlnx_efuse_set_bit:
+ * @s: the efuse object
+ * @bit: the efuse bit-address to be written a value of 1
+ *
+ * Returns: true on success, false on failure
+ */
+bool xlnx_efuse_set_bit(XlnxEFuse *s, unsigned int bit);
+
+/**
+ * xlnx_efuse_k256_check:
+ * @s: the efuse object
+ * @crc: the 32-bit CRC to be compared with
+ * @start: the efuse bit-address (which must be multiple of 32) of the
+ * start of a 256-bit array
+ *
+ * This function computes the CRC of a 256-bit array starting at @start
+ * then compares to the given @crc
+ *
+ * Returns: true of @crc == computed, false otherwise
+ */
+bool xlnx_efuse_k256_check(XlnxEFuse *s, uint32_t crc, unsigned start);
+
+/**
+ * xlnx_efuse_tbits_check:
+ * @s: the efuse object
+ *
+ * This function inspects a number of efuse bits at specific addresses
+ * to see if they match a validation pattern. Each pattern is a group
+ * of 4 bits, and there are 3 groups.
+ *
+ * Returns: a 3-bit mask, where a bit of '1' means the corresponding
+ * group has a valid pattern.
+ */
+uint32_t xlnx_efuse_tbits_check(XlnxEFuse *s);
+
+/**
+ * xlnx_efuse_get_row:
+ * @s: the efuse object
+ * @bit: the efuse bit address for which a 32-bit value is read
+ *
+ * Returns: the entire 32 bits of the efuse, starting at a bit
+ * address that is multiple of 32 and contains the bit at @bit
+ */
+static inline uint32_t xlnx_efuse_get_row(XlnxEFuse *s, unsigned int bit)
+{
+ if (!(s->fuse32)) {
+ return 0;
+ } else {
+ unsigned int row_idx = bit / 32;
+
+ assert(row_idx < (s->efuse_size * s->efuse_nr / 32));
+ return s->fuse32[row_idx];
+ }
+}
+
+#endif
diff --git a/include/hw/nvram/xlnx-versal-efuse.h b/include/hw/nvram/xlnx-versal-efuse.h
new file mode 100644
index 0000000000..86e2261b9a
--- /dev/null
+++ b/include/hw/nvram/xlnx-versal-efuse.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2020 Xilinx Inc.
+ *
+ * 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.
+ */
+#ifndef XLNX_VERSAL_EFUSE_H
+#define XLNX_VERSAL_EFUSE_H
+
+#include "hw/irq.h"
+#include "hw/sysbus.h"
+#include "hw/register.h"
+#include "hw/nvram/xlnx-efuse.h"
+
+#define XLNX_VERSAL_EFUSE_CTRL_R_MAX ((0x100 / 4) + 1)
+
+#define TYPE_XLNX_VERSAL_EFUSE_CTRL "xlnx-versal-efuse"
+#define TYPE_XLNX_VERSAL_EFUSE_CACHE "xlnx-pmc-efuse-cache"
+
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalEFuseCtrl, XLNX_VERSAL_EFUSE_CTRL);
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalEFuseCache, XLNX_VERSAL_EFUSE_CACHE);
+
+struct XlnxVersalEFuseCtrl {
+ SysBusDevice parent_obj;
+ qemu_irq irq_efuse_imr;
+
+ XlnxEFuse *efuse;
+
+ void *extra_pg0_lock_spec; /* Opaque property */
+ uint32_t extra_pg0_lock_n16;
+
+ uint32_t regs[XLNX_VERSAL_EFUSE_CTRL_R_MAX];
+ RegisterInfo regs_info[XLNX_VERSAL_EFUSE_CTRL_R_MAX];
+};
+
+struct XlnxVersalEFuseCache {
+ SysBusDevice parent_obj;
+ MemoryRegion iomem;
+
+ XlnxEFuse *efuse;
+};
+
+/**
+ * xlnx_versal_efuse_read_row:
+ * @s: the efuse object
+ * @bit: the bit-address within the 32-bit row to be read
+ * @denied: if non-NULL, to receive true if the row is write-only
+ *
+ * Returns: the 32-bit word containing address @bit; 0 if @denies is true
+ */
+uint32_t xlnx_versal_efuse_read_row(XlnxEFuse *s, uint32_t bit, bool *denied);
+
+#endif
diff --git a/include/hw/nvram/xlnx-zynqmp-efuse.h b/include/hw/nvram/xlnx-zynqmp-efuse.h
new file mode 100644
index 0000000000..f5beacc2e6
--- /dev/null
+++ b/include/hw/nvram/xlnx-zynqmp-efuse.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021 Xilinx Inc.
+ *
+ * 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.
+ */
+#ifndef XLNX_ZYNQMP_EFUSE_H
+#define XLNX_ZYNQMP_EFUSE_H
+
+#include "hw/irq.h"
+#include "hw/sysbus.h"
+#include "hw/register.h"
+#include "hw/nvram/xlnx-efuse.h"
+
+#define XLNX_ZYNQMP_EFUSE_R_MAX ((0x10fc / 4) + 1)
+
+#define TYPE_XLNX_ZYNQMP_EFUSE "xlnx-zynqmp-efuse"
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPEFuse, XLNX_ZYNQMP_EFUSE);
+
+struct XlnxZynqMPEFuse {
+ SysBusDevice parent_obj;
+ qemu_irq irq;
+
+ XlnxEFuse *efuse;
+ uint32_t regs[XLNX_ZYNQMP_EFUSE_R_MAX];
+ RegisterInfo regs_info[XLNX_ZYNQMP_EFUSE_R_MAX];
+};
+
+#endif
diff --git a/include/hw/openrisc/boot.h b/include/hw/openrisc/boot.h
new file mode 100644
index 0000000000..25a313d63a
--- /dev/null
+++ b/include/hw/openrisc/boot.h
@@ -0,0 +1,34 @@
+/*
+ * QEMU OpenRISC boot helpers.
+ *
+ * Copyright (c) 2022 Stafford Horne <shorne@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef OPENRISC_BOOT_H
+#define OPENRISC_BOOT_H
+
+#include "exec/cpu-defs.h"
+
+hwaddr openrisc_load_kernel(ram_addr_t ram_size,
+ const char *kernel_filename,
+ uint32_t *bootstrap_pc);
+
+hwaddr openrisc_load_initrd(void *fdt, const char *filename,
+ hwaddr load_start, uint64_t mem_size);
+
+uint32_t openrisc_load_fdt(void *fdt, hwaddr load_start,
+ uint64_t mem_size);
+
+#endif /* OPENRISC_BOOT_H */
diff --git a/include/hw/or-irq.h b/include/hw/or-irq.h
index 0038bfbe3d..c0a42f3711 100644
--- a/include/hw/or-irq.h
+++ b/include/hw/or-irq.h
@@ -35,9 +35,7 @@
*/
#define MAX_OR_LINES 48
-typedef struct OrIRQState qemu_or_irq;
-
-#define OR_IRQ(obj) OBJECT_CHECK(qemu_or_irq, (obj), TYPE_OR_IRQ)
+OBJECT_DECLARE_SIMPLE_TYPE(OrIRQState, OR_IRQ)
struct OrIRQState {
DeviceState parent_obj;
diff --git a/include/hw/pci-bridge/cxl_upstream_port.h b/include/hw/pci-bridge/cxl_upstream_port.h
new file mode 100644
index 0000000000..12635139f6
--- /dev/null
+++ b/include/hw/pci-bridge/cxl_upstream_port.h
@@ -0,0 +1,19 @@
+
+#ifndef CXL_USP_H
+#define CXL_USP_H
+#include "hw/pci/pcie.h"
+#include "hw/pci/pcie_port.h"
+#include "hw/cxl/cxl.h"
+
+typedef struct CXLUpstreamPort {
+ /*< private >*/
+ PCIEPort parent_obj;
+
+ /*< public >*/
+ CXLComponentState cxl_cstate;
+ CXLCCI swcci;
+ DOECap doe_cdat;
+ uint64_t sn;
+} CXLUpstreamPort;
+
+#endif /* CXL_SUP_H */
diff --git a/include/hw/pci-bridge/pci_expander_bridge.h b/include/hw/pci-bridge/pci_expander_bridge.h
new file mode 100644
index 0000000000..0b3856d615
--- /dev/null
+++ b/include/hw/pci-bridge/pci_expander_bridge.h
@@ -0,0 +1,12 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef PCI_EXPANDER_BRIDGE_H
+#define PCI_EXPANDER_BRIDGE_H
+
+#include "hw/cxl/cxl.h"
+
+void pxb_cxl_hook_up_registers(CXLState *state, PCIBus *bus, Error **errp);
+
+#endif /* PCI_EXPANDER_BRIDGE_H */
diff --git a/include/hw/pci-bridge/simba.h b/include/hw/pci-bridge/simba.h
index d8649973ee..979cb17435 100644
--- a/include/hw/pci-bridge/simba.h
+++ b/include/hw/pci-bridge/simba.h
@@ -28,15 +28,15 @@
#define HW_PCI_BRIDGE_SIMBA_H
#include "hw/pci/pci_bridge.h"
+#include "qom/object.h"
-typedef struct SimbaPCIBridge {
+struct SimbaPCIBridge {
/*< private >*/
PCIBridge parent_obj;
-} SimbaPCIBridge;
+};
#define TYPE_SIMBA_PCI_BRIDGE "pbm-bridge"
-#define SIMBA_PCI_BRIDGE(obj) \
- OBJECT_CHECK(SimbaPCIBridge, (obj), TYPE_SIMBA_PCI_BRIDGE)
+OBJECT_DECLARE_SIMPLE_TYPE(SimbaPCIBridge, SIMBA_PCI_BRIDGE)
#endif
diff --git a/include/hw/pci-bridge/xio3130_downstream.h b/include/hw/pci-bridge/xio3130_downstream.h
new file mode 100644
index 0000000000..1d10139aea
--- /dev/null
+++ b/include/hw/pci-bridge/xio3130_downstream.h
@@ -0,0 +1,15 @@
+/*
+ * TI X3130 pci express downstream port switch
+ *
+ * Copyright (C) 2022 Igor Mammedov <imammedo@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_PCI_BRIDGE_XIO3130_DOWNSTREAM_H
+#define HW_PCI_BRIDGE_XIO3130_DOWNSTREAM_H
+
+#define TYPE_XIO3130_DOWNSTREAM "xio3130-downstream"
+
+#endif
+
diff --git a/include/hw/pci-host/articia.h b/include/hw/pci-host/articia.h
new file mode 100644
index 0000000000..529c240274
--- /dev/null
+++ b/include/hw/pci-host/articia.h
@@ -0,0 +1,17 @@
+/*
+ * Mai Logic Articia S emulation
+ *
+ * Copyright (c) 2023 BALATON Zoltan
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ *
+ */
+
+#ifndef ARTICIA_H
+#define ARTICIA_H
+
+#define TYPE_ARTICIA "articia"
+#define TYPE_ARTICIA_PCI_HOST "articia-pci-host"
+#define TYPE_ARTICIA_PCI_BRIDGE "articia-pci-bridge"
+
+#endif
diff --git a/include/hw/pci-host/astro.h b/include/hw/pci-host/astro.h
new file mode 100644
index 0000000000..e2966917cd
--- /dev/null
+++ b/include/hw/pci-host/astro.h
@@ -0,0 +1,94 @@
+/*
+ * HP-PARISC Astro Bus connector with Elroy PCI host bridges
+ */
+
+#ifndef ASTRO_H
+#define ASTRO_H
+
+#include "hw/pci/pci_host.h"
+
+#define ASTRO_HPA 0xfed00000
+
+#define ROPES_PER_IOC 8 /* per Ike half or Pluto/Astro */
+
+#define TYPE_ASTRO_CHIP "astro-chip"
+OBJECT_DECLARE_SIMPLE_TYPE(AstroState, ASTRO_CHIP)
+
+#define TYPE_ELROY_PCI_HOST_BRIDGE "elroy-pcihost"
+OBJECT_DECLARE_SIMPLE_TYPE(ElroyState, ELROY_PCI_HOST_BRIDGE)
+
+#define ELROY_NUM 4 /* # of Elroys */
+#define ELROY_IRQS 8 /* IOSAPIC IRQs */
+
+/* ASTRO Memory and I/O regions */
+#define LMMIO_DIST_BASE_ADDR 0xf4000000ULL
+#define LMMIO_DIST_BASE_SIZE 0x4000000ULL
+
+#define IOS_DIST_BASE_ADDR 0xfffee00000ULL
+#define IOS_DIST_BASE_SIZE 0x10000ULL
+
+#define HF_ENABLE 0x40 /* enable HF mode (default is -1 mode) */
+
+struct AstroState;
+
+struct ElroyState {
+ PCIHostState parent_obj;
+
+ /* parent Astro device */
+ struct AstroState *astro;
+
+ /* HPA of this Elroy */
+ hwaddr hpa;
+
+ /* PCI bus number (Elroy number) */
+ unsigned int pci_bus_num;
+
+ uint64_t config_address;
+ uint64_t config_reg_elroy;
+
+ uint64_t status_control;
+ uint64_t arb_mask;
+ uint64_t mmio_base[(0x0250 - 0x200) / 8];
+ uint64_t error_config;
+
+ uint32_t iosapic_reg_select;
+ uint64_t iosapic_reg[0x20];
+
+ uint32_t ilr;
+
+ MemoryRegion this_mem;
+
+ MemoryRegion pci_mmio;
+ MemoryRegion pci_mmio_alias;
+ MemoryRegion pci_hole;
+ MemoryRegion pci_io;
+};
+
+struct AstroState {
+ PCIHostState parent_obj;
+
+ uint64_t ioc_ctrl;
+ uint64_t ioc_status_ctrl;
+ uint64_t ioc_ranges[(0x03d8 - 0x300) / 8];
+ uint64_t ioc_rope_config;
+ uint64_t ioc_status_control;
+ uint64_t ioc_flush_control;
+ uint64_t ioc_rope_control[8];
+ uint64_t tlb_ibase;
+ uint64_t tlb_imask;
+ uint64_t tlb_pcom;
+ uint64_t tlb_tcnfg;
+ uint64_t tlb_pdir_base;
+
+ struct ElroyState *elroy[ELROY_NUM];
+
+ MemoryRegion this_mem;
+
+ MemoryRegion pci_mmio;
+ MemoryRegion pci_io;
+
+ IOMMUMemoryRegion iommu;
+ AddressSpace iommu_as;
+};
+
+#endif
diff --git a/include/hw/pci-host/bonito.h b/include/hw/pci-host/bonito.h
new file mode 100644
index 0000000000..b8ecf7870a
--- /dev/null
+++ b/include/hw/pci-host/bonito.h
@@ -0,0 +1,18 @@
+/*
+ * QEMU Bonito64 north bridge support
+ *
+ * Copyright (c) 2008 yajin (yajin@vm-kernel.org)
+ * Copyright (c) 2010 Huacai Chen (zltjiangshi@gmail.com)
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_PCI_HOST_BONITO_H
+#define HW_PCI_HOST_BONITO_H
+
+#include "qom/object.h"
+
+#define TYPE_BONITO_PCI_HOST_BRIDGE "Bonito-pcihost"
+OBJECT_DECLARE_SIMPLE_TYPE(BonitoState, BONITO_PCI_HOST_BRIDGE)
+
+#endif
diff --git a/include/hw/pci-host/designware.h b/include/hw/pci-host/designware.h
index 31c41231b1..908f3d946b 100644
--- a/include/hw/pci-host/designware.h
+++ b/include/hw/pci-host/designware.h
@@ -6,7 +6,7 @@
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -22,21 +22,16 @@
#define DESIGNWARE_H
#include "hw/sysbus.h"
-#include "hw/pci/pci.h"
-#include "hw/pci/pci_bus.h"
-#include "hw/pci/pcie_host.h"
#include "hw/pci/pci_bridge.h"
+#include "qom/object.h"
#define TYPE_DESIGNWARE_PCIE_HOST "designware-pcie-host"
-#define DESIGNWARE_PCIE_HOST(obj) \
- OBJECT_CHECK(DesignwarePCIEHost, (obj), TYPE_DESIGNWARE_PCIE_HOST)
+OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIEHost, DESIGNWARE_PCIE_HOST)
#define TYPE_DESIGNWARE_PCIE_ROOT "designware-pcie-root"
-#define DESIGNWARE_PCIE_ROOT(obj) \
- OBJECT_CHECK(DesignwarePCIERoot, (obj), TYPE_DESIGNWARE_PCIE_ROOT)
+OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIERoot, DESIGNWARE_PCIE_ROOT)
struct DesignwarePCIERoot;
-typedef struct DesignwarePCIERoot DesignwarePCIERoot;
typedef struct DesignwarePCIEViewport {
DesignwarePCIERoot *root;
@@ -80,7 +75,7 @@ struct DesignwarePCIERoot {
DesignwarePCIEMSI msi;
};
-typedef struct DesignwarePCIEHost {
+struct DesignwarePCIEHost {
PCIHostState parent_obj;
DesignwarePCIERoot root;
@@ -96,6 +91,6 @@ typedef struct DesignwarePCIEHost {
} pci;
MemoryRegion mmio;
-} DesignwarePCIEHost;
+};
#endif /* DESIGNWARE_H */
diff --git a/include/hw/pci-host/dino.h b/include/hw/pci-host/dino.h
new file mode 100644
index 0000000000..fd7975c798
--- /dev/null
+++ b/include/hw/pci-host/dino.h
@@ -0,0 +1,146 @@
+/*
+ * HP-PARISC Dino PCI chipset emulation, as in B160L and similar machines
+ *
+ * (C) 2017-2019 by Helge Deller <deller@gmx.de>
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ *
+ * Documentation available at:
+ * https://parisc.wiki.kernel.org/images-parisc/9/91/Dino_ers.pdf
+ * https://parisc.wiki.kernel.org/images-parisc/7/70/Dino_3_1_Errata.pdf
+ */
+
+#ifndef DINO_H
+#define DINO_H
+
+#include "hw/pci/pci_host.h"
+
+#define TYPE_DINO_PCI_HOST_BRIDGE "dino-pcihost"
+OBJECT_DECLARE_SIMPLE_TYPE(DinoState, DINO_PCI_HOST_BRIDGE)
+
+#define DINO_IAR0 0x004
+#define DINO_IODC 0x008
+#define DINO_IRR0 0x00C /* RO */
+#define DINO_IAR1 0x010
+#define DINO_IRR1 0x014 /* RO */
+#define DINO_IMR 0x018
+#define DINO_IPR 0x01C
+#define DINO_TOC_ADDR 0x020
+#define DINO_ICR 0x024
+#define DINO_ILR 0x028 /* RO */
+#define DINO_IO_COMMAND 0x030 /* WO */
+#define DINO_IO_STATUS 0x034 /* RO */
+#define DINO_IO_CONTROL 0x038
+#define DINO_IO_GSC_ERR_RESP 0x040 /* RO */
+#define DINO_IO_ERR_INFO 0x044 /* RO */
+#define DINO_IO_PCI_ERR_RESP 0x048 /* RO */
+#define DINO_IO_FBB_EN 0x05c
+#define DINO_IO_ADDR_EN 0x060
+#define DINO_PCI_CONFIG_ADDR 0x064
+#define DINO_PCI_CONFIG_DATA 0x068
+#define DINO_PCI_IO_DATA 0x06c
+#define DINO_PCI_MEM_DATA 0x070 /* Dino 3.x only */
+#define DINO_GSC2X_CONFIG 0x7b4 /* RO */
+#define DINO_GMASK 0x800
+#define DINO_PAMR 0x804
+#define DINO_PAPR 0x808
+#define DINO_DAMODE 0x80c
+#define DINO_PCICMD 0x810
+#define DINO_PCISTS 0x814 /* R/WC */
+#define DINO_MLTIM 0x81c
+#define DINO_BRDG_FEAT 0x820
+#define DINO_PCIROR 0x824
+#define DINO_PCIWOR 0x828
+#define DINO_TLTIM 0x830
+
+#define DINO_IRQS 11 /* bits 0-10 are architected */
+#define DINO_IRR_MASK 0x5ff /* only 10 bits are implemented */
+#define DINO_LOCAL_IRQS (DINO_IRQS + 1)
+#define DINO_MASK_IRQ(x) (1 << (x))
+
+#define DINO_IRQ_PCIINTA 0
+#define DINO_IRQ_PCIINTB 1
+#define DINO_IRQ_PCIINTC 2
+#define DINO_IRQ_PCIINTD 3
+#define DINO_IRQ_PCIINTE 4
+#define DINO_IRQ_PCIINTF 5
+#define DINO_IRQ_GSCEXTINT 6
+#define DINO_IRQ_BUSERRINT 7
+#define DINO_IRQ_PS2INT 8
+#define DINO_IRQ_UNUSED 9
+#define DINO_IRQ_RS232INT 10
+
+#define PCIINTA 0x001
+#define PCIINTB 0x002
+#define PCIINTC 0x004
+#define PCIINTD 0x008
+#define PCIINTE 0x010
+#define PCIINTF 0x020
+#define GSCEXTINT 0x040
+/* #define xxx 0x080 - bit 7 is "default" */
+/* #define xxx 0x100 - bit 8 not used */
+/* #define xxx 0x200 - bit 9 not used */
+#define RS232INT 0x400
+
+#define DINO_MEM_CHUNK_SIZE (8 * MiB)
+
+#define DINO800_REGS (1 + (DINO_TLTIM - DINO_GMASK) / 4)
+static const uint32_t reg800_keep_bits[DINO800_REGS] = {
+ MAKE_64BIT_MASK(0, 1), /* GMASK */
+ MAKE_64BIT_MASK(0, 7), /* PAMR */
+ MAKE_64BIT_MASK(0, 7), /* PAPR */
+ MAKE_64BIT_MASK(0, 8), /* DAMODE */
+ MAKE_64BIT_MASK(0, 7), /* PCICMD */
+ MAKE_64BIT_MASK(0, 9), /* PCISTS */
+ MAKE_64BIT_MASK(0, 32), /* Undefined */
+ MAKE_64BIT_MASK(0, 8), /* MLTIM */
+ MAKE_64BIT_MASK(0, 30), /* BRDG_FEAT */
+ MAKE_64BIT_MASK(0, 24), /* PCIROR */
+ MAKE_64BIT_MASK(0, 22), /* PCIWOR */
+ MAKE_64BIT_MASK(0, 32), /* Undocumented */
+ MAKE_64BIT_MASK(0, 9), /* TLTIM */
+};
+
+/* offsets to DINO HPA: */
+#define DINO_PCI_ADDR 0x064
+#define DINO_CONFIG_DATA 0x068
+#define DINO_IO_DATA 0x06c
+
+struct DinoState {
+ PCIHostState parent_obj;
+
+ /*
+ * PCI_CONFIG_ADDR is parent_obj.config_reg, via pci_host_conf_be_ops,
+ * so that we can map PCI_CONFIG_DATA to pci_host_data_be_ops.
+ */
+ uint32_t config_reg_dino; /* keep original copy, including 2 lowest bits */
+
+ uint32_t iar0;
+ uint32_t iar1;
+ uint32_t imr;
+ uint32_t ipr;
+ uint32_t icr;
+ uint32_t ilr;
+ uint32_t io_fbb_en;
+ uint32_t io_addr_en;
+ uint32_t io_control;
+ uint32_t toc_addr;
+
+ uint32_t reg800[DINO800_REGS];
+
+ MemoryRegion this_mem;
+ MemoryRegion pci_mem;
+ MemoryRegion pci_mem_alias[32];
+
+ MemoryRegion *memory_as;
+
+ AddressSpace bm_as;
+ MemoryRegion bm;
+ MemoryRegion bm_ram_alias;
+ MemoryRegion bm_pci_alias;
+ MemoryRegion bm_cpu_alias;
+
+ qemu_irq irqs[DINO_IRQS];
+};
+
+#endif
diff --git a/include/hw/pci-host/gpex.h b/include/hw/pci-host/gpex.h
index faea040a93..dce883573b 100644
--- a/include/hw/pci-host/gpex.h
+++ b/include/hw/pci-host/gpex.h
@@ -20,27 +20,36 @@
#ifndef HW_GPEX_H
#define HW_GPEX_H
+#include "exec/hwaddr.h"
#include "hw/sysbus.h"
-#include "hw/pci/pci.h"
+#include "hw/pci/pci_device.h"
#include "hw/pci/pcie_host.h"
+#include "qom/object.h"
#define TYPE_GPEX_HOST "gpex-pcihost"
-#define GPEX_HOST(obj) \
- OBJECT_CHECK(GPEXHost, (obj), TYPE_GPEX_HOST)
+OBJECT_DECLARE_SIMPLE_TYPE(GPEXHost, GPEX_HOST)
#define TYPE_GPEX_ROOT_DEVICE "gpex-root"
-#define MCH_PCI_DEVICE(obj) \
- OBJECT_CHECK(GPEXRootState, (obj), TYPE_GPEX_ROOT_DEVICE)
+OBJECT_DECLARE_SIMPLE_TYPE(GPEXRootState, GPEX_ROOT_DEVICE)
#define GPEX_NUM_IRQS 4
-typedef struct GPEXRootState {
+struct GPEXRootState {
/*< private >*/
PCIDevice parent_obj;
/*< public >*/
-} GPEXRootState;
+};
-typedef struct GPEXHost {
+struct GPEXConfig {
+ MemMapEntry ecam;
+ MemMapEntry mmio32;
+ MemMapEntry mmio64;
+ MemMapEntry pio;
+ int irq;
+ PCIBus *bus;
+};
+
+struct GPEXHost {
/*< private >*/
PCIExpressHost parent_obj;
/*< public >*/
@@ -49,10 +58,28 @@ typedef struct GPEXHost {
MemoryRegion io_ioport;
MemoryRegion io_mmio;
+ MemoryRegion io_ioport_window;
+ MemoryRegion io_mmio_window;
qemu_irq irq[GPEX_NUM_IRQS];
int irq_num[GPEX_NUM_IRQS];
-} GPEXHost;
+
+ bool allow_unmapped_accesses;
+
+ struct GPEXConfig gpex_cfg;
+};
int gpex_set_irq_num(GPEXHost *s, int index, int gsi);
+void acpi_dsdt_add_gpex(Aml *scope, struct GPEXConfig *cfg);
+void acpi_dsdt_add_gpex_host(Aml *scope, uint32_t irq);
+
+#define PCI_HOST_PIO_BASE "x-pio-base"
+#define PCI_HOST_PIO_SIZE "x-pio-size"
+#define PCI_HOST_ECAM_BASE "x-ecam-base"
+#define PCI_HOST_ECAM_SIZE "x-ecam-size"
+#define PCI_HOST_BELOW_4G_MMIO_BASE "x-below-4g-mmio-base"
+#define PCI_HOST_BELOW_4G_MMIO_SIZE "x-below-4g-mmio-size"
+#define PCI_HOST_ABOVE_4G_MMIO_BASE "x-above-4g-mmio-base"
+#define PCI_HOST_ABOVE_4G_MMIO_SIZE "x-above-4g-mmio-size"
+
#endif /* HW_GPEX_H */
diff --git a/include/hw/pci-host/grackle.h b/include/hw/pci-host/grackle.h
new file mode 100644
index 0000000000..7ad3a779f0
--- /dev/null
+++ b/include/hw/pci-host/grackle.h
@@ -0,0 +1,44 @@
+/*
+ * QEMU Grackle PCI host (heathrow OldWorld PowerMac)
+ *
+ * Copyright (c) 2006-2007 Fabrice Bellard
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * 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.
+ */
+
+#ifndef GRACKLE_H
+#define GRACKLE_H
+
+#include "hw/pci/pci_host.h"
+
+#define TYPE_GRACKLE_PCI_HOST_BRIDGE "grackle-pcihost"
+OBJECT_DECLARE_SIMPLE_TYPE(GrackleState, GRACKLE_PCI_HOST_BRIDGE)
+
+struct GrackleState {
+ PCIHostState parent_obj;
+
+ uint32_t ofw_addr;
+ qemu_irq irqs[4];
+ MemoryRegion pci_mmio;
+ MemoryRegion pci_hole;
+ MemoryRegion pci_io;
+};
+
+#endif
diff --git a/include/hw/pci-host/i440fx.h b/include/hw/pci-host/i440fx.h
index cc58d82ed4..c988f70890 100644
--- a/include/hw/pci-host/i440fx.h
+++ b/include/hw/pci-host/i440fx.h
@@ -11,41 +11,27 @@
#ifndef HW_PCI_I440FX_H
#define HW_PCI_I440FX_H
-#include "hw/hw.h"
-#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_device.h"
#include "hw/pci-host/pam.h"
+#include "qom/object.h"
+
+#define I440FX_HOST_PROP_PCI_TYPE "pci-type"
#define TYPE_I440FX_PCI_HOST_BRIDGE "i440FX-pcihost"
#define TYPE_I440FX_PCI_DEVICE "i440FX"
-#define I440FX_PCI_DEVICE(obj) \
- OBJECT_CHECK(PCII440FXState, (obj), TYPE_I440FX_PCI_DEVICE)
+OBJECT_DECLARE_SIMPLE_TYPE(PCII440FXState, I440FX_PCI_DEVICE)
-typedef struct PCII440FXState {
+struct PCII440FXState {
/*< private >*/
PCIDevice parent_obj;
/*< public >*/
- MemoryRegion *system_memory;
- MemoryRegion *pci_address_space;
- MemoryRegion *ram_memory;
- PAMMemoryRegion pam_regions[13];
+ PAMMemoryRegion pam_regions[PAM_REGIONS_COUNT];
MemoryRegion smram_region;
MemoryRegion smram, low_smram;
-} PCII440FXState;
+};
#define TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE "igd-passthrough-i440FX"
-PCIBus *i440fx_init(const char *host_type, const char *pci_type,
- PCII440FXState **pi440fx_state,
- MemoryRegion *address_space_mem,
- MemoryRegion *address_space_io,
- ram_addr_t ram_size,
- ram_addr_t below_4g_mem_size,
- ram_addr_t above_4g_mem_size,
- MemoryRegion *pci_memory,
- MemoryRegion *ram_memory);
-
-PCIBus *find_i440fx(void);
-
#endif
diff --git a/include/hw/pci-host/ls7a.h b/include/hw/pci-host/ls7a.h
new file mode 100644
index 0000000000..e753449593
--- /dev/null
+++ b/include/hw/pci-host/ls7a.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch CPU
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef HW_LS7A_H
+#define HW_LS7A_H
+
+#include "hw/pci-host/pam.h"
+#include "qemu/units.h"
+#include "qemu/range.h"
+#include "qom/object.h"
+
+#define VIRT_PCI_MEM_BASE 0x40000000UL
+#define VIRT_PCI_MEM_SIZE 0x40000000UL
+#define VIRT_PCI_IO_OFFSET 0x4000
+#define VIRT_PCI_CFG_BASE 0x20000000
+#define VIRT_PCI_CFG_SIZE 0x08000000
+#define VIRT_PCI_IO_BASE 0x18004000UL
+#define VIRT_PCI_IO_SIZE 0xC000
+
+#define VIRT_PCH_REG_BASE 0x10000000UL
+#define VIRT_IOAPIC_REG_BASE (VIRT_PCH_REG_BASE)
+#define VIRT_PCH_MSI_ADDR_LOW 0x2FF00000UL
+
+/*
+ * GSI_BASE is hard-coded with 64 in linux kernel, else kernel fails to boot
+ * 0 - 15 GSI for ISA devices even if there is no ISA devices
+ * 16 - 63 GSI for CPU devices such as timers/perf monitor etc
+ * 64 - GSI for external devices
+ */
+#define VIRT_PCH_PIC_IRQ_NUM 32
+#define VIRT_GSI_BASE 64
+#define VIRT_DEVICE_IRQS 16
+#define VIRT_UART_IRQ (VIRT_GSI_BASE + 2)
+#define VIRT_UART_BASE 0x1fe001e0
+#define VIRT_UART_SIZE 0X100
+#define VIRT_RTC_IRQ (VIRT_GSI_BASE + 3)
+#define VIRT_MISC_REG_BASE (VIRT_PCH_REG_BASE + 0x00080000)
+#define VIRT_RTC_REG_BASE (VIRT_MISC_REG_BASE + 0x00050100)
+#define VIRT_RTC_LEN 0x100
+#define VIRT_SCI_IRQ (VIRT_GSI_BASE + 4)
+
+#define VIRT_PLATFORM_BUS_BASEADDRESS 0x16000000
+#define VIRT_PLATFORM_BUS_SIZE 0x2000000
+#define VIRT_PLATFORM_BUS_NUM_IRQS 2
+#define VIRT_PLATFORM_BUS_IRQ (VIRT_GSI_BASE + 5)
+#endif
diff --git a/include/hw/pci-host/mv64361.h b/include/hw/pci-host/mv64361.h
new file mode 100644
index 0000000000..9cdb35cb3c
--- /dev/null
+++ b/include/hw/pci-host/mv64361.h
@@ -0,0 +1,8 @@
+#ifndef MV64361_H
+#define MV64361_H
+
+#define TYPE_MV64361 "mv64361"
+
+PCIBus *mv64361_get_pci_bus(DeviceState *dev, int n);
+
+#endif
diff --git a/include/hw/pci-host/pam.h b/include/hw/pci-host/pam.h
index fec5cd35d6..005916f826 100644
--- a/include/hw/pci-host/pam.h
+++ b/include/hw/pci-host/pam.h
@@ -80,13 +80,16 @@
#define SMRAM_C_BASE_SEG_MASK ((uint8_t)0x7)
#define SMRAM_C_BASE_SEG ((uint8_t)0x2) /* hardwired to b010 */
+#define PAM_REGIONS_COUNT 13
+
typedef struct PAMMemoryRegion {
MemoryRegion alias[4]; /* index = PAM value */
unsigned current;
} PAMMemoryRegion;
-void init_pam(DeviceState *dev, MemoryRegion *ram, MemoryRegion *system,
- MemoryRegion *pci, PAMMemoryRegion *mem, uint32_t start, uint32_t size);
+void init_pam(PAMMemoryRegion *mem, Object *owner, MemoryRegion *ram,
+ MemoryRegion *system, MemoryRegion *pci,
+ uint32_t start, uint32_t size);
void pam_update(PAMMemoryRegion *mem, int idx, uint8_t val);
#endif /* QEMU_PAM_H */
diff --git a/include/hw/pci-host/pnv_phb3.h b/include/hw/pci-host/pnv_phb3.h
index 75b787867a..d62b3091ac 100644
--- a/include/hw/pci-host/pnv_phb3.h
+++ b/include/hw/pci-host/pnv_phb3.h
@@ -10,9 +10,9 @@
#ifndef PCI_HOST_PNV_PHB3_H
#define PCI_HOST_PNV_PHB3_H
-#include "hw/pci/pcie_host.h"
-#include "hw/pci/pcie_port.h"
#include "hw/ppc/xics.h"
+#include "qom/object.h"
+#include "hw/pci-host/pnv_phb.h"
typedef struct PnvPHB3 PnvPHB3;
@@ -20,18 +20,20 @@ typedef struct PnvPHB3 PnvPHB3;
* PHB3 XICS Source for MSIs
*/
#define TYPE_PHB3_MSI "phb3-msi"
-#define PHB3_MSI(obj) OBJECT_CHECK(Phb3MsiState, (obj), TYPE_PHB3_MSI)
+typedef struct Phb3MsiState Phb3MsiState;
+DECLARE_INSTANCE_CHECKER(Phb3MsiState, PHB3_MSI,
+ TYPE_PHB3_MSI)
#define PHB3_MAX_MSI 2048
-typedef struct Phb3MsiState {
+struct Phb3MsiState {
ICSState ics;
qemu_irq *qirqs;
PnvPHB3 *phb;
uint64_t rba[PHB3_MAX_MSI / 64];
uint32_t rba_sum;
-} Phb3MsiState;
+};
void pnv_phb3_msi_update_config(Phb3MsiState *msis, uint32_t base,
uint32_t count);
@@ -69,9 +71,9 @@ typedef struct PnvPhb3DMASpace {
* PHB3 Power Bus Common Queue
*/
#define TYPE_PNV_PBCQ "pnv-pbcq"
-#define PNV_PBCQ(obj) OBJECT_CHECK(PnvPBCQState, (obj), TYPE_PNV_PBCQ)
+OBJECT_DECLARE_SIMPLE_TYPE(PnvPBCQState, PNV_PBCQ)
-typedef struct PnvPBCQState {
+struct PnvPBCQState {
DeviceState parent;
uint32_t nest_xbase;
@@ -96,24 +98,25 @@ typedef struct PnvPBCQState {
MemoryRegion xscom_nest_regs;
MemoryRegion xscom_pci_regs;
MemoryRegion xscom_spci_regs;
-} PnvPBCQState;
+};
/*
- * PHB3 PCIe Root port
+ * PHB3 PCIe Root Bus
*/
-#define TYPE_PNV_PHB3_ROOT_BUS "pnv-phb3-root-bus"
-
-#define TYPE_PNV_PHB3_ROOT_PORT "pnv-phb3-root-port"
+#define TYPE_PNV_PHB3_ROOT_BUS "pnv-phb3-root"
+struct PnvPHB3RootBus {
+ PCIBus parent;
-typedef struct PnvPHB3RootPort {
- PCIESlot parent_obj;
-} PnvPHB3RootPort;
+ uint32_t chip_id;
+ uint32_t phb_id;
+};
+OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB3RootBus, PNV_PHB3_ROOT_BUS)
/*
* PHB3 PCIe Host Bridge for PowerNV machines (POWER8)
*/
#define TYPE_PNV_PHB3 "pnv-phb3"
-#define PNV_PHB3(obj) OBJECT_CHECK(PnvPHB3, (obj), TYPE_PNV_PHB3)
+OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB3, PNV_PHB3)
#define PNV_PHB3_NUM_M64 16
#define PNV_PHB3_NUM_REGS (0x1000 >> 3)
@@ -123,7 +126,9 @@ typedef struct PnvPHB3RootPort {
#define PCI_MMIO_TOTAL_SIZE (0x1ull << 60)
struct PnvPHB3 {
- PCIExpressHost parent_obj;
+ DeviceState parent;
+
+ PnvPHB *phb_base;
uint32_t chip_id;
uint32_t phb_id;
@@ -151,14 +156,15 @@ struct PnvPHB3 {
PnvPBCQState pbcq;
- PnvPHB3RootPort root;
-
QLIST_HEAD(, PnvPhb3DMASpace) dma_spaces;
+
+ PnvChip *chip;
};
uint64_t pnv_phb3_reg_read(void *opaque, hwaddr off, unsigned size);
void pnv_phb3_reg_write(void *opaque, hwaddr off, uint64_t val, unsigned size);
void pnv_phb3_update_regions(PnvPHB3 *phb);
void pnv_phb3_remap_irqs(PnvPHB3 *phb);
+void pnv_phb3_bus_init(DeviceState *dev, PnvPHB3 *phb);
#endif /* PCI_HOST_PNV_PHB3_H */
diff --git a/include/hw/pci-host/pnv_phb3_regs.h b/include/hw/pci-host/pnv_phb3_regs.h
index a174ef1f70..38f8ce9d74 100644
--- a/include/hw/pci-host/pnv_phb3_regs.h
+++ b/include/hw/pci-host/pnv_phb3_regs.h
@@ -13,22 +13,6 @@
#include "qemu/host-utils.h"
/*
- * QEMU version of the GETFIELD/SETFIELD macros
- *
- * These are common with the PnvXive model.
- */
-static inline uint64_t GETFIELD(uint64_t mask, uint64_t word)
-{
- return (word & mask) >> ctz64(mask);
-}
-
-static inline uint64_t SETFIELD(uint64_t mask, uint64_t word,
- uint64_t value)
-{
- return (word & ~mask) | ((value << ctz64(mask)) & mask);
-}
-
-/*
* PBCQ XSCOM registers
*/
diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h
index c882bfd0aa..3212e68160 100644
--- a/include/hw/pci-host/pnv_phb4.h
+++ b/include/hw/pci-host/pnv_phb4.h
@@ -10,14 +10,14 @@
#ifndef PCI_HOST_PNV_PHB4_H
#define PCI_HOST_PNV_PHB4_H
-#include "hw/pci/pcie_host.h"
-#include "hw/pci/pcie_port.h"
+#include "hw/pci-host/pnv_phb.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/ppc/pnv.h"
#include "hw/ppc/xive.h"
+#include "qom/object.h"
-typedef struct PnvPhb4PecState PnvPhb4PecState;
typedef struct PnvPhb4PecStack PnvPhb4PecStack;
typedef struct PnvPHB4 PnvPHB4;
-typedef struct PnvChip PnvChip;
/*
* We have one such address space wrapper per possible device under
@@ -44,20 +44,22 @@ typedef struct PnvPhb4DMASpace {
} PnvPhb4DMASpace;
/*
- * PHB4 PCIe Root port
+ * PHB4 PCIe Root Bus
*/
-#define TYPE_PNV_PHB4_ROOT_BUS "pnv-phb4-root-bus"
-#define TYPE_PNV_PHB4_ROOT_PORT "pnv-phb4-root-port"
+#define TYPE_PNV_PHB4_ROOT_BUS "pnv-phb4-root"
+struct PnvPHB4RootBus {
+ PCIBus parent;
-typedef struct PnvPHB4RootPort {
- PCIESlot parent_obj;
-} PnvPHB4RootPort;
+ uint32_t chip_id;
+ uint32_t phb_id;
+};
+OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB4RootBus, PNV_PHB4_ROOT_BUS)
/*
* PHB4 PCIe Host Bridge for PowerNV machines (POWER9)
*/
#define TYPE_PNV_PHB4 "pnv-phb4"
-#define PNV_PHB4(obj) OBJECT_CHECK(PnvPHB4, (obj), TYPE_PNV_PHB4)
+OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB4, PNV_PHB4)
#define PNV_PHB4_MAX_LSIs 8
#define PNV_PHB4_MAX_INTs 4096
@@ -76,15 +78,15 @@ typedef struct PnvPHB4RootPort {
#define PCI_MMIO_TOTAL_SIZE (0x1ull << 60)
struct PnvPHB4 {
- PCIExpressHost parent_obj;
+ DeviceState parent;
- PnvPHB4RootPort root;
+ PnvPHB *phb_base;
uint32_t chip_id;
uint32_t phb_id;
- uint64_t version;
- uint16_t device_id;
+ /* The owner PEC */
+ PnvPhb4PecState *pec;
char bus_path[8];
@@ -109,6 +111,29 @@ struct PnvPHB4 {
MemoryRegion pci_mmio;
MemoryRegion pci_io;
+ /* PCI registers (excluding pass-through) */
+#define PHB4_PEC_PCI_STK_REGS_COUNT 0xf
+ uint64_t pci_regs[PHB4_PEC_PCI_STK_REGS_COUNT];
+ MemoryRegion pci_regs_mr;
+
+ /* Nest registers */
+#define PHB4_PEC_NEST_STK_REGS_COUNT 0x18
+ uint64_t nest_regs[PHB4_PEC_NEST_STK_REGS_COUNT];
+ MemoryRegion nest_regs_mr;
+
+ /* PHB pass-through XSCOM */
+ MemoryRegion phb_regs_mr;
+
+ /* Memory windows from PowerBus to PHB */
+ MemoryRegion phbbar;
+ MemoryRegion intbar;
+ MemoryRegion mmbar0;
+ MemoryRegion mmbar1;
+ uint64_t mmio0_base;
+ uint64_t mmio0_size;
+ uint64_t mmio1_base;
+ uint64_t mmio1_size;
+
/* On-chip IODA tables */
uint64_t ioda_LIST[PNV_PHB4_MAX_LSIs];
uint64_t ioda_MIST[PNV_PHB4_MAX_MIST];
@@ -127,62 +152,20 @@ struct PnvPHB4 {
XiveSource xsrc;
qemu_irq *qirqs;
- PnvPhb4PecStack *stack;
-
QLIST_HEAD(, PnvPhb4DMASpace) dma_spaces;
};
void pnv_phb4_pic_print_info(PnvPHB4 *phb, Monitor *mon);
-void pnv_phb4_update_regions(PnvPhb4PecStack *stack);
+int pnv_phb4_pec_get_phb_id(PnvPhb4PecState *pec, int stack_index);
+PnvPhb4PecState *pnv_pec_add_phb(PnvChip *chip, PnvPHB *phb, Error **errp);
+void pnv_phb4_bus_init(DeviceState *dev, PnvPHB4 *phb);
extern const MemoryRegionOps pnv_phb4_xscom_ops;
/*
* PHB4 PEC (PCI Express Controller)
*/
#define TYPE_PNV_PHB4_PEC "pnv-phb4-pec"
-#define PNV_PHB4_PEC(obj) \
- OBJECT_CHECK(PnvPhb4PecState, (obj), TYPE_PNV_PHB4_PEC)
-
-#define TYPE_PNV_PHB4_PEC_STACK "pnv-phb4-pec-stack"
-#define PNV_PHB4_PEC_STACK(obj) \
- OBJECT_CHECK(PnvPhb4PecStack, (obj), TYPE_PNV_PHB4_PEC_STACK)
-
-/* Per-stack data */
-struct PnvPhb4PecStack {
- DeviceState parent;
-
- /* My own stack number */
- uint32_t stack_no;
-
- /* Nest registers */
-#define PHB4_PEC_NEST_STK_REGS_COUNT 0x17
- uint64_t nest_regs[PHB4_PEC_NEST_STK_REGS_COUNT];
- MemoryRegion nest_regs_mr;
-
- /* PCI registers (excluding pass-through) */
-#define PHB4_PEC_PCI_STK_REGS_COUNT 0xf
- uint64_t pci_regs[PHB4_PEC_PCI_STK_REGS_COUNT];
- MemoryRegion pci_regs_mr;
-
- /* PHB pass-through XSCOM */
- MemoryRegion phb_regs_mr;
-
- /* Memory windows from PowerBus to PHB */
- MemoryRegion mmbar0;
- MemoryRegion mmbar1;
- MemoryRegion phbbar;
- MemoryRegion intbar;
- uint64_t mmio0_base;
- uint64_t mmio0_size;
- uint64_t mmio1_base;
- uint64_t mmio1_size;
-
- /* The owner PEC */
- PnvPhb4PecState *pec;
-
- /* The actual PHB */
- PnvPHB4 phb;
-};
+OBJECT_DECLARE_TYPE(PnvPhb4PecState, PnvPhb4PecClass, PNV_PHB4_PEC)
struct PnvPhb4PecState {
DeviceState parent;
@@ -191,30 +174,26 @@ struct PnvPhb4PecState {
uint32_t index;
uint32_t chip_id;
- MemoryRegion *system_memory;
-
/* Nest registers, excuding per-stack */
#define PHB4_PEC_NEST_REGS_COUNT 0xf
uint64_t nest_regs[PHB4_PEC_NEST_REGS_COUNT];
MemoryRegion nest_regs_mr;
/* PCI registers, excluding per-stack */
-#define PHB4_PEC_PCI_REGS_COUNT 0x2
+#define PHB4_PEC_PCI_REGS_COUNT 0x3
uint64_t pci_regs[PHB4_PEC_PCI_REGS_COUNT];
MemoryRegion pci_regs_mr;
- /* Stacks */
- #define PHB4_PEC_MAX_STACKS 3
- uint32_t num_stacks;
- PnvPhb4PecStack stacks[PHB4_PEC_MAX_STACKS];
+ /* PHBs */
+ uint32_t num_phbs;
+#define MAX_PHBS_PER_PEC 3
+ PnvPHB *phbs[MAX_PHBS_PER_PEC];
+
+ PnvChip *chip;
};
-#define PNV_PHB4_PEC_CLASS(klass) \
- OBJECT_CLASS_CHECK(PnvPhb4PecClass, (klass), TYPE_PNV_PHB4_PEC)
-#define PNV_PHB4_PEC_GET_CLASS(obj) \
- OBJECT_GET_CLASS(PnvPhb4PecClass, (obj), TYPE_PNV_PHB4_PEC)
-typedef struct PnvPhb4PecClass {
+struct PnvPhb4PecClass {
DeviceClass parent_class;
uint32_t (*xscom_nest_base)(PnvPhb4PecState *pec);
@@ -225,6 +204,23 @@ typedef struct PnvPhb4PecClass {
int compat_size;
const char *stk_compat;
int stk_compat_size;
-} PnvPhb4PecClass;
+ uint64_t version;
+ const char *phb_type;
+ const uint32_t *num_phbs;
+};
+
+/*
+ * POWER10 definitions
+ */
+
+#define TYPE_PNV_PHB5 "pnv-phb5"
+#define PNV_PHB5(obj) \
+ OBJECT_CHECK(PnvPhb4, (obj), TYPE_PNV_PHB5)
+
+#define PNV_PHB5_VERSION 0x000000a500000002ull
+
+#define TYPE_PNV_PHB5_PEC "pnv-phb5-pec"
+#define PNV_PHB5_PEC(obj) \
+ OBJECT_CHECK(PnvPhb4PecState, (obj), TYPE_PNV_PHB5_PEC)
#endif /* PCI_HOST_PNV_PHB4_H */
diff --git a/include/hw/pci-host/pnv_phb4_regs.h b/include/hw/pci-host/pnv_phb4_regs.h
index 55df2c3e5e..bea96f4d91 100644
--- a/include/hw/pci-host/pnv_phb4_regs.h
+++ b/include/hw/pci-host/pnv_phb4_regs.h
@@ -77,10 +77,12 @@
#define PEC_NEST_STK_BAR_EN_PHB PPC_BIT(2)
#define PEC_NEST_STK_BAR_EN_INT PPC_BIT(3)
#define PEC_NEST_STK_DATA_FRZ_TYPE 0x15
-#define PEC_NEST_STK_PBCQ_TUN_BAR 0x16
+#define PEC_NEST_STK_PBCQ_SPARSE_PAGE 0x16 /* P10 */
+#define PEC_NEST_STK_PBCQ_CACHE_INJ 0x17 /* P10 */
/* XSCOM PCI global registers */
#define PEC_PCI_PBAIB_HW_CONFIG 0x00
+#define PEC_PCI_PBAIB_HW_OVR 0x01
#define PEC_PCI_PBAIB_READ_STK_OVR 0x02
/* XSCOM PCI per-stack registers */
@@ -220,11 +222,14 @@
#define PHB_PAPR_ERR_INJ_MASK_MMIO PPC_BITMASK(16, 63)
#define PHB_ETU_ERR_SUMMARY 0x2c8
#define PHB_INT_NOTIFY_ADDR 0x300
+#define PHB_INT_NOTIFY_ADDR_64K PPC_BIT(1) /* P10 */
#define PHB_INT_NOTIFY_INDEX 0x308
/* Fundamental register set B */
#define PHB_VERSION 0x800
#define PHB_CTRLR 0x810
+#define PHB_CTRLR_IRQ_PQ_DISABLE PPC_BIT(9) /* P10 */
+#define PHB_CTRLR_IRQ_ABT_MODE PPC_BIT(10) /* P10 */
#define PHB_CTRLR_IRQ_PGSZ_64K PPC_BIT(11)
#define PHB_CTRLR_IRQ_STORE_EOI PPC_BIT(12)
#define PHB_CTRLR_MMIO_RD_STRICT PPC_BIT(13)
diff --git a/include/hw/pci-host/ppc4xx.h b/include/hw/pci-host/ppc4xx.h
new file mode 100644
index 0000000000..32396417fc
--- /dev/null
+++ b/include/hw/pci-host/ppc4xx.h
@@ -0,0 +1,17 @@
+/*
+ * QEMU PowerPC 4xx PCI-host definitions
+ *
+ * Copyright (c) 2018-2023 BALATON Zoltan
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_PCIHOST_PPC4XX_H
+#define HW_PCIHOST_PPC4XX_H
+
+#define TYPE_PPC4xx_HOST_BRIDGE "ppc4xx-host-bridge"
+#define TYPE_PPC4xx_PCI_HOST "ppc4xx-pci-host"
+#define TYPE_PPC440_PCIX_HOST "ppc440-pcix-host"
+#define TYPE_PPC460EX_PCIE_HOST "ppc460ex-pcie-host"
+
+#endif
diff --git a/include/hw/pci-host/q35.h b/include/hw/pci-host/q35.h
index 070305f83d..22fadfa3ed 100644
--- a/include/hw/pci-host/q35.h
+++ b/include/hw/pci-host/q35.h
@@ -22,21 +22,20 @@
#ifndef HW_Q35_H
#define HW_Q35_H
-#include "hw/pci/pci.h"
+#include "hw/pci/pci_device.h"
#include "hw/pci/pcie_host.h"
#include "hw/pci-host/pam.h"
#include "qemu/units.h"
#include "qemu/range.h"
+#include "qom/object.h"
#define TYPE_Q35_HOST_DEVICE "q35-pcihost"
-#define Q35_HOST_DEVICE(obj) \
- OBJECT_CHECK(Q35PCIHost, (obj), TYPE_Q35_HOST_DEVICE)
+OBJECT_DECLARE_SIMPLE_TYPE(Q35PCIHost, Q35_HOST_DEVICE)
#define TYPE_MCH_PCI_DEVICE "mch"
-#define MCH_PCI_DEVICE(obj) \
- OBJECT_CHECK(MCHPCIState, (obj), TYPE_MCH_PCI_DEVICE)
+OBJECT_DECLARE_SIMPLE_TYPE(MCHPCIState, MCH_PCI_DEVICE)
-typedef struct MCHPCIState {
+struct MCHPCIState {
/*< private >*/
PCIDevice parent_obj;
/*< public >*/
@@ -45,28 +44,28 @@ typedef struct MCHPCIState {
MemoryRegion *pci_address_space;
MemoryRegion *system_memory;
MemoryRegion *address_space_io;
- PAMMemoryRegion pam_regions[13];
+ PAMMemoryRegion pam_regions[PAM_REGIONS_COUNT];
MemoryRegion smram_region, open_high_smram;
MemoryRegion smram, low_smram, high_smram;
MemoryRegion tseg_blackhole, tseg_window;
MemoryRegion smbase_blackhole, smbase_window;
bool has_smram_at_smbase;
+ bool has_smm_ranges;
Range pci_hole;
uint64_t below_4g_mem_size;
uint64_t above_4g_mem_size;
uint64_t pci_hole64_size;
- uint32_t short_root_bus;
uint16_t ext_tseg_mbytes;
-} MCHPCIState;
+};
-typedef struct Q35PCIHost {
+struct Q35PCIHost {
/*< private >*/
PCIExpressHost parent_obj;
/*< public >*/
bool pci_hole64_fix;
MCHPCIState mch;
-} Q35PCIHost;
+};
#define Q35_MASK(bit, ms_bit, ls_bit) \
((uint##bit##_t)(((1ULL << ((ms_bit) + 1)) - 1) & ~((1ULL << ls_bit) - 1)))
@@ -75,11 +74,6 @@ typedef struct Q35PCIHost {
* gmch part
*/
-#define MCH_HOST_PROP_RAM_MEM "ram-mem"
-#define MCH_HOST_PROP_PCI_MEM "pci-mem"
-#define MCH_HOST_PROP_SYSTEM_MEM "system-mem"
-#define MCH_HOST_PROP_IO_MEM "io-mem"
-
/* PCI configuration */
#define MCH_HOST_BRIDGE "MCH"
diff --git a/include/hw/pci-host/remote.h b/include/hw/pci-host/remote.h
new file mode 100644
index 0000000000..690a01f0fe
--- /dev/null
+++ b/include/hw/pci-host/remote.h
@@ -0,0 +1,30 @@
+/*
+ * PCI Host for remote device
+ *
+ * Copyright © 2018, 2021 Oracle and/or its affiliates.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef PCI_HOST_REMOTE_H
+#define PCI_HOST_REMOTE_H
+
+#include "exec/memory.h"
+#include "hw/pci/pcie_host.h"
+
+#define TYPE_REMOTE_PCIHOST "remote-pcihost"
+OBJECT_DECLARE_SIMPLE_TYPE(RemotePCIHost, REMOTE_PCIHOST)
+
+struct RemotePCIHost {
+ /*< private >*/
+ PCIExpressHost parent_obj;
+ /*< public >*/
+
+ MemoryRegion *mr_pci_mem;
+ MemoryRegion *mr_sys_io;
+ MemoryRegion *mr_sys_mem;
+};
+
+#endif
diff --git a/include/hw/pci-host/sabre.h b/include/hw/pci-host/sabre.h
index 99b5aefbec..d12de84ea2 100644
--- a/include/hw/pci-host/sabre.h
+++ b/include/hw/pci-host/sabre.h
@@ -1,9 +1,10 @@
#ifndef HW_PCI_HOST_SABRE_H
#define HW_PCI_HOST_SABRE_H
-#include "hw/pci/pci.h"
+#include "hw/pci/pci_device.h"
#include "hw/pci/pci_host.h"
#include "hw/sparc/sun4u_iommu.h"
+#include "qom/object.h"
#define MAX_IVEC 0x40
@@ -16,15 +17,14 @@
#define OBIO_MSE_IRQ 0x2a
#define OBIO_SER_IRQ 0x2b
-typedef struct SabrePCIState {
+struct SabrePCIState {
PCIDevice parent_obj;
-} SabrePCIState;
+};
#define TYPE_SABRE_PCI_DEVICE "sabre-pci"
-#define SABRE_PCI_DEVICE(obj) \
- OBJECT_CHECK(SabrePCIState, (obj), TYPE_SABRE_PCI_DEVICE)
+OBJECT_DECLARE_SIMPLE_TYPE(SabrePCIState, SABRE_PCI_DEVICE)
-typedef struct SabreState {
+struct SabreState {
PCIHostState parent_obj;
hwaddr special_base;
@@ -45,10 +45,9 @@ typedef struct SabreState {
unsigned int irq_request;
uint32_t reset_control;
unsigned int nr_resets;
-} SabreState;
+};
#define TYPE_SABRE "sabre"
-#define SABRE_DEVICE(obj) \
- OBJECT_CHECK(SabreState, (obj), TYPE_SABRE)
+OBJECT_DECLARE_SIMPLE_TYPE(SabreState, SABRE)
#endif
diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
index 600eb55c34..3778aac27b 100644
--- a/include/hw/pci-host/spapr.h
+++ b/include/hw/pci-host/spapr.h
@@ -6,7 +6,7 @@
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -24,15 +24,14 @@
#include "hw/pci/pci.h"
#include "hw/pci/pci_host.h"
#include "hw/ppc/xics.h"
+#include "qom/object.h"
#define TYPE_SPAPR_PCI_HOST_BRIDGE "spapr-pci-host-bridge"
-#define SPAPR_PCI_HOST_BRIDGE(obj) \
- OBJECT_CHECK(SpaprPhbState, (obj), TYPE_SPAPR_PCI_HOST_BRIDGE)
+OBJECT_DECLARE_SIMPLE_TYPE(SpaprPhbState, SPAPR_PCI_HOST_BRIDGE)
#define SPAPR_PCI_DMA_MAX_WINDOWS 2
-typedef struct SpaprPhbState SpaprPhbState;
typedef struct SpaprPciMsi {
uint32_t first_irq;
@@ -48,8 +47,6 @@ typedef struct SpaprPciLsi {
uint32_t irq;
} SpaprPciLsi;
-typedef struct SpaprPhbPciNvGpuConfig SpaprPhbPciNvGpuConfig;
-
struct SpaprPhbState {
PCIHostState parent_obj;
@@ -91,9 +88,6 @@ struct SpaprPhbState {
uint32_t mig_liobn;
hwaddr mig_mem_win_addr, mig_mem_win_size;
hwaddr mig_io_win_addr, mig_io_win_size;
- hwaddr nv2_gpa_win_addr;
- hwaddr nv2_atsd_win_addr;
- SpaprPhbPciNvGpuConfig *nvgpus;
bool pre_5_1_assoc;
};
@@ -113,22 +107,6 @@ struct SpaprPhbState {
#define SPAPR_PCI_MSI_WINDOW 0x40000000000ULL
-#define SPAPR_PCI_NV2RAM64_WIN_BASE SPAPR_PCI_LIMIT
-#define SPAPR_PCI_NV2RAM64_WIN_SIZE (2 * TiB) /* For up to 6 GPUs 256GB each */
-
-/* Max number of these GPUsper a physical box */
-#define NVGPU_MAX_NUM 6
-/* Max number of NVLinks per GPU in any physical box */
-#define NVGPU_MAX_LINKS 3
-
-/*
- * GPU RAM starts at 64TiB so huge DMA window to cover it all ends at 128TiB
- * which is enough. We do not need DMA for ATSD so we put them at 128TiB.
- */
-#define SPAPR_PCI_NV2ATSD_WIN_BASE (128 * TiB)
-#define SPAPR_PCI_NV2ATSD_WIN_SIZE (NVGPU_MAX_NUM * NVGPU_MAX_LINKS * \
- 64 * KiB)
-
int spapr_dt_phb(SpaprMachineState *spapr, SpaprPhbState *phb,
uint32_t intc_phandle, void *fdt, int *node_offset);
@@ -152,13 +130,6 @@ int spapr_phb_vfio_eeh_get_state(SpaprPhbState *sphb, int *state);
int spapr_phb_vfio_eeh_reset(SpaprPhbState *sphb, int option);
int spapr_phb_vfio_eeh_configure(SpaprPhbState *sphb);
void spapr_phb_vfio_reset(DeviceState *qdev);
-void spapr_phb_nvgpu_setup(SpaprPhbState *sphb, Error **errp);
-void spapr_phb_nvgpu_free(SpaprPhbState *sphb);
-void spapr_phb_nvgpu_populate_dt(SpaprPhbState *sphb, void *fdt, int bus_off,
- Error **errp);
-void spapr_phb_nvgpu_ram_populate_dt(SpaprPhbState *sphb, void *fdt);
-void spapr_phb_nvgpu_populate_pcidev_dt(PCIDevice *dev, void *fdt, int offset,
- SpaprPhbState *sphb);
#else
static inline bool spapr_phb_eeh_available(SpaprPhbState *sphb)
{
@@ -185,25 +156,6 @@ static inline int spapr_phb_vfio_eeh_configure(SpaprPhbState *sphb)
static inline void spapr_phb_vfio_reset(DeviceState *qdev)
{
}
-static inline void spapr_phb_nvgpu_setup(SpaprPhbState *sphb, Error **errp)
-{
-}
-static inline void spapr_phb_nvgpu_free(SpaprPhbState *sphb)
-{
-}
-static inline void spapr_phb_nvgpu_populate_dt(SpaprPhbState *sphb, void *fdt,
- int bus_off, Error **errp)
-{
-}
-static inline void spapr_phb_nvgpu_ram_populate_dt(SpaprPhbState *sphb,
- void *fdt)
-{
-}
-static inline void spapr_phb_nvgpu_populate_pcidev_dt(PCIDevice *dev, void *fdt,
- int offset,
- SpaprPhbState *sphb)
-{
-}
#endif
void spapr_phb_dma_reset(SpaprPhbState *sphb);
@@ -213,4 +165,6 @@ static inline unsigned spapr_phb_windows_supported(SpaprPhbState *sphb)
return sphb->ddw_enabled ? SPAPR_PCI_DMA_MAX_WINDOWS : 1;
}
+char *spapr_pci_fw_dev_name(PCIDevice *dev);
+
#endif /* PCI_HOST_SPAPR_H */
diff --git a/include/hw/pci-host/uninorth.h b/include/hw/pci-host/uninorth.h
index 72d2a97355..62bd81e721 100644
--- a/include/hw/pci-host/uninorth.h
+++ b/include/hw/pci-host/uninorth.h
@@ -26,7 +26,7 @@
#define UNINORTH_H
#include "hw/pci/pci_host.h"
-#include "hw/ppc/openpic.h"
+#include "qom/object.h"
/* UniNorth version */
#define UNINORTH_VERSION_10A 0x7
@@ -36,34 +36,33 @@
#define TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE "uni-north-internal-pci-pcihost"
#define TYPE_U3_AGP_HOST_BRIDGE "u3-agp-pcihost"
-#define UNI_NORTH_PCI_HOST_BRIDGE(obj) \
- OBJECT_CHECK(UNINHostState, (obj), TYPE_UNI_NORTH_PCI_HOST_BRIDGE)
-#define UNI_NORTH_AGP_HOST_BRIDGE(obj) \
- OBJECT_CHECK(UNINHostState, (obj), TYPE_UNI_NORTH_AGP_HOST_BRIDGE)
-#define UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE(obj) \
- OBJECT_CHECK(UNINHostState, (obj), TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE)
-#define U3_AGP_HOST_BRIDGE(obj) \
- OBJECT_CHECK(UNINHostState, (obj), TYPE_U3_AGP_HOST_BRIDGE)
+typedef struct UNINHostState UNINHostState;
+DECLARE_INSTANCE_CHECKER(UNINHostState, UNI_NORTH_PCI_HOST_BRIDGE,
+ TYPE_UNI_NORTH_PCI_HOST_BRIDGE)
+DECLARE_INSTANCE_CHECKER(UNINHostState, UNI_NORTH_AGP_HOST_BRIDGE,
+ TYPE_UNI_NORTH_AGP_HOST_BRIDGE)
+DECLARE_INSTANCE_CHECKER(UNINHostState, UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE,
+ TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE)
+DECLARE_INSTANCE_CHECKER(UNINHostState, U3_AGP_HOST_BRIDGE,
+ TYPE_U3_AGP_HOST_BRIDGE)
-typedef struct UNINHostState {
+struct UNINHostState {
PCIHostState parent_obj;
uint32_t ofw_addr;
- OpenPICState *pic;
qemu_irq irqs[4];
MemoryRegion pci_mmio;
MemoryRegion pci_hole;
MemoryRegion pci_io;
-} UNINHostState;
+};
-typedef struct UNINState {
+struct UNINState {
SysBusDevice parent_obj;
MemoryRegion mem;
-} UNINState;
+};
#define TYPE_UNI_NORTH "uni-north"
-#define UNI_NORTH(obj) \
- OBJECT_CHECK(UNINState, (obj), TYPE_UNI_NORTH)
+OBJECT_DECLARE_SIMPLE_TYPE(UNINState, UNI_NORTH)
#endif /* UNINORTH_H */
diff --git a/include/hw/pci-host/xilinx-pcie.h b/include/hw/pci-host/xilinx-pcie.h
index c0f15314be..e1b3c1c280 100644
--- a/include/hw/pci-host/xilinx-pcie.h
+++ b/include/hw/pci-host/xilinx-pcie.h
@@ -6,7 +6,7 @@
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -21,28 +21,26 @@
#define HW_XILINX_PCIE_H
#include "hw/sysbus.h"
-#include "hw/pci/pci.h"
#include "hw/pci/pci_bridge.h"
#include "hw/pci/pcie_host.h"
+#include "qom/object.h"
#define TYPE_XILINX_PCIE_HOST "xilinx-pcie-host"
-#define XILINX_PCIE_HOST(obj) \
- OBJECT_CHECK(XilinxPCIEHost, (obj), TYPE_XILINX_PCIE_HOST)
+OBJECT_DECLARE_SIMPLE_TYPE(XilinxPCIEHost, XILINX_PCIE_HOST)
#define TYPE_XILINX_PCIE_ROOT "xilinx-pcie-root"
-#define XILINX_PCIE_ROOT(obj) \
- OBJECT_CHECK(XilinxPCIERoot, (obj), TYPE_XILINX_PCIE_ROOT)
+OBJECT_DECLARE_SIMPLE_TYPE(XilinxPCIERoot, XILINX_PCIE_ROOT)
-typedef struct XilinxPCIERoot {
+struct XilinxPCIERoot {
PCIBridge parent_obj;
-} XilinxPCIERoot;
+};
typedef struct XilinxPCIEInt {
uint32_t fifo_reg1;
uint32_t fifo_reg2;
} XilinxPCIEInt;
-typedef struct XilinxPCIEHost {
+struct XilinxPCIEHost {
PCIExpressHost parent_obj;
char name[16];
@@ -62,6 +60,6 @@ typedef struct XilinxPCIEHost {
XilinxPCIEInt intr_fifo[16];
unsigned int intr_fifo_r, intr_fifo_w;
uint32_t rpscr;
-} XilinxPCIEHost;
+};
#endif /* HW_XILINX_PCIE_H */
diff --git a/include/hw/pci/msi.h b/include/hw/pci/msi.h
index 4087688486..abcfd13925 100644
--- a/include/hw/pci/msi.h
+++ b/include/hw/pci/msi.h
@@ -21,7 +21,7 @@
#ifndef QEMU_MSI_H
#define QEMU_MSI_H
-#include "hw/pci/pci.h"
+#include "hw/pci/pci_device.h"
struct MSIMessage {
uint64_t address;
@@ -33,6 +33,7 @@ extern bool msi_nonbroken;
void msi_set_message(PCIDevice *dev, MSIMessage msg);
MSIMessage msi_get_message(PCIDevice *dev, unsigned int vector);
bool msi_enabled(const PCIDevice *dev);
+void msi_set_enabled(PCIDevice *dev);
int msi_init(struct PCIDevice *dev, uint8_t offset,
unsigned int nr_vectors, bool msi64bit,
bool msi_per_vector_mask, Error **errp);
@@ -43,6 +44,7 @@ void msi_notify(PCIDevice *dev, unsigned int vector);
void msi_send_message(PCIDevice *dev, MSIMessage msg);
void msi_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len);
unsigned int msi_nr_vectors_allocated(const PCIDevice *dev);
+void msi_set_mask(PCIDevice *dev, int vector, bool mask, Error **errp);
static inline bool msi_present(const PCIDevice *dev)
{
diff --git a/include/hw/pci/msix.h b/include/hw/pci/msix.h
index 4c4a60c739..0e6f257e45 100644
--- a/include/hw/pci/msix.h
+++ b/include/hw/pci/msix.h
@@ -33,9 +33,10 @@ bool msix_is_masked(PCIDevice *dev, unsigned vector);
void msix_set_pending(PCIDevice *dev, unsigned vector);
void msix_clr_pending(PCIDevice *dev, int vector);
-int msix_vector_use(PCIDevice *dev, unsigned vector);
+void msix_vector_use(PCIDevice *dev, unsigned vector);
void msix_vector_unuse(PCIDevice *dev, unsigned vector);
void msix_unuse_all_vectors(PCIDevice *dev);
+void msix_set_mask(PCIDevice *dev, int vector, bool mask);
void msix_notify(PCIDevice *dev, unsigned vector);
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index c1bf7d5356..eaa3fc99d8 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -7,8 +7,6 @@
/* PCI includes legacy ISA access. */
#include "hw/isa/isa.h"
-#include "hw/pci/pcie.h"
-
extern bool pci_available;
/* PCI bus */
@@ -18,6 +16,7 @@ extern bool pci_available;
#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
#define PCI_FUNC(devfn) ((devfn) & 0x07)
#define PCI_BUILD_BDF(bus, devfn) ((bus << 8) | (devfn))
+#define PCI_BDF_TO_DEVFN(x) ((x) & 0xff)
#define PCI_BUS_MAX 256
#define PCI_DEVFN_MAX 256
#define PCI_SLOT_MAX 32
@@ -77,6 +76,7 @@ extern bool pci_available;
#define PCI_SUBVENDOR_ID_REDHAT_QUMRANET 0x1af4
#define PCI_SUBDEVICE_ID_QEMU 0x1100
+/* legacy virtio-pci devices */
#define PCI_DEVICE_ID_VIRTIO_NET 0x1000
#define PCI_DEVICE_ID_VIRTIO_BLOCK 0x1001
#define PCI_DEVICE_ID_VIRTIO_BALLOON 0x1002
@@ -85,9 +85,15 @@ extern bool pci_available;
#define PCI_DEVICE_ID_VIRTIO_RNG 0x1005
#define PCI_DEVICE_ID_VIRTIO_9P 0x1009
#define PCI_DEVICE_ID_VIRTIO_VSOCK 0x1012
-#define PCI_DEVICE_ID_VIRTIO_PMEM 0x1013
-#define PCI_DEVICE_ID_VIRTIO_IOMMU 0x1014
-#define PCI_DEVICE_ID_VIRTIO_MEM 0x1015
+
+/*
+ * modern virtio-pci devices get their id assigned automatically,
+ * there is no need to add #defines here. It gets calculated as
+ *
+ * PCI_DEVICE_ID = PCI_DEVICE_ID_VIRTIO_10_BASE +
+ * virtio_bus_get_vdev_id(bus)
+ */
+#define PCI_DEVICE_ID_VIRTIO_10_BASE 0x1040
#define PCI_VENDOR_ID_REDHAT 0x1b36
#define PCI_DEVICE_ID_REDHAT_BRIDGE 0x0001
@@ -105,6 +111,10 @@ extern bool pci_available;
#define PCI_DEVICE_ID_REDHAT_XHCI 0x000d
#define PCI_DEVICE_ID_REDHAT_PCIE_BRIDGE 0x000e
#define PCI_DEVICE_ID_REDHAT_MDPY 0x000f
+#define PCI_DEVICE_ID_REDHAT_NVME 0x0010
+#define PCI_DEVICE_ID_REDHAT_PVPANIC 0x0011
+#define PCI_DEVICE_ID_REDHAT_ACPI_ERST 0x0012
+#define PCI_DEVICE_ID_REDHAT_UFS 0x0013
#define PCI_DEVICE_ID_REDHAT_QXL 0x0100
#define FMT_PCIBUS PRIx64
@@ -126,6 +136,10 @@ typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type);
typedef void PCIUnregisterFunc(PCIDevice *pci_dev);
+typedef void MSITriggerFunc(PCIDevice *dev, MSIMessage msg);
+typedef MSIMessage MSIPrepareMessageFunc(PCIDevice *dev, unsigned vector);
+typedef MSIMessage MSIxPrepareMessageFunc(PCIDevice *dev, unsigned vector);
+
typedef struct PCIIORegion {
pcibus_t addr; /* current PCI mapping address. -1 means not mapped */
#define PCI_BAR_UNMAPPED (~(pcibus_t)0)
@@ -192,22 +206,14 @@ enum {
QEMU_PCIE_LNKSTA_DLLLA = (1 << QEMU_PCIE_LNKSTA_DLLLA_BITNR),
#define QEMU_PCIE_EXTCAP_INIT_BITNR 9
QEMU_PCIE_EXTCAP_INIT = (1 << QEMU_PCIE_EXTCAP_INIT_BITNR),
+#define QEMU_PCIE_CXL_BITNR 10
+ QEMU_PCIE_CAP_CXL = (1 << QEMU_PCIE_CXL_BITNR),
+#define QEMU_PCIE_ERR_UNC_MASK_BITNR 11
+ QEMU_PCIE_ERR_UNC_MASK = (1 << QEMU_PCIE_ERR_UNC_MASK_BITNR),
+#define QEMU_PCIE_ARI_NEXTFN_1_BITNR 12
+ QEMU_PCIE_ARI_NEXTFN_1 = (1 << QEMU_PCIE_ARI_NEXTFN_1_BITNR),
};
-#define TYPE_PCI_DEVICE "pci-device"
-#define PCI_DEVICE(obj) \
- OBJECT_CHECK(PCIDevice, (obj), TYPE_PCI_DEVICE)
-#define PCI_DEVICE_CLASS(klass) \
- OBJECT_CLASS_CHECK(PCIDeviceClass, (klass), TYPE_PCI_DEVICE)
-#define PCI_DEVICE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(PCIDeviceClass, (obj), TYPE_PCI_DEVICE)
-
-/* Implemented by devices that can be plugged on PCI Express buses */
-#define INTERFACE_PCIE_DEVICE "pci-express-device"
-
-/* Implemented by devices that can be plugged on Conventional PCI buses */
-#define INTERFACE_CONVENTIONAL_PCI_DEVICE "conventional-pci-device"
-
typedef struct PCIINTxRoute {
enum {
PCI_INTX_ENABLED,
@@ -217,32 +223,6 @@ typedef struct PCIINTxRoute {
int irq;
} PCIINTxRoute;
-typedef struct PCIDeviceClass {
- DeviceClass parent_class;
-
- void (*realize)(PCIDevice *dev, Error **errp);
- PCIUnregisterFunc *exit;
- PCIConfigReadFunc *config_read;
- PCIConfigWriteFunc *config_write;
-
- uint16_t vendor_id;
- uint16_t device_id;
- uint8_t revision;
- uint16_t class_id;
- uint16_t subsystem_vendor_id; /* only for header type = 0 */
- uint16_t subsystem_id; /* only for header type = 0 */
-
- /*
- * pci-to-pci bridge or normal device.
- * This doesn't mean pci host switch.
- * When card bus bridge is supported, this would be enhanced.
- */
- bool is_bridge;
-
- /* rom bar */
- const char *romfile;
-} PCIDeviceClass;
-
typedef void (*PCIINTxRoutingNotifier)(PCIDevice *dev);
typedef int (*MSIVectorUseNotifier)(PCIDevice *dev, unsigned int vector,
MSIMessage msg);
@@ -251,115 +231,6 @@ typedef void (*MSIVectorPollNotifier)(PCIDevice *dev,
unsigned int vector_start,
unsigned int vector_end);
-enum PCIReqIDType {
- PCI_REQ_ID_INVALID = 0,
- PCI_REQ_ID_BDF,
- PCI_REQ_ID_SECONDARY_BUS,
- PCI_REQ_ID_MAX,
-};
-typedef enum PCIReqIDType PCIReqIDType;
-
-struct PCIReqIDCache {
- PCIDevice *dev;
- PCIReqIDType type;
-};
-typedef struct PCIReqIDCache PCIReqIDCache;
-
-struct PCIDevice {
- DeviceState qdev;
- bool partially_hotplugged;
-
- /* PCI config space */
- uint8_t *config;
-
- /* Used to enable config checks on load. Note that writable bits are
- * never checked even if set in cmask. */
- uint8_t *cmask;
-
- /* Used to implement R/W bytes */
- uint8_t *wmask;
-
- /* Used to implement RW1C(Write 1 to Clear) bytes */
- uint8_t *w1cmask;
-
- /* Used to allocate config space for capabilities. */
- uint8_t *used;
-
- /* the following fields are read only */
- int32_t devfn;
- /* Cached device to fetch requester ID from, to avoid the PCI
- * tree walking every time we invoke PCI request (e.g.,
- * MSI). For conventional PCI root complex, this field is
- * meaningless. */
- PCIReqIDCache requester_id_cache;
- char name[64];
- PCIIORegion io_regions[PCI_NUM_REGIONS];
- AddressSpace bus_master_as;
- MemoryRegion bus_master_container_region;
- MemoryRegion bus_master_enable_region;
-
- /* do not access the following fields */
- PCIConfigReadFunc *config_read;
- PCIConfigWriteFunc *config_write;
-
- /* Legacy PCI VGA regions */
- MemoryRegion *vga_regions[QEMU_PCI_VGA_NUM_REGIONS];
- bool has_vga;
-
- /* Current IRQ levels. Used internally by the generic PCI code. */
- uint8_t irq_state;
-
- /* Capability bits */
- uint32_t cap_present;
-
- /* Offset of MSI-X capability in config space */
- uint8_t msix_cap;
-
- /* MSI-X entries */
- int msix_entries_nr;
-
- /* Space to store MSIX table & pending bit array */
- uint8_t *msix_table;
- uint8_t *msix_pba;
- /* MemoryRegion container for msix exclusive BAR setup */
- MemoryRegion msix_exclusive_bar;
- /* Memory Regions for MSIX table and pending bit entries. */
- MemoryRegion msix_table_mmio;
- MemoryRegion msix_pba_mmio;
- /* Reference-count for entries actually in use by driver. */
- unsigned *msix_entry_used;
- /* MSIX function mask set or MSIX disabled */
- bool msix_function_masked;
- /* Version id needed for VMState */
- int32_t version_id;
-
- /* Offset of MSI capability in config space */
- uint8_t msi_cap;
-
- /* PCI Express */
- PCIExpressDevice exp;
-
- /* SHPC */
- SHPCDevice *shpc;
-
- /* Location of option rom */
- char *romfile;
- bool has_rom;
- MemoryRegion rom;
- uint32_t rom_bar;
-
- /* INTx routing notifier */
- PCIINTxRoutingNotifier intx_routing_notifier;
-
- /* MSI-X notifiers */
- MSIVectorUseNotifier msix_vector_use_notifier;
- MSIVectorReleaseNotifier msix_vector_release_notifier;
- MSIVectorPollNotifier msix_vector_poll_notifier;
-
- /* ID of standby device in net_failover pair */
- char *failover_pair_id;
-};
-
void pci_register_bar(PCIDevice *pci_dev, int region_num,
uint8_t attr, MemoryRegion *memory);
void pci_register_vga(PCIDevice *pci_dev, MemoryRegion *mem,
@@ -396,27 +267,32 @@ typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num);
typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin);
#define TYPE_PCI_BUS "PCI"
-#define PCI_BUS(obj) OBJECT_CHECK(PCIBus, (obj), TYPE_PCI_BUS)
-#define PCI_BUS_CLASS(klass) OBJECT_CLASS_CHECK(PCIBusClass, (klass), TYPE_PCI_BUS)
-#define PCI_BUS_GET_CLASS(obj) OBJECT_GET_CLASS(PCIBusClass, (obj), TYPE_PCI_BUS)
+OBJECT_DECLARE_TYPE(PCIBus, PCIBusClass, PCI_BUS)
#define TYPE_PCIE_BUS "PCIE"
+#define TYPE_CXL_BUS "CXL"
+
+typedef void (*pci_bus_dev_fn)(PCIBus *b, PCIDevice *d, void *opaque);
+typedef void (*pci_bus_fn)(PCIBus *b, void *opaque);
+typedef void *(*pci_bus_ret_fn)(PCIBus *b, void *opaque);
-bool pci_bus_is_express(PCIBus *bus);
+bool pci_bus_is_express(const PCIBus *bus);
-void pci_root_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent,
- const char *name,
- MemoryRegion *address_space_mem,
- MemoryRegion *address_space_io,
- uint8_t devfn_min, const char *typename);
+void pci_root_bus_init(PCIBus *bus, size_t bus_size, DeviceState *parent,
+ const char *name,
+ MemoryRegion *mem, MemoryRegion *io,
+ uint8_t devfn_min, const char *typename);
PCIBus *pci_root_bus_new(DeviceState *parent, const char *name,
- MemoryRegion *address_space_mem,
- MemoryRegion *address_space_io,
+ MemoryRegion *mem, MemoryRegion *io,
uint8_t devfn_min, const char *typename);
void pci_root_bus_cleanup(PCIBus *bus);
-void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
+void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq,
void *irq_opaque, int nirq);
+void pci_bus_map_irqs(PCIBus *bus, pci_map_irq_fn map_irq);
void pci_bus_irqs_cleanup(PCIBus *bus);
int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
+uint32_t pci_bus_get_slot_reserved_mask(PCIBus *bus);
+void pci_bus_set_slot_reserved_mask(PCIBus *bus, uint32_t mask);
+void pci_bus_clear_slot_reserved_mask(PCIBus *bus, uint32_t mask);
/* 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD */
static inline int pci_swizzle(int slot, int pin)
{
@@ -426,8 +302,7 @@ int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin);
PCIBus *pci_register_root_bus(DeviceState *parent, const char *name,
pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
void *irq_opaque,
- MemoryRegion *address_space_mem,
- MemoryRegion *address_space_io,
+ MemoryRegion *mem, MemoryRegion *io,
uint8_t devfn_min, int nirq,
const char *typename);
void pci_unregister_root_bus(PCIBus *bus);
@@ -439,10 +314,9 @@ void pci_device_set_intx_routing_notifier(PCIDevice *dev,
PCIINTxRoutingNotifier notifier);
void pci_device_reset(PCIDevice *dev);
-PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
- const char *default_model,
- const char *default_devaddr);
-
+void pci_init_nic_devices(PCIBus *bus, const char *default_model);
+bool pci_init_nic_in_slot(PCIBus *rootbus, const char *default_model,
+ const char *alias, const char *devaddr);
PCIDevice *pci_vga_init(PCIBus *bus);
static inline PCIBus *pci_get_bus(const PCIDevice *dev)
@@ -450,6 +324,7 @@ static inline PCIBus *pci_get_bus(const PCIDevice *dev)
return PCI_BUS(qdev_get_parent_bus(DEVICE(dev)));
}
int pci_bus_num(PCIBus *s);
+void pci_bus_range(PCIBus *bus, int *min_bus, int *max_bus);
static inline int pci_dev_bus_num(const PCIDevice *dev)
{
return pci_bus_num(pci_get_bus(dev));
@@ -457,39 +332,75 @@ static inline int pci_dev_bus_num(const PCIDevice *dev)
int pci_bus_numa_node(PCIBus *bus);
void pci_for_each_device(PCIBus *bus, int bus_num,
- void (*fn)(PCIBus *bus, PCIDevice *d, void *opaque),
+ pci_bus_dev_fn fn,
void *opaque);
void pci_for_each_device_reverse(PCIBus *bus, int bus_num,
- void (*fn)(PCIBus *bus, PCIDevice *d,
- void *opaque),
+ pci_bus_dev_fn fn,
void *opaque);
-void pci_for_each_bus_depth_first(PCIBus *bus,
- void *(*begin)(PCIBus *bus, void *parent_state),
- void (*end)(PCIBus *bus, void *state),
- void *parent_state);
+void pci_for_each_device_under_bus(PCIBus *bus,
+ pci_bus_dev_fn fn, void *opaque);
+void pci_for_each_device_under_bus_reverse(PCIBus *bus,
+ pci_bus_dev_fn fn,
+ void *opaque);
+void pci_for_each_bus_depth_first(PCIBus *bus, pci_bus_ret_fn begin,
+ pci_bus_fn end, void *parent_state);
PCIDevice *pci_get_function_0(PCIDevice *pci_dev);
/* Use this wrapper when specific scan order is not required. */
static inline
-void pci_for_each_bus(PCIBus *bus,
- void (*fn)(PCIBus *bus, void *opaque),
- void *opaque)
+void pci_for_each_bus(PCIBus *bus, pci_bus_fn fn, void *opaque)
{
pci_for_each_bus_depth_first(bus, NULL, fn, opaque);
}
PCIBus *pci_device_root_bus(const PCIDevice *d);
const char *pci_root_bus_path(PCIDevice *dev);
+bool pci_bus_bypass_iommu(PCIBus *bus);
PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn);
int pci_qdev_find_device(const char *id, PCIDevice **pdev);
void pci_bus_get_w64_range(PCIBus *bus, Range *range);
void pci_device_deassert_intx(PCIDevice *dev);
-typedef AddressSpace *(*PCIIOMMUFunc)(PCIBus *, void *, int);
+
+/**
+ * struct PCIIOMMUOps: callbacks structure for specific IOMMU handlers
+ * of a PCIBus
+ *
+ * Allows to modify the behavior of some IOMMU operations of the PCI
+ * framework for a set of devices on a PCI bus.
+ */
+typedef struct PCIIOMMUOps {
+ /**
+ * @get_address_space: get the address space for a set of devices
+ * on a PCI bus.
+ *
+ * Mandatory callback which returns a pointer to an #AddressSpace
+ *
+ * @bus: the #PCIBus being accessed.
+ *
+ * @opaque: the data passed to pci_setup_iommu().
+ *
+ * @devfn: device and function number
+ */
+ AddressSpace * (*get_address_space)(PCIBus *bus, void *opaque, int devfn);
+} PCIIOMMUOps;
AddressSpace *pci_device_iommu_address_space(PCIDevice *dev);
-void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque);
+
+/**
+ * pci_setup_iommu: Initialize specific IOMMU handlers for a PCIBus
+ *
+ * Let PCI host bridges define specific operations.
+ *
+ * @bus: the #PCIBus being updated.
+ * @ops: the #PCIIOMMUOps
+ * @opaque: passed to callbacks of the @ops structure.
+ */
+void pci_setup_iommu(PCIBus *bus, const PCIIOMMUOps *ops, void *opaque);
+
+pcibus_t pci_bar_address(PCIDevice *d,
+ int reg, uint8_t type, pcibus_t size);
static inline void
pci_set_byte(uint8_t *config, uint8_t val)
@@ -657,69 +568,51 @@ static inline void
pci_set_byte_by_mask(uint8_t *config, uint8_t mask, uint8_t reg)
{
uint8_t val = pci_get_byte(config);
- uint8_t rval = reg << ctz32(mask);
- pci_set_byte(config, (~mask & val) | (mask & rval));
-}
+ uint8_t rval;
-static inline uint8_t
-pci_get_byte_by_mask(uint8_t *config, uint8_t mask)
-{
- uint8_t val = pci_get_byte(config);
- return (val & mask) >> ctz32(mask);
+ assert(mask);
+ rval = reg << ctz32(mask);
+ pci_set_byte(config, (~mask & val) | (mask & rval));
}
static inline void
pci_set_word_by_mask(uint8_t *config, uint16_t mask, uint16_t reg)
{
uint16_t val = pci_get_word(config);
- uint16_t rval = reg << ctz32(mask);
- pci_set_word(config, (~mask & val) | (mask & rval));
-}
+ uint16_t rval;
-static inline uint16_t
-pci_get_word_by_mask(uint8_t *config, uint16_t mask)
-{
- uint16_t val = pci_get_word(config);
- return (val & mask) >> ctz32(mask);
+ assert(mask);
+ rval = reg << ctz32(mask);
+ pci_set_word(config, (~mask & val) | (mask & rval));
}
static inline void
pci_set_long_by_mask(uint8_t *config, uint32_t mask, uint32_t reg)
{
uint32_t val = pci_get_long(config);
- uint32_t rval = reg << ctz32(mask);
- pci_set_long(config, (~mask & val) | (mask & rval));
-}
+ uint32_t rval;
-static inline uint32_t
-pci_get_long_by_mask(uint8_t *config, uint32_t mask)
-{
- uint32_t val = pci_get_long(config);
- return (val & mask) >> ctz32(mask);
+ assert(mask);
+ rval = reg << ctz32(mask);
+ pci_set_long(config, (~mask & val) | (mask & rval));
}
static inline void
pci_set_quad_by_mask(uint8_t *config, uint64_t mask, uint64_t reg)
{
uint64_t val = pci_get_quad(config);
- uint64_t rval = reg << ctz32(mask);
- pci_set_quad(config, (~mask & val) | (mask & rval));
-}
+ uint64_t rval;
-static inline uint64_t
-pci_get_quad_by_mask(uint8_t *config, uint64_t mask)
-{
- uint64_t val = pci_get_quad(config);
- return (val & mask) >> ctz32(mask);
+ assert(mask);
+ rval = reg << ctz32(mask);
+ pci_set_quad(config, (~mask & val) | (mask & rval));
}
-PCIDevice *pci_new_multifunction(int devfn, bool multifunction,
- const char *name);
+PCIDevice *pci_new_multifunction(int devfn, const char *name);
PCIDevice *pci_new(int devfn, const char *name);
bool pci_realize_and_unref(PCIDevice *dev, PCIBus *bus, Error **errp);
PCIDevice *pci_create_simple_multifunction(PCIBus *bus, int devfn,
- bool multifunction,
const char *name);
PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name);
@@ -748,122 +641,7 @@ static inline void pci_irq_pulse(PCIDevice *pci_dev)
pci_irq_deassert(pci_dev);
}
-static inline int pci_is_express(const PCIDevice *d)
-{
- return d->cap_present & QEMU_PCI_CAP_EXPRESS;
-}
-
-static inline int pci_is_express_downstream_port(const PCIDevice *d)
-{
- uint8_t type;
-
- if (!pci_is_express(d) || !d->exp.exp_cap) {
- return 0;
- }
-
- type = pcie_cap_get_type(d);
-
- return type == PCI_EXP_TYPE_DOWNSTREAM || type == PCI_EXP_TYPE_ROOT_PORT;
-}
-
-static inline uint32_t pci_config_size(const PCIDevice *d)
-{
- return pci_is_express(d) ? PCIE_CONFIG_SPACE_SIZE : PCI_CONFIG_SPACE_SIZE;
-}
-
-static inline uint16_t pci_get_bdf(PCIDevice *dev)
-{
- return PCI_BUILD_BDF(pci_bus_num(pci_get_bus(dev)), dev->devfn);
-}
-
-uint16_t pci_requester_id(PCIDevice *dev);
-
-/* DMA access functions */
-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)
-{
- dma_memory_rw(pci_get_address_space(dev), addr, buf, len, dir);
- return 0;
-}
-
-static inline int 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)
-{
- return pci_dma_rw(dev, addr, (void *) buf, len, DMA_DIRECTION_FROM_DEVICE);
-}
-
-#define PCI_DMA_DEFINE_LDST(_l, _s, _bits) \
- static inline uint##_bits##_t ld##_l##_pci_dma(PCIDevice *dev, \
- dma_addr_t addr) \
- { \
- return ld##_l##_dma(pci_get_address_space(dev), addr); \
- } \
- static inline void st##_s##_pci_dma(PCIDevice *dev, \
- dma_addr_t addr, uint##_bits##_t val) \
- { \
- st##_s##_dma(pci_get_address_space(dev), addr, val); \
- }
-
-PCI_DMA_DEFINE_LDST(ub, b, 8);
-PCI_DMA_DEFINE_LDST(uw_le, w_le, 16)
-PCI_DMA_DEFINE_LDST(l_le, l_le, 32);
-PCI_DMA_DEFINE_LDST(q_le, q_le, 64);
-PCI_DMA_DEFINE_LDST(uw_be, w_be, 16)
-PCI_DMA_DEFINE_LDST(l_be, l_be, 32);
-PCI_DMA_DEFINE_LDST(q_be, q_be, 64);
-
-#undef PCI_DMA_DEFINE_LDST
-
-static inline void *pci_dma_map(PCIDevice *dev, dma_addr_t addr,
- dma_addr_t *plen, DMADirection dir)
-{
- void *buf;
-
- buf = dma_memory_map(pci_get_address_space(dev), addr, plen, dir);
- return buf;
-}
-
-static inline void pci_dma_unmap(PCIDevice *dev, void *buffer, dma_addr_t len,
- DMADirection dir, dma_addr_t access_len)
-{
- dma_memory_unmap(pci_get_address_space(dev), buffer, len, dir, access_len);
-}
-
-static inline void pci_dma_sglist_init(QEMUSGList *qsg, PCIDevice *dev,
- int alloc_hint)
-{
- qemu_sglist_init(qsg, DEVICE(dev), alloc_hint, pci_get_address_space(dev));
-}
-
-extern const VMStateDescription vmstate_pci_device;
-
-#define VMSTATE_PCI_DEVICE(_field, _state) { \
- .name = (stringify(_field)), \
- .size = sizeof(PCIDevice), \
- .vmsd = &vmstate_pci_device, \
- .flags = VMS_STRUCT, \
- .offset = vmstate_offset_value(_state, _field, PCIDevice), \
-}
-
-#define VMSTATE_PCI_DEVICE_POINTER(_field, _state) { \
- .name = (stringify(_field)), \
- .size = sizeof(PCIDevice), \
- .vmsd = &vmstate_pci_device, \
- .flags = VMS_STRUCT|VMS_POINTER, \
- .offset = vmstate_offset_pointer(_state, _field, PCIDevice), \
-}
-
MSIMessage pci_get_msi_message(PCIDevice *dev, int vector);
+void pci_set_power(PCIDevice *pci_dev, bool state);
#endif
diff --git a/include/hw/pci/pci_bridge.h b/include/hw/pci/pci_bridge.h
index 99c674e949..5cd452115a 100644
--- a/include/hw/pci/pci_bridge.h
+++ b/include/hw/pci/pci_bridge.h
@@ -26,8 +26,10 @@
#ifndef QEMU_PCI_BRIDGE_H
#define QEMU_PCI_BRIDGE_H
-#include "hw/pci/pci.h"
+#include "hw/pci/pci_device.h"
#include "hw/pci/pci_bus.h"
+#include "hw/cxl/cxl.h"
+#include "qom/object.h"
typedef struct PCIBridgeWindows PCIBridgeWindows;
@@ -50,7 +52,8 @@ struct PCIBridgeWindows {
};
#define TYPE_PCI_BRIDGE "base-pci-bridge"
-#define PCI_BRIDGE(obj) OBJECT_CHECK(PCIBridge, (obj), TYPE_PCI_BRIDGE)
+OBJECT_DECLARE_SIMPLE_TYPE(PCIBridge, PCI_BRIDGE)
+#define IS_PCI_BRIDGE(dev) object_dynamic_cast(OBJECT(dev), TYPE_PCI_BRIDGE)
struct PCIBridge {
/*< private >*/
@@ -70,15 +73,49 @@ struct PCIBridge {
MemoryRegion address_space_mem;
MemoryRegion address_space_io;
- PCIBridgeWindows *windows;
+ PCIBridgeWindows windows;
pci_map_irq_fn map_irq;
const char *bus_name;
+
+ /* SLT is RO for PCIE to PCIE bridges, but old QEMU versions had it RW */
+ bool pcie_writeable_slt_bug;
};
#define PCI_BRIDGE_DEV_PROP_CHASSIS_NR "chassis_nr"
#define PCI_BRIDGE_DEV_PROP_MSI "msi"
#define PCI_BRIDGE_DEV_PROP_SHPC "shpc"
+typedef struct CXLHost CXLHost;
+
+typedef struct PXBDev {
+ /*< private >*/
+ PCIDevice parent_obj;
+ /*< public >*/
+
+ uint8_t bus_nr;
+ uint16_t numa_node;
+ bool bypass_iommu;
+} PXBDev;
+
+typedef struct PXBPCIEDev {
+ /*< private >*/
+ PXBDev parent_obj;
+} PXBPCIEDev;
+
+#define TYPE_PXB_DEV "pxb"
+OBJECT_DECLARE_SIMPLE_TYPE(PXBDev, PXB_DEV)
+
+typedef struct PXBCXLDev {
+ /*< private >*/
+ PXBPCIEDev parent_obj;
+ /*< public >*/
+
+ bool hdm_for_passthrough;
+ CXLHost *cxl_host_bridge; /* Pointer to a CXLHost */
+} PXBCXLDev;
+
+#define TYPE_PXB_CXL_DEV "pxb-cxl"
+OBJECT_DECLARE_SIMPLE_TYPE(PXBCXLDev, PXB_CXL_DEV)
int pci_bridge_ssvid_init(PCIDevice *dev, uint8_t offset,
uint16_t svid, uint16_t ssid,
@@ -115,11 +152,11 @@ void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
pci_map_irq_fn map_irq);
/* TODO: add this define to pci_regs.h in linux and then in qemu. */
-#define PCI_BRIDGE_CTL_VGA_16BIT 0x10 /* VGA 16-bit decode */
-#define PCI_BRIDGE_CTL_DISCARD 0x100 /* Primary discard timer */
-#define PCI_BRIDGE_CTL_SEC_DISCARD 0x200 /* Secondary discard timer */
-#define PCI_BRIDGE_CTL_DISCARD_STATUS 0x400 /* Discard timer status */
-#define PCI_BRIDGE_CTL_DISCARD_SERR 0x800 /* Discard timer SERR# enable */
+#define PCI_BRIDGE_CTL_VGA_16BIT 0x10 /* VGA 16-bit decode */
+#define PCI_BRIDGE_CTL_DISCARD 0x100 /* Primary discard timer */
+#define PCI_BRIDGE_CTL_SEC_DISCARD 0x200 /* Secondary discard timer */
+#define PCI_BRIDGE_CTL_DISCARD_STATUS 0x400 /* Discard timer status */
+#define PCI_BRIDGE_CTL_DISCARD_SERR 0x800 /* Discard timer SERR# enable */
typedef struct PCIBridgeQemuCap {
uint8_t id; /* Standard PCI capability header field */
@@ -137,6 +174,7 @@ typedef struct PCIBridgeQemuCap {
uint64_t mem_pref_64; /* Prefetchable memory to reserve (64-bit MMIO) */
} PCIBridgeQemuCap;
+#define REDHAT_PCI_CAP_TYPE_OFFSET 3
#define REDHAT_PCI_CAP_RESOURCE_RESERVE 1
/*
@@ -151,6 +189,13 @@ typedef struct PCIResReserve {
uint64_t mem_pref_64;
} PCIResReserve;
+#define REDHAT_PCI_CAP_RES_RESERVE_BUS_RES 4
+#define REDHAT_PCI_CAP_RES_RESERVE_IO 8
+#define REDHAT_PCI_CAP_RES_RESERVE_MEM 16
+#define REDHAT_PCI_CAP_RES_RESERVE_PREF_MEM_32 20
+#define REDHAT_PCI_CAP_RES_RESERVE_PREF_MEM_64 24
+#define REDHAT_PCI_CAP_RES_RESERVE_CAP_SIZE 32
+
int pci_bridge_qemu_reserve_cap_init(PCIDevice *dev, int cap_offset,
PCIResReserve res_reserve, Error **errp);
diff --git a/include/hw/pci/pci_bus.h b/include/hw/pci/pci_bus.h
index 0714f578af..2261312546 100644
--- a/include/hw/pci/pci_bus.h
+++ b/include/hw/pci/pci_bus.h
@@ -10,26 +10,30 @@
* use accessor functions in pci.h
*/
-typedef struct PCIBusClass {
+struct PCIBusClass {
/*< private >*/
BusClass parent_class;
/*< public >*/
int (*bus_num)(PCIBus *bus);
uint16_t (*numa_node)(PCIBus *bus);
-} PCIBusClass;
+};
enum PCIBusFlags {
/* This bus is the root of a PCI domain */
PCI_BUS_IS_ROOT = 0x0001,
/* PCIe extended configuration space is accessible on this bus */
PCI_BUS_EXTENDED_CONFIG_SPACE = 0x0002,
+ /* This is a CXL Type BUS */
+ PCI_BUS_CXL = 0x0004,
};
+#define PCI_NO_PASID UINT32_MAX
+
struct PCIBus {
BusState qbus;
enum PCIBusFlags flags;
- PCIIOMMUFunc iommu_fn;
+ const PCIIOMMUOps *iommu_ops;
void *iommu_opaque;
uint8_t devfn_min;
uint32_t slot_reserved_mask;
@@ -53,6 +57,11 @@ struct PCIBus {
Notifier machine_done;
};
+static inline bool pci_bus_is_cxl(PCIBus *bus)
+{
+ return !!(bus->flags & PCI_BUS_CXL);
+}
+
static inline bool pci_bus_is_root(PCIBus *bus)
{
return !!(bus->flags & PCI_BUS_IS_ROOT);
diff --git a/include/hw/pci/pci_device.h b/include/hw/pci/pci_device.h
new file mode 100644
index 0000000000..d3dd0f64b2
--- /dev/null
+++ b/include/hw/pci/pci_device.h
@@ -0,0 +1,350 @@
+#ifndef QEMU_PCI_DEVICE_H
+#define QEMU_PCI_DEVICE_H
+
+#include "hw/pci/pci.h"
+#include "hw/pci/pcie.h"
+
+#define TYPE_PCI_DEVICE "pci-device"
+typedef struct PCIDeviceClass PCIDeviceClass;
+DECLARE_OBJ_CHECKERS(PCIDevice, PCIDeviceClass,
+ PCI_DEVICE, TYPE_PCI_DEVICE)
+
+/*
+ * Implemented by devices that can be plugged on CXL buses. In the spec, this is
+ * actually a "CXL Component, but we name it device to match the PCI naming.
+ */
+#define INTERFACE_CXL_DEVICE "cxl-device"
+
+/* Implemented by devices that can be plugged on PCI Express buses */
+#define INTERFACE_PCIE_DEVICE "pci-express-device"
+
+/* Implemented by devices that can be plugged on Conventional PCI buses */
+#define INTERFACE_CONVENTIONAL_PCI_DEVICE "conventional-pci-device"
+
+struct PCIDeviceClass {
+ DeviceClass parent_class;
+
+ void (*realize)(PCIDevice *dev, Error **errp);
+ PCIUnregisterFunc *exit;
+ PCIConfigReadFunc *config_read;
+ PCIConfigWriteFunc *config_write;
+
+ uint16_t vendor_id;
+ uint16_t device_id;
+ uint8_t revision;
+ uint16_t class_id;
+ uint16_t subsystem_vendor_id; /* only for header type = 0 */
+ uint16_t subsystem_id; /* only for header type = 0 */
+
+ const char *romfile; /* rom bar */
+};
+
+enum PCIReqIDType {
+ PCI_REQ_ID_INVALID = 0,
+ PCI_REQ_ID_BDF,
+ PCI_REQ_ID_SECONDARY_BUS,
+ PCI_REQ_ID_MAX,
+};
+typedef enum PCIReqIDType PCIReqIDType;
+
+struct PCIReqIDCache {
+ PCIDevice *dev;
+ PCIReqIDType type;
+};
+typedef struct PCIReqIDCache PCIReqIDCache;
+
+struct PCIDevice {
+ DeviceState qdev;
+ bool partially_hotplugged;
+ bool has_power;
+
+ /* PCI config space */
+ uint8_t *config;
+
+ /*
+ * Used to enable config checks on load. Note that writable bits are
+ * never checked even if set in cmask.
+ */
+ uint8_t *cmask;
+
+ /* Used to implement R/W bytes */
+ uint8_t *wmask;
+
+ /* Used to implement RW1C(Write 1 to Clear) bytes */
+ uint8_t *w1cmask;
+
+ /* Used to allocate config space for capabilities. */
+ uint8_t *used;
+
+ /* the following fields are read only */
+ int32_t devfn;
+ /*
+ * Cached device to fetch requester ID from, to avoid the PCI tree
+ * walking every time we invoke PCI request (e.g., MSI). For
+ * conventional PCI root complex, this field is meaningless.
+ */
+ PCIReqIDCache requester_id_cache;
+ char name[64];
+ PCIIORegion io_regions[PCI_NUM_REGIONS];
+ AddressSpace bus_master_as;
+ MemoryRegion bus_master_container_region;
+ MemoryRegion bus_master_enable_region;
+
+ /* do not access the following fields */
+ PCIConfigReadFunc *config_read;
+ PCIConfigWriteFunc *config_write;
+
+ /* Legacy PCI VGA regions */
+ MemoryRegion *vga_regions[QEMU_PCI_VGA_NUM_REGIONS];
+ bool has_vga;
+
+ /* Current IRQ levels. Used internally by the generic PCI code. */
+ uint8_t irq_state;
+
+ /* Capability bits */
+ uint32_t cap_present;
+
+ /* Offset of MSI-X capability in config space */
+ uint8_t msix_cap;
+
+ /* MSI-X entries */
+ int msix_entries_nr;
+
+ /* Space to store MSIX table & pending bit array */
+ uint8_t *msix_table;
+ uint8_t *msix_pba;
+
+ /* May be used by INTx or MSI during interrupt notification */
+ void *irq_opaque;
+
+ MSITriggerFunc *msi_trigger;
+ MSIPrepareMessageFunc *msi_prepare_message;
+ MSIxPrepareMessageFunc *msix_prepare_message;
+
+ /* MemoryRegion container for msix exclusive BAR setup */
+ MemoryRegion msix_exclusive_bar;
+ /* Memory Regions for MSIX table and pending bit entries. */
+ MemoryRegion msix_table_mmio;
+ MemoryRegion msix_pba_mmio;
+ /* Reference-count for entries actually in use by driver. */
+ unsigned *msix_entry_used;
+ /* MSIX function mask set or MSIX disabled */
+ bool msix_function_masked;
+ /* Version id needed for VMState */
+ int32_t version_id;
+
+ /* Offset of MSI capability in config space */
+ uint8_t msi_cap;
+
+ /* PCI Express */
+ PCIExpressDevice exp;
+
+ /* SHPC */
+ SHPCDevice *shpc;
+
+ /* Location of option rom */
+ char *romfile;
+ uint32_t romsize;
+ bool has_rom;
+ MemoryRegion rom;
+ uint32_t rom_bar;
+
+ /* INTx routing notifier */
+ PCIINTxRoutingNotifier intx_routing_notifier;
+
+ /* MSI-X notifiers */
+ MSIVectorUseNotifier msix_vector_use_notifier;
+ MSIVectorReleaseNotifier msix_vector_release_notifier;
+ MSIVectorPollNotifier msix_vector_poll_notifier;
+
+ /* ID of standby device in net_failover pair */
+ char *failover_pair_id;
+ uint32_t acpi_index;
+};
+
+static inline int pci_intx(PCIDevice *pci_dev)
+{
+ return pci_get_byte(pci_dev->config + PCI_INTERRUPT_PIN) - 1;
+}
+
+static inline int pci_is_cxl(const PCIDevice *d)
+{
+ return d->cap_present & QEMU_PCIE_CAP_CXL;
+}
+
+static inline int pci_is_express(const PCIDevice *d)
+{
+ return d->cap_present & QEMU_PCI_CAP_EXPRESS;
+}
+
+static inline int pci_is_express_downstream_port(const PCIDevice *d)
+{
+ uint8_t type;
+
+ if (!pci_is_express(d) || !d->exp.exp_cap) {
+ return 0;
+ }
+
+ type = pcie_cap_get_type(d);
+
+ return type == PCI_EXP_TYPE_DOWNSTREAM || type == PCI_EXP_TYPE_ROOT_PORT;
+}
+
+static inline int pci_is_vf(const PCIDevice *d)
+{
+ return d->exp.sriov_vf.pf != NULL;
+}
+
+static inline uint32_t pci_config_size(const PCIDevice *d)
+{
+ return pci_is_express(d) ? PCIE_CONFIG_SPACE_SIZE : PCI_CONFIG_SPACE_SIZE;
+}
+
+static inline uint16_t pci_get_bdf(PCIDevice *dev)
+{
+ return PCI_BUILD_BDF(pci_bus_num(pci_get_bus(dev)), dev->devfn);
+}
+
+uint16_t pci_requester_id(PCIDevice *dev);
+
+/* DMA access functions */
+static inline AddressSpace *pci_get_address_space(PCIDevice *dev)
+{
+ return &dev->bus_master_as;
+}
+
+/**
+ * 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, MemTxAttrs attrs)
+{
+ return dma_memory_rw(pci_get_address_space(dev), addr, buf, len,
+ dir, attrs);
+}
+
+/**
+ * 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, MEMTXATTRS_UNSPECIFIED);
+}
+
+/**
+ * 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, MEMTXATTRS_UNSPECIFIED);
+}
+
+#define PCI_DMA_DEFINE_LDST(_l, _s, _bits) \
+ static inline MemTxResult ld##_l##_pci_dma(PCIDevice *dev, \
+ dma_addr_t addr, \
+ uint##_bits##_t *val, \
+ MemTxAttrs attrs) \
+ { \
+ return ld##_l##_dma(pci_get_address_space(dev), addr, val, attrs); \
+ } \
+ static inline MemTxResult st##_s##_pci_dma(PCIDevice *dev, \
+ dma_addr_t addr, \
+ uint##_bits##_t val, \
+ MemTxAttrs attrs) \
+ { \
+ return st##_s##_dma(pci_get_address_space(dev), addr, val, attrs); \
+ }
+
+PCI_DMA_DEFINE_LDST(ub, b, 8);
+PCI_DMA_DEFINE_LDST(uw_le, w_le, 16)
+PCI_DMA_DEFINE_LDST(l_le, l_le, 32);
+PCI_DMA_DEFINE_LDST(q_le, q_le, 64);
+PCI_DMA_DEFINE_LDST(uw_be, w_be, 16)
+PCI_DMA_DEFINE_LDST(l_be, l_be, 32);
+PCI_DMA_DEFINE_LDST(q_be, q_be, 64);
+
+#undef PCI_DMA_DEFINE_LDST
+
+/**
+ * pci_dma_map: Map device PCI address space range into host virtual address
+ * @dev: #PCIDevice to be accessed
+ * @addr: address within that device's address space
+ * @plen: pointer to length of buffer; updated on return to indicate
+ * if only a subset of the requested range has been mapped
+ * @dir: indicates the transfer direction
+ *
+ * Return: A host pointer, or %NULL if the resources needed to
+ * perform the mapping are exhausted (in that case *@plen
+ * is set to zero).
+ */
+static inline void *pci_dma_map(PCIDevice *dev, dma_addr_t addr,
+ dma_addr_t *plen, DMADirection dir)
+{
+ return dma_memory_map(pci_get_address_space(dev), addr, plen, dir,
+ MEMTXATTRS_UNSPECIFIED);
+}
+
+static inline void pci_dma_unmap(PCIDevice *dev, void *buffer, dma_addr_t len,
+ DMADirection dir, dma_addr_t access_len)
+{
+ dma_memory_unmap(pci_get_address_space(dev), buffer, len, dir, access_len);
+}
+
+static inline void pci_dma_sglist_init(QEMUSGList *qsg, PCIDevice *dev,
+ int alloc_hint)
+{
+ qemu_sglist_init(qsg, DEVICE(dev), alloc_hint, pci_get_address_space(dev));
+}
+
+extern const VMStateDescription vmstate_pci_device;
+
+#define VMSTATE_PCI_DEVICE(_field, _state) { \
+ .name = (stringify(_field)), \
+ .size = sizeof(PCIDevice), \
+ .vmsd = &vmstate_pci_device, \
+ .flags = VMS_STRUCT, \
+ .offset = vmstate_offset_value(_state, _field, PCIDevice), \
+}
+
+#define VMSTATE_PCI_DEVICE_POINTER(_field, _state) { \
+ .name = (stringify(_field)), \
+ .size = sizeof(PCIDevice), \
+ .vmsd = &vmstate_pci_device, \
+ .flags = VMS_STRUCT | VMS_POINTER, \
+ .offset = vmstate_offset_pointer(_state, _field, PCIDevice), \
+}
+
+#endif
diff --git a/include/hw/pci/pci_host.h b/include/hw/pci/pci_host.h
index 6210a7e14d..e52d8ec2cd 100644
--- a/include/hw/pci/pci_host.h
+++ b/include/hw/pci/pci_host.h
@@ -29,14 +29,12 @@
#define PCI_HOST_H
#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define PCI_HOST_BYPASS_IOMMU "bypass-iommu"
#define TYPE_PCI_HOST_BRIDGE "pci-host-bridge"
-#define PCI_HOST_BRIDGE(obj) \
- OBJECT_CHECK(PCIHostState, (obj), TYPE_PCI_HOST_BRIDGE)
-#define PCI_HOST_BRIDGE_CLASS(klass) \
- OBJECT_CLASS_CHECK(PCIHostBridgeClass, (klass), TYPE_PCI_HOST_BRIDGE)
-#define PCI_HOST_BRIDGE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(PCIHostBridgeClass, (obj), TYPE_PCI_HOST_BRIDGE)
+OBJECT_DECLARE_TYPE(PCIHostState, PCIHostBridgeClass, PCI_HOST_BRIDGE)
struct PCIHostState {
SysBusDevice busdev;
@@ -47,15 +45,16 @@ struct PCIHostState {
uint32_t config_reg;
bool mig_enabled;
PCIBus *bus;
+ bool bypass_iommu;
QLIST_ENTRY(PCIHostState) next;
};
-typedef struct PCIHostBridgeClass {
+struct PCIHostBridgeClass {
SysBusDeviceClass parent_class;
const char *(*root_bus_path)(PCIHostState *, PCIBus *);
-} PCIHostBridgeClass;
+};
/* common internal helpers for PCI/PCIe hosts, cut off overflows */
void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr,
diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h
index 11f8ab7149..f1a53fea8d 100644
--- a/include/hw/pci/pci_ids.h
+++ b/include/hw/pci/pci_ids.h
@@ -26,6 +26,7 @@
#define PCI_CLASS_STORAGE_SATA 0x0106
#define PCI_CLASS_STORAGE_SAS 0x0107
#define PCI_CLASS_STORAGE_EXPRESS 0x0108
+#define PCI_CLASS_STORAGE_UFS 0x0109
#define PCI_CLASS_STORAGE_OTHER 0x0180
#define PCI_BASE_CLASS_NETWORK 0x02
@@ -53,6 +54,7 @@
#define PCI_BASE_CLASS_MEMORY 0x05
#define PCI_CLASS_MEMORY_RAM 0x0500
#define PCI_CLASS_MEMORY_FLASH 0x0501
+#define PCI_CLASS_MEMORY_CXL 0x0502
#define PCI_CLASS_MEMORY_OTHER 0x0580
#define PCI_BASE_CLASS_BRIDGE 0x06
@@ -156,6 +158,9 @@
/* Vendors and devices. Sort key: vendor first, device next. */
+/* Ref: PCIe r6.0 Table 6-32 */
+#define PCI_VENDOR_ID_PCI_SIG 0x0001
+
#define PCI_VENDOR_ID_LSI_LOGIC 0x1000
#define PCI_DEVICE_ID_LSI_53C810 0x0001
#define PCI_DEVICE_ID_LSI_53C895A 0x0012
@@ -165,7 +170,6 @@
#define PCI_VENDOR_ID_DEC 0x1011
#define PCI_DEVICE_ID_DEC_21143 0x0019
-#define PCI_DEVICE_ID_DEC_21154 0x0026
#define PCI_VENDOR_ID_CIRRUS 0x1013
@@ -175,6 +179,8 @@
#define PCI_DEVICE_ID_AMD_LANCE 0x2000
#define PCI_DEVICE_ID_AMD_SCSI 0x2020
+#define PCI_VENDOR_ID_HP 0x103c
+
#define PCI_VENDOR_ID_TI 0x104c
#define PCI_VENDOR_ID_MOTOROLA 0x1057
@@ -192,6 +198,9 @@
#define PCI_DEVICE_ID_SUN_SIMBA 0x5000
#define PCI_DEVICE_ID_SUN_SABRE 0xa000
+#define PCI_VENDOR_ID_ORACLE 0x108e
+#define PCI_DEVICE_ID_REMOTE_IOHUB 0xb000
+
#define PCI_VENDOR_ID_CMD 0x1095
#define PCI_DEVICE_ID_CMD_646 0x0646
@@ -201,14 +210,17 @@
#define PCI_VENDOR_ID_XILINX 0x10ee
#define PCI_VENDOR_ID_VIA 0x1106
-#define PCI_DEVICE_ID_VIA_ISA_BRIDGE 0x0686
+#define PCI_DEVICE_ID_VIA_82C686B_ISA 0x0686
#define PCI_DEVICE_ID_VIA_IDE 0x0571
#define PCI_DEVICE_ID_VIA_UHCI 0x3038
-#define PCI_DEVICE_ID_VIA_ACPI 0x3057
+#define PCI_DEVICE_ID_VIA_82C686B_PM 0x3057
#define PCI_DEVICE_ID_VIA_AC97 0x3058
#define PCI_DEVICE_ID_VIA_MC97 0x3068
+#define PCI_DEVICE_ID_VIA_8231_ISA 0x8231
+#define PCI_DEVICE_ID_VIA_8231_PM 0x8235
#define PCI_VENDOR_ID_MARVELL 0x11ab
+#define PCI_DEVICE_ID_MARVELL_MV6436X 0x6460
#define PCI_VENDOR_ID_SILICON_MOTION 0x126f
#define PCI_DEVICE_ID_SM501 0x0501
@@ -221,6 +233,9 @@
#define PCI_VENDOR_ID_FREESCALE 0x1957
#define PCI_DEVICE_ID_MPC8533E 0x0030
+#define PCI_VENDOR_ID_BAIDU 0x1d22
+#define PCI_DEVICE_ID_KUNLUN_VF 0x3685
+
#define PCI_VENDOR_ID_INTEL 0x8086
#define PCI_DEVICE_ID_INTEL_82378 0x0484
#define PCI_DEVICE_ID_INTEL_82441 0x1237
@@ -228,6 +243,7 @@
#define PCI_DEVICE_ID_INTEL_82801BA_11 0x244e
#define PCI_DEVICE_ID_INTEL_82801D 0x24CD
#define PCI_DEVICE_ID_INTEL_ESB_9 0x25ab
+#define PCI_DEVICE_ID_INTEL_NVME 0x5845
#define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000
#define PCI_DEVICE_ID_INTEL_82371SB_1 0x7010
#define PCI_DEVICE_ID_INTEL_82371SB_2 0x7020
diff --git a/include/hw/pci/pci_regs.h b/include/hw/pci/pci_regs.h
index 77ba64b931..a590140962 100644
--- a/include/hw/pci/pci_regs.h
+++ b/include/hw/pci/pci_regs.h
@@ -4,5 +4,6 @@
#include "standard-headers/linux/pci_regs.h"
#define PCI_PM_CAP_VER_1_1 0x0002 /* PCI PM spec ver. 1.1 */
+#define PCI_PM_CAP_VER_1_2 0x0003 /* PCI PM spec ver. 1.2 */
#endif
diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h
index 14c58ebdb6..11f5a91bbb 100644
--- a/include/hw/pci/pcie.h
+++ b/include/hw/pci/pcie.h
@@ -24,17 +24,10 @@
#include "hw/pci/pci_regs.h"
#include "hw/pci/pcie_regs.h"
#include "hw/pci/pcie_aer.h"
+#include "hw/pci/pcie_sriov.h"
#include "hw/hotplug.h"
typedef enum {
- /* for attention and power indicator */
- PCI_EXP_HP_IND_RESERVED = PCI_EXP_SLTCTL_IND_RESERVED,
- PCI_EXP_HP_IND_ON = PCI_EXP_SLTCTL_IND_ON,
- PCI_EXP_HP_IND_BLINK = PCI_EXP_SLTCTL_IND_BLINK,
- PCI_EXP_HP_IND_OFF = PCI_EXP_SLTCTL_IND_OFF,
-} PCIExpressIndicator;
-
-typedef enum {
/* these bits must match the bits in Slot Control/Status registers.
* PCI_EXP_HP_EV_xxx = PCI_EXP_SLTCTL_xxxE = PCI_EXP_SLTSTA_xxx
*
@@ -81,6 +74,11 @@ struct PCIExpressDevice {
/* ACS */
uint16_t acs_cap;
+
+ /* SR/IOV */
+ uint16_t sriov_cap;
+ PCIESriovPF sriov_pf;
+ PCIESriovVF sriov_vf;
};
#define COMPAT_PROP_PCP "power_controller_present"
@@ -95,6 +93,7 @@ void pcie_cap_exit(PCIDevice *dev);
int pcie_endpoint_cap_v1_init(PCIDevice *dev, uint8_t offset);
void pcie_cap_v1_exit(PCIDevice *dev);
uint8_t pcie_cap_get_type(const PCIDevice *dev);
+uint8_t pcie_cap_get_version(const PCIDevice *dev);
void pcie_cap_flags_set_vector(PCIDevice *dev, uint8_t vector);
uint8_t pcie_cap_flags_get_vector(PCIDevice *dev);
@@ -112,6 +111,7 @@ void pcie_cap_slot_write_config(PCIDevice *dev,
uint32_t addr, uint32_t val, int len);
int pcie_cap_slot_post_load(void *opaque, int version_id);
void pcie_cap_slot_push_attention_button(PCIDevice *dev);
+void pcie_cap_slot_enable_power(PCIDevice *dev);
void pcie_cap_root_init(PCIDevice *dev);
void pcie_cap_root_reset(PCIDevice *dev);
@@ -135,9 +135,9 @@ void pcie_sync_bridge_lnk(PCIDevice *dev);
void pcie_acs_init(PCIDevice *dev, uint16_t offset);
void pcie_acs_reset(PCIDevice *dev);
-void pcie_ari_init(PCIDevice *dev, uint16_t offset, uint16_t nextfn);
+void pcie_ari_init(PCIDevice *dev, uint16_t offset);
void pcie_dev_ser_num_init(PCIDevice *dev, uint16_t offset, uint64_t ser_num);
-void pcie_ats_init(PCIDevice *dev, uint16_t offset);
+void pcie_ats_init(PCIDevice *dev, uint16_t offset, bool aligned);
void pcie_cap_slot_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp);
diff --git a/include/hw/pci/pcie_aer.h b/include/hw/pci/pcie_aer.h
index 65e71d98fe..4a9f0ea69d 100644
--- a/include/hw/pci/pcie_aer.h
+++ b/include/hw/pci/pcie_aer.h
@@ -40,7 +40,7 @@ struct PCIEAERLog {
* The specified value will be clipped down to PCIE_AER_LOG_MAX_LIMIT
* to avoid unreasonable memory usage.
* I bet that 128 log size would be big enough, otherwise too many errors
- * for system to function normaly. But could consecutive errors occur?
+ * for system to function normally. But could consecutive errors occur?
*/
#define PCIE_AER_LOG_MAX_DEFAULT 8
#define PCIE_AER_LOG_MAX_LIMIT 128
@@ -100,4 +100,5 @@ void pcie_aer_root_write_config(PCIDevice *dev,
uint32_t addr, uint32_t val, int len,
uint32_t root_cmd_prev);
+int pcie_aer_inject_error(PCIDevice *dev, const PCIEAERErr *err);
#endif /* QEMU_PCIE_AER_H */
diff --git a/include/hw/pci/pcie_doe.h b/include/hw/pci/pcie_doe.h
new file mode 100644
index 0000000000..87dc17dcef
--- /dev/null
+++ b/include/hw/pci/pcie_doe.h
@@ -0,0 +1,122 @@
+/*
+ * PCIe Data Object Exchange
+ *
+ * Copyright (C) 2021 Avery Design Systems, Inc.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef PCIE_DOE_H
+#define PCIE_DOE_H
+
+#include "qemu/range.h"
+#include "hw/register.h"
+
+/*
+ * Reference:
+ * PCIe r6.0 - 7.9.24 Data Object Exchange Extended Capability
+ */
+/* Capabilities Register - r6.0 7.9.24.2 */
+#define PCI_EXP_DOE_CAP 0x04
+REG32(PCI_DOE_CAP_REG, 0)
+ FIELD(PCI_DOE_CAP_REG, INTR_SUPP, 0, 1)
+ FIELD(PCI_DOE_CAP_REG, DOE_INTR_MSG_NUM, 1, 11)
+
+/* Control Register - r6.0 7.9.24.3 */
+#define PCI_EXP_DOE_CTRL 0x08
+REG32(PCI_DOE_CAP_CONTROL, 0)
+ FIELD(PCI_DOE_CAP_CONTROL, DOE_ABORT, 0, 1)
+ FIELD(PCI_DOE_CAP_CONTROL, DOE_INTR_EN, 1, 1)
+ FIELD(PCI_DOE_CAP_CONTROL, DOE_GO, 31, 1)
+
+/* Status Register - r6.0 7.9.24.4 */
+#define PCI_EXP_DOE_STATUS 0x0c
+REG32(PCI_DOE_CAP_STATUS, 0)
+ FIELD(PCI_DOE_CAP_STATUS, DOE_BUSY, 0, 1)
+ FIELD(PCI_DOE_CAP_STATUS, DOE_INTR_STATUS, 1, 1)
+ FIELD(PCI_DOE_CAP_STATUS, DOE_ERROR, 2, 1)
+ FIELD(PCI_DOE_CAP_STATUS, DATA_OBJ_RDY, 31, 1)
+
+/* Write Data Mailbox Register - r6.0 7.9.24.5 */
+#define PCI_EXP_DOE_WR_DATA_MBOX 0x10
+
+/* Read Data Mailbox Register - 7.9.xx.6 */
+#define PCI_EXP_DOE_RD_DATA_MBOX 0x14
+
+/* PCI-SIG defined Data Object Types - r6.0 Table 6-32 */
+#define PCI_SIG_DOE_DISCOVERY 0x00
+
+#define PCI_DOE_DW_SIZE_MAX (1 << 18)
+#define PCI_DOE_PROTOCOL_NUM_MAX 256
+
+#define DATA_OBJ_BUILD_HEADER1(v, p) (((p) << 16) | (v))
+#define DATA_OBJ_LEN_MASK(len) ((len) & (PCI_DOE_DW_SIZE_MAX - 1))
+
+typedef struct DOEHeader DOEHeader;
+typedef struct DOEProtocol DOEProtocol;
+typedef struct DOECap DOECap;
+
+struct DOEHeader {
+ uint16_t vendor_id;
+ uint8_t data_obj_type;
+ uint8_t reserved;
+ uint32_t length;
+} QEMU_PACKED;
+
+/* Protocol infos and rsp function callback */
+struct DOEProtocol {
+ uint16_t vendor_id;
+ uint8_t data_obj_type;
+ bool (*handle_request)(DOECap *);
+};
+
+struct DOECap {
+ /* Owner */
+ PCIDevice *pdev;
+
+ uint16_t offset;
+
+ struct {
+ bool intr;
+ uint16_t vec;
+ } cap;
+
+ struct {
+ bool abort;
+ bool intr;
+ bool go;
+ } ctrl;
+
+ struct {
+ bool busy;
+ bool intr;
+ bool error;
+ bool ready;
+ } status;
+
+ uint32_t *write_mbox;
+ uint32_t *read_mbox;
+
+ /* Mailbox position indicator */
+ uint32_t read_mbox_idx;
+ uint32_t read_mbox_len;
+ uint32_t write_mbox_len;
+
+ /* Protocols and its callback response */
+ DOEProtocol *protocols;
+ uint16_t protocol_num;
+};
+
+void pcie_doe_init(PCIDevice *pdev, DOECap *doe_cap, uint16_t offset,
+ DOEProtocol *protocols, bool intr, uint16_t vec);
+void pcie_doe_fini(DOECap *doe_cap);
+bool pcie_doe_read_config(DOECap *doe_cap, uint32_t addr, int size,
+ uint32_t *buf);
+void pcie_doe_write_config(DOECap *doe_cap, uint32_t addr,
+ uint32_t val, int size);
+uint32_t pcie_doe_build_protocol(DOEProtocol *p);
+void *pcie_doe_get_write_mbox_ptr(DOECap *doe_cap);
+void pcie_doe_set_rsp(DOECap *doe_cap, void *rsp);
+uint32_t pcie_doe_get_obj_len(void *obj);
+#endif /* PCIE_DOE_H */
diff --git a/include/hw/pci/pcie_host.h b/include/hw/pci/pcie_host.h
index 3f7b9886d1..82d92177da 100644
--- a/include/hw/pci/pcie_host.h
+++ b/include/hw/pci/pcie_host.h
@@ -23,10 +23,10 @@
#include "hw/pci/pci_host.h"
#include "exec/memory.h"
+#include "qom/object.h"
#define TYPE_PCIE_HOST_BRIDGE "pcie-host-bridge"
-#define PCIE_HOST_BRIDGE(obj) \
- OBJECT_CHECK(PCIExpressHost, (obj), TYPE_PCIE_HOST_BRIDGE)
+OBJECT_DECLARE_SIMPLE_TYPE(PCIExpressHost, PCIE_HOST_BRIDGE)
#define PCIE_HOST_MCFG_BASE "MCFG"
#define PCIE_HOST_MCFG_SIZE "mcfg_size"
@@ -60,15 +60,15 @@ void pcie_host_mmcfg_update(PCIExpressHost *e,
/*
* PCI express ECAM (Enhanced Configuration Address Mapping) format.
* AKA mmcfg address
- * bit 20 - 28: bus number
+ * bit 20 - 27: bus number
* bit 15 - 19: device number
* bit 12 - 14: function number
* bit 0 - 11: offset in configuration space of a given device
*/
-#define PCIE_MMCFG_SIZE_MAX (1ULL << 29)
+#define PCIE_MMCFG_SIZE_MAX (1ULL << 28)
#define PCIE_MMCFG_SIZE_MIN (1ULL << 20)
#define PCIE_MMCFG_BUS_BIT 20
-#define PCIE_MMCFG_BUS_MASK 0x1ff
+#define PCIE_MMCFG_BUS_MASK 0xff
#define PCIE_MMCFG_DEVFN_BIT 12
#define PCIE_MMCFG_DEVFN_MASK 0xff
#define PCIE_MMCFG_CONFOFFSET_MASK 0xfff
diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h
index caae57573b..90e6cf45b8 100644
--- a/include/hw/pci/pcie_port.h
+++ b/include/hw/pci/pcie_port.h
@@ -23,9 +23,11 @@
#include "hw/pci/pci_bridge.h"
#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_device.h"
+#include "qom/object.h"
#define TYPE_PCIE_PORT "pcie-port"
-#define PCIE_PORT(obj) OBJECT_CHECK(PCIEPort, (obj), TYPE_PCIE_PORT)
+OBJECT_DECLARE_SIMPLE_TYPE(PCIEPort, PCIE_PORT)
struct PCIEPort {
/*< private >*/
@@ -38,8 +40,12 @@ struct PCIEPort {
void pcie_port_init_reg(PCIDevice *d);
+PCIDevice *pcie_find_port_by_pn(PCIBus *bus, uint8_t pn);
+PCIDevice *pcie_find_port_first(PCIBus *bus);
+int pcie_count_ds_ports(PCIBus *bus);
+
#define TYPE_PCIE_SLOT "pcie-slot"
-#define PCIE_SLOT(obj) OBJECT_CHECK(PCIESlot, (obj), TYPE_PCIE_SLOT)
+OBJECT_DECLARE_SIMPLE_TYPE(PCIESlot, PCIE_SLOT)
struct PCIESlot {
/*< private >*/
@@ -56,8 +62,12 @@ struct PCIESlot {
/* Disable ACS (really for a pcie_root_port) */
bool disable_acs;
- /* Indicates whether hot-plug is enabled on the slot */
+ /* Indicates whether any type of hot-plug is allowed on the slot */
bool hotplug;
+
+ /* broken ACPI hotplug compat knob to preserve 6.1 ABI intact */
+ bool hide_native_hotplug_cap;
+
QLIST_ENTRY(PCIESlot) next;
};
@@ -67,15 +77,14 @@ int pcie_chassis_add_slot(struct PCIESlot *slot);
void pcie_chassis_del_slot(PCIESlot *s);
#define TYPE_PCIE_ROOT_PORT "pcie-root-port-base"
-#define PCIE_ROOT_PORT_CLASS(klass) \
- OBJECT_CLASS_CHECK(PCIERootPortClass, (klass), TYPE_PCIE_ROOT_PORT)
-#define PCIE_ROOT_PORT_GET_CLASS(obj) \
- OBJECT_GET_CLASS(PCIERootPortClass, (obj), TYPE_PCIE_ROOT_PORT)
+typedef struct PCIERootPortClass PCIERootPortClass;
+DECLARE_CLASS_CHECKERS(PCIERootPortClass, PCIE_ROOT_PORT,
+ TYPE_PCIE_ROOT_PORT)
-typedef struct PCIERootPortClass {
+struct PCIERootPortClass {
PCIDeviceClass parent_class;
DeviceRealize parent_realize;
- DeviceReset parent_reset;
+ ResettablePhases parent_phases;
uint8_t (*aer_vector)(const PCIDevice *dev);
int (*interrupts_init)(PCIDevice *dev, Error **errp);
@@ -86,6 +95,6 @@ typedef struct PCIERootPortClass {
int ssvid_offset;
int acs_offset; /* If nonzero, optional ACS capability offset */
int ssid;
-} PCIERootPortClass;
+};
#endif /* QEMU_PCIE_PORT_H */
diff --git a/include/hw/pci/pcie_regs.h b/include/hw/pci/pcie_regs.h
index 1db86b0ec4..9d3b6868dc 100644
--- a/include/hw/pci/pcie_regs.h
+++ b/include/hw/pci/pcie_regs.h
@@ -39,6 +39,8 @@ typedef enum PCIExpLinkSpeed {
QEMU_PCI_EXP_LNK_5GT,
QEMU_PCI_EXP_LNK_8GT,
QEMU_PCI_EXP_LNK_16GT,
+ QEMU_PCI_EXP_LNK_32GT,
+ QEMU_PCI_EXP_LNK_64GT,
} PCIExpLinkSpeed;
#define QEMU_PCI_EXP_LNKCAP_MLS(speed) (speed)
@@ -66,20 +68,6 @@ typedef enum PCIExpLinkWidth {
#define PCI_EXP_SLTCAP_PSN_SHIFT ctz32(PCI_EXP_SLTCAP_PSN)
-#define PCI_EXP_SLTCTL_IND_RESERVED 0x0
-#define PCI_EXP_SLTCTL_IND_ON 0x1
-#define PCI_EXP_SLTCTL_IND_BLINK 0x2
-#define PCI_EXP_SLTCTL_IND_OFF 0x3
-#define PCI_EXP_SLTCTL_AIC_SHIFT ctz32(PCI_EXP_SLTCTL_AIC)
-#define PCI_EXP_SLTCTL_AIC_OFF \
- (PCI_EXP_SLTCTL_IND_OFF << PCI_EXP_SLTCTL_AIC_SHIFT)
-
-#define PCI_EXP_SLTCTL_PIC_SHIFT ctz32(PCI_EXP_SLTCTL_PIC)
-#define PCI_EXP_SLTCTL_PIC_OFF \
- (PCI_EXP_SLTCTL_IND_OFF << PCI_EXP_SLTCTL_PIC_SHIFT)
-#define PCI_EXP_SLTCTL_PIC_ON \
- (PCI_EXP_SLTCTL_IND_ON << PCI_EXP_SLTCTL_PIC_SHIFT)
-
#define PCI_EXP_SLTCTL_SUPPORTED \
(PCI_EXP_SLTCTL_ABPE | \
PCI_EXP_SLTCTL_PDCE | \
@@ -155,6 +143,9 @@ typedef enum PCIExpLinkWidth {
PCI_ERR_UNC_ATOP_EBLOCKED | \
PCI_ERR_UNC_TLP_PRF_BLOCKED)
+#define PCI_ERR_UNC_MASK_DEFAULT (PCI_ERR_UNC_INTN | \
+ PCI_ERR_UNC_TLP_PRF_BLOCKED)
+
#define PCI_ERR_UNC_SEVERITY_DEFAULT (PCI_ERR_UNC_DLP | \
PCI_ERR_UNC_SDN | \
PCI_ERR_UNC_FCP | \
@@ -179,4 +170,8 @@ typedef enum PCIExpLinkWidth {
#define PCI_ACS_VER 0x1
#define PCI_ACS_SIZEOF 8
+/* DOE Capability Register Fields */
+#define PCI_DOE_VER 0x1
+#define PCI_DOE_SIZEOF 24
+
#endif /* QEMU_PCIE_REGS_H */
diff --git a/include/hw/pci/pcie_sriov.h b/include/hw/pci/pcie_sriov.h
new file mode 100644
index 0000000000..b77eb7bf58
--- /dev/null
+++ b/include/hw/pci/pcie_sriov.h
@@ -0,0 +1,82 @@
+/*
+ * pcie_sriov.h:
+ *
+ * Implementation of SR/IOV emulation support.
+ *
+ * Copyright (c) 2015 Knut Omang <knut.omang@oracle.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef QEMU_PCIE_SRIOV_H
+#define QEMU_PCIE_SRIOV_H
+
+#include "hw/pci/pci.h"
+
+struct PCIESriovPF {
+ uint16_t num_vfs; /* Number of virtual functions created */
+ uint8_t vf_bar_type[PCI_NUM_REGIONS]; /* Store type for each VF bar */
+ const char *vfname; /* Reference to the device type used for the VFs */
+ PCIDevice **vf; /* Pointer to an array of num_vfs VF devices */
+};
+
+struct PCIESriovVF {
+ PCIDevice *pf; /* Pointer back to owner physical function */
+ uint16_t vf_number; /* Logical VF number of this function */
+};
+
+void pcie_sriov_pf_init(PCIDevice *dev, uint16_t offset,
+ const char *vfname, uint16_t vf_dev_id,
+ uint16_t init_vfs, uint16_t total_vfs,
+ uint16_t vf_offset, uint16_t vf_stride);
+void pcie_sriov_pf_exit(PCIDevice *dev);
+
+/* Set up a VF bar in the SR/IOV bar area */
+void pcie_sriov_pf_init_vf_bar(PCIDevice *dev, int region_num,
+ uint8_t type, dma_addr_t size);
+
+/* Instantiate a bar for a VF */
+void pcie_sriov_vf_register_bar(PCIDevice *dev, int region_num,
+ MemoryRegion *memory);
+
+/*
+ * Default (minimal) page size support values
+ * as required by the SR/IOV standard:
+ * 0x553 << 12 = 0x553000 = 4K + 8K + 64K + 256K + 1M + 4M
+ */
+#define SRIOV_SUP_PGSIZE_MINREQ 0x553
+
+/*
+ * Optionally add supported page sizes to the mask of supported page sizes
+ * Page size values are interpreted as opt_sup_pgsize << 12.
+ */
+void pcie_sriov_pf_add_sup_pgsize(PCIDevice *dev, uint16_t opt_sup_pgsize);
+
+/* SR/IOV capability config write handler */
+void pcie_sriov_config_write(PCIDevice *dev, uint32_t address,
+ uint32_t val, int len);
+
+/* Reset SR/IOV */
+void pcie_sriov_pf_reset(PCIDevice *dev);
+
+/* Get logical VF number of a VF - only valid for VFs */
+uint16_t pcie_sriov_vf_number(PCIDevice *dev);
+
+/*
+ * Get the physical function that owns this VF.
+ * Returns NULL if dev is not a virtual function
+ */
+PCIDevice *pcie_sriov_get_pf(PCIDevice *dev);
+
+/*
+ * Get the n-th VF of this physical function - only valid for PF.
+ * Returns NULL if index is invalid
+ */
+PCIDevice *pcie_sriov_get_vf_at_index(PCIDevice *dev, int n);
+
+/* Returns the current number of virtual functions. */
+uint16_t pcie_sriov_num_vfs(PCIDevice *dev);
+
+#endif /* QEMU_PCIE_SRIOV_H */
diff --git a/include/hw/pci/shpc.h b/include/hw/pci/shpc.h
index d5683b7399..a0789df153 100644
--- a/include/hw/pci/shpc.h
+++ b/include/hw/pci/shpc.h
@@ -3,7 +3,7 @@
#include "exec/memory.h"
#include "hw/hotplug.h"
-#include "hw/pci/pci.h"
+#include "hw/pci/pci_device.h"
#include "migration/vmstate.h"
struct SHPCDevice {
@@ -52,7 +52,7 @@ void shpc_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
void shpc_device_unplug_request_cb(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp);
-extern VMStateInfo shpc_vmstate_info;
+extern const VMStateInfo shpc_vmstate_info;
#define SHPC_VMSTATE(_field, _type, _test) \
VMSTATE_BUFFER_UNSAFE_INFO_TEST(_field, _type, _test, 0, \
shpc_vmstate_info, 0)
diff --git a/include/hw/pcmcia.h b/include/hw/pcmcia.h
index ebad7bc504..ab26802751 100644
--- a/include/hw/pcmcia.h
+++ b/include/hw/pcmcia.h
@@ -4,6 +4,7 @@
/* PCMCIA/Cardbus */
#include "hw/qdev-core.h"
+#include "qom/object.h"
typedef struct PCMCIASocket {
qemu_irq irq;
@@ -11,22 +12,17 @@ typedef struct PCMCIASocket {
} PCMCIASocket;
#define TYPE_PCMCIA_CARD "pcmcia-card"
-#define PCMCIA_CARD(obj) \
- OBJECT_CHECK(PCMCIACardState, (obj), TYPE_PCMCIA_CARD)
-#define PCMCIA_CARD_GET_CLASS(obj) \
- OBJECT_GET_CLASS(PCMCIACardClass, obj, TYPE_PCMCIA_CARD)
-#define PCMCIA_CARD_CLASS(cls) \
- OBJECT_CLASS_CHECK(PCMCIACardClass, cls, TYPE_PCMCIA_CARD)
+OBJECT_DECLARE_TYPE(PCMCIACardState, PCMCIACardClass, PCMCIA_CARD)
-typedef struct PCMCIACardState {
+struct PCMCIACardState {
/*< private >*/
DeviceState parent_obj;
/*< public >*/
PCMCIASocket *slot;
-} PCMCIACardState;
+};
-typedef struct PCMCIACardClass {
+struct PCMCIACardClass {
/*< private >*/
DeviceClass parent_class;
/*< public >*/
@@ -45,24 +41,24 @@ typedef struct PCMCIACardClass {
uint32_t address, uint16_t value);
uint16_t (*io_read)(PCMCIACardState *card, uint32_t address);
void (*io_write)(PCMCIACardState *card, uint32_t address, uint16_t value);
-} PCMCIACardClass;
+};
-#define CISTPL_DEVICE 0x01 /* 5V Device Information Tuple */
-#define CISTPL_NO_LINK 0x14 /* No Link Tuple */
-#define CISTPL_VERS_1 0x15 /* Level 1 Version Tuple */
-#define CISTPL_JEDEC_C 0x18 /* JEDEC ID Tuple */
-#define CISTPL_JEDEC_A 0x19 /* JEDEC ID Tuple */
-#define CISTPL_CONFIG 0x1a /* Configuration Tuple */
-#define CISTPL_CFTABLE_ENTRY 0x1b /* 16-bit PCCard Configuration */
-#define CISTPL_DEVICE_OC 0x1c /* Additional Device Information */
-#define CISTPL_DEVICE_OA 0x1d /* Additional Device Information */
-#define CISTPL_DEVICE_GEO 0x1e /* Additional Device Information */
-#define CISTPL_DEVICE_GEO_A 0x1f /* Additional Device Information */
-#define CISTPL_MANFID 0x20 /* Manufacture ID Tuple */
-#define CISTPL_FUNCID 0x21 /* Function ID Tuple */
-#define CISTPL_FUNCE 0x22 /* Function Extension Tuple */
-#define CISTPL_END 0xff /* Tuple End */
-#define CISTPL_ENDMARK 0xff
+#define CISTPL_DEVICE 0x01 /* 5V Device Information Tuple */
+#define CISTPL_NO_LINK 0x14 /* No Link Tuple */
+#define CISTPL_VERS_1 0x15 /* Level 1 Version Tuple */
+#define CISTPL_JEDEC_C 0x18 /* JEDEC ID Tuple */
+#define CISTPL_JEDEC_A 0x19 /* JEDEC ID Tuple */
+#define CISTPL_CONFIG 0x1a /* Configuration Tuple */
+#define CISTPL_CFTABLE_ENTRY 0x1b /* 16-bit PCCard Configuration */
+#define CISTPL_DEVICE_OC 0x1c /* Additional Device Information */
+#define CISTPL_DEVICE_OA 0x1d /* Additional Device Information */
+#define CISTPL_DEVICE_GEO 0x1e /* Additional Device Information */
+#define CISTPL_DEVICE_GEO_A 0x1f /* Additional Device Information */
+#define CISTPL_MANFID 0x20 /* Manufacture ID Tuple */
+#define CISTPL_FUNCID 0x21 /* Function ID Tuple */
+#define CISTPL_FUNCE 0x22 /* Function Extension Tuple */
+#define CISTPL_END 0xff /* Tuple End */
+#define CISTPL_ENDMARK 0xff
/* dscm1xxxx.c */
PCMCIACardState *dscm1xxxx_init(DriveInfo *bdrv);
diff --git a/include/hw/platform-bus.h b/include/hw/platform-bus.h
index 19e20c57ce..44f30c5353 100644
--- a/include/hw/platform-bus.h
+++ b/include/hw/platform-bus.h
@@ -11,7 +11,7 @@
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -23,16 +23,11 @@
*/
#include "hw/sysbus.h"
+#include "qom/object.h"
-typedef struct PlatformBusDevice PlatformBusDevice;
#define TYPE_PLATFORM_BUS_DEVICE "platform-bus-device"
-#define PLATFORM_BUS_DEVICE(obj) \
- OBJECT_CHECK(PlatformBusDevice, (obj), TYPE_PLATFORM_BUS_DEVICE)
-#define PLATFORM_BUS_DEVICE_CLASS(klass) \
- OBJECT_CLASS_CHECK(PlatformBusDeviceClass, (klass), TYPE_PLATFORM_BUS_DEVICE)
-#define PLATFORM_BUS_DEVICE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(PlatformBusDeviceClass, (obj), TYPE_PLATFORM_BUS_DEVICE)
+OBJECT_DECLARE_SIMPLE_TYPE(PlatformBusDevice, PLATFORM_BUS_DEVICE)
struct PlatformBusDevice {
/*< private >*/
diff --git a/include/hw/ppc/fdt.h b/include/hw/ppc/fdt.h
index a8cd85069f..b56ac2a8cb 100644
--- a/include/hw/ppc/fdt.h
+++ b/include/hw/ppc/fdt.h
@@ -15,10 +15,10 @@
#define _FDT(exp) \
do { \
- int ret = (exp); \
- if (ret < 0) { \
- error_report("error creating device tree: %s: %s", \
- #exp, fdt_strerror(ret)); \
+ int _ret = (exp); \
+ if (_ret < 0) { \
+ error_report("error creating device tree: %s: %s", \
+ #exp, fdt_strerror(_ret)); \
exit(1); \
} \
} while (0)
diff --git a/include/hw/ppc/mac_dbdma.h b/include/hw/ppc/mac_dbdma.h
index 26cc469de4..4a3f644516 100644
--- a/include/hw/ppc/mac_dbdma.h
+++ b/include/hw/ppc/mac_dbdma.h
@@ -27,6 +27,7 @@
#include "qemu/iov.h"
#include "sysemu/dma.h"
#include "hw/sysbus.h"
+#include "qom/object.h"
typedef struct DBDMA_io DBDMA_io;
@@ -160,13 +161,14 @@ typedef struct DBDMA_channel {
dbdma_cmd current;
} DBDMA_channel;
-typedef struct {
+struct DBDMAState {
SysBusDevice parent_obj;
MemoryRegion mem;
DBDMA_channel channels[DBDMA_CHANNELS];
QEMUBH *bh;
-} DBDMAState;
+};
+typedef struct DBDMAState DBDMAState;
/* Externally callable functions */
@@ -176,6 +178,6 @@ void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq,
void DBDMA_kick(DBDMAState *dbdma);
#define TYPE_MAC_DBDMA "mac-dbdma"
-#define MAC_DBDMA(obj) OBJECT_CHECK(DBDMAState, (obj), TYPE_MAC_DBDMA)
+OBJECT_DECLARE_SIMPLE_TYPE(DBDMAState, MAC_DBDMA)
#endif
diff --git a/include/hw/ppc/openpic.h b/include/hw/ppc/openpic.h
index db0d29e6c2..9c6af8e207 100644
--- a/include/hw/ppc/openpic.h
+++ b/include/hw/ppc/openpic.h
@@ -3,6 +3,7 @@
#include "hw/sysbus.h"
#include "hw/core/cpu.h"
+#include "qom/object.h"
#define MAX_CPU 32
#define MAX_MSI 8
@@ -13,14 +14,13 @@ enum {
OPENPIC_OUTPUT_INT = 0, /* IRQ */
OPENPIC_OUTPUT_CINT, /* critical IRQ */
OPENPIC_OUTPUT_MCK, /* Machine check event */
- OPENPIC_OUTPUT_DEBUG, /* Inconditional debug event */
+ OPENPIC_OUTPUT_DEBUG, /* Unconditional debug event */
OPENPIC_OUTPUT_RESET, /* Core reset event */
OPENPIC_OUTPUT_NB,
};
typedef struct IrqLines { qemu_irq irq[OPENPIC_OUTPUT_NB]; } IrqLines;
-#define OPENPIC_MODEL_RAVEN 0
#define OPENPIC_MODEL_FSL_MPIC_20 1
#define OPENPIC_MODEL_FSL_MPIC_42 2
#define OPENPIC_MODEL_KEYLARGO 3
@@ -31,13 +31,6 @@ typedef struct IrqLines { qemu_irq irq[OPENPIC_OUTPUT_NB]; } IrqLines;
#define OPENPIC_MAX_IRQ (OPENPIC_MAX_SRC + OPENPIC_MAX_IPI + \
OPENPIC_MAX_TMR)
-/* Raven */
-#define RAVEN_MAX_CPU 2
-#define RAVEN_MAX_EXT 48
-#define RAVEN_MAX_IRQ 64
-#define RAVEN_MAX_TMR OPENPIC_MAX_TMR
-#define RAVEN_MAX_IPI OPENPIC_MAX_IPI
-
/* KeyLargo */
#define KEYLARGO_MAX_CPU 4
#define KEYLARGO_MAX_EXT 64
@@ -48,14 +41,6 @@ typedef struct IrqLines { qemu_irq irq[OPENPIC_OUTPUT_NB]; } IrqLines;
/* Timers don't exist but this makes the code happy... */
#define KEYLARGO_TMR_IRQ (KEYLARGO_IPI_IRQ + KEYLARGO_MAX_IPI)
-/* Interrupt definitions */
-#define RAVEN_FE_IRQ (RAVEN_MAX_EXT) /* Internal functional IRQ */
-#define RAVEN_ERR_IRQ (RAVEN_MAX_EXT + 1) /* Error IRQ */
-#define RAVEN_TMR_IRQ (RAVEN_MAX_EXT + 2) /* First timer IRQ */
-#define RAVEN_IPI_IRQ (RAVEN_TMR_IRQ + RAVEN_MAX_TMR) /* First IPI IRQ */
-/* First doorbell IRQ */
-#define RAVEN_DBL_IRQ (RAVEN_IPI_IRQ + (RAVEN_MAX_CPU * RAVEN_MAX_IPI))
-
typedef struct FslMpicInfo {
int max_ext;
} FslMpicInfo;
@@ -66,10 +51,11 @@ typedef enum IRQType {
IRQ_TYPE_FSLSPECIAL, /* FSL timer/IPI interrupt, edge, no polarity */
} IRQType;
-/* Round up to the nearest 64 IRQs so that the queue length
+/*
+ * Round up to the nearest 64 IRQs so that the queue length
* won't change when moving between 32 and 64 bit hosts.
*/
-#define IRQQUEUE_SIZE_BITS ((OPENPIC_MAX_IRQ + 63) & ~63)
+#define IRQQUEUE_SIZE_BITS ROUND_UP(OPENPIC_MAX_IRQ, 64)
typedef struct IRQQueue {
unsigned long *queue;
@@ -116,8 +102,10 @@ typedef struct OpenPICTimer {
bool qemu_timer_active; /* Is the qemu_timer is running? */
struct QEMUTimer *qemu_timer;
struct OpenPICState *opp; /* Device timer is part of. */
- /* The QEMU_CLOCK_VIRTUAL time (in ns) corresponding to the last
- current_count written or read, only defined if qemu_timer_active. */
+ /*
+ * The QEMU_CLOCK_VIRTUAL time (in ns) corresponding to the last
+ * current_count written or read, only defined if qemu_timer_active.
+ */
uint64_t origin_time;
} OpenPICTimer;
@@ -136,9 +124,9 @@ typedef struct IRQDest {
} IRQDest;
#define TYPE_OPENPIC "openpic"
-#define OPENPIC(obj) OBJECT_CHECK(OpenPICState, (obj), TYPE_OPENPIC)
+OBJECT_DECLARE_SIMPLE_TYPE(OpenPICState, OPENPIC)
-typedef struct OpenPICState {
+struct OpenPICState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -183,6 +171,6 @@ typedef struct OpenPICState {
uint32_t irq_ipi0;
uint32_t irq_tim0;
uint32_t irq_msi;
-} OpenPICState;
+};
#endif /* OPENPIC_H */
diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index d4b0b0e2ff..476b136146 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -6,7 +6,7 @@
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -20,187 +20,56 @@
#ifndef PPC_PNV_H
#define PPC_PNV_H
+#include "cpu.h"
#include "hw/boards.h"
#include "hw/sysbus.h"
#include "hw/ipmi/ipmi.h"
-#include "hw/ppc/pnv_lpc.h"
#include "hw/ppc/pnv_pnor.h"
-#include "hw/ppc/pnv_psi.h"
-#include "hw/ppc/pnv_occ.h"
-#include "hw/ppc/pnv_homer.h"
-#include "hw/ppc/pnv_xive.h"
-#include "hw/ppc/pnv_core.h"
-#include "hw/pci-host/pnv_phb3.h"
-#include "hw/pci-host/pnv_phb4.h"
#define TYPE_PNV_CHIP "pnv-chip"
-#define PNV_CHIP(obj) OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP)
-#define PNV_CHIP_CLASS(klass) \
- OBJECT_CLASS_CHECK(PnvChipClass, (klass), TYPE_PNV_CHIP)
-#define PNV_CHIP_GET_CLASS(obj) \
- OBJECT_GET_CLASS(PnvChipClass, (obj), TYPE_PNV_CHIP)
-typedef struct PnvChip {
- /*< private >*/
- SysBusDevice parent_obj;
-
- /*< public >*/
- uint32_t chip_id;
- uint64_t ram_start;
- uint64_t ram_size;
-
- uint32_t nr_cores;
- uint32_t nr_threads;
- uint64_t cores_mask;
- PnvCore **cores;
-
- uint32_t num_phbs;
-
- MemoryRegion xscom_mmio;
- MemoryRegion xscom;
- AddressSpace xscom_as;
-
- gchar *dt_isa_nodename;
-} PnvChip;
-
-#define TYPE_PNV8_CHIP "pnv8-chip"
-#define PNV8_CHIP(obj) OBJECT_CHECK(Pnv8Chip, (obj), TYPE_PNV8_CHIP)
-
-typedef struct Pnv8Chip {
- /*< private >*/
- PnvChip parent_obj;
-
- /*< public >*/
- MemoryRegion icp_mmio;
-
- PnvLpcController lpc;
- Pnv8Psi psi;
- PnvOCC occ;
- PnvHomer homer;
-
-#define PNV8_CHIP_PHB3_MAX 4
- PnvPHB3 phbs[PNV8_CHIP_PHB3_MAX];
-
- XICSFabric *xics;
-} Pnv8Chip;
-
-#define TYPE_PNV9_CHIP "pnv9-chip"
-#define PNV9_CHIP(obj) OBJECT_CHECK(Pnv9Chip, (obj), TYPE_PNV9_CHIP)
-
-typedef struct Pnv9Chip {
- /*< private >*/
- PnvChip parent_obj;
-
- /*< public >*/
- PnvXive xive;
- Pnv9Psi psi;
- PnvLpcController lpc;
- PnvOCC occ;
- PnvHomer homer;
-
- uint32_t nr_quads;
- PnvQuad *quads;
-
-#define PNV9_CHIP_MAX_PEC 3
- PnvPhb4PecState pecs[PNV9_CHIP_MAX_PEC];
-} Pnv9Chip;
-
-/*
- * A SMT8 fused core is a pair of SMT4 cores.
- */
-#define PNV9_PIR2FUSEDCORE(pir) (((pir) >> 3) & 0xf)
-#define PNV9_PIR2CHIP(pir) (((pir) >> 8) & 0x7f)
-
-#define TYPE_PNV10_CHIP "pnv10-chip"
-#define PNV10_CHIP(obj) OBJECT_CHECK(Pnv10Chip, (obj), TYPE_PNV10_CHIP)
-
-typedef struct Pnv10Chip {
- /*< private >*/
- PnvChip parent_obj;
-
- /*< public >*/
- Pnv9Psi psi;
- PnvLpcController lpc;
-} Pnv10Chip;
-
-typedef struct PnvChipClass {
- /*< private >*/
- SysBusDeviceClass parent_class;
-
- /*< public >*/
- uint64_t chip_cfam_id;
- uint64_t cores_mask;
- uint32_t num_phbs;
-
- DeviceRealize parent_realize;
-
- uint32_t (*core_pir)(PnvChip *chip, uint32_t core_id);
- void (*intc_create)(PnvChip *chip, PowerPCCPU *cpu, Error **errp);
- void (*intc_reset)(PnvChip *chip, PowerPCCPU *cpu);
- void (*intc_destroy)(PnvChip *chip, PowerPCCPU *cpu);
- void (*intc_print_info)(PnvChip *chip, PowerPCCPU *cpu, Monitor *mon);
- ISABus *(*isa_create)(PnvChip *chip, Error **errp);
- void (*dt_populate)(PnvChip *chip, void *fdt);
- void (*pic_print_info)(PnvChip *chip, Monitor *mon);
- uint64_t (*xscom_core_base)(PnvChip *chip, uint32_t core_id);
- uint32_t (*xscom_pcba)(PnvChip *chip, uint64_t addr);
-} PnvChipClass;
+typedef struct PnvCore PnvCore;
+typedef struct PnvChip PnvChip;
+typedef struct Pnv8Chip Pnv8Chip;
+typedef struct Pnv9Chip Pnv9Chip;
+typedef struct Pnv10Chip Pnv10Chip;
#define PNV_CHIP_TYPE_SUFFIX "-" TYPE_PNV_CHIP
#define PNV_CHIP_TYPE_NAME(cpu_model) cpu_model PNV_CHIP_TYPE_SUFFIX
#define TYPE_PNV_CHIP_POWER8E PNV_CHIP_TYPE_NAME("power8e_v2.1")
-#define PNV_CHIP_POWER8E(obj) \
- OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER8E)
+DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER8E,
+ TYPE_PNV_CHIP_POWER8E)
#define TYPE_PNV_CHIP_POWER8 PNV_CHIP_TYPE_NAME("power8_v2.0")
-#define PNV_CHIP_POWER8(obj) \
- OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER8)
+DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER8,
+ TYPE_PNV_CHIP_POWER8)
#define TYPE_PNV_CHIP_POWER8NVL PNV_CHIP_TYPE_NAME("power8nvl_v1.0")
-#define PNV_CHIP_POWER8NVL(obj) \
- OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER8NVL)
-
-#define TYPE_PNV_CHIP_POWER9 PNV_CHIP_TYPE_NAME("power9_v2.0")
-#define PNV_CHIP_POWER9(obj) \
- OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER9)
+DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER8NVL,
+ TYPE_PNV_CHIP_POWER8NVL)
-#define TYPE_PNV_CHIP_POWER10 PNV_CHIP_TYPE_NAME("power10_v1.0")
-#define PNV_CHIP_POWER10(obj) \
- OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER10)
+#define TYPE_PNV_CHIP_POWER9 PNV_CHIP_TYPE_NAME("power9_v2.2")
+DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER9,
+ TYPE_PNV_CHIP_POWER9)
-/*
- * This generates a HW chip id depending on an index, as found on a
- * two socket system with dual chip modules :
- *
- * 0x0, 0x1, 0x10, 0x11
- *
- * 4 chips should be the maximum
- *
- * TODO: use a machine property to define the chip ids
- */
-#define PNV_CHIP_HWID(i) ((((i) & 0x3e) << 3) | ((i) & 0x1))
-
-/*
- * Converts back a HW chip id to an index. This is useful to calculate
- * the MMIO addresses of some controllers which depend on the chip id.
- */
-#define PNV_CHIP_INDEX(chip) \
- (((chip)->chip_id >> 2) * 2 + ((chip)->chip_id & 0x3))
+#define TYPE_PNV_CHIP_POWER10 PNV_CHIP_TYPE_NAME("power10_v2.0")
+DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER10,
+ TYPE_PNV_CHIP_POWER10)
+PnvCore *pnv_chip_find_core(PnvChip *chip, uint32_t core_id);
PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir);
-#define TYPE_PNV_MACHINE MACHINE_TYPE_NAME("powernv")
-#define PNV_MACHINE(obj) \
- OBJECT_CHECK(PnvMachineState, (obj), TYPE_PNV_MACHINE)
-#define PNV_MACHINE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(PnvMachineClass, obj, TYPE_PNV_MACHINE)
-#define PNV_MACHINE_CLASS(klass) \
- OBJECT_CLASS_CHECK(PnvMachineClass, klass, TYPE_PNV_MACHINE)
+typedef struct PnvPHB PnvPHB;
+#define TYPE_PNV_MACHINE MACHINE_TYPE_NAME("powernv")
+typedef struct PnvMachineClass PnvMachineClass;
typedef struct PnvMachineState PnvMachineState;
+DECLARE_OBJ_CHECKERS(PnvMachineState, PnvMachineClass,
+ PNV_MACHINE, TYPE_PNV_MACHINE)
+
-typedef struct PnvMachineClass {
+struct PnvMachineClass {
/*< private >*/
MachineClass parent_class;
@@ -209,7 +78,8 @@ typedef struct PnvMachineClass {
int compat_size;
void (*dt_power_mgt)(PnvMachineState *pnv, void *fdt);
-} PnvMachineClass;
+ void (*i2c_init)(PnvMachineState *pnv);
+};
struct PnvMachineState {
/*< private >*/
@@ -232,6 +102,9 @@ struct PnvMachineState {
hwaddr fw_load_addr;
};
+PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id);
+PnvChip *pnv_chip_add_phb(PnvChip *chip, PnvPHB *phb);
+
#define PNV_FDT_ADDR 0x01000000
#define PNV_TIMEBASE_FREQ 512000000ULL
@@ -254,11 +127,11 @@ void pnv_bmc_set_pnor(IPMIBmc *bmc, PnvPnor *pnor);
#define PNV_OCC_COMMON_AREA_SIZE 0x0000000000800000ull
#define PNV_OCC_COMMON_AREA_BASE 0x7fff800000ull
#define PNV_OCC_SENSOR_BASE(chip) (PNV_OCC_COMMON_AREA_BASE + \
- PNV_OCC_SENSOR_DATA_BLOCK_BASE(PNV_CHIP_INDEX(chip)))
+ PNV_OCC_SENSOR_DATA_BLOCK_BASE((chip)->chip_id))
#define PNV_HOMER_SIZE 0x0000000000400000ull
#define PNV_HOMER_BASE(chip) \
- (0x7ffd800000ull + ((uint64_t)PNV_CHIP_INDEX(chip)) * PNV_HOMER_SIZE)
+ (0x7ffd800000ull + ((uint64_t)(chip)->chip_id) * PNV_HOMER_SIZE)
/*
@@ -277,16 +150,16 @@ void pnv_bmc_set_pnor(IPMIBmc *bmc, PnvPnor *pnor);
*/
#define PNV_ICP_SIZE 0x0000000000100000ull
#define PNV_ICP_BASE(chip) \
- (0x0003ffff80000000ull + (uint64_t) PNV_CHIP_INDEX(chip) * PNV_ICP_SIZE)
+ (0x0003ffff80000000ull + (uint64_t) (chip)->chip_id * PNV_ICP_SIZE)
#define PNV_PSIHB_SIZE 0x0000000000100000ull
#define PNV_PSIHB_BASE(chip) \
- (0x0003fffe80000000ull + (uint64_t)PNV_CHIP_INDEX(chip) * PNV_PSIHB_SIZE)
+ (0x0003fffe80000000ull + (uint64_t)(chip)->chip_id * PNV_PSIHB_SIZE)
#define PNV_PSIHB_FSP_SIZE 0x0000000100000000ull
#define PNV_PSIHB_FSP_BASE(chip) \
- (0x0003ffe000000000ull + (uint64_t)PNV_CHIP_INDEX(chip) * \
+ (0x0003ffe000000000ull + (uint64_t)(chip)->chip_id * \
PNV_PSIHB_FSP_SIZE)
/*
@@ -322,11 +195,11 @@ void pnv_bmc_set_pnor(IPMIBmc *bmc, PnvPnor *pnor);
#define PNV9_OCC_COMMON_AREA_SIZE 0x0000000000800000ull
#define PNV9_OCC_COMMON_AREA_BASE 0x203fff800000ull
#define PNV9_OCC_SENSOR_BASE(chip) (PNV9_OCC_COMMON_AREA_BASE + \
- PNV_OCC_SENSOR_DATA_BLOCK_BASE(PNV_CHIP_INDEX(chip)))
+ PNV_OCC_SENSOR_DATA_BLOCK_BASE((chip)->chip_id))
#define PNV9_HOMER_SIZE 0x0000000000400000ull
#define PNV9_HOMER_BASE(chip) \
- (0x203ffd800000ull + ((uint64_t)PNV_CHIP_INDEX(chip)) * PNV9_HOMER_SIZE)
+ (0x203ffd800000ull + ((uint64_t)(chip)->chip_id) * PNV9_HOMER_SIZE)
/*
* POWER10 MMIO base addresses - 16TB stride per chip
@@ -340,10 +213,37 @@ void pnv_bmc_set_pnor(IPMIBmc *bmc, PnvPnor *pnor);
#define PNV10_LPCM_SIZE 0x0000000100000000ull
#define PNV10_LPCM_BASE(chip) PNV10_CHIP_BASE(chip, 0x0006030000000000ull)
+#define PNV10_XIVE2_IC_SIZE 0x0000000002000000ull
+#define PNV10_XIVE2_IC_BASE(chip) PNV10_CHIP_BASE(chip, 0x0006030200000000ull)
+
#define PNV10_PSIHB_ESB_SIZE 0x0000000000100000ull
#define PNV10_PSIHB_ESB_BASE(chip) PNV10_CHIP_BASE(chip, 0x0006030202000000ull)
#define PNV10_PSIHB_SIZE 0x0000000000100000ull
#define PNV10_PSIHB_BASE(chip) PNV10_CHIP_BASE(chip, 0x0006030203000000ull)
+#define PNV10_XIVE2_TM_SIZE 0x0000000000040000ull
+#define PNV10_XIVE2_TM_BASE(chip) PNV10_CHIP_BASE(chip, 0x0006030203180000ull)
+
+#define PNV10_XIVE2_NVC_SIZE 0x0000000008000000ull
+#define PNV10_XIVE2_NVC_BASE(chip) PNV10_CHIP_BASE(chip, 0x0006030208000000ull)
+
+#define PNV10_XIVE2_NVPG_SIZE 0x0000010000000000ull
+#define PNV10_XIVE2_NVPG_BASE(chip) PNV10_CHIP_BASE(chip, 0x0006040000000000ull)
+
+#define PNV10_XIVE2_ESB_SIZE 0x0000010000000000ull
+#define PNV10_XIVE2_ESB_BASE(chip) PNV10_CHIP_BASE(chip, 0x0006050000000000ull)
+
+#define PNV10_XIVE2_END_SIZE 0x0000020000000000ull
+#define PNV10_XIVE2_END_BASE(chip) PNV10_CHIP_BASE(chip, 0x0006060000000000ull)
+
+#define PNV10_OCC_COMMON_AREA_SIZE 0x0000000000800000ull
+#define PNV10_OCC_COMMON_AREA_BASE 0x300fff800000ull
+#define PNV10_OCC_SENSOR_BASE(chip) (PNV10_OCC_COMMON_AREA_BASE + \
+ PNV_OCC_SENSOR_DATA_BLOCK_BASE((chip)->chip_id))
+
+#define PNV10_HOMER_SIZE 0x0000000000400000ull
+#define PNV10_HOMER_BASE(chip) \
+ (0x300ffd800000ll + ((uint64_t)(chip)->chip_id) * PNV10_HOMER_SIZE)
+
#endif /* PPC_PNV_H */
diff --git a/include/hw/ppc/pnv_chip.h b/include/hw/ppc/pnv_chip.h
new file mode 100644
index 0000000000..8589f3291e
--- /dev/null
+++ b/include/hw/ppc/pnv_chip.h
@@ -0,0 +1,162 @@
+#ifndef PPC_PNV_CHIP_H
+#define PPC_PNV_CHIP_H
+
+#include "hw/pci-host/pnv_phb4.h"
+#include "hw/ppc/pnv_chiptod.h"
+#include "hw/ppc/pnv_core.h"
+#include "hw/ppc/pnv_homer.h"
+#include "hw/ppc/pnv_n1_chiplet.h"
+#include "hw/ppc/pnv_lpc.h"
+#include "hw/ppc/pnv_occ.h"
+#include "hw/ppc/pnv_psi.h"
+#include "hw/ppc/pnv_sbe.h"
+#include "hw/ppc/pnv_xive.h"
+#include "hw/ppc/pnv_i2c.h"
+#include "hw/sysbus.h"
+
+OBJECT_DECLARE_TYPE(PnvChip, PnvChipClass,
+ PNV_CHIP)
+
+struct PnvChip {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ uint32_t chip_id;
+ uint64_t ram_start;
+ uint64_t ram_size;
+
+ uint32_t nr_cores;
+ uint32_t nr_threads;
+ uint64_t cores_mask;
+ PnvCore **cores;
+
+ uint32_t num_pecs;
+
+ MemoryRegion xscom_mmio;
+ MemoryRegion xscom;
+ AddressSpace xscom_as;
+
+ MemoryRegion *fw_mr;
+ gchar *dt_isa_nodename;
+};
+
+#define TYPE_PNV8_CHIP "pnv8-chip"
+DECLARE_INSTANCE_CHECKER(Pnv8Chip, PNV8_CHIP,
+ TYPE_PNV8_CHIP)
+
+struct Pnv8Chip {
+ /*< private >*/
+ PnvChip parent_obj;
+
+ /*< public >*/
+ MemoryRegion icp_mmio;
+
+ PnvLpcController lpc;
+ Pnv8Psi psi;
+ PnvOCC occ;
+ PnvHomer homer;
+
+#define PNV8_CHIP_PHB3_MAX 4
+ /*
+ * The array is used to allow quick access to the phbs by
+ * pnv_ics_get_child() and pnv_ics_resend_child().
+ */
+ PnvPHB *phbs[PNV8_CHIP_PHB3_MAX];
+ uint32_t num_phbs;
+
+ XICSFabric *xics;
+};
+
+#define TYPE_PNV9_CHIP "pnv9-chip"
+DECLARE_INSTANCE_CHECKER(Pnv9Chip, PNV9_CHIP,
+ TYPE_PNV9_CHIP)
+
+struct Pnv9Chip {
+ /*< private >*/
+ PnvChip parent_obj;
+
+ /*< public >*/
+ PnvXive xive;
+ Pnv9Psi psi;
+ PnvLpcController lpc;
+ PnvChipTOD chiptod;
+ PnvOCC occ;
+ PnvSBE sbe;
+ PnvHomer homer;
+
+ uint32_t nr_quads;
+ PnvQuad *quads;
+
+#define PNV9_CHIP_MAX_PEC 3
+ PnvPhb4PecState pecs[PNV9_CHIP_MAX_PEC];
+
+#define PNV9_CHIP_MAX_I2C 4
+ PnvI2C i2c[PNV9_CHIP_MAX_I2C];
+};
+
+/*
+ * A SMT8 fused core is a pair of SMT4 cores.
+ */
+#define PNV9_PIR2FUSEDCORE(pir) (((pir) >> 3) & 0xf)
+#define PNV9_PIR2CHIP(pir) (((pir) >> 8) & 0x7f)
+
+#define TYPE_PNV10_CHIP "pnv10-chip"
+DECLARE_INSTANCE_CHECKER(Pnv10Chip, PNV10_CHIP,
+ TYPE_PNV10_CHIP)
+
+struct Pnv10Chip {
+ /*< private >*/
+ PnvChip parent_obj;
+
+ /*< public >*/
+ PnvXive2 xive;
+ Pnv9Psi psi;
+ PnvLpcController lpc;
+ PnvChipTOD chiptod;
+ PnvOCC occ;
+ PnvSBE sbe;
+ PnvHomer homer;
+ PnvN1Chiplet n1_chiplet;
+
+ uint32_t nr_quads;
+ PnvQuad *quads;
+
+#define PNV10_CHIP_MAX_PEC 2
+ PnvPhb4PecState pecs[PNV10_CHIP_MAX_PEC];
+
+#define PNV10_CHIP_MAX_I2C 4
+ PnvI2C i2c[PNV10_CHIP_MAX_I2C];
+};
+
+#define PNV10_PIR2FUSEDCORE(pir) (((pir) >> 3) & 0xf)
+#define PNV10_PIR2CHIP(pir) (((pir) >> 8) & 0x7f)
+
+struct PnvChipClass {
+ /*< private >*/
+ SysBusDeviceClass parent_class;
+
+ /*< public >*/
+ uint64_t chip_cfam_id;
+ uint64_t cores_mask;
+ uint32_t num_pecs;
+ uint32_t num_phbs;
+
+ uint32_t i2c_num_engines;
+ const int *i2c_ports_per_engine;
+
+ DeviceRealize parent_realize;
+
+ uint32_t (*chip_pir)(PnvChip *chip, uint32_t core_id, uint32_t thread_id);
+ void (*intc_create)(PnvChip *chip, PowerPCCPU *cpu, Error **errp);
+ void (*intc_reset)(PnvChip *chip, PowerPCCPU *cpu);
+ void (*intc_destroy)(PnvChip *chip, PowerPCCPU *cpu);
+ void (*intc_print_info)(PnvChip *chip, PowerPCCPU *cpu, Monitor *mon);
+ ISABus *(*isa_create)(PnvChip *chip, Error **errp);
+ void (*dt_populate)(PnvChip *chip, void *fdt);
+ void (*pic_print_info)(PnvChip *chip, Monitor *mon);
+ uint64_t (*xscom_core_base)(PnvChip *chip, uint32_t core_id);
+ uint32_t (*xscom_pcba)(PnvChip *chip, uint64_t addr);
+};
+
+#endif
diff --git a/include/hw/ppc/pnv_chiptod.h b/include/hw/ppc/pnv_chiptod.h
new file mode 100644
index 0000000000..fde569bcbf
--- /dev/null
+++ b/include/hw/ppc/pnv_chiptod.h
@@ -0,0 +1,53 @@
+/*
+ * QEMU PowerPC PowerNV Emulation of some CHIPTOD behaviour
+ *
+ * Copyright (c) 2022-2023, IBM Corporation.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef PPC_PNV_CHIPTOD_H
+#define PPC_PNV_CHIPTOD_H
+
+#include "qom/object.h"
+
+#define TYPE_PNV_CHIPTOD "pnv-chiptod"
+OBJECT_DECLARE_TYPE(PnvChipTOD, PnvChipTODClass, PNV_CHIPTOD)
+#define TYPE_PNV9_CHIPTOD TYPE_PNV_CHIPTOD "-POWER9"
+DECLARE_INSTANCE_CHECKER(PnvChipTOD, PNV9_CHIPTOD, TYPE_PNV9_CHIPTOD)
+#define TYPE_PNV10_CHIPTOD TYPE_PNV_CHIPTOD "-POWER10"
+DECLARE_INSTANCE_CHECKER(PnvChipTOD, PNV10_CHIPTOD, TYPE_PNV10_CHIPTOD)
+
+enum tod_state {
+ tod_error = 0,
+ tod_not_set = 7,
+ tod_running = 2,
+ tod_stopped = 1,
+};
+
+typedef struct PnvCore PnvCore;
+
+struct PnvChipTOD {
+ DeviceState xd;
+
+ PnvChip *chip;
+ MemoryRegion xscom_regs;
+
+ bool primary;
+ bool secondary;
+ enum tod_state tod_state;
+ uint64_t tod_error;
+ uint64_t pss_mss_ctrl_reg;
+ PnvCore *slave_pc_target;
+};
+
+struct PnvChipTODClass {
+ DeviceClass parent_class;
+
+ void (*broadcast_ttype)(PnvChipTOD *sender, uint32_t trigger);
+ PnvCore *(*tx_ttype_target)(PnvChipTOD *chiptod, uint64_t val);
+
+ int xscom_size;
+};
+
+#endif /* PPC_PNV_CHIPTOD_H */
diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h
index 113550eb7f..c6d62fd145 100644
--- a/include/hw/ppc/pnv_core.h
+++ b/include/hw/ppc/pnv_core.h
@@ -5,7 +5,7 @@
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2 of
+ * as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
@@ -22,35 +22,33 @@
#include "hw/cpu/core.h"
#include "target/ppc/cpu.h"
+#include "hw/ppc/pnv.h"
+#include "qom/object.h"
#define TYPE_PNV_CORE "powernv-cpu-core"
-#define PNV_CORE(obj) \
- OBJECT_CHECK(PnvCore, (obj), TYPE_PNV_CORE)
-#define PNV_CORE_CLASS(klass) \
- OBJECT_CLASS_CHECK(PnvCoreClass, (klass), TYPE_PNV_CORE)
-#define PNV_CORE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(PnvCoreClass, (obj), TYPE_PNV_CORE)
+OBJECT_DECLARE_TYPE(PnvCore, PnvCoreClass,
+ PNV_CORE)
-typedef struct PnvChip PnvChip;
-
-typedef struct PnvCore {
+struct PnvCore {
/*< private >*/
CPUCore parent_obj;
/*< public >*/
PowerPCCPU **threads;
uint32_t pir;
+ uint32_t hwid;
uint64_t hrmor;
PnvChip *chip;
MemoryRegion xscom_regs;
-} PnvCore;
+};
-typedef struct PnvCoreClass {
+struct PnvCoreClass {
DeviceClass parent_class;
const MemoryRegionOps *xscom_ops;
-} PnvCoreClass;
+ uint64_t xscom_size;
+};
#define PNV_CORE_TYPE_SUFFIX "-" TYPE_PNV_CORE
#define PNV_CORE_TYPE_NAME(cpu_model) cpu_model PNV_CORE_TYPE_SUFFIX
@@ -64,14 +62,28 @@ static inline PnvCPUState *pnv_cpu_state(PowerPCCPU *cpu)
return (PnvCPUState *)cpu->machine_data;
}
+struct PnvQuadClass {
+ DeviceClass parent_class;
+
+ const MemoryRegionOps *xscom_ops;
+ uint64_t xscom_size;
+
+ const MemoryRegionOps *xscom_qme_ops;
+ uint64_t xscom_qme_size;
+};
+
#define TYPE_PNV_QUAD "powernv-cpu-quad"
-#define PNV_QUAD(obj) \
- OBJECT_CHECK(PnvQuad, (obj), TYPE_PNV_QUAD)
-typedef struct PnvQuad {
+#define PNV_QUAD_TYPE_SUFFIX "-" TYPE_PNV_QUAD
+#define PNV_QUAD_TYPE_NAME(cpu_model) cpu_model PNV_QUAD_TYPE_SUFFIX
+
+OBJECT_DECLARE_TYPE(PnvQuad, PnvQuadClass, PNV_QUAD)
+
+struct PnvQuad {
DeviceState parent_obj;
- uint32_t id;
+ uint32_t quad_id;
MemoryRegion xscom_regs;
-} PnvQuad;
+ MemoryRegion xscom_qme_regs;
+};
#endif /* PPC_PNV_CORE_H */
diff --git a/include/hw/ppc/pnv_homer.h b/include/hw/ppc/pnv_homer.h
index 1e91c950f6..b1c5d498dc 100644
--- a/include/hw/ppc/pnv_homer.h
+++ b/include/hw/ppc/pnv_homer.h
@@ -6,7 +6,7 @@
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -21,28 +21,31 @@
#define PPC_PNV_HOMER_H
#include "hw/ppc/pnv.h"
+#include "qom/object.h"
#define TYPE_PNV_HOMER "pnv-homer"
-#define PNV_HOMER(obj) OBJECT_CHECK(PnvHomer, (obj), TYPE_PNV_HOMER)
+OBJECT_DECLARE_TYPE(PnvHomer, PnvHomerClass,
+ PNV_HOMER)
#define TYPE_PNV8_HOMER TYPE_PNV_HOMER "-POWER8"
-#define PNV8_HOMER(obj) OBJECT_CHECK(PnvHomer, (obj), TYPE_PNV8_HOMER)
+DECLARE_INSTANCE_CHECKER(PnvHomer, PNV8_HOMER,
+ TYPE_PNV8_HOMER)
#define TYPE_PNV9_HOMER TYPE_PNV_HOMER "-POWER9"
-#define PNV9_HOMER(obj) OBJECT_CHECK(PnvHomer, (obj), TYPE_PNV9_HOMER)
+DECLARE_INSTANCE_CHECKER(PnvHomer, PNV9_HOMER,
+ TYPE_PNV9_HOMER)
+#define TYPE_PNV10_HOMER TYPE_PNV_HOMER "-POWER10"
+DECLARE_INSTANCE_CHECKER(PnvHomer, PNV10_HOMER,
+ TYPE_PNV10_HOMER)
-typedef struct PnvHomer {
+struct PnvHomer {
DeviceState parent;
- struct PnvChip *chip;
+ PnvChip *chip;
MemoryRegion pba_regs;
MemoryRegion regs;
-} PnvHomer;
+};
-#define PNV_HOMER_CLASS(klass) \
- OBJECT_CLASS_CHECK(PnvHomerClass, (klass), TYPE_PNV_HOMER)
-#define PNV_HOMER_GET_CLASS(obj) \
- OBJECT_GET_CLASS(PnvHomerClass, (obj), TYPE_PNV_HOMER)
-typedef struct PnvHomerClass {
+struct PnvHomerClass {
DeviceClass parent_class;
int pba_size;
@@ -51,6 +54,6 @@ typedef struct PnvHomerClass {
const MemoryRegionOps *homer_ops;
hwaddr core_max_base;
-} PnvHomerClass;
+};
#endif /* PPC_PNV_HOMER_H */
diff --git a/include/hw/ppc/pnv_i2c.h b/include/hw/ppc/pnv_i2c.h
new file mode 100644
index 0000000000..1a37730f1e
--- /dev/null
+++ b/include/hw/ppc/pnv_i2c.h
@@ -0,0 +1,38 @@
+/*
+ * QEMU PowerPC PowerNV Processor I2C model
+ *
+ * Copyright (c) 2019-2023, IBM Corporation.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef PPC_PNV_I2C_H
+#define PPC_PNV_I2C_H
+
+#include "hw/ppc/pnv.h"
+#include "hw/i2c/i2c.h"
+#include "qemu/fifo8.h"
+
+#define TYPE_PNV_I2C "pnv-i2c"
+#define PNV_I2C(obj) OBJECT_CHECK(PnvI2C, (obj), TYPE_PNV_I2C)
+
+#define PNV_I2C_REGS 0x20
+
+typedef struct PnvI2C {
+ DeviceState parent;
+
+ struct PnvChip *chip;
+
+ qemu_irq psi_irq;
+
+ uint64_t regs[PNV_I2C_REGS];
+ uint32_t engine;
+ uint32_t num_busses;
+ I2CBus **busses;
+
+ MemoryRegion xscom_regs;
+
+ Fifo8 fifo;
+} PnvI2C;
+
+#endif /* PPC_PNV_I2C_H */
diff --git a/include/hw/ppc/pnv_lpc.h b/include/hw/ppc/pnv_lpc.h
index c1ec85d5e2..5d22c45570 100644
--- a/include/hw/ppc/pnv_lpc.h
+++ b/include/hw/ppc/pnv_lpc.h
@@ -1,12 +1,12 @@
/*
* QEMU PowerPC PowerNV LPC controller
*
- * Copyright (c) 2016, IBM Corporation.
+ * Copyright (c) 2016-2022, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -20,21 +20,28 @@
#ifndef PPC_PNV_LPC_H
#define PPC_PNV_LPC_H
-#include "hw/ppc/pnv_psi.h"
+#include "exec/memory.h"
+#include "hw/ppc/pnv.h"
+#include "hw/qdev-core.h"
#define TYPE_PNV_LPC "pnv-lpc"
-#define PNV_LPC(obj) \
- OBJECT_CHECK(PnvLpcController, (obj), TYPE_PNV_LPC)
+typedef struct PnvLpcClass PnvLpcClass;
+typedef struct PnvLpcController PnvLpcController;
+DECLARE_OBJ_CHECKERS(PnvLpcController, PnvLpcClass,
+ PNV_LPC, TYPE_PNV_LPC)
#define TYPE_PNV8_LPC TYPE_PNV_LPC "-POWER8"
-#define PNV8_LPC(obj) OBJECT_CHECK(PnvLpcController, (obj), TYPE_PNV8_LPC)
+DECLARE_INSTANCE_CHECKER(PnvLpcController, PNV8_LPC,
+ TYPE_PNV8_LPC)
#define TYPE_PNV9_LPC TYPE_PNV_LPC "-POWER9"
-#define PNV9_LPC(obj) OBJECT_CHECK(PnvLpcController, (obj), TYPE_PNV9_LPC)
+DECLARE_INSTANCE_CHECKER(PnvLpcController, PNV9_LPC,
+ TYPE_PNV9_LPC)
#define TYPE_PNV10_LPC TYPE_PNV_LPC "-POWER10"
-#define PNV10_LPC(obj) OBJECT_CHECK(PnvLpcController, (obj), TYPE_PNV10_LPC)
+DECLARE_INSTANCE_CHECKER(PnvLpcController, PNV10_LPC,
+ TYPE_PNV10_LPC)
-typedef struct PnvLpcController {
+struct PnvLpcController {
DeviceState parent;
uint64_t eccb_stat_reg;
@@ -78,29 +85,17 @@ typedef struct PnvLpcController {
MemoryRegion xscom_regs;
/* PSI to generate interrupts */
- PnvPsi *psi;
-} PnvLpcController;
+ qemu_irq psi_irq;
+};
-#define PNV_LPC_CLASS(klass) \
- OBJECT_CLASS_CHECK(PnvLpcClass, (klass), TYPE_PNV_LPC)
-#define PNV_LPC_GET_CLASS(obj) \
- OBJECT_GET_CLASS(PnvLpcClass, (obj), TYPE_PNV_LPC)
-
-typedef struct PnvLpcClass {
+struct PnvLpcClass {
DeviceClass parent_class;
- int psi_irq;
-
DeviceRealize parent_realize;
-} PnvLpcClass;
-
-/*
- * Old compilers error on typdef forward declarations. Keep them happy.
- */
-struct PnvChip;
+};
ISABus *pnv_lpc_isa_create(PnvLpcController *lpc, bool use_cpld, Error **errp);
-int pnv_dt_lpc(struct PnvChip *chip, void *fdt, int root_offset,
+int pnv_dt_lpc(PnvChip *chip, void *fdt, int root_offset,
uint64_t lpcm_addr, uint64_t lpcm_size);
#endif /* PPC_PNV_LPC_H */
diff --git a/include/hw/ppc/pnv_n1_chiplet.h b/include/hw/ppc/pnv_n1_chiplet.h
new file mode 100644
index 0000000000..a7ad039668
--- /dev/null
+++ b/include/hw/ppc/pnv_n1_chiplet.h
@@ -0,0 +1,32 @@
+/*
+ * QEMU PowerPC N1 chiplet model
+ *
+ * Copyright (c) 2023, IBM Corporation.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef PPC_PNV_N1_CHIPLET_H
+#define PPC_PNV_N1_CHIPLET_H
+
+#include "hw/ppc/pnv_nest_pervasive.h"
+
+#define TYPE_PNV_N1_CHIPLET "pnv-N1-chiplet"
+#define PNV_N1_CHIPLET(obj) OBJECT_CHECK(PnvN1Chiplet, (obj), TYPE_PNV_N1_CHIPLET)
+
+typedef struct PnvPbScom {
+ uint64_t mode;
+ uint64_t hp_mode2_curr;
+} PnvPbScom;
+
+typedef struct PnvN1Chiplet {
+ DeviceState parent;
+ MemoryRegion xscom_pb_eq_mr;
+ MemoryRegion xscom_pb_es_mr;
+ PnvNestChipletPervasive nest_pervasive; /* common pervasive chiplet unit */
+#define PNV_PB_SCOM_EQ_SIZE 8
+ PnvPbScom eq[PNV_PB_SCOM_EQ_SIZE];
+#define PNV_PB_SCOM_ES_SIZE 4
+ PnvPbScom es[PNV_PB_SCOM_ES_SIZE];
+} PnvN1Chiplet;
+#endif /*PPC_PNV_N1_CHIPLET_H */
diff --git a/include/hw/ppc/pnv_nest_pervasive.h b/include/hw/ppc/pnv_nest_pervasive.h
new file mode 100644
index 0000000000..73cacf3823
--- /dev/null
+++ b/include/hw/ppc/pnv_nest_pervasive.h
@@ -0,0 +1,32 @@
+/*
+ * QEMU PowerPC nest pervasive common chiplet model
+ *
+ * Copyright (c) 2023, IBM Corporation.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef PPC_PNV_NEST_CHIPLET_PERVASIVE_H
+#define PPC_PNV_NEST_CHIPLET_PERVASIVE_H
+
+#define TYPE_PNV_NEST_CHIPLET_PERVASIVE "pnv-nest-chiplet-pervasive"
+#define PNV_NEST_CHIPLET_PERVASIVE(obj) OBJECT_CHECK(PnvNestChipletPervasive, (obj), TYPE_PNV_NEST_CHIPLET_PERVASIVE)
+
+typedef struct PnvPervasiveCtrlRegs {
+#define PNV_CPLT_CTRL_SIZE 6
+ uint64_t cplt_ctrl[PNV_CPLT_CTRL_SIZE];
+ uint64_t cplt_cfg0;
+ uint64_t cplt_cfg1;
+ uint64_t cplt_stat0;
+ uint64_t cplt_mask0;
+ uint64_t ctrl_protect_mode;
+ uint64_t ctrl_atomic_lock;
+} PnvPervasiveCtrlRegs;
+
+typedef struct PnvNestChipletPervasive {
+ DeviceState parent;
+ MemoryRegion xscom_ctrl_regs_mr;
+ PnvPervasiveCtrlRegs control_regs;
+} PnvNestChipletPervasive;
+
+#endif /*PPC_PNV_NEST_CHIPLET_PERVASIVE_H */
diff --git a/include/hw/ppc/pnv_occ.h b/include/hw/ppc/pnv_occ.h
index f8d3061419..df321244e3 100644
--- a/include/hw/ppc/pnv_occ.h
+++ b/include/hw/ppc/pnv_occ.h
@@ -1,12 +1,12 @@
/*
* QEMU PowerPC PowerNV Emulation of a few OCC related registers
*
- * Copyright (c) 2015-2017, IBM Corporation.
+ * Copyright (c) 2015-2022, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -20,42 +20,42 @@
#ifndef PPC_PNV_OCC_H
#define PPC_PNV_OCC_H
-#include "hw/ppc/pnv_psi.h"
+#include "exec/memory.h"
+#include "hw/qdev-core.h"
#define TYPE_PNV_OCC "pnv-occ"
-#define PNV_OCC(obj) OBJECT_CHECK(PnvOCC, (obj), TYPE_PNV_OCC)
+OBJECT_DECLARE_TYPE(PnvOCC, PnvOCCClass,
+ PNV_OCC)
#define TYPE_PNV8_OCC TYPE_PNV_OCC "-POWER8"
-#define PNV8_OCC(obj) OBJECT_CHECK(PnvOCC, (obj), TYPE_PNV8_OCC)
+DECLARE_INSTANCE_CHECKER(PnvOCC, PNV8_OCC,
+ TYPE_PNV8_OCC)
#define TYPE_PNV9_OCC TYPE_PNV_OCC "-POWER9"
-#define PNV9_OCC(obj) OBJECT_CHECK(PnvOCC, (obj), TYPE_PNV9_OCC)
+DECLARE_INSTANCE_CHECKER(PnvOCC, PNV9_OCC,
+ TYPE_PNV9_OCC)
+#define TYPE_PNV10_OCC TYPE_PNV_OCC "-POWER10"
+DECLARE_INSTANCE_CHECKER(PnvOCC, PNV10_OCC, TYPE_PNV10_OCC)
#define PNV_OCC_SENSOR_DATA_BLOCK_OFFSET 0x00580000
#define PNV_OCC_SENSOR_DATA_BLOCK_SIZE 0x00025800
-typedef struct PnvOCC {
+struct PnvOCC {
DeviceState xd;
/* OCC Misc interrupt */
uint64_t occmisc;
- PnvPsi *psi;
+ qemu_irq psi_irq;
MemoryRegion xscom_regs;
MemoryRegion sram_regs;
-} PnvOCC;
+};
-#define PNV_OCC_CLASS(klass) \
- OBJECT_CLASS_CHECK(PnvOCCClass, (klass), TYPE_PNV_OCC)
-#define PNV_OCC_GET_CLASS(obj) \
- OBJECT_GET_CLASS(PnvOCCClass, (obj), TYPE_PNV_OCC)
-
-typedef struct PnvOCCClass {
+struct PnvOCCClass {
DeviceClass parent_class;
int xscom_size;
const MemoryRegionOps *xscom_ops;
- int psi_irq;
-} PnvOCCClass;
+};
#define PNV_OCC_SENSOR_DATA_BLOCK_BASE(i) \
(PNV_OCC_SENSOR_DATA_BLOCK_OFFSET + (i) * PNV_OCC_SENSOR_DATA_BLOCK_SIZE)
diff --git a/include/hw/ppc/pnv_pnor.h b/include/hw/ppc/pnv_pnor.h
index 4f96abdfb4..2e37ac88bf 100644
--- a/include/hw/ppc/pnv_pnor.h
+++ b/include/hw/ppc/pnv_pnor.h
@@ -6,8 +6,11 @@
* This code is licensed under the GPL version 2 or later. See the
* COPYING file in the top-level directory.
*/
-#ifndef _PPC_PNV_PNOR_H
-#define _PPC_PNV_PNOR_H
+
+#ifndef PPC_PNV_PNOR_H
+#define PPC_PNV_PNOR_H
+
+#include "hw/sysbus.h"
/*
* PNOR offset on the LPC FW address space
@@ -15,9 +18,9 @@
#define PNOR_SPI_OFFSET 0x0c000000UL
#define TYPE_PNV_PNOR "pnv-pnor"
-#define PNV_PNOR(obj) OBJECT_CHECK(PnvPnor, (obj), TYPE_PNV_PNOR)
+OBJECT_DECLARE_SIMPLE_TYPE(PnvPnor, PNV_PNOR)
-typedef struct PnvPnor {
+struct PnvPnor {
SysBusDevice parent_obj;
BlockBackend *blk;
@@ -25,6 +28,6 @@ typedef struct PnvPnor {
uint8_t *storage;
int64_t size;
MemoryRegion mmio;
-} PnvPnor;
+};
-#endif /* _PPC_PNV_PNOR_H */
+#endif /* PPC_PNV_PNOR_H */
diff --git a/include/hw/ppc/pnv_psi.h b/include/hw/ppc/pnv_psi.h
index 979fc59f33..2a6f715350 100644
--- a/include/hw/ppc/pnv_psi.h
+++ b/include/hw/ppc/pnv_psi.h
@@ -1,12 +1,12 @@
/*
* QEMU PowerPC PowerNV Processor Service Interface (PSI) model
*
- * Copyright (c) 2015-2017, IBM Corporation.
+ * Copyright (c) 2015-2022, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -23,14 +23,15 @@
#include "hw/sysbus.h"
#include "hw/ppc/xics.h"
#include "hw/ppc/xive.h"
+#include "hw/qdev-core.h"
#define TYPE_PNV_PSI "pnv-psi"
-#define PNV_PSI(obj) \
- OBJECT_CHECK(PnvPsi, (obj), TYPE_PNV_PSI)
+OBJECT_DECLARE_TYPE(PnvPsi, PnvPsiClass,
+ PNV_PSI)
#define PSIHB_XSCOM_MAX 0x20
-typedef struct PnvPsi {
+struct PnvPsi {
DeviceState parent;
MemoryRegion regs_mr;
@@ -47,36 +48,30 @@ typedef struct PnvPsi {
uint64_t regs[PSIHB_XSCOM_MAX];
MemoryRegion xscom_regs;
-} PnvPsi;
+};
#define TYPE_PNV8_PSI TYPE_PNV_PSI "-POWER8"
-#define PNV8_PSI(obj) \
- OBJECT_CHECK(Pnv8Psi, (obj), TYPE_PNV8_PSI)
+OBJECT_DECLARE_SIMPLE_TYPE(Pnv8Psi, PNV8_PSI)
-typedef struct Pnv8Psi {
+struct Pnv8Psi {
PnvPsi parent;
ICSState ics;
-} Pnv8Psi;
+};
#define TYPE_PNV9_PSI TYPE_PNV_PSI "-POWER9"
-#define PNV9_PSI(obj) \
- OBJECT_CHECK(Pnv9Psi, (obj), TYPE_PNV9_PSI)
+OBJECT_DECLARE_SIMPLE_TYPE(Pnv9Psi, PNV9_PSI)
-typedef struct Pnv9Psi {
+struct Pnv9Psi {
PnvPsi parent;
XiveSource source;
-} Pnv9Psi;
+};
#define TYPE_PNV10_PSI TYPE_PNV_PSI "-POWER10"
-#define PNV_PSI_CLASS(klass) \
- OBJECT_CLASS_CHECK(PnvPsiClass, (klass), TYPE_PNV_PSI)
-#define PNV_PSI_GET_CLASS(obj) \
- OBJECT_GET_CLASS(PnvPsiClass, (obj), TYPE_PNV_PSI)
-typedef struct PnvPsiClass {
+struct PnvPsiClass {
SysBusDeviceClass parent_class;
uint32_t xscom_pcba;
@@ -84,13 +79,10 @@ typedef struct PnvPsiClass {
uint64_t bar_mask;
const char *compat;
int compat_size;
-
- void (*irq_set)(PnvPsi *psi, int, bool state);
-} PnvPsiClass;
+};
/* The PSI and FSP interrupts are muxed on the same IRQ number */
typedef enum PnvPsiIrq {
- PSIHB_IRQ_PSI, /* internal use only */
PSIHB_IRQ_FSP, /* internal use only */
PSIHB_IRQ_OCC,
PSIHB_IRQ_FSI,
@@ -101,8 +93,6 @@ typedef enum PnvPsiIrq {
#define PSI_NUM_INTERRUPTS 6
-void pnv_psi_irq_set(PnvPsi *psi, int irq, bool state);
-
/* P9 PSI Interrupts */
#define PSIHB9_IRQ_PSI 0
#define PSIHB9_IRQ_OCC 1
diff --git a/include/hw/ppc/pnv_sbe.h b/include/hw/ppc/pnv_sbe.h
new file mode 100644
index 0000000000..b6b378ad14
--- /dev/null
+++ b/include/hw/ppc/pnv_sbe.h
@@ -0,0 +1,56 @@
+/*
+ * QEMU PowerPC PowerNV Emulation of some SBE behaviour
+ *
+ * Copyright (c) 2022, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef PPC_PNV_SBE_H
+#define PPC_PNV_SBE_H
+
+#include "exec/memory.h"
+#include "hw/qdev-core.h"
+
+#define TYPE_PNV_SBE "pnv-sbe"
+OBJECT_DECLARE_TYPE(PnvSBE, PnvSBEClass, PNV_SBE)
+#define TYPE_PNV9_SBE TYPE_PNV_SBE "-POWER9"
+DECLARE_INSTANCE_CHECKER(PnvSBE, PNV9_SBE, TYPE_PNV9_SBE)
+#define TYPE_PNV10_SBE TYPE_PNV_SBE "-POWER10"
+DECLARE_INSTANCE_CHECKER(PnvSBE, PNV10_SBE, TYPE_PNV10_SBE)
+
+struct PnvSBE {
+ DeviceState xd;
+
+ uint64_t mbox[8];
+ uint64_t sbe_doorbell;
+ uint64_t host_doorbell;
+
+ qemu_irq psi_irq;
+ QEMUTimer *timer;
+
+ MemoryRegion xscom_mbox_regs;
+ MemoryRegion xscom_ctrl_regs;
+};
+
+struct PnvSBEClass {
+ DeviceClass parent_class;
+
+ int xscom_ctrl_size;
+ int xscom_mbox_size;
+ const MemoryRegionOps *xscom_ctrl_ops;
+ const MemoryRegionOps *xscom_mbox_ops;
+};
+
+#endif /* PPC_PNV_SBE_H */
diff --git a/include/hw/ppc/pnv_xive.h b/include/hw/ppc/pnv_xive.h
index 76cf16f644..9c48430ee4 100644
--- a/include/hw/ppc/pnv_xive.h
+++ b/include/hw/ppc/pnv_xive.h
@@ -10,16 +10,14 @@
#ifndef PPC_PNV_XIVE_H
#define PPC_PNV_XIVE_H
+#include "hw/ppc/pnv.h"
#include "hw/ppc/xive.h"
-
-struct PnvChip;
+#include "qom/object.h"
+#include "hw/ppc/xive2.h"
#define TYPE_PNV_XIVE "pnv-xive"
-#define PNV_XIVE(obj) OBJECT_CHECK(PnvXive, (obj), TYPE_PNV_XIVE)
-#define PNV_XIVE_CLASS(klass) \
- OBJECT_CLASS_CHECK(PnvXiveClass, (klass), TYPE_PNV_XIVE)
-#define PNV_XIVE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(PnvXiveClass, (obj), TYPE_PNV_XIVE)
+OBJECT_DECLARE_TYPE(PnvXive, PnvXiveClass,
+ PNV_XIVE)
#define XIVE_BLOCK_MAX 16
@@ -28,11 +26,11 @@ struct PnvChip;
#define XIVE_TABLE_VDT_MAX 16 /* VDT Domain Table (0-15) */
#define XIVE_TABLE_EDT_MAX 64 /* EDT Domain Table (0-63) */
-typedef struct PnvXive {
+struct PnvXive {
XiveRouter parent_obj;
/* Owning chip */
- struct PnvChip *chip;
+ PnvChip *chip;
/* XSCOM addresses giving access to the controller registers */
MemoryRegion xscom_regs;
@@ -87,14 +85,84 @@ typedef struct PnvXive {
uint64_t mig[XIVE_TABLE_MIG_MAX];
uint64_t vdt[XIVE_TABLE_VDT_MAX];
uint64_t edt[XIVE_TABLE_EDT_MAX];
-} PnvXive;
+};
-typedef struct PnvXiveClass {
+struct PnvXiveClass {
XiveRouterClass parent_class;
DeviceRealize parent_realize;
-} PnvXiveClass;
+};
void pnv_xive_pic_print_info(PnvXive *xive, Monitor *mon);
+/*
+ * XIVE2 interrupt controller (POWER10)
+ */
+#define TYPE_PNV_XIVE2 "pnv-xive2"
+OBJECT_DECLARE_TYPE(PnvXive2, PnvXive2Class, PNV_XIVE2);
+
+typedef struct PnvXive2 {
+ Xive2Router parent_obj;
+
+ /* Owning chip */
+ PnvChip *chip;
+
+ /* XSCOM addresses giving access to the controller registers */
+ MemoryRegion xscom_regs;
+
+ MemoryRegion ic_mmio;
+ MemoryRegion ic_mmios[8];
+ MemoryRegion esb_mmio;
+ MemoryRegion end_mmio;
+ MemoryRegion nvc_mmio;
+ MemoryRegion nvpg_mmio;
+ MemoryRegion tm_mmio;
+
+ /* Shortcut values for the Main MMIO regions */
+ hwaddr ic_base;
+ uint32_t ic_shift;
+ hwaddr esb_base;
+ uint32_t esb_shift;
+ hwaddr end_base;
+ uint32_t end_shift;
+ hwaddr nvc_base;
+ uint32_t nvc_shift;
+ hwaddr nvpg_base;
+ uint32_t nvpg_shift;
+ hwaddr tm_base;
+ uint32_t tm_shift;
+
+ /* Interrupt controller registers */
+ uint64_t cq_regs[0x40];
+ uint64_t vc_regs[0x100];
+ uint64_t pc_regs[0x100];
+ uint64_t tctxt_regs[0x30];
+
+ /* To change default behavior */
+ uint64_t capabilities;
+ uint64_t config;
+
+ /* Our XIVE source objects for IPIs and ENDs */
+ XiveSource ipi_source;
+ Xive2EndSource end_source;
+
+ /*
+ * Virtual Structure Descriptor tables
+ * These are in a SRAM protected by ECC.
+ */
+ uint64_t vsds[9][XIVE_BLOCK_MAX];
+
+ /* Translation tables */
+ uint64_t tables[8][XIVE_BLOCK_MAX];
+
+} PnvXive2;
+
+typedef struct PnvXive2Class {
+ Xive2RouterClass parent_class;
+
+ DeviceRealize parent_realize;
+} PnvXive2Class;
+
+void pnv_xive2_pic_print_info(PnvXive2 *xive, Monitor *mon);
+
#endif /* PPC_PNV_XIVE_H */
diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h
index 09156a5a7a..6209e18492 100644
--- a/include/hw/ppc/pnv_xscom.h
+++ b/include/hw/ppc/pnv_xscom.h
@@ -6,7 +6,7 @@
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -20,23 +20,22 @@
#ifndef PPC_PNV_XSCOM_H
#define PPC_PNV_XSCOM_H
-#include "qom/object.h"
+#include "exec/memory.h"
+#include "hw/ppc/pnv.h"
typedef struct PnvXScomInterface PnvXScomInterface;
#define TYPE_PNV_XSCOM_INTERFACE "pnv-xscom-interface"
#define PNV_XSCOM_INTERFACE(obj) \
INTERFACE_CHECK(PnvXScomInterface, (obj), TYPE_PNV_XSCOM_INTERFACE)
-#define PNV_XSCOM_INTERFACE_CLASS(klass) \
- OBJECT_CLASS_CHECK(PnvXScomInterfaceClass, (klass), \
+typedef struct PnvXScomInterfaceClass PnvXScomInterfaceClass;
+DECLARE_CLASS_CHECKERS(PnvXScomInterfaceClass, PNV_XSCOM_INTERFACE,
TYPE_PNV_XSCOM_INTERFACE)
-#define PNV_XSCOM_INTERFACE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(PnvXScomInterfaceClass, (obj), TYPE_PNV_XSCOM_INTERFACE)
-typedef struct PnvXScomInterfaceClass {
+struct PnvXScomInterfaceClass {
InterfaceClass parent;
int (*dt_xscom)(PnvXScomInterface *dev, void *fdt, int offset);
-} PnvXScomInterfaceClass;
+};
/*
* Layout of the XSCOM PCB addresses of EX core 1 (POWER 8)
@@ -65,6 +64,9 @@ typedef struct PnvXScomInterfaceClass {
#define PNV_XSCOM_PSIHB_BASE 0x2010900
#define PNV_XSCOM_PSIHB_SIZE 0x20
+#define PNV_XSCOM_CHIPTOD_BASE 0x0040000
+#define PNV_XSCOM_CHIPTOD_SIZE 0x31
+
#define PNV_XSCOM_OCC_BASE 0x0066000
#define PNV_XSCOM_OCC_SIZE 0x6000
@@ -91,9 +93,21 @@ typedef struct PnvXScomInterfaceClass {
((uint64_t)(((core) & 0x1C) + 0x40) << 22)
#define PNV9_XSCOM_EQ_SIZE 0x100000
+#define PNV9_XSCOM_I2CM_BASE 0xa0000
+#define PNV9_XSCOM_I2CM_SIZE 0x1000
+
+#define PNV9_XSCOM_CHIPTOD_BASE PNV_XSCOM_CHIPTOD_BASE
+#define PNV9_XSCOM_CHIPTOD_SIZE PNV_XSCOM_CHIPTOD_SIZE
+
#define PNV9_XSCOM_OCC_BASE PNV_XSCOM_OCC_BASE
#define PNV9_XSCOM_OCC_SIZE 0x8000
+#define PNV9_XSCOM_SBE_CTRL_BASE 0x00050008
+#define PNV9_XSCOM_SBE_CTRL_SIZE 0x1
+
+#define PNV9_XSCOM_SBE_MBOX_BASE 0x000D0050
+#define PNV9_XSCOM_SBE_MBOX_SIZE 0x16
+
#define PNV9_XSCOM_PBA_BASE 0x5012b00
#define PNV9_XSCOM_PBA_SIZE 0x40
@@ -122,18 +136,65 @@ typedef struct PnvXScomInterfaceClass {
#define PNV10_XSCOM_EC(proc) \
((0x2 << 16) | ((1 << (3 - (proc))) << 12))
+#define PNV10_XSCOM_QME(chiplet) \
+ (PNV10_XSCOM_EQ(chiplet) | (0xE << 16))
+
+/*
+ * Make the region larger by 0x1000 (instead of starting at an offset) so the
+ * modelled addresses start from 0
+ */
+#define PNV10_XSCOM_QME_BASE(core) \
+ ((uint64_t) PNV10_XSCOM_QME(PNV10_XSCOM_EQ_CHIPLET(core)))
+#define PNV10_XSCOM_QME_SIZE (0x8000 + 0x1000)
+
#define PNV10_XSCOM_EQ_BASE(core) \
((uint64_t) PNV10_XSCOM_EQ(PNV10_XSCOM_EQ_CHIPLET(core)))
-#define PNV10_XSCOM_EQ_SIZE 0x100000
+#define PNV10_XSCOM_EQ_SIZE 0x20000
#define PNV10_XSCOM_EC_BASE(core) \
((uint64_t) PNV10_XSCOM_EQ_BASE(core) | PNV10_XSCOM_EC(core & 0x3))
-#define PNV10_XSCOM_EC_SIZE 0x100000
+#define PNV10_XSCOM_EC_SIZE 0x1000
#define PNV10_XSCOM_PSIHB_BASE 0x3011D00
#define PNV10_XSCOM_PSIHB_SIZE 0x100
-void pnv_xscom_realize(PnvChip *chip, uint64_t size, Error **errp);
+#define PNV10_XSCOM_I2CM_BASE PNV9_XSCOM_I2CM_BASE
+#define PNV10_XSCOM_I2CM_SIZE PNV9_XSCOM_I2CM_SIZE
+
+#define PNV10_XSCOM_CHIPTOD_BASE PNV9_XSCOM_CHIPTOD_BASE
+#define PNV10_XSCOM_CHIPTOD_SIZE PNV9_XSCOM_CHIPTOD_SIZE
+
+#define PNV10_XSCOM_OCC_BASE PNV9_XSCOM_OCC_BASE
+#define PNV10_XSCOM_OCC_SIZE PNV9_XSCOM_OCC_SIZE
+
+#define PNV10_XSCOM_SBE_CTRL_BASE PNV9_XSCOM_SBE_CTRL_BASE
+#define PNV10_XSCOM_SBE_CTRL_SIZE PNV9_XSCOM_SBE_CTRL_SIZE
+
+#define PNV10_XSCOM_SBE_MBOX_BASE PNV9_XSCOM_SBE_MBOX_BASE
+#define PNV10_XSCOM_SBE_MBOX_SIZE PNV9_XSCOM_SBE_MBOX_SIZE
+
+#define PNV10_XSCOM_PBA_BASE 0x01010CDA
+#define PNV10_XSCOM_PBA_SIZE 0x40
+
+#define PNV10_XSCOM_XIVE2_BASE 0x2010800
+#define PNV10_XSCOM_XIVE2_SIZE 0x400
+
+#define PNV10_XSCOM_N1_CHIPLET_CTRL_REGS_BASE 0x3000000
+#define PNV10_XSCOM_CHIPLET_CTRL_REGS_SIZE 0x400
+
+#define PNV10_XSCOM_N1_PB_SCOM_EQ_BASE 0x3011000
+#define PNV10_XSCOM_N1_PB_SCOM_EQ_SIZE 0x200
+
+#define PNV10_XSCOM_N1_PB_SCOM_ES_BASE 0x3011300
+#define PNV10_XSCOM_N1_PB_SCOM_ES_SIZE 0x100
+
+#define PNV10_XSCOM_PEC_NEST_BASE 0x3011800 /* index goes downwards ... */
+#define PNV10_XSCOM_PEC_NEST_SIZE 0x100
+
+#define PNV10_XSCOM_PEC_PCI_BASE 0x8010800 /* index goes upwards ... */
+#define PNV10_XSCOM_PEC_PCI_SIZE 0x200
+
+void pnv_xscom_init(PnvChip *chip, uint64_t size, hwaddr addr);
int pnv_dt_xscom(PnvChip *chip, void *fdt, int root_offset,
uint64_t xscom_base, uint64_t xscom_size,
const char *compat, int compat_size);
@@ -141,7 +202,7 @@ int pnv_dt_xscom(PnvChip *chip, void *fdt, int root_offset,
void pnv_xscom_add_subregion(PnvChip *chip, hwaddr offset,
MemoryRegion *mr);
void pnv_xscom_region_init(MemoryRegion *mr,
- struct Object *owner,
+ Object *owner,
const MemoryRegionOps *ops,
void *opaque,
const char *name,
diff --git a/include/hw/ppc/ppc.h b/include/hw/ppc/ppc.h
index 93e614cffd..d5d119ea7f 100644
--- a/include/hw/ppc/ppc.h
+++ b/include/hw/ppc/ppc.h
@@ -1,11 +1,12 @@
#ifndef HW_PPC_H
#define HW_PPC_H
-#include "target/ppc/cpu-qom.h"
+#include "target/ppc/cpu.h"
void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level);
PowerPCCPU *ppc_get_vcpu_by_pir(int pir);
int ppc_cpu_pir(PowerPCCPU *cpu);
+int ppc_cpu_tir(PowerPCCPU *cpu);
/* PowerPC hardware exceptions management helpers */
typedef void (*clk_setup_cb)(void *opaque, uint32_t freq);
@@ -53,7 +54,12 @@ struct ppc_tb_t {
*/
uint64_t cpu_ppc_get_tb(ppc_tb_t *tb_env, uint64_t vmclk, int64_t tb_offset);
-clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq);
+void cpu_ppc_tb_init(CPUPPCState *env, uint32_t freq);
+void cpu_ppc_tb_reset(CPUPPCState *env);
+void cpu_ppc_tb_free(CPUPPCState *env);
+void cpu_ppc_hdecr_init(CPUPPCState *env);
+void cpu_ppc_hdecr_exit(CPUPPCState *env);
+
/* Embedded PowerPC DCR management */
typedef uint32_t (*dcr_read_cb)(void *opaque, int dcrn);
typedef void (*dcr_write_cb)(void *opaque, int dcrn, uint32_t val);
@@ -95,11 +101,11 @@ enum {
ARCH_MAC99_U3,
};
-#define FW_CFG_PPC_WIDTH (FW_CFG_ARCH_LOCAL + 0x00)
-#define FW_CFG_PPC_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01)
-#define FW_CFG_PPC_DEPTH (FW_CFG_ARCH_LOCAL + 0x02)
-#define FW_CFG_PPC_TBFREQ (FW_CFG_ARCH_LOCAL + 0x03)
-#define FW_CFG_PPC_CLOCKFREQ (FW_CFG_ARCH_LOCAL + 0x04)
+#define FW_CFG_PPC_WIDTH (FW_CFG_ARCH_LOCAL + 0x00)
+#define FW_CFG_PPC_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01)
+#define FW_CFG_PPC_DEPTH (FW_CFG_ARCH_LOCAL + 0x02)
+#define FW_CFG_PPC_TBFREQ (FW_CFG_ARCH_LOCAL + 0x03)
+#define FW_CFG_PPC_CLOCKFREQ (FW_CFG_ARCH_LOCAL + 0x04)
#define FW_CFG_PPC_IS_KVM (FW_CFG_ARCH_LOCAL + 0x05)
#define FW_CFG_PPC_KVM_HC (FW_CFG_ARCH_LOCAL + 0x06)
#define FW_CFG_PPC_KVM_PID (FW_CFG_ARCH_LOCAL + 0x07)
diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h
index cc19c8da5b..1bd9b8821b 100644
--- a/include/hw/ppc/ppc4xx.h
+++ b/include/hw/ppc/ppc4xx.h
@@ -27,35 +27,127 @@
#include "hw/ppc/ppc.h"
#include "exec/memory.h"
+#include "hw/sysbus.h"
-/* PowerPC 4xx core initialization */
-PowerPCCPU *ppc4xx_init(const char *cpu_model,
- clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
- uint32_t sysclk);
+/*
+ * Generic DCR device
+ */
+#define TYPE_PPC4xx_DCR_DEVICE "ppc4xx-dcr-device"
+OBJECT_DECLARE_SIMPLE_TYPE(Ppc4xxDcrDeviceState, PPC4xx_DCR_DEVICE);
+struct Ppc4xxDcrDeviceState {
+ SysBusDevice parent_obj;
+
+ PowerPCCPU *cpu;
+};
+
+void ppc4xx_dcr_register(Ppc4xxDcrDeviceState *dev, int dcrn, void *opaque,
+ dcr_read_cb dcr_read, dcr_write_cb dcr_write);
+bool ppc4xx_dcr_realize(Ppc4xxDcrDeviceState *dev, PowerPCCPU *cpu,
+ Error **errp);
+
+/* Memory Access Layer (MAL) */
+#define TYPE_PPC4xx_MAL "ppc4xx-mal"
+OBJECT_DECLARE_SIMPLE_TYPE(Ppc4xxMalState, PPC4xx_MAL);
+struct Ppc4xxMalState {
+ Ppc4xxDcrDeviceState parent_obj;
+
+ qemu_irq irqs[4];
+ uint32_t cfg;
+ uint32_t esr;
+ uint32_t ier;
+ uint32_t txcasr;
+ uint32_t txcarr;
+ uint32_t txeobisr;
+ uint32_t txdeir;
+ uint32_t rxcasr;
+ uint32_t rxcarr;
+ uint32_t rxeobisr;
+ uint32_t rxdeir;
+ uint32_t *txctpr;
+ uint32_t *rxctpr;
+ uint32_t *rcbs;
+ uint8_t txcnum;
+ uint8_t rxcnum;
+};
+
+/* Peripheral local bus arbitrer */
+#define TYPE_PPC4xx_PLB "ppc4xx-plb"
+OBJECT_DECLARE_SIMPLE_TYPE(Ppc4xxPlbState, PPC4xx_PLB);
+struct Ppc4xxPlbState {
+ Ppc4xxDcrDeviceState parent_obj;
+
+ uint32_t acr;
+ uint32_t bear;
+ uint32_t besr;
+};
+
+/* Peripheral controller */
+#define TYPE_PPC4xx_EBC "ppc4xx-ebc"
+OBJECT_DECLARE_SIMPLE_TYPE(Ppc4xxEbcState, PPC4xx_EBC);
+struct Ppc4xxEbcState {
+ Ppc4xxDcrDeviceState parent_obj;
+
+ uint32_t addr;
+ uint32_t bcr[8];
+ uint32_t bap[8];
+ uint32_t bear;
+ uint32_t besr0;
+ uint32_t besr1;
+ uint32_t cfg;
+};
+
+/* SDRAM DDR controller */
+typedef struct {
+ MemoryRegion ram;
+ MemoryRegion container; /* used for clipping */
+ hwaddr base;
+ hwaddr size;
+ uint32_t bcr;
+} Ppc4xxSdramBank;
-/* PowerPC 4xx universal interrupt controller */
-enum {
- PPCUIC_OUTPUT_INT = 0,
- PPCUIC_OUTPUT_CINT = 1,
- PPCUIC_OUTPUT_NB,
+#define SDR0_DDR0_DDRM_ENCODE(n) ((((unsigned long)(n)) & 0x03) << 29)
+#define SDR0_DDR0_DDRM_DDR1 0x20000000
+#define SDR0_DDR0_DDRM_DDR2 0x40000000
+
+#define TYPE_PPC4xx_SDRAM_DDR "ppc4xx-sdram-ddr"
+OBJECT_DECLARE_SIMPLE_TYPE(Ppc4xxSdramDdrState, PPC4xx_SDRAM_DDR);
+struct Ppc4xxSdramDdrState {
+ Ppc4xxDcrDeviceState parent_obj;
+
+ MemoryRegion *dram_mr;
+ uint32_t nbanks; /* Banks to use from 4, e.g. when board has less slots */
+ Ppc4xxSdramBank bank[4];
+ qemu_irq irq;
+
+ uint32_t addr;
+ uint32_t besr0;
+ uint32_t besr1;
+ uint32_t bear;
+ uint32_t cfg;
+ uint32_t status;
+ uint32_t rtr;
+ uint32_t pmit;
+ uint32_t tr;
+ uint32_t ecccfg;
+ uint32_t eccesr;
};
-qemu_irq *ppcuic_init (CPUPPCState *env, qemu_irq *irqs,
- uint32_t dcr_base, int has_ssr, int has_vr);
-void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks,
- MemoryRegion ram_memories[],
- hwaddr ram_bases[], hwaddr ram_sizes[],
- const ram_addr_t sdram_bank_sizes[]);
+void ppc4xx_sdram_ddr_enable(Ppc4xxSdramDdrState *s);
-void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks,
- MemoryRegion ram_memories[],
- hwaddr *ram_bases,
- hwaddr *ram_sizes,
- int do_init);
+/* SDRAM DDR2 controller */
+#define TYPE_PPC4xx_SDRAM_DDR2 "ppc4xx-sdram-ddr2"
+OBJECT_DECLARE_SIMPLE_TYPE(Ppc4xxSdramDdr2State, PPC4xx_SDRAM_DDR2);
+struct Ppc4xxSdramDdr2State {
+ Ppc4xxDcrDeviceState parent_obj;
-void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum,
- qemu_irq irqs[4]);
+ MemoryRegion *dram_mr;
+ uint32_t nbanks; /* Banks to use from 4, e.g. when board has less slots */
+ Ppc4xxSdramBank bank[4];
+
+ uint32_t addr;
+ uint32_t mcopt2;
+};
-#define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost"
+void ppc4xx_sdram_ddr2_enable(Ppc4xxSdramDdr2State *s);
#endif /* PPC4XX_H */
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 3134d339e8..4aaf23d28f 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -8,9 +8,11 @@
#include "hw/mem/pc-dimm.h"
#include "hw/ppc/spapr_ovec.h"
#include "hw/ppc/spapr_irq.h"
+#include "qom/object.h"
#include "hw/ppc/spapr_xive.h" /* For SpaprXive */
#include "hw/ppc/xics.h" /* For ICSState */
#include "hw/ppc/spapr_tpm_proxy.h"
+#include "hw/ppc/spapr_nested.h" /* For SpaprMachineStateNested */
struct SpaprVioBus;
struct SpaprPhbState;
@@ -20,6 +22,8 @@ typedef struct SpaprEventLogEntry SpaprEventLogEntry;
typedef struct SpaprEventSource SpaprEventSource;
typedef struct SpaprPendingHpt SpaprPendingHpt;
+typedef struct Vof Vof;
+
#define HPTE64_V_HPTE_DIRTY 0x0000000000000040ULL
#define SPAPR_ENTRY_POINT 0x100
@@ -27,10 +31,8 @@ typedef struct SpaprPendingHpt SpaprPendingHpt;
#define TYPE_SPAPR_RTC "spapr-rtc"
-#define SPAPR_RTC(obj) \
- OBJECT_CHECK(SpaprRtcState, (obj), TYPE_SPAPR_RTC)
+OBJECT_DECLARE_SIMPLE_TYPE(SpaprRtcState, SPAPR_RTC)
-typedef struct SpaprRtcState SpaprRtcState;
struct SpaprRtcState {
/*< private >*/
DeviceState parent_obj;
@@ -38,15 +40,9 @@ struct SpaprRtcState {
};
typedef struct SpaprDimmState SpaprDimmState;
-typedef struct SpaprMachineClass SpaprMachineClass;
#define TYPE_SPAPR_MACHINE "spapr-machine"
-#define SPAPR_MACHINE(obj) \
- OBJECT_CHECK(SpaprMachineState, (obj), TYPE_SPAPR_MACHINE)
-#define SPAPR_MACHINE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(SpaprMachineClass, obj, TYPE_SPAPR_MACHINE)
-#define SPAPR_MACHINE_CLASS(klass) \
- OBJECT_CLASS_CHECK(SpaprMachineClass, klass, TYPE_SPAPR_MACHINE)
+OBJECT_DECLARE_TYPE(SpaprMachineState, SpaprMachineClass, SPAPR_MACHINE)
typedef enum {
SPAPR_RESIZE_HPT_DEFAULT = 0,
@@ -81,8 +77,14 @@ typedef enum {
#define SPAPR_CAP_CCF_ASSIST 0x09
/* Implements PAPR FWNMI option */
#define SPAPR_CAP_FWNMI 0x0A
+/* Support H_RPT_INVALIDATE */
+#define SPAPR_CAP_RPT_INVALIDATE 0x0B
+/* Support for AIL modes */
+#define SPAPR_CAP_AIL_MODE_3 0x0C
+/* Nested PAPR */
+#define SPAPR_CAP_NESTED_PAPR 0x0D
/* Num Caps */
-#define SPAPR_CAP_NUM (SPAPR_CAP_FWNMI + 1)
+#define SPAPR_CAP_NUM (SPAPR_CAP_NESTED_PAPR + 1)
/*
* Capability Values
@@ -102,7 +104,29 @@ typedef enum {
#define SPAPR_CAP_FIXED_CCD 0x03
#define SPAPR_CAP_FIXED_NA 0x10 /* Lets leave a bit of a gap... */
-#define FDT_MAX_SIZE 0x100000
+#define FDT_MAX_SIZE 0x200000
+
+/* Max number of NUMA nodes */
+#define NUMA_NODES_MAX_NUM (MAX_NODES)
+
+/*
+ * NUMA FORM1 macros. FORM1_DIST_REF_POINTS was taken from
+ * MAX_DISTANCE_REF_POINTS in arch/powerpc/mm/numa.h from Linux
+ * kernel source. It represents the amount of associativity domains
+ * for non-CPU resources.
+ *
+ * FORM1_NUMA_ASSOC_SIZE is the base array size of an ibm,associativity
+ * array for any non-CPU resource.
+ */
+#define FORM1_DIST_REF_POINTS 4
+#define FORM1_NUMA_ASSOC_SIZE (FORM1_DIST_REF_POINTS + 1)
+
+/*
+ * FORM2 NUMA affinity has a single associativity domain, giving
+ * us a assoc size of 2.
+ */
+#define FORM2_DIST_REF_POINTS 1
+#define FORM2_NUMA_ASSOC_SIZE (FORM2_DIST_REF_POINTS + 1)
typedef struct SpaprCapabilities SpaprCapabilities;
struct SpaprCapabilities {
@@ -130,17 +154,33 @@ struct SpaprMachineClass {
bool smp_threads_vsmt; /* set VSMT to smp_threads by default */
hwaddr rma_limit; /* clamp the RMA to this size */
bool pre_5_1_assoc_refpoints;
+ bool pre_5_2_numa_associativity;
+ bool pre_6_2_numa_affinity;
- void (*phb_placement)(SpaprMachineState *spapr, uint32_t index,
- uint64_t *buid, hwaddr *pio,
+ bool (*phb_placement)(SpaprMachineState *spapr, uint32_t index,
+ uint64_t *buid, hwaddr *pio,
hwaddr *mmio32, hwaddr *mmio64,
- unsigned n_dma, uint32_t *liobns, hwaddr *nv2gpa,
- hwaddr *nv2atsd, Error **errp);
+ unsigned n_dma, uint32_t *liobns, Error **errp);
SpaprResizeHpt resize_hpt_default;
SpaprCapabilities default_caps;
SpaprIrq *irq;
};
+#define WDT_MAX_WATCHDOGS 4 /* Maximum number of watchdog devices */
+
+#define TYPE_SPAPR_WDT "spapr-wdt"
+OBJECT_DECLARE_SIMPLE_TYPE(SpaprWatchdog, SPAPR_WDT)
+
+typedef struct SpaprWatchdog {
+ /*< private >*/
+ DeviceState parent_obj;
+ /*< public >*/
+
+ QEMUTimer timer;
+ uint8_t action; /* One of PSERIES_WDTF_ACTION_xxx */
+ uint8_t leave_others; /* leaveOtherWatchdogsRunningOnTimeout */
+} SpaprWatchdog;
+
/**
* SpaprMachineState:
*/
@@ -156,23 +196,28 @@ struct SpaprMachineState {
SpaprResizeHpt resize_hpt;
void *htab;
uint32_t htab_shift;
- uint64_t patb_entry; /* Process tbl registed in H_REGISTER_PROCESS_TABLE */
+ uint64_t patb_entry; /* Process tbl registered in H_REGISTER_PROC_TBL */
SpaprPendingHpt *pending_hpt; /* in-progress resize */
hwaddr rma_size;
uint32_t fdt_size;
uint32_t fdt_initial_size;
void *fdt_blob;
+ uint8_t fdt_rng_seed[32];
long kernel_size;
bool kernel_le;
uint64_t kernel_addr;
uint32_t initrd_base;
long initrd_size;
+ Vof *vof;
uint64_t rtc_offset; /* Now used only during incoming migration */
struct PPCTimebase tb;
- bool has_graphics;
+ bool want_stdout_path;
uint32_t vsmt; /* Virtual SMT mode (KVM's "core stride") */
+ /* Nested HV support (TCG only) */
+ SpaprMachineStateNested nested;
+
Notifier epow_notifier;
QTAILQ_HEAD(, SpaprEventLogEntry) pending_events;
bool use_hotplug_event_source;
@@ -211,6 +256,9 @@ struct SpaprMachineState {
int fwnmi_machine_check_interlock;
QemuCond fwnmi_machine_check_interlock_cond;
+ /* Set by -boot */
+ char *boot_device;
+
/*< public >*/
char *kvm_type;
char *host_model;
@@ -227,10 +275,14 @@ struct SpaprMachineState {
bool cmd_line_caps[SPAPR_CAP_NUM];
SpaprCapabilities def, eff, mig;
- unsigned gpu_numa_id;
SpaprTpmProxy *tpm_proxy;
+ uint32_t FORM1_assoc_array[NUMA_NODES_MAX_NUM][FORM1_NUMA_ASSOC_SIZE];
+ uint32_t FORM2_assoc_array[NUMA_NODES_MAX_NUM][FORM2_NUMA_ASSOC_SIZE];
+
Error *fwnmi_migration_blocker;
+
+ SpaprWatchdog wds[WDT_MAX_WATCHDOGS];
};
#define H_SUCCESS 0
@@ -311,7 +363,12 @@ struct SpaprMachineState {
#define H_P7 -60
#define H_P8 -61
#define H_P9 -62
+#define H_NOOP -63
+#define H_UNSUPPORTED -67
#define H_OVERLAP -68
+#define H_STATE -75
+#define H_IN_USE -77
+#define H_INVALID_ELEMENT_VALUE -81
#define H_UNSUPPORTED_FLAG -256
#define H_MULTI_THREADS_ACTIVE -9005
@@ -349,7 +406,7 @@ struct SpaprMachineState {
/* Values for 2nd argument to H_SET_MODE */
#define H_SET_MODE_RESOURCE_SET_CIABR 1
-#define H_SET_MODE_RESOURCE_SET_DAWR 2
+#define H_SET_MODE_RESOURCE_SET_DAWR0 2
#define H_SET_MODE_RESOURCE_ADDR_TRANS_MODE 3
#define H_SET_MODE_RESOURCE_LE 4
@@ -381,10 +438,13 @@ struct SpaprMachineState {
#define H_CPU_CHAR_THR_RECONF_TRIG PPC_BIT(6)
#define H_CPU_CHAR_CACHE_COUNT_DIS PPC_BIT(7)
#define H_CPU_CHAR_BCCTR_FLUSH_ASSIST PPC_BIT(9)
+
#define H_CPU_BEHAV_FAVOUR_SECURITY PPC_BIT(0)
#define H_CPU_BEHAV_L1D_FLUSH_PR PPC_BIT(1)
#define H_CPU_BEHAV_BNDS_CHK_SPEC_BAR PPC_BIT(2)
#define H_CPU_BEHAV_FLUSH_COUNT_CACHE PPC_BIT(5)
+#define H_CPU_BEHAV_NO_L1D_FLUSH_ENTRY PPC_BIT(7)
+#define H_CPU_BEHAV_NO_L1D_FLUSH_UACCESS PPC_BIT(8)
/* Each control block has to be on a 4K boundary */
#define H_CB_ALIGNMENT 4096
@@ -524,8 +584,20 @@ struct SpaprMachineState {
#define H_SCM_BIND_MEM 0x3EC
#define H_SCM_UNBIND_MEM 0x3F0
#define H_SCM_UNBIND_ALL 0x3FC
-
-#define MAX_HCALL_OPCODE H_SCM_UNBIND_ALL
+#define H_SCM_HEALTH 0x400
+#define H_RPT_INVALIDATE 0x448
+#define H_SCM_FLUSH 0x44C
+#define H_WATCHDOG 0x45C
+#define H_GUEST_GET_CAPABILITIES 0x460
+#define H_GUEST_SET_CAPABILITIES 0x464
+#define H_GUEST_CREATE 0x470
+#define H_GUEST_CREATE_VCPU 0x474
+#define H_GUEST_GET_STATE 0x478
+#define H_GUEST_SET_STATE 0x47C
+#define H_GUEST_RUN_VCPU 0x480
+#define H_GUEST_DELETE 0x488
+
+#define MAX_HCALL_OPCODE H_GUEST_DELETE
/* The hcalls above are standardized in PAPR and implemented by pHyp
* as well.
@@ -540,7 +612,16 @@ struct SpaprMachineState {
/* Client Architecture support */
#define KVMPPC_H_CAS (KVMPPC_HCALL_BASE + 0x2)
#define KVMPPC_H_UPDATE_DT (KVMPPC_HCALL_BASE + 0x3)
-#define KVMPPC_HCALL_MAX KVMPPC_H_UPDATE_DT
+/* 0x4 was used for KVMPPC_H_UPDATE_PHANDLE in SLOF */
+#define KVMPPC_H_VOF_CLIENT (KVMPPC_HCALL_BASE + 0x5)
+
+/* Platform-specific hcalls used for nested HV KVM */
+#define KVMPPC_H_SET_PARTITION_TABLE (KVMPPC_HCALL_BASE + 0x800)
+#define KVMPPC_H_ENTER_NESTED (KVMPPC_HCALL_BASE + 0x804)
+#define KVMPPC_H_TLB_INVALIDATE (KVMPPC_HCALL_BASE + 0x808)
+#define KVMPPC_H_COPY_TOFROM_GUEST (KVMPPC_HCALL_BASE + 0x80C)
+
+#define KVMPPC_HCALL_MAX KVMPPC_H_COPY_TOFROM_GUEST
/*
* The hcall range 0xEF00 to 0xEF80 is reserved for use in facilitating
@@ -550,7 +631,6 @@ struct SpaprMachineState {
#define SVM_H_TPM_COMM 0xEF10
#define SVM_HCALL_MAX SVM_H_TPM_COMM
-
typedef struct SpaprDeviceTreeUpdateHeader {
uint32_t version_id;
} SpaprDeviceTreeUpdateHeader;
@@ -565,13 +645,19 @@ typedef target_ulong (*spapr_hcall_fn)(PowerPCCPU *cpu, SpaprMachineState *sm,
target_ulong *args);
void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn);
+void spapr_unregister_hypercall(target_ulong opcode);
target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode,
target_ulong *args);
-target_ulong do_client_architecture_support(PowerPCCPU *cpu,
- SpaprMachineState *spapr,
- target_ulong addr,
- target_ulong fdt_bufsize);
+target_ulong vhyp_mmu_resize_hpt_prepare(PowerPCCPU *cpu,
+ SpaprMachineState *spapr,
+ target_ulong shift);
+target_ulong vhyp_mmu_resize_hpt_commit(PowerPCCPU *cpu,
+ SpaprMachineState *spapr,
+ target_ulong flags,
+ target_ulong shift);
+bool is_ram_address(SpaprMachineState *spapr, hwaddr addr);
+void push_sregs_to_kvm_pr(SpaprMachineState *spapr);
/* Virtual Processor Area structure constants */
#define VPA_MIN_SIZE 640
@@ -633,6 +719,7 @@ target_ulong do_client_architecture_support(PowerPCCPU *cpu,
#define RTAS_DDW_PGSIZE_128M 0x20
#define RTAS_DDW_PGSIZE_256M 0x40
#define RTAS_DDW_PGSIZE_16G 0x80
+#define RTAS_DDW_PGSIZE_2M 0x100
/* RTAS tokens */
#define RTAS_TOKEN_BASE 0x2000
@@ -716,7 +803,8 @@ static inline uint64_t ppc64_phys_to_real(uint64_t addr)
static inline uint32_t rtas_ld(target_ulong phys, int n)
{
- return ldl_be_phys(&address_space_memory, ppc64_phys_to_real(phys + 4*n));
+ return ldl_be_phys(&address_space_memory,
+ ppc64_phys_to_real(phys + 4 * n));
}
static inline uint64_t rtas_ldq(target_ulong phys, int n)
@@ -726,7 +814,7 @@ static inline uint64_t rtas_ldq(target_ulong phys, int n)
static inline void rtas_st(target_ulong phys, int n, uint32_t val)
{
- stl_be_phys(&address_space_memory, ppc64_phys_to_real(phys + 4*n), val);
+ stl_be_phys(&address_space_memory, ppc64_phys_to_real(phys + 4 * n), val);
}
typedef void (*spapr_rtas_fn)(PowerPCCPU *cpu, SpaprMachineState *sm,
@@ -751,7 +839,7 @@ void spapr_load_rtas(SpaprMachineState *spapr, void *fdt, hwaddr addr);
#define SPAPR_IS_PCI_LIOBN(liobn) (!!((liobn) & 0x80000000))
#define SPAPR_PCI_DMA_WINDOW_NUM(liobn) ((liobn) & 0xff)
-#define RTAS_SIZE 2048
+#define RTAS_MIN_SIZE 20 /* hv_rtas_size in SLOF */
#define RTAS_ERROR_LOG_MAX 2048
/* Offset from rtas-base where error log is placed */
@@ -769,15 +857,13 @@ static inline void spapr_dt_irq(uint32_t *intspec, int irq, bool is_lsi)
intspec[1] = is_lsi ? cpu_to_be32(1) : 0;
}
-typedef struct SpaprTceTable SpaprTceTable;
#define TYPE_SPAPR_TCE_TABLE "spapr-tce-table"
-#define SPAPR_TCE_TABLE(obj) \
- OBJECT_CHECK(SpaprTceTable, (obj), TYPE_SPAPR_TCE_TABLE)
+OBJECT_DECLARE_SIMPLE_TYPE(SpaprTceTable, SPAPR_TCE_TABLE)
#define TYPE_SPAPR_IOMMU_MEMORY_REGION "spapr-iommu-memory-region"
-#define SPAPR_IOMMU_MEMORY_REGION(obj) \
- OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_SPAPR_IOMMU_MEMORY_REGION)
+DECLARE_INSTANCE_CHECKER(IOMMUMemoryRegion, SPAPR_IOMMU_MEMORY_REGION,
+ TYPE_SPAPR_IOMMU_MEMORY_REGION)
struct SpaprTceTable {
DeviceState parent;
@@ -791,6 +877,7 @@ struct SpaprTceTable {
bool bypass;
bool need_vfio;
bool skipping_replay;
+ bool def_win;
int fd;
MemoryRegion root;
IOMMUMemoryRegion iommu;
@@ -813,6 +900,7 @@ void spapr_dt_events(SpaprMachineState *sm, void *fdt);
void close_htab_fd(SpaprMachineState *spapr);
void spapr_setup_hpt(SpaprMachineState *spapr);
void spapr_free_hpt(SpaprMachineState *spapr);
+void spapr_check_mmu_mode(bool guest_radix);
SpaprTceTable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn);
void spapr_tce_table_enable(SpaprTceTable *tcet,
uint32_t page_shift, uint64_t bus_offset,
@@ -825,7 +913,7 @@ int spapr_dma_dt(void *fdt, int node_off, const char *propname,
uint32_t liobn, uint64_t window, uint32_t size);
int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname,
SpaprTceTable *tcet);
-void spapr_pci_switch_vga(bool big_endian);
+void spapr_pci_switch_vga(SpaprMachineState *spapr, bool big_endian);
void spapr_hotplug_req_add_by_index(SpaprDrc *drc);
void spapr_hotplug_req_remove_by_index(SpaprDrc *drc);
void spapr_hotplug_req_add_by_count(SpaprDrcType drc_type,
@@ -837,10 +925,10 @@ void spapr_hotplug_req_add_by_count_indexed(SpaprDrcType drc_type,
void spapr_hotplug_req_remove_by_count_indexed(SpaprDrcType drc_type,
uint32_t count, uint32_t index);
int spapr_hpt_shift_for_ramsize(uint64_t ramsize);
-void spapr_reallocate_hpt(SpaprMachineState *spapr, int shift,
- Error **errp);
+int spapr_reallocate_hpt(SpaprMachineState *spapr, int shift, Error **errp);
void spapr_clear_pending_events(SpaprMachineState *spapr);
void spapr_clear_pending_hotplug_events(SpaprMachineState *spapr);
+void spapr_memory_unplug_rollback(SpaprMachineState *spapr, DeviceState *dev);
int spapr_max_server_number(SpaprMachineState *spapr);
void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
uint64_t pte0, uint64_t pte1);
@@ -894,7 +982,7 @@ void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg);
#define HTAB_SIZE(spapr) (1ULL << ((spapr)->htab_shift))
int spapr_get_vcpu_id(PowerPCCPU *cpu);
-void spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp);
+bool spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp);
PowerPCCPU *spapr_find_cpu(int vcpu_id);
int spapr_caps_pre_load(void *opaque);
@@ -911,9 +999,12 @@ extern const VMStateDescription vmstate_spapr_cap_sbbc;
extern const VMStateDescription vmstate_spapr_cap_ibs;
extern const VMStateDescription vmstate_spapr_cap_hpt_maxpagesize;
extern const VMStateDescription vmstate_spapr_cap_nested_kvm_hv;
+extern const VMStateDescription vmstate_spapr_cap_nested_papr;
extern const VMStateDescription vmstate_spapr_cap_large_decr;
extern const VMStateDescription vmstate_spapr_cap_ccf_assist;
extern const VMStateDescription vmstate_spapr_cap_fwnmi;
+extern const VMStateDescription vmstate_spapr_cap_rpt_invalidate;
+extern const VMStateDescription vmstate_spapr_wdt;
static inline uint8_t spapr_get_cap(SpaprMachineState *spapr, int cap)
{
@@ -926,7 +1017,7 @@ void spapr_caps_cpu_apply(SpaprMachineState *spapr, PowerPCCPU *cpu);
void spapr_caps_add_properties(SpaprMachineClass *smc);
int spapr_caps_post_migration(SpaprMachineState *spapr);
-void spapr_check_pagesize(SpaprMachineState *spapr, hwaddr pagesize,
+bool spapr_check_pagesize(SpaprMachineState *spapr, hwaddr pagesize,
Error **errp);
/*
* XIVE definitions
@@ -936,5 +1027,27 @@ void spapr_check_pagesize(SpaprMachineState *spapr, hwaddr pagesize,
#define SPAPR_OV5_XIVE_BOTH 0x80 /* Only to advertise on the platform */
void spapr_set_all_lpcrs(target_ulong value, target_ulong mask);
+void spapr_init_all_lpcrs(target_ulong value, target_ulong mask);
hwaddr spapr_get_rtas_addr(void);
+bool spapr_memory_hot_unplug_supported(SpaprMachineState *spapr);
+
+void spapr_vof_reset(SpaprMachineState *spapr, void *fdt, Error **errp);
+void spapr_vof_quiesce(MachineState *ms);
+bool spapr_vof_setprop(MachineState *ms, const char *path, const char *propname,
+ void *val, int vallen);
+target_ulong spapr_h_vof_client(PowerPCCPU *cpu, SpaprMachineState *spapr,
+ target_ulong opcode, target_ulong *args);
+target_ulong spapr_vof_client_architecture_support(MachineState *ms,
+ CPUState *cs,
+ target_ulong ovec_addr);
+void spapr_vof_client_dt_finalize(SpaprMachineState *spapr, void *fdt);
+
+/* H_WATCHDOG */
+void spapr_watchdog_init(SpaprMachineState *spapr);
+void spapr_register_nested_hv(void);
+void spapr_unregister_nested_hv(void);
+void spapr_nested_reset(SpaprMachineState *spapr);
+void spapr_register_nested_papr(void);
+void spapr_unregister_nested_papr(void);
+
#endif /* HW_SPAPR_H */
diff --git a/include/hw/ppc/spapr_cpu_core.h b/include/hw/ppc/spapr_cpu_core.h
index 7aed8f555b..69a52e39b8 100644
--- a/include/hw/ppc/spapr_cpu_core.h
+++ b/include/hw/ppc/spapr_cpu_core.h
@@ -13,18 +13,15 @@
#include "hw/qdev-core.h"
#include "target/ppc/cpu-qom.h"
#include "target/ppc/cpu.h"
+#include "qom/object.h"
#define TYPE_SPAPR_CPU_CORE "spapr-cpu-core"
-#define SPAPR_CPU_CORE(obj) \
- OBJECT_CHECK(SpaprCpuCore, (obj), TYPE_SPAPR_CPU_CORE)
-#define SPAPR_CPU_CORE_CLASS(klass) \
- OBJECT_CLASS_CHECK(SpaprCpuCoreClass, (klass), TYPE_SPAPR_CPU_CORE)
-#define SPAPR_CPU_CORE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(SpaprCpuCoreClass, (obj), TYPE_SPAPR_CPU_CORE)
+OBJECT_DECLARE_TYPE(SpaprCpuCore, SpaprCpuCoreClass,
+ SPAPR_CPU_CORE)
#define SPAPR_CPU_CORE_TYPE_NAME(model) model "-" TYPE_SPAPR_CPU_CORE
-typedef struct SpaprCpuCore {
+struct SpaprCpuCore {
/*< private >*/
CPUCore parent_obj;
@@ -32,18 +29,20 @@ typedef struct SpaprCpuCore {
PowerPCCPU **threads;
int node_id;
bool pre_3_0_migration; /* older machine don't know about SpaprCpuState */
-} SpaprCpuCore;
+};
-typedef struct SpaprCpuCoreClass {
+struct SpaprCpuCoreClass {
DeviceClass parent_class;
const char *cpu_type;
-} SpaprCpuCoreClass;
+};
const char *spapr_get_cpu_core_type(const char *cpu_type);
void spapr_cpu_set_entry_state(PowerPCCPU *cpu, target_ulong nip,
target_ulong r1, target_ulong r3,
target_ulong r4);
+struct nested_ppc_state;
+
typedef struct SpaprCpuState {
uint64_t vpa_addr;
uint64_t slb_shadow_addr, slb_shadow_size;
@@ -51,6 +50,10 @@ typedef struct SpaprCpuState {
bool prod; /* not migrated, only used to improve dispatch latencies */
struct ICPState *icp;
struct XiveTCTX *tctx;
+
+ /* Fields for nested-HV support */
+ bool in_nested; /* true while the L2 is executing */
+ struct nested_ppc_state *nested_host_state; /* holds the L1 state while L2 executes */
} SpaprCpuState;
static inline SpaprCpuState *spapr_cpu_state(PowerPCCPU *cpu)
diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h
index 21af8deac1..02a63b3666 100644
--- a/include/hw/ppc/spapr_drc.h
+++ b/include/hw/ppc/spapr_drc.h
@@ -29,62 +29,21 @@
TYPE_SPAPR_DR_CONNECTOR)
#define TYPE_SPAPR_DRC_PHYSICAL "spapr-drc-physical"
-#define SPAPR_DRC_PHYSICAL_GET_CLASS(obj) \
- OBJECT_GET_CLASS(SpaprDrcClass, obj, TYPE_SPAPR_DRC_PHYSICAL)
-#define SPAPR_DRC_PHYSICAL_CLASS(klass) \
- OBJECT_CLASS_CHECK(SpaprDrcClass, klass, \
- TYPE_SPAPR_DRC_PHYSICAL)
#define SPAPR_DRC_PHYSICAL(obj) OBJECT_CHECK(SpaprDrcPhysical, (obj), \
TYPE_SPAPR_DRC_PHYSICAL)
#define TYPE_SPAPR_DRC_LOGICAL "spapr-drc-logical"
-#define SPAPR_DRC_LOGICAL_GET_CLASS(obj) \
- OBJECT_GET_CLASS(SpaprDrcClass, obj, TYPE_SPAPR_DRC_LOGICAL)
-#define SPAPR_DRC_LOGICAL_CLASS(klass) \
- OBJECT_CLASS_CHECK(SpaprDrcClass, klass, \
- TYPE_SPAPR_DRC_LOGICAL)
-#define SPAPR_DRC_LOGICAL(obj) OBJECT_CHECK(SpaprDrc, (obj), \
- TYPE_SPAPR_DRC_LOGICAL)
#define TYPE_SPAPR_DRC_CPU "spapr-drc-cpu"
-#define SPAPR_DRC_CPU_GET_CLASS(obj) \
- OBJECT_GET_CLASS(SpaprDrcClass, obj, TYPE_SPAPR_DRC_CPU)
-#define SPAPR_DRC_CPU_CLASS(klass) \
- OBJECT_CLASS_CHECK(SpaprDrcClass, klass, TYPE_SPAPR_DRC_CPU)
-#define SPAPR_DRC_CPU(obj) OBJECT_CHECK(SpaprDrc, (obj), \
- TYPE_SPAPR_DRC_CPU)
#define TYPE_SPAPR_DRC_PCI "spapr-drc-pci"
-#define SPAPR_DRC_PCI_GET_CLASS(obj) \
- OBJECT_GET_CLASS(SpaprDrcClass, obj, TYPE_SPAPR_DRC_PCI)
-#define SPAPR_DRC_PCI_CLASS(klass) \
- OBJECT_CLASS_CHECK(SpaprDrcClass, klass, TYPE_SPAPR_DRC_PCI)
-#define SPAPR_DRC_PCI(obj) OBJECT_CHECK(SpaprDrc, (obj), \
- TYPE_SPAPR_DRC_PCI)
#define TYPE_SPAPR_DRC_LMB "spapr-drc-lmb"
-#define SPAPR_DRC_LMB_GET_CLASS(obj) \
- OBJECT_GET_CLASS(SpaprDrcClass, obj, TYPE_SPAPR_DRC_LMB)
-#define SPAPR_DRC_LMB_CLASS(klass) \
- OBJECT_CLASS_CHECK(SpaprDrcClass, klass, TYPE_SPAPR_DRC_LMB)
-#define SPAPR_DRC_LMB(obj) OBJECT_CHECK(SpaprDrc, (obj), \
- TYPE_SPAPR_DRC_LMB)
#define TYPE_SPAPR_DRC_PHB "spapr-drc-phb"
-#define SPAPR_DRC_PHB_GET_CLASS(obj) \
- OBJECT_GET_CLASS(SpaprDrcClass, obj, TYPE_SPAPR_DRC_PHB)
-#define SPAPR_DRC_PHB_CLASS(klass) \
- OBJECT_CLASS_CHECK(SpaprDrcClass, klass, TYPE_SPAPR_DRC_PHB)
-#define SPAPR_DRC_PHB(obj) OBJECT_CHECK(SpaprDrc, (obj), \
- TYPE_SPAPR_DRC_PHB)
#define TYPE_SPAPR_DRC_PMEM "spapr-drc-pmem"
-#define SPAPR_DRC_PMEM_GET_CLASS(obj) \
- OBJECT_GET_CLASS(SpaprDrcClass, obj, TYPE_SPAPR_DRC_PMEM)
-#define SPAPR_DRC_PMEM_CLASS(klass) \
- OBJECT_CLASS_CHECK(SpaprDrcClass, klass, TYPE_SPAPR_DRC_PMEM)
-#define SPAPR_DRC_PMEM(obj) OBJECT_CHECK(SpaprDrc, (obj), \
- TYPE_SPAPR_DRC_PMEM)
+
/*
* Various hotplug types managed by SpaprDrc
*
@@ -265,7 +224,8 @@ static inline bool spapr_drc_hotplugged(DeviceState *dev)
return dev->hotplugged && !runstate_check(RUN_STATE_INMIGRATE);
}
-void spapr_drc_reset(SpaprDrc *drc);
+/* Returns true if an unplug request completed */
+bool spapr_drc_reset(SpaprDrc *drc);
uint32_t spapr_drc_index(SpaprDrc *drc);
SpaprDrcType spapr_drc_type(SpaprDrc *drc);
@@ -276,11 +236,20 @@ SpaprDrc *spapr_drc_by_index(uint32_t index);
SpaprDrc *spapr_drc_by_id(const char *type, uint32_t id);
int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask);
-void spapr_drc_attach(SpaprDrc *drc, DeviceState *d, Error **errp);
-void spapr_drc_detach(SpaprDrc *drc);
+/*
+ * These functions respectively abort if called with a device already
+ * attached or no device attached. In the case of spapr_drc_attach(),
+ * this means that the attachability of the DRC *must* be checked
+ * beforehand (eg. check drc->dev at pre-plug).
+ */
+void spapr_drc_attach(SpaprDrc *drc, DeviceState *d);
+void spapr_drc_unplug_request(SpaprDrc *drc);
-/* Returns true if a hot plug/unplug request is pending */
-bool spapr_drc_transient(SpaprDrc *drc);
+/*
+ * Reset all DRCs, causing pending hot-plug/unplug requests to complete.
+ * Safely handles potential DRC removal (eg. PHBs or PCI bridges).
+ */
+void spapr_drc_reset_all(struct SpaprMachineState *spapr);
static inline bool spapr_drc_unplug_requested(SpaprDrc *drc)
{
diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
index ca8cb44213..4fd2d5853d 100644
--- a/include/hw/ppc/spapr_irq.h
+++ b/include/hw/ppc/spapr_irq.h
@@ -11,11 +11,24 @@
#define HW_SPAPR_IRQ_H
#include "target/ppc/cpu-qom.h"
+#include "qom/object.h"
/*
- * IRQ range offsets per device type
+ * The XIVE IRQ backend uses the same layout as the XICS backend but
+ * covers the full range of the IRQ number space. The IRQ numbers for
+ * the CPU IPIs are allocated at the bottom of this space, below 4K,
+ * to preserve compatibility with XICS which does not use that range.
+ */
+
+/*
+ * CPU IPI range (XIVE only)
*/
#define SPAPR_IRQ_IPI 0x0
+#define SPAPR_IRQ_NR_IPIS 0x1000
+
+/*
+ * IRQ range offsets per device type
+ */
#define SPAPR_XIRQ_BASE XICS_IRQ_BASE /* 0x1000 */
#define SPAPR_IRQ_EPOW (SPAPR_XIRQ_BASE + 0x0000)
@@ -28,19 +41,18 @@
#define SPAPR_NR_XIRQS 0x1000
-typedef struct SpaprMachineState SpaprMachineState;
+struct SpaprMachineState;
typedef struct SpaprInterruptController SpaprInterruptController;
#define TYPE_SPAPR_INTC "spapr-interrupt-controller"
#define SPAPR_INTC(obj) \
INTERFACE_CHECK(SpaprInterruptController, (obj), TYPE_SPAPR_INTC)
-#define SPAPR_INTC_CLASS(klass) \
- OBJECT_CLASS_CHECK(SpaprInterruptControllerClass, (klass), TYPE_SPAPR_INTC)
-#define SPAPR_INTC_GET_CLASS(obj) \
- OBJECT_GET_CLASS(SpaprInterruptControllerClass, (obj), TYPE_SPAPR_INTC)
+typedef struct SpaprInterruptControllerClass SpaprInterruptControllerClass;
+DECLARE_CLASS_CHECKERS(SpaprInterruptControllerClass, SPAPR_INTC,
+ TYPE_SPAPR_INTC)
-typedef struct SpaprInterruptControllerClass {
+struct SpaprInterruptControllerClass {
InterfaceClass parent;
int (*activate)(SpaprInterruptController *intc, uint32_t nr_servers,
@@ -65,22 +77,22 @@ typedef struct SpaprInterruptControllerClass {
void (*dt)(SpaprInterruptController *intc, uint32_t nr_servers,
void *fdt, uint32_t phandle);
int (*post_load)(SpaprInterruptController *intc, int version_id);
-} SpaprInterruptControllerClass;
+};
-void spapr_irq_update_active_intc(SpaprMachineState *spapr);
+void spapr_irq_update_active_intc(struct SpaprMachineState *spapr);
-int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
+int spapr_irq_cpu_intc_create(struct SpaprMachineState *spapr,
PowerPCCPU *cpu, Error **errp);
-void spapr_irq_cpu_intc_reset(SpaprMachineState *spapr, PowerPCCPU *cpu);
-void spapr_irq_cpu_intc_destroy(SpaprMachineState *spapr, PowerPCCPU *cpu);
-void spapr_irq_print_info(SpaprMachineState *spapr, Monitor *mon);
-void spapr_irq_dt(SpaprMachineState *spapr, uint32_t nr_servers,
+void spapr_irq_cpu_intc_reset(struct SpaprMachineState *spapr, PowerPCCPU *cpu);
+void spapr_irq_cpu_intc_destroy(struct SpaprMachineState *spapr, PowerPCCPU *cpu);
+void spapr_irq_print_info(struct SpaprMachineState *spapr, Monitor *mon);
+void spapr_irq_dt(struct SpaprMachineState *spapr, uint32_t nr_servers,
void *fdt, uint32_t phandle);
-uint32_t spapr_irq_nr_msis(SpaprMachineState *spapr);
-int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
+uint32_t spapr_irq_nr_msis(struct SpaprMachineState *spapr);
+int spapr_irq_msi_alloc(struct SpaprMachineState *spapr, uint32_t num, bool align,
Error **errp);
-void spapr_irq_msi_free(SpaprMachineState *spapr, int irq, uint32_t num);
+void spapr_irq_msi_free(struct SpaprMachineState *spapr, int irq, uint32_t num);
typedef struct SpaprIrq {
bool xics;
@@ -92,13 +104,13 @@ extern SpaprIrq spapr_irq_xics_legacy;
extern SpaprIrq spapr_irq_xive;
extern SpaprIrq spapr_irq_dual;
-void spapr_irq_init(SpaprMachineState *spapr, Error **errp);
-int spapr_irq_claim(SpaprMachineState *spapr, int irq, bool lsi, Error **errp);
-void spapr_irq_free(SpaprMachineState *spapr, int irq, int num);
-qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq);
-int spapr_irq_post_load(SpaprMachineState *spapr, int version_id);
-void spapr_irq_reset(SpaprMachineState *spapr, Error **errp);
-int spapr_irq_get_phandle(SpaprMachineState *spapr, void *fdt, Error **errp);
+void spapr_irq_init(struct SpaprMachineState *spapr, Error **errp);
+int spapr_irq_claim(struct SpaprMachineState *spapr, int irq, bool lsi, Error **errp);
+void spapr_irq_free(struct SpaprMachineState *spapr, int irq, int num);
+qemu_irq spapr_qirq(struct SpaprMachineState *spapr, int irq);
+int spapr_irq_post_load(struct SpaprMachineState *spapr, int version_id);
+void spapr_irq_reset(struct SpaprMachineState *spapr, Error **errp);
+int spapr_irq_get_phandle(struct SpaprMachineState *spapr, void *fdt, Error **errp);
typedef int (*SpaprInterruptControllerInitKvm)(SpaprInterruptController *,
uint32_t, Error **);
@@ -111,7 +123,7 @@ int spapr_irq_init_kvm(SpaprInterruptControllerInitKvm fn,
/*
* XICS legacy routines
*/
-int spapr_irq_find(SpaprMachineState *spapr, int num, bool align, Error **errp);
+int spapr_irq_find(struct SpaprMachineState *spapr, int num, bool align, Error **errp);
#define spapr_irq_findone(spapr, errp) spapr_irq_find(spapr, 1, false, errp)
#endif
diff --git a/include/hw/ppc/spapr_nested.h b/include/hw/ppc/spapr_nested.h
new file mode 100644
index 0000000000..93ef14adcc
--- /dev/null
+++ b/include/hw/ppc/spapr_nested.h
@@ -0,0 +1,524 @@
+#ifndef HW_SPAPR_NESTED_H
+#define HW_SPAPR_NESTED_H
+
+#include "target/ppc/cpu.h"
+
+/* Guest State Buffer Element IDs */
+#define GSB_HV_VCPU_IGNORED_ID 0x0000 /* An element whose value is ignored */
+#define GSB_HV_VCPU_STATE_SIZE 0x0001 /* HV internal format VCPU state size */
+#define GSB_VCPU_OUT_BUF_MIN_SZ 0x0002 /* Min size of the Run VCPU o/p buffer */
+#define GSB_VCPU_LPVR 0x0003 /* Logical PVR */
+#define GSB_TB_OFFSET 0x0004 /* Timebase Offset */
+#define GSB_PART_SCOPED_PAGETBL 0x0005 /* Partition Scoped Page Table */
+#define GSB_PROCESS_TBL 0x0006 /* Process Table */
+ /* RESERVED 0x0007 - 0x0BFF */
+#define GSB_VCPU_IN_BUFFER 0x0C00 /* Run VCPU Input Buffer */
+#define GSB_VCPU_OUT_BUFFER 0x0C01 /* Run VCPU Out Buffer */
+#define GSB_VCPU_VPA 0x0C02 /* HRA to Guest VCPU VPA */
+ /* RESERVED 0x0C03 - 0x0FFF */
+#define GSB_VCPU_GPR0 0x1000
+#define GSB_VCPU_GPR1 0x1001
+#define GSB_VCPU_GPR2 0x1002
+#define GSB_VCPU_GPR3 0x1003
+#define GSB_VCPU_GPR4 0x1004
+#define GSB_VCPU_GPR5 0x1005
+#define GSB_VCPU_GPR6 0x1006
+#define GSB_VCPU_GPR7 0x1007
+#define GSB_VCPU_GPR8 0x1008
+#define GSB_VCPU_GPR9 0x1009
+#define GSB_VCPU_GPR10 0x100A
+#define GSB_VCPU_GPR11 0x100B
+#define GSB_VCPU_GPR12 0x100C
+#define GSB_VCPU_GPR13 0x100D
+#define GSB_VCPU_GPR14 0x100E
+#define GSB_VCPU_GPR15 0x100F
+#define GSB_VCPU_GPR16 0x1010
+#define GSB_VCPU_GPR17 0x1011
+#define GSB_VCPU_GPR18 0x1012
+#define GSB_VCPU_GPR19 0x1013
+#define GSB_VCPU_GPR20 0x1014
+#define GSB_VCPU_GPR21 0x1015
+#define GSB_VCPU_GPR22 0x1016
+#define GSB_VCPU_GPR23 0x1017
+#define GSB_VCPU_GPR24 0x1018
+#define GSB_VCPU_GPR25 0x1019
+#define GSB_VCPU_GPR26 0x101A
+#define GSB_VCPU_GPR27 0x101B
+#define GSB_VCPU_GPR28 0x101C
+#define GSB_VCPU_GPR29 0x101D
+#define GSB_VCPU_GPR30 0x101E
+#define GSB_VCPU_GPR31 0x101F
+#define GSB_VCPU_HDEC_EXPIRY_TB 0x1020
+#define GSB_VCPU_SPR_NIA 0x1021
+#define GSB_VCPU_SPR_MSR 0x1022
+#define GSB_VCPU_SPR_LR 0x1023
+#define GSB_VCPU_SPR_XER 0x1024
+#define GSB_VCPU_SPR_CTR 0x1025
+#define GSB_VCPU_SPR_CFAR 0x1026
+#define GSB_VCPU_SPR_SRR0 0x1027
+#define GSB_VCPU_SPR_SRR1 0x1028
+#define GSB_VCPU_SPR_DAR 0x1029
+#define GSB_VCPU_DEC_EXPIRE_TB 0x102A
+#define GSB_VCPU_SPR_VTB 0x102B
+#define GSB_VCPU_SPR_LPCR 0x102C
+#define GSB_VCPU_SPR_HFSCR 0x102D
+#define GSB_VCPU_SPR_FSCR 0x102E
+#define GSB_VCPU_SPR_FPSCR 0x102F
+#define GSB_VCPU_SPR_DAWR0 0x1030
+#define GSB_VCPU_SPR_DAWR1 0x1031
+#define GSB_VCPU_SPR_CIABR 0x1032
+#define GSB_VCPU_SPR_PURR 0x1033
+#define GSB_VCPU_SPR_SPURR 0x1034
+#define GSB_VCPU_SPR_IC 0x1035
+#define GSB_VCPU_SPR_SPRG0 0x1036
+#define GSB_VCPU_SPR_SPRG1 0x1037
+#define GSB_VCPU_SPR_SPRG2 0x1038
+#define GSB_VCPU_SPR_SPRG3 0x1039
+#define GSB_VCPU_SPR_PPR 0x103A
+#define GSB_VCPU_SPR_MMCR0 0x103B
+#define GSB_VCPU_SPR_MMCR1 0x103C
+#define GSB_VCPU_SPR_MMCR2 0x103D
+#define GSB_VCPU_SPR_MMCR3 0x103E
+#define GSB_VCPU_SPR_MMCRA 0x103F
+#define GSB_VCPU_SPR_SIER 0x1040
+#define GSB_VCPU_SPR_SIER2 0x1041
+#define GSB_VCPU_SPR_SIER3 0x1042
+#define GSB_VCPU_SPR_BESCR 0x1043
+#define GSB_VCPU_SPR_EBBHR 0x1044
+#define GSB_VCPU_SPR_EBBRR 0x1045
+#define GSB_VCPU_SPR_AMR 0x1046
+#define GSB_VCPU_SPR_IAMR 0x1047
+#define GSB_VCPU_SPR_AMOR 0x1048
+#define GSB_VCPU_SPR_UAMOR 0x1049
+#define GSB_VCPU_SPR_SDAR 0x104A
+#define GSB_VCPU_SPR_SIAR 0x104B
+#define GSB_VCPU_SPR_DSCR 0x104C
+#define GSB_VCPU_SPR_TAR 0x104D
+#define GSB_VCPU_SPR_DEXCR 0x104E
+#define GSB_VCPU_SPR_HDEXCR 0x104F
+#define GSB_VCPU_SPR_HASHKEYR 0x1050
+#define GSB_VCPU_SPR_HASHPKEYR 0x1051
+#define GSB_VCPU_SPR_CTRL 0x1052
+ /* RESERVED 0x1053 - 0x1FFF */
+#define GSB_VCPU_SPR_CR 0x2000
+#define GSB_VCPU_SPR_PIDR 0x2001
+#define GSB_VCPU_SPR_DSISR 0x2002
+#define GSB_VCPU_SPR_VSCR 0x2003
+#define GSB_VCPU_SPR_VRSAVE 0x2004
+#define GSB_VCPU_SPR_DAWRX0 0x2005
+#define GSB_VCPU_SPR_DAWRX1 0x2006
+#define GSB_VCPU_SPR_PMC1 0x2007
+#define GSB_VCPU_SPR_PMC2 0x2008
+#define GSB_VCPU_SPR_PMC3 0x2009
+#define GSB_VCPU_SPR_PMC4 0x200A
+#define GSB_VCPU_SPR_PMC5 0x200B
+#define GSB_VCPU_SPR_PMC6 0x200C
+#define GSB_VCPU_SPR_WORT 0x200D
+#define GSB_VCPU_SPR_PSPB 0x200E
+ /* RESERVED 0x200F - 0x2FFF */
+#define GSB_VCPU_SPR_VSR0 0x3000
+#define GSB_VCPU_SPR_VSR1 0x3001
+#define GSB_VCPU_SPR_VSR2 0x3002
+#define GSB_VCPU_SPR_VSR3 0x3003
+#define GSB_VCPU_SPR_VSR4 0x3004
+#define GSB_VCPU_SPR_VSR5 0x3005
+#define GSB_VCPU_SPR_VSR6 0x3006
+#define GSB_VCPU_SPR_VSR7 0x3007
+#define GSB_VCPU_SPR_VSR8 0x3008
+#define GSB_VCPU_SPR_VSR9 0x3009
+#define GSB_VCPU_SPR_VSR10 0x300A
+#define GSB_VCPU_SPR_VSR11 0x300B
+#define GSB_VCPU_SPR_VSR12 0x300C
+#define GSB_VCPU_SPR_VSR13 0x300D
+#define GSB_VCPU_SPR_VSR14 0x300E
+#define GSB_VCPU_SPR_VSR15 0x300F
+#define GSB_VCPU_SPR_VSR16 0x3010
+#define GSB_VCPU_SPR_VSR17 0x3011
+#define GSB_VCPU_SPR_VSR18 0x3012
+#define GSB_VCPU_SPR_VSR19 0x3013
+#define GSB_VCPU_SPR_VSR20 0x3014
+#define GSB_VCPU_SPR_VSR21 0x3015
+#define GSB_VCPU_SPR_VSR22 0x3016
+#define GSB_VCPU_SPR_VSR23 0x3017
+#define GSB_VCPU_SPR_VSR24 0x3018
+#define GSB_VCPU_SPR_VSR25 0x3019
+#define GSB_VCPU_SPR_VSR26 0x301A
+#define GSB_VCPU_SPR_VSR27 0x301B
+#define GSB_VCPU_SPR_VSR28 0x301C
+#define GSB_VCPU_SPR_VSR29 0x301D
+#define GSB_VCPU_SPR_VSR30 0x301E
+#define GSB_VCPU_SPR_VSR31 0x301F
+#define GSB_VCPU_SPR_VSR32 0x3020
+#define GSB_VCPU_SPR_VSR33 0x3021
+#define GSB_VCPU_SPR_VSR34 0x3022
+#define GSB_VCPU_SPR_VSR35 0x3023
+#define GSB_VCPU_SPR_VSR36 0x3024
+#define GSB_VCPU_SPR_VSR37 0x3025
+#define GSB_VCPU_SPR_VSR38 0x3026
+#define GSB_VCPU_SPR_VSR39 0x3027
+#define GSB_VCPU_SPR_VSR40 0x3028
+#define GSB_VCPU_SPR_VSR41 0x3029
+#define GSB_VCPU_SPR_VSR42 0x302A
+#define GSB_VCPU_SPR_VSR43 0x302B
+#define GSB_VCPU_SPR_VSR44 0x302C
+#define GSB_VCPU_SPR_VSR45 0x302D
+#define GSB_VCPU_SPR_VSR46 0x302E
+#define GSB_VCPU_SPR_VSR47 0x302F
+#define GSB_VCPU_SPR_VSR48 0x3030
+#define GSB_VCPU_SPR_VSR49 0x3031
+#define GSB_VCPU_SPR_VSR50 0x3032
+#define GSB_VCPU_SPR_VSR51 0x3033
+#define GSB_VCPU_SPR_VSR52 0x3034
+#define GSB_VCPU_SPR_VSR53 0x3035
+#define GSB_VCPU_SPR_VSR54 0x3036
+#define GSB_VCPU_SPR_VSR55 0x3037
+#define GSB_VCPU_SPR_VSR56 0x3038
+#define GSB_VCPU_SPR_VSR57 0x3039
+#define GSB_VCPU_SPR_VSR58 0x303A
+#define GSB_VCPU_SPR_VSR59 0x303B
+#define GSB_VCPU_SPR_VSR60 0x303C
+#define GSB_VCPU_SPR_VSR61 0x303D
+#define GSB_VCPU_SPR_VSR62 0x303E
+#define GSB_VCPU_SPR_VSR63 0x303F
+ /* RESERVED 0x3040 - 0xEFFF */
+#define GSB_VCPU_SPR_HDAR 0xF000
+#define GSB_VCPU_SPR_HDSISR 0xF001
+#define GSB_VCPU_SPR_HEIR 0xF002
+#define GSB_VCPU_SPR_ASDR 0xF003
+/* End of list of Guest State Buffer Element IDs */
+#define GSB_LAST GSB_VCPU_SPR_ASDR
+
+typedef struct SpaprMachineStateNested {
+ uint64_t ptcr;
+ uint8_t api;
+#define NESTED_API_KVM_HV 1
+#define NESTED_API_PAPR 2
+ bool capabilities_set;
+ uint32_t pvr_base;
+ GHashTable *guests;
+} SpaprMachineStateNested;
+
+typedef struct SpaprMachineStateNestedGuest {
+ uint32_t pvr_logical;
+ unsigned long nr_vcpus;
+ uint64_t parttbl[2];
+ uint64_t tb_offset;
+ struct SpaprMachineStateNestedGuestVcpu *vcpus;
+} SpaprMachineStateNestedGuest;
+
+/* Nested PAPR API related macros */
+#define H_GUEST_CAPABILITIES_COPY_MEM 0x8000000000000000
+#define H_GUEST_CAPABILITIES_P9_MODE 0x4000000000000000
+#define H_GUEST_CAPABILITIES_P10_MODE 0x2000000000000000
+#define H_GUEST_CAP_VALID_MASK (H_GUEST_CAPABILITIES_P10_MODE | \
+ H_GUEST_CAPABILITIES_P9_MODE)
+#define H_GUEST_CAP_COPY_MEM_BMAP 0
+#define H_GUEST_CAP_P9_MODE_BMAP 1
+#define H_GUEST_CAP_P10_MODE_BMAP 2
+#define PAPR_NESTED_GUEST_MAX 4096
+#define H_GUEST_DELETE_ALL_FLAG 0x8000000000000000ULL
+#define PAPR_NESTED_GUEST_VCPU_MAX 2048
+#define VCPU_OUT_BUF_MIN_SZ 0x80ULL
+#define HVMASK_DEFAULT 0xffffffffffffffff
+#define HVMASK_LPCR 0x0070000003820800
+#define HVMASK_MSR 0xEBFFFFFFFFBFEFFF
+#define HVMASK_HDEXCR 0x00000000FFFFFFFF
+#define HVMASK_TB_OFFSET 0x000000FFFFFFFFFF
+#define GSB_MAX_BUF_SIZE (1024 * 1024)
+#define H_GUEST_GETSET_STATE_FLAG_GUEST_WIDE 0x8000000000000000
+#define GUEST_STATE_REQUEST_GUEST_WIDE 0x1
+#define GUEST_STATE_REQUEST_SET 0x2
+
+/*
+ * As per ISA v3.1B, following bits are reserved:
+ * 0:2
+ * 4:57 (ISA mentions bit 58 as well but it should be used for P10)
+ * 61:63 (hence, haven't included PCR bits for v2.06 and v2.05
+ * in LOW BITS)
+ */
+#define PCR_LOW_BITS (PCR_COMPAT_3_10 | PCR_COMPAT_3_00)
+#define HVMASK_PCR (~PCR_LOW_BITS)
+
+#define GUEST_STATE_ELEMENT(i, sz, s, f, ptr, c) { \
+ .id = (i), \
+ .size = (sz), \
+ .location = ptr, \
+ .offset = offsetof(struct s, f), \
+ .copy = (c) \
+}
+
+#define GSBE_NESTED(i, sz, f, c) { \
+ .id = (i), \
+ .size = (sz), \
+ .location = get_guest_ptr, \
+ .offset = offsetof(struct SpaprMachineStateNestedGuest, f),\
+ .copy = (c), \
+ .mask = HVMASK_DEFAULT \
+}
+
+#define GSBE_NESTED_MSK(i, sz, f, c, m) { \
+ .id = (i), \
+ .size = (sz), \
+ .location = get_guest_ptr, \
+ .offset = offsetof(struct SpaprMachineStateNestedGuest, f),\
+ .copy = (c), \
+ .mask = (m) \
+}
+
+#define GSBE_NESTED_VCPU(i, sz, f, c) { \
+ .id = (i), \
+ .size = (sz), \
+ .location = get_vcpu_ptr, \
+ .offset = offsetof(struct SpaprMachineStateNestedGuestVcpu, f),\
+ .copy = (c), \
+ .mask = HVMASK_DEFAULT \
+}
+
+#define GUEST_STATE_ELEMENT_NOP(i, sz) { \
+ .id = (i), \
+ .size = (sz), \
+ .location = NULL, \
+ .offset = 0, \
+ .copy = NULL, \
+ .mask = HVMASK_DEFAULT \
+}
+
+#define GUEST_STATE_ELEMENT_NOP_DW(i) \
+ GUEST_STATE_ELEMENT_NOP(i, 8)
+#define GUEST_STATE_ELEMENT_NOP_W(i) \
+ GUEST_STATE_ELEMENT_NOP(i, 4)
+
+#define GUEST_STATE_ELEMENT_BASE(i, s, c) { \
+ .id = (i), \
+ .size = (s), \
+ .location = get_vcpu_state_ptr, \
+ .offset = 0, \
+ .copy = (c), \
+ .mask = HVMASK_DEFAULT \
+ }
+
+#define GUEST_STATE_ELEMENT_OFF(i, s, f, c) { \
+ .id = (i), \
+ .size = (s), \
+ .location = get_vcpu_state_ptr, \
+ .offset = offsetof(struct nested_ppc_state, f), \
+ .copy = (c), \
+ .mask = HVMASK_DEFAULT \
+ }
+
+#define GUEST_STATE_ELEMENT_MSK(i, s, f, c, m) { \
+ .id = (i), \
+ .size = (s), \
+ .location = get_vcpu_state_ptr, \
+ .offset = offsetof(struct nested_ppc_state, f), \
+ .copy = (c), \
+ .mask = (m) \
+ }
+
+#define GUEST_STATE_ELEMENT_ENV_QW(i, f) \
+ GUEST_STATE_ELEMENT_OFF(i, 16, f, copy_state_16to16)
+#define GUEST_STATE_ELEMENT_ENV_DW(i, f) \
+ GUEST_STATE_ELEMENT_OFF(i, 8, f, copy_state_8to8)
+#define GUEST_STATE_ELEMENT_ENV_W(i, f) \
+ GUEST_STATE_ELEMENT_OFF(i, 4, f, copy_state_4to8)
+#define GUEST_STATE_ELEMENT_ENV_WW(i, f) \
+ GUEST_STATE_ELEMENT_OFF(i, 4, f, copy_state_4to4)
+#define GSE_ENV_DWM(i, f, m) \
+ GUEST_STATE_ELEMENT_MSK(i, 8, f, copy_state_8to8, m)
+
+struct guest_state_element {
+ uint16_t id;
+ uint16_t size;
+ uint8_t value[];
+} QEMU_PACKED;
+
+struct guest_state_buffer {
+ uint32_t num_elements;
+ struct guest_state_element elements[];
+} QEMU_PACKED;
+
+/* Actual buffer plus some metadata about the request */
+struct guest_state_request {
+ struct guest_state_buffer *gsb;
+ int64_t buf;
+ int64_t len;
+ uint16_t flags;
+};
+
+/*
+ * Register state for entering a nested guest with H_ENTER_NESTED.
+ * New member must be added at the end.
+ */
+struct kvmppc_hv_guest_state {
+ uint64_t version; /* version of this structure layout, must be first */
+ uint32_t lpid;
+ uint32_t vcpu_token;
+ /* These registers are hypervisor privileged (at least for writing) */
+ uint64_t lpcr;
+ uint64_t pcr;
+ uint64_t amor;
+ uint64_t dpdes;
+ uint64_t hfscr;
+ int64_t tb_offset;
+ uint64_t dawr0;
+ uint64_t dawrx0;
+ uint64_t ciabr;
+ uint64_t hdec_expiry;
+ uint64_t purr;
+ uint64_t spurr;
+ uint64_t ic;
+ uint64_t vtb;
+ uint64_t hdar;
+ uint64_t hdsisr;
+ uint64_t heir;
+ uint64_t asdr;
+ /* These are OS privileged but need to be set late in guest entry */
+ uint64_t srr0;
+ uint64_t srr1;
+ uint64_t sprg[4];
+ uint64_t pidr;
+ uint64_t cfar;
+ uint64_t ppr;
+ /* Version 1 ends here */
+ uint64_t dawr1;
+ uint64_t dawrx1;
+ /* Version 2 ends here */
+};
+
+/* Latest version of hv_guest_state structure */
+#define HV_GUEST_STATE_VERSION 2
+
+/* Linux 64-bit powerpc pt_regs struct, used by nested HV */
+struct kvmppc_pt_regs {
+ uint64_t gpr[32];
+ uint64_t nip;
+ uint64_t msr;
+ uint64_t orig_gpr3; /* Used for restarting system calls */
+ uint64_t ctr;
+ uint64_t link;
+ uint64_t xer;
+ uint64_t ccr;
+ uint64_t softe; /* Soft enabled/disabled */
+ uint64_t trap; /* Reason for being here */
+ uint64_t dar; /* Fault registers */
+ uint64_t dsisr; /* on 4xx/Book-E used for ESR */
+ uint64_t result; /* Result of a system call */
+};
+
+/*
+ * nested_ppc_state is used to save the host CPU state before switching it to
+ * the guest CPU state, to be restored on H_ENTER_NESTED exit.
+ */
+struct nested_ppc_state {
+ uint64_t gpr[32];
+ uint64_t lr;
+ uint64_t ctr;
+ uint64_t cfar;
+ uint64_t msr;
+ uint64_t nip;
+ uint32_t cr;
+
+ uint64_t xer;
+
+ uint64_t lpcr;
+ uint64_t lpidr;
+ uint64_t pidr;
+ uint64_t pcr;
+ uint64_t dpdes;
+ uint64_t hfscr;
+ uint64_t srr0;
+ uint64_t srr1;
+ uint64_t sprg0;
+ uint64_t sprg1;
+ uint64_t sprg2;
+ uint64_t sprg3;
+ uint64_t ppr;
+
+ int64_t tb_offset;
+ /* Nested PAPR API */
+ uint64_t amor;
+ uint64_t dawr0;
+ uint64_t dawrx0;
+ uint64_t ciabr;
+ uint64_t purr;
+ uint64_t spurr;
+ uint64_t ic;
+ uint64_t vtb;
+ uint64_t hdar;
+ uint64_t hdsisr;
+ uint64_t heir;
+ uint64_t asdr;
+ uint64_t dawr1;
+ uint64_t dawrx1;
+ uint64_t dexcr;
+ uint64_t hdexcr;
+ uint64_t hashkeyr;
+ uint64_t hashpkeyr;
+ ppc_vsr_t vsr[64] QEMU_ALIGNED(16);
+ uint64_t ebbhr;
+ uint64_t tar;
+ uint64_t ebbrr;
+ uint64_t bescr;
+ uint64_t iamr;
+ uint64_t amr;
+ uint64_t uamor;
+ uint64_t dscr;
+ uint64_t fscr;
+ uint64_t pspb;
+ uint64_t ctrl;
+ uint64_t vrsave;
+ uint64_t dar;
+ uint64_t dsisr;
+ uint64_t pmc1;
+ uint64_t pmc2;
+ uint64_t pmc3;
+ uint64_t pmc4;
+ uint64_t pmc5;
+ uint64_t pmc6;
+ uint64_t mmcr0;
+ uint64_t mmcr1;
+ uint64_t mmcr2;
+ uint64_t mmcra;
+ uint64_t sdar;
+ uint64_t siar;
+ uint64_t sier;
+ uint32_t vscr;
+ uint64_t fpscr;
+ int64_t dec_expiry_tb;
+};
+
+struct SpaprMachineStateNestedGuestVcpuRunBuf {
+ uint64_t addr;
+ uint64_t size;
+};
+
+typedef struct SpaprMachineStateNestedGuestVcpu {
+ bool enabled;
+ struct nested_ppc_state state;
+ struct SpaprMachineStateNestedGuestVcpuRunBuf runbufin;
+ struct SpaprMachineStateNestedGuestVcpuRunBuf runbufout;
+ int64_t tb_offset;
+ uint64_t hdecr_expiry_tb;
+} SpaprMachineStateNestedGuestVcpu;
+
+struct guest_state_element_type {
+ uint16_t id;
+ int size;
+#define GUEST_STATE_ELEMENT_TYPE_FLAG_GUEST_WIDE 0x1
+#define GUEST_STATE_ELEMENT_TYPE_FLAG_READ_ONLY 0x2
+ uint16_t flags;
+ void *(*location)(SpaprMachineStateNestedGuest *, target_ulong);
+ size_t offset;
+ void (*copy)(void *, void *, bool);
+ uint64_t mask;
+};
+
+void spapr_exit_nested(PowerPCCPU *cpu, int excp);
+typedef struct SpaprMachineState SpaprMachineState;
+bool spapr_get_pate_nested_hv(SpaprMachineState *spapr, PowerPCCPU *cpu,
+ target_ulong lpid, ppc_v3_pate_t *entry);
+uint8_t spapr_nested_api(SpaprMachineState *spapr);
+void spapr_nested_gsb_init(void);
+bool spapr_get_pate_nested_papr(SpaprMachineState *spapr, PowerPCCPU *cpu,
+ target_ulong lpid, ppc_v3_pate_t *entry);
+#endif /* HW_SPAPR_NESTED_H */
diff --git a/include/hw/ppc/spapr_numa.h b/include/hw/ppc/spapr_numa.h
new file mode 100644
index 0000000000..7cb3367400
--- /dev/null
+++ b/include/hw/ppc/spapr_numa.h
@@ -0,0 +1,37 @@
+/*
+ * QEMU PowerPC pSeries Logical Partition NUMA associativity handling
+ *
+ * Copyright IBM Corp. 2020
+ *
+ * Authors:
+ * Daniel Henrique Barboza <danielhb413@gmail.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef HW_SPAPR_NUMA_H
+#define HW_SPAPR_NUMA_H
+
+#include "hw/boards.h"
+#include "hw/ppc/spapr.h"
+
+/*
+ * Having both SpaprMachineState and MachineState as arguments
+ * feels odd, but it will spare a MACHINE() call inside the
+ * function. spapr_machine_init() is the only caller for it, and
+ * it has both pointers resolved already.
+ */
+void spapr_numa_associativity_init(SpaprMachineState *spapr,
+ MachineState *machine);
+void spapr_numa_associativity_check(SpaprMachineState *spapr);
+void spapr_numa_write_rtas_dt(SpaprMachineState *spapr, void *fdt, int rtas);
+void spapr_numa_write_associativity_dt(SpaprMachineState *spapr, void *fdt,
+ int offset, int nodeid);
+int spapr_numa_fixup_cpu_dt(SpaprMachineState *spapr, void *fdt,
+ int offset, PowerPCCPU *cpu);
+int spapr_numa_write_assoc_lookup_arrays(SpaprMachineState *spapr, void *fdt,
+ int offset);
+unsigned int spapr_numa_initial_nvgpu_numa_id(MachineState *machine);
+
+#endif /* HW_SPAPR_NUMA_H */
diff --git a/include/hw/ppc/spapr_nvdimm.h b/include/hw/ppc/spapr_nvdimm.h
index b3330cc485..e9436cb6ef 100644
--- a/include/hw/ppc/spapr_nvdimm.h
+++ b/include/hw/ppc/spapr_nvdimm.h
@@ -11,27 +11,16 @@
#define HW_SPAPR_NVDIMM_H
#include "hw/mem/nvdimm.h"
-#include "hw/ppc/spapr.h"
-/*
- * The nvdimm size should be aligned to SCM block size.
- * The SCM block size should be aligned to SPAPR_MEMORY_BLOCK_SIZE
- * inorder to have SCM regions not to overlap with dimm memory regions.
- * The SCM devices can have variable block sizes. For now, fixing the
- * block size to the minimum value.
- */
-#define SPAPR_MINIMUM_SCM_BLOCK_SIZE SPAPR_MEMORY_BLOCK_SIZE
-
-/* Have an explicit check for alignment */
-QEMU_BUILD_BUG_ON(SPAPR_MINIMUM_SCM_BLOCK_SIZE % SPAPR_MEMORY_BLOCK_SIZE);
+typedef struct SpaprDrc SpaprDrc;
+typedef struct SpaprMachineState SpaprMachineState;
int spapr_pmem_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
void *fdt, int *fdt_start_offset, Error **errp);
-int spapr_dt_nvdimm(void *fdt, int parent_offset, NVDIMMDevice *nvdimm);
-void spapr_dt_persistent_memory(void *fdt);
-void spapr_nvdimm_validate_opts(NVDIMMDevice *nvdimm, uint64_t size,
- Error **errp);
-void spapr_add_nvdimm(DeviceState *dev, uint64_t slot, Error **errp);
-void spapr_create_nvdimm_dr_connectors(SpaprMachineState *spapr);
+void spapr_dt_persistent_memory(SpaprMachineState *spapr, void *fdt);
+bool spapr_nvdimm_validate(HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm,
+ uint64_t size, Error **errp);
+void spapr_add_nvdimm(DeviceState *dev, uint64_t slot);
+void spapr_nvdimm_finish_flushes(void);
#endif
diff --git a/include/hw/ppc/spapr_ovec.h b/include/hw/ppc/spapr_ovec.h
index d4dee9e06a..c3e8b98e7e 100644
--- a/include/hw/ppc/spapr_ovec.h
+++ b/include/hw/ppc/spapr_ovec.h
@@ -49,6 +49,7 @@ typedef struct SpaprOptionVector SpaprOptionVector;
/* option vector 5 */
#define OV5_DRCONF_MEMORY OV_BIT(2, 2)
#define OV5_FORM1_AFFINITY OV_BIT(5, 0)
+#define OV5_FORM2_AFFINITY OV_BIT(5, 2)
#define OV5_HP_EVT OV_BIT(6, 5)
#define OV5_HPT_RESIZE OV_BIT(6, 7)
#define OV5_DRMEM_V2 OV_BIT(22, 0)
@@ -71,6 +72,7 @@ void spapr_ovec_cleanup(SpaprOptionVector *ov);
void spapr_ovec_set(SpaprOptionVector *ov, long bitnr);
void spapr_ovec_clear(SpaprOptionVector *ov, long bitnr);
bool spapr_ovec_test(SpaprOptionVector *ov, long bitnr);
+bool spapr_ovec_empty(SpaprOptionVector *ov);
SpaprOptionVector *spapr_ovec_parse_vector(target_ulong table_addr, int vector);
int spapr_dt_ovec(void *fdt, int fdt_offset,
SpaprOptionVector *ov, const char *name);
diff --git a/include/hw/ppc/spapr_rtas.h b/include/hw/ppc/spapr_rtas.h
deleted file mode 100644
index 383611f10f..0000000000
--- a/include/hw/ppc/spapr_rtas.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef HW_SPAPR_RTAS_H
-#define HW_SPAPR_RTAS_H
-/*
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-uint64_t qtest_rtas_call(char *cmd, uint32_t nargs, uint64_t args,
- uint32_t nret, uint64_t rets);
-#endif /* HW_SPAPR_RTAS_H */
diff --git a/include/hw/ppc/spapr_tpm_proxy.h b/include/hw/ppc/spapr_tpm_proxy.h
index c574e22ba4..96d2a9697e 100644
--- a/include/hw/ppc/spapr_tpm_proxy.h
+++ b/include/hw/ppc/spapr_tpm_proxy.h
@@ -17,15 +17,14 @@
#include "hw/qdev-core.h"
#define TYPE_SPAPR_TPM_PROXY "spapr-tpm-proxy"
-#define SPAPR_TPM_PROXY(obj) OBJECT_CHECK(SpaprTpmProxy, (obj), \
- TYPE_SPAPR_TPM_PROXY)
+OBJECT_DECLARE_SIMPLE_TYPE(SpaprTpmProxy, SPAPR_TPM_PROXY)
-typedef struct SpaprTpmProxy {
+struct SpaprTpmProxy {
/*< private >*/
DeviceState parent;
char *host_path;
int host_fd;
-} SpaprTpmProxy;
+};
#endif /* HW_SPAPR_TPM_PROXY_H */
diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h
index bed7df60e3..7eae1a4847 100644
--- a/include/hw/ppc/spapr_vio.h
+++ b/include/hw/ppc/spapr_vio.h
@@ -11,7 +11,7 @@
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -25,17 +25,14 @@
#include "hw/ppc/spapr.h"
#include "sysemu/dma.h"
#include "hw/irq.h"
+#include "qom/object.h"
#define TYPE_VIO_SPAPR_DEVICE "vio-spapr-device"
-#define VIO_SPAPR_DEVICE(obj) \
- OBJECT_CHECK(SpaprVioDevice, (obj), TYPE_VIO_SPAPR_DEVICE)
-#define VIO_SPAPR_DEVICE_CLASS(klass) \
- OBJECT_CLASS_CHECK(SpaprVioDeviceClass, (klass), TYPE_VIO_SPAPR_DEVICE)
-#define VIO_SPAPR_DEVICE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(SpaprVioDeviceClass, (obj), TYPE_VIO_SPAPR_DEVICE)
+OBJECT_DECLARE_TYPE(SpaprVioDevice, SpaprVioDeviceClass,
+ VIO_SPAPR_DEVICE)
#define TYPE_SPAPR_VIO_BUS "spapr-vio-bus"
-#define SPAPR_VIO_BUS(obj) OBJECT_CHECK(SpaprVioBus, (obj), TYPE_SPAPR_VIO_BUS)
+OBJECT_DECLARE_SIMPLE_TYPE(SpaprVioBus, SPAPR_VIO_BUS)
#define TYPE_SPAPR_VIO_BRIDGE "spapr-vio-bridge"
@@ -46,10 +43,8 @@ typedef struct SpaprVioCrq {
int(*SendFunc)(struct SpaprVioDevice *vdev, uint8_t *crq);
} SpaprVioCrq;
-typedef struct SpaprVioDevice SpaprVioDevice;
-typedef struct SpaprVioBus SpaprVioBus;
-typedef struct SpaprVioDeviceClass {
+struct SpaprVioDeviceClass {
DeviceClass parent_class;
const char *dt_name, *dt_type, *dt_compatible;
@@ -59,7 +54,7 @@ typedef struct SpaprVioDeviceClass {
void (*reset)(SpaprVioDevice *dev);
int (*devnode)(SpaprVioDevice *dev, void *fdt, int node_off);
const char *(*get_dt_compatible)(SpaprVioDevice *dev);
-} SpaprVioDeviceClass;
+};
struct SpaprVioDevice {
DeviceState qdev;
@@ -96,35 +91,47 @@ static inline void spapr_vio_irq_pulse(SpaprVioDevice *dev)
static inline bool spapr_vio_dma_valid(SpaprVioDevice *dev, uint64_t taddr,
uint32_t size, DMADirection dir)
{
- return dma_memory_valid(&dev->as, taddr, size, dir);
+ return dma_memory_valid(&dev->as, taddr, size, dir, MEMTXATTRS_UNSPECIFIED);
}
static inline int spapr_vio_dma_read(SpaprVioDevice *dev, uint64_t taddr,
void *buf, uint32_t size)
{
- return (dma_memory_read(&dev->as, taddr, buf, size) != 0) ?
+ return (dma_memory_read(&dev->as, taddr,
+ buf, size, MEMTXATTRS_UNSPECIFIED) != 0) ?
H_DEST_PARM : H_SUCCESS;
}
static inline int spapr_vio_dma_write(SpaprVioDevice *dev, uint64_t taddr,
const void *buf, uint32_t size)
{
- return (dma_memory_write(&dev->as, taddr, buf, size) != 0) ?
+ return (dma_memory_write(&dev->as, taddr,
+ buf, size, MEMTXATTRS_UNSPECIFIED) != 0) ?
H_DEST_PARM : H_SUCCESS;
}
static inline int spapr_vio_dma_set(SpaprVioDevice *dev, uint64_t taddr,
uint8_t c, uint32_t size)
{
- return (dma_memory_set(&dev->as, taddr, c, size) != 0) ?
+ return (dma_memory_set(&dev->as, taddr,
+ c, size, MEMTXATTRS_UNSPECIFIED) != 0) ?
H_DEST_PARM : H_SUCCESS;
}
-#define vio_stb(_dev, _addr, _val) (stb_dma(&(_dev)->as, (_addr), (_val)))
-#define vio_sth(_dev, _addr, _val) (stw_be_dma(&(_dev)->as, (_addr), (_val)))
-#define vio_stl(_dev, _addr, _val) (stl_be_dma(&(_dev)->as, (_addr), (_val)))
-#define vio_stq(_dev, _addr, _val) (stq_be_dma(&(_dev)->as, (_addr), (_val)))
-#define vio_ldq(_dev, _addr) (ldq_be_dma(&(_dev)->as, (_addr)))
+#define vio_stb(_dev, _addr, _val) \
+ (stb_dma(&(_dev)->as, (_addr), (_val), MEMTXATTRS_UNSPECIFIED))
+#define vio_sth(_dev, _addr, _val) \
+ (stw_be_dma(&(_dev)->as, (_addr), (_val), MEMTXATTRS_UNSPECIFIED))
+#define vio_stl(_dev, _addr, _val) \
+ (stl_be_dma(&(_dev)->as, (_addr), (_val), MEMTXATTRS_UNSPECIFIED))
+#define vio_stq(_dev, _addr, _val) \
+ (stq_be_dma(&(_dev)->as, (_addr), (_val), MEMTXATTRS_UNSPECIFIED))
+#define vio_ldq(_dev, _addr) \
+ ({ \
+ uint64_t _val; \
+ ldq_be_dma(&(_dev)->as, (_addr), &_val, MEMTXATTRS_UNSPECIFIED); \
+ _val; \
+ })
int spapr_vio_send_crq(SpaprVioDevice *dev, uint8_t *crq);
diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h
index 93d09d68de..b282960ad9 100644
--- a/include/hw/ppc/spapr_xive.h
+++ b/include/hw/ppc/spapr_xive.h
@@ -49,6 +49,8 @@ typedef struct SpaprXive {
void *tm_mmap;
MemoryRegion tm_mmio_kvm;
VMChangeStateEntry *change;
+
+ uint8_t hv_prio;
} SpaprXive;
typedef struct SpaprXiveClass {
@@ -64,9 +66,8 @@ typedef struct SpaprXiveClass {
*/
#define SPAPR_XIVE_BLOCK_ID 0x0
-void spapr_xive_pic_print_info(SpaprXive *xive, Monitor *mon);
-
-void spapr_xive_hcall_init(SpaprMachineState *spapr);
+struct SpaprMachineState;
+void spapr_xive_hcall_init(struct SpaprMachineState *spapr);
void spapr_xive_mmio_set_enabled(SpaprXive *xive, bool enable);
void spapr_xive_map_mmio(SpaprXive *xive);
@@ -80,15 +81,15 @@ int kvmppc_xive_connect(SpaprInterruptController *intc, uint32_t nr_servers,
Error **errp);
void kvmppc_xive_disconnect(SpaprInterruptController *intc);
void kvmppc_xive_reset(SpaprXive *xive, Error **errp);
-void kvmppc_xive_set_source_config(SpaprXive *xive, uint32_t lisn, XiveEAS *eas,
- Error **errp);
+int kvmppc_xive_set_source_config(SpaprXive *xive, uint32_t lisn, XiveEAS *eas,
+ Error **errp);
void kvmppc_xive_sync_source(SpaprXive *xive, uint32_t lisn, Error **errp);
uint64_t kvmppc_xive_esb_rw(XiveSource *xsrc, int srcno, uint32_t offset,
uint64_t data, bool write);
-void kvmppc_xive_set_queue_config(SpaprXive *xive, uint8_t end_blk,
+int kvmppc_xive_set_queue_config(SpaprXive *xive, uint8_t end_blk,
uint32_t end_idx, XiveEND *end,
Error **errp);
-void kvmppc_xive_get_queue_config(SpaprXive *xive, uint8_t end_blk,
+int kvmppc_xive_get_queue_config(SpaprXive *xive, uint8_t end_blk,
uint32_t end_idx, XiveEND *end,
Error **errp);
void kvmppc_xive_synchronize_state(SpaprXive *xive, Error **errp);
diff --git a/include/hw/ppc/vof.h b/include/hw/ppc/vof.h
new file mode 100644
index 0000000000..d3f293da8b
--- /dev/null
+++ b/include/hw/ppc/vof.h
@@ -0,0 +1,65 @@
+/*
+ * Virtual Open Firmware
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef HW_VOF_H
+#define HW_VOF_H
+
+#include "qom/object.h"
+#include "exec/address-spaces.h"
+#include "exec/memory.h"
+#include "exec/cpu-defs.h"
+
+typedef struct Vof {
+ uint64_t top_addr; /* copied from rma_size */
+ GArray *claimed; /* array of SpaprOfClaimed */
+ uint64_t claimed_base;
+ GHashTable *of_instances; /* ihandle -> SpaprOfInstance */
+ uint32_t of_instance_last;
+ char *bootargs;
+ long fw_size;
+} Vof;
+
+int vof_client_call(MachineState *ms, Vof *vof, void *fdt,
+ target_ulong args_real);
+uint64_t vof_claim(Vof *vof, uint64_t virt, uint64_t size, uint64_t align);
+void vof_init(Vof *vof, uint64_t top_addr, Error **errp);
+void vof_cleanup(Vof *vof);
+void vof_build_dt(void *fdt, Vof *vof);
+uint32_t vof_client_open_store(void *fdt, Vof *vof, const char *nodename,
+ const char *prop, const char *path);
+
+#define TYPE_VOF_MACHINE_IF "vof-machine-if"
+
+typedef struct VofMachineIfClass VofMachineIfClass;
+DECLARE_CLASS_CHECKERS(VofMachineIfClass, VOF_MACHINE, TYPE_VOF_MACHINE_IF)
+
+struct VofMachineIfClass {
+ InterfaceClass parent;
+ target_ulong (*client_architecture_support)(MachineState *ms, CPUState *cs,
+ target_ulong vec);
+ void (*quiesce)(MachineState *ms);
+ bool (*setprop)(MachineState *ms, const char *path, const char *propname,
+ void *val, int vallen);
+};
+
+/*
+ * Initial stack size is from
+ * https://www.devicetree.org/open-firmware/bindings/ppc/release/ppc-2_1.html#REF27292
+ *
+ * "Client programs shall be invoked with a valid stack pointer (r1) with
+ * at least 32K bytes of memory available for stack growth".
+ */
+#define VOF_STACK_SIZE 0x8000
+
+#define VOF_MEM_READ(pa, buf, size) \
+ address_space_read(&address_space_memory, \
+ (pa), MEMTXATTRS_UNSPECIFIED, (buf), (size))
+#define VOF_MEM_WRITE(pa, buf, size) \
+ address_space_write(&address_space_memory, \
+ (pa), MEMTXATTRS_UNSPECIFIED, (buf), (size))
+
+#define PROM_ERROR (~0U)
+
+#endif /* HW_VOF_H */
diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
index 9ed58ec7e9..95ead0dd7c 100644
--- a/include/hw/ppc/xics.h
+++ b/include/hw/ppc/xics.h
@@ -30,6 +30,7 @@
#include "exec/memory.h"
#include "hw/qdev-core.h"
+#include "qom/object.h"
#define XICS_IPI 0x2
#define XICS_BUID 0x1
@@ -40,8 +41,6 @@
* (the kernel implementation supports more but we don't exploit
* that yet)
*/
-typedef struct ICPStateClass ICPStateClass;
-typedef struct ICPState ICPState;
typedef struct PnvICPState PnvICPState;
typedef struct ICSStateClass ICSStateClass;
typedef struct ICSState ICSState;
@@ -49,15 +48,13 @@ typedef struct ICSIRQState ICSIRQState;
typedef struct XICSFabric XICSFabric;
#define TYPE_ICP "icp"
-#define ICP(obj) OBJECT_CHECK(ICPState, (obj), TYPE_ICP)
+OBJECT_DECLARE_TYPE(ICPState, ICPStateClass,
+ ICP)
#define TYPE_PNV_ICP "pnv-icp"
-#define PNV_ICP(obj) OBJECT_CHECK(PnvICPState, (obj), TYPE_PNV_ICP)
+DECLARE_INSTANCE_CHECKER(PnvICPState, PNV_ICP,
+ TYPE_PNV_ICP)
-#define ICP_CLASS(klass) \
- OBJECT_CLASS_CHECK(ICPStateClass, (klass), TYPE_ICP)
-#define ICP_GET_CLASS(obj) \
- OBJECT_GET_CLASS(ICPStateClass, (obj), TYPE_ICP)
struct ICPStateClass {
DeviceClass parent_class;
@@ -90,18 +87,15 @@ struct PnvICPState {
};
#define TYPE_ICS "ics"
-#define ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS)
+DECLARE_OBJ_CHECKERS(ICSState, ICSStateClass,
+ ICS, TYPE_ICS)
-#define ICS_CLASS(klass) \
- OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS)
-#define ICS_GET_CLASS(obj) \
- OBJECT_GET_CLASS(ICSStateClass, (obj), TYPE_ICS)
struct ICSStateClass {
DeviceClass parent_class;
DeviceRealize parent_realize;
- DeviceReset parent_reset;
+ ResettablePhases parent_phases;
void (*reject)(ICSState *s, uint32_t irq);
void (*resend)(ICSState *s);
@@ -145,17 +139,16 @@ struct ICSIRQState {
#define TYPE_XICS_FABRIC "xics-fabric"
#define XICS_FABRIC(obj) \
INTERFACE_CHECK(XICSFabric, (obj), TYPE_XICS_FABRIC)
-#define XICS_FABRIC_CLASS(klass) \
- OBJECT_CLASS_CHECK(XICSFabricClass, (klass), TYPE_XICS_FABRIC)
-#define XICS_FABRIC_GET_CLASS(obj) \
- OBJECT_GET_CLASS(XICSFabricClass, (obj), TYPE_XICS_FABRIC)
+typedef struct XICSFabricClass XICSFabricClass;
+DECLARE_CLASS_CHECKERS(XICSFabricClass, XICS_FABRIC,
+ TYPE_XICS_FABRIC)
-typedef struct XICSFabricClass {
+struct XICSFabricClass {
InterfaceClass parent;
ICSState *(*ics_get)(XICSFabric *xi, int irq);
void (*ics_resend)(XICSFabric *xi);
ICPState *(*icp_get)(XICSFabric *xi, int server);
-} XICSFabricClass;
+};
ICPState *xics_icp_get(XICSFabric *xi, int server);
diff --git a/include/hw/ppc/xics_spapr.h b/include/hw/ppc/xics_spapr.h
index 1c65c96e3c..de752c0d2c 100644
--- a/include/hw/ppc/xics_spapr.h
+++ b/include/hw/ppc/xics_spapr.h
@@ -28,13 +28,16 @@
#define XICS_SPAPR_H
#include "hw/ppc/spapr.h"
+#include "qom/object.h"
#define TYPE_ICS_SPAPR "ics-spapr"
-#define ICS_SPAPR(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SPAPR)
+/* This is reusing the ICSState typedef from TYPE_ICS */
+DECLARE_INSTANCE_CHECKER(ICSState, ICS_SPAPR,
+ TYPE_ICS_SPAPR)
int xics_kvm_connect(SpaprInterruptController *intc, uint32_t nr_servers,
Error **errp);
void xics_kvm_disconnect(SpaprInterruptController *intc);
-bool xics_kvm_has_broken_disconnect(SpaprMachineState *spapr);
+bool xics_kvm_has_broken_disconnect(void);
#endif /* XICS_SPAPR_H */
diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h
index 705cf48176..f120874e0f 100644
--- a/include/hw/ppc/xive.h
+++ b/include/hw/ppc/xive.h
@@ -143,6 +143,7 @@
#include "sysemu/kvm.h"
#include "hw/sysbus.h"
#include "hw/ppc/xive_regs.h"
+#include "qom/object.h"
/*
* XIVE Notifier (Interface between Source and Router)
@@ -153,22 +154,21 @@ typedef struct XiveNotifier XiveNotifier;
#define TYPE_XIVE_NOTIFIER "xive-notifier"
#define XIVE_NOTIFIER(obj) \
INTERFACE_CHECK(XiveNotifier, (obj), TYPE_XIVE_NOTIFIER)
-#define XIVE_NOTIFIER_CLASS(klass) \
- OBJECT_CLASS_CHECK(XiveNotifierClass, (klass), TYPE_XIVE_NOTIFIER)
-#define XIVE_NOTIFIER_GET_CLASS(obj) \
- OBJECT_GET_CLASS(XiveNotifierClass, (obj), TYPE_XIVE_NOTIFIER)
+typedef struct XiveNotifierClass XiveNotifierClass;
+DECLARE_CLASS_CHECKERS(XiveNotifierClass, XIVE_NOTIFIER,
+ TYPE_XIVE_NOTIFIER)
-typedef struct XiveNotifierClass {
+struct XiveNotifierClass {
InterfaceClass parent;
- void (*notify)(XiveNotifier *xn, uint32_t lisn);
-} XiveNotifierClass;
+ void (*notify)(XiveNotifier *xn, uint32_t lisn, bool pq_checked);
+};
/*
* XIVE Interrupt Source
*/
#define TYPE_XIVE_SOURCE "xive-source"
-#define XIVE_SOURCE(obj) OBJECT_CHECK(XiveSource, (obj), TYPE_XIVE_SOURCE)
+OBJECT_DECLARE_SIMPLE_TYPE(XiveSource, XIVE_SOURCE)
/*
* XIVE Interrupt Source characteristics, which define how the ESB are
@@ -176,8 +176,9 @@ typedef struct XiveNotifierClass {
*/
#define XIVE_SRC_H_INT_ESB 0x1 /* ESB managed with hcall H_INT_ESB */
#define XIVE_SRC_STORE_EOI 0x2 /* Store EOI supported */
+#define XIVE_SRC_PQ_DISABLE 0x4 /* Disable check on the PQ state bits */
-typedef struct XiveSource {
+struct XiveSource {
DeviceState parent;
/* IRQs */
@@ -186,18 +187,20 @@ typedef struct XiveSource {
/* PQ bits and LSI assertion bit */
uint8_t *status;
+ uint8_t reset_pq; /* PQ state on reset */
/* ESB memory region */
uint64_t esb_flags;
uint32_t esb_shift;
MemoryRegion esb_mmio;
+ MemoryRegion esb_mmio_emulated;
/* KVM support */
void *esb_mmap;
MemoryRegion esb_mmio_kvm;
XiveNotifier *xive;
-} XiveSource;
+};
/*
* ESB MMIO setting. Can be one page, for both source triggering and
@@ -215,6 +218,11 @@ static inline bool xive_source_esb_has_2page(XiveSource *xsrc)
xsrc->esb_shift == XIVE_ESB_4K_2PAGE;
}
+static inline size_t xive_source_esb_len(XiveSource *xsrc)
+{
+ return (1ull << xsrc->esb_shift) * xsrc->nr_irqs;
+}
+
/* The trigger page is always the first/even page */
static inline hwaddr xive_source_esb_page(XiveSource *xsrc, uint32_t srcno)
{
@@ -255,6 +263,10 @@ static inline hwaddr xive_source_esb_mgmt(XiveSource *xsrc, int srcno)
#define XIVE_ESB_QUEUED (XIVE_ESB_VAL_P | XIVE_ESB_VAL_Q)
#define XIVE_ESB_OFF XIVE_ESB_VAL_Q
+bool xive_esb_trigger(uint8_t *pq);
+bool xive_esb_eoi(uint8_t *pq);
+uint8_t xive_esb_set(uint8_t *pq, uint8_t value);
+
/*
* "magic" Event State Buffer (ESB) MMIO offsets.
*
@@ -268,6 +280,7 @@ static inline hwaddr xive_source_esb_mgmt(XiveSource *xsrc, int srcno)
#define XIVE_ESB_STORE_EOI 0x400 /* Store */
#define XIVE_ESB_LOAD_EOI 0x000 /* Load */
#define XIVE_ESB_GET 0x800 /* Load */
+#define XIVE_ESB_INJECT 0x800 /* Store */
#define XIVE_ESB_SET_PQ_00 0xc00 /* Load */
#define XIVE_ESB_SET_PQ_01 0xd00 /* Load */
#define XIVE_ESB_SET_PQ_10 0xe00 /* Load */
@@ -276,6 +289,30 @@ static inline hwaddr xive_source_esb_mgmt(XiveSource *xsrc, int srcno)
uint8_t xive_source_esb_get(XiveSource *xsrc, uint32_t srcno);
uint8_t xive_source_esb_set(XiveSource *xsrc, uint32_t srcno, uint8_t pq);
+/*
+ * Source status helpers
+ */
+static inline void xive_source_set_status(XiveSource *xsrc, uint32_t srcno,
+ uint8_t status, bool enable)
+{
+ if (enable) {
+ xsrc->status[srcno] |= status;
+ } else {
+ xsrc->status[srcno] &= ~status;
+ }
+}
+
+static inline void xive_source_set_asserted(XiveSource *xsrc, uint32_t srcno,
+ bool enable)
+{
+ xive_source_set_status(xsrc, srcno, XIVE_STATUS_ASSERTED, enable);
+}
+
+static inline bool xive_source_is_asserted(XiveSource *xsrc, uint32_t srcno)
+{
+ return xsrc->status[srcno] & XIVE_STATUS_ASSERTED;
+}
+
void xive_source_pic_print_info(XiveSource *xsrc, uint32_t offset,
Monitor *mon);
@@ -298,7 +335,7 @@ void xive_source_set_irq(void *opaque, int srcno, int val);
*/
#define TYPE_XIVE_TCTX "xive-tctx"
-#define XIVE_TCTX(obj) OBJECT_CHECK(XiveTCTX, (obj), TYPE_XIVE_TCTX)
+OBJECT_DECLARE_SIMPLE_TYPE(XiveTCTX, XIVE_TCTX)
/*
* XIVE Thread interrupt Management register rings :
@@ -313,7 +350,7 @@ void xive_source_set_irq(void *opaque, int srcno, int val);
typedef struct XivePresenter XivePresenter;
-typedef struct XiveTCTX {
+struct XiveTCTX {
DeviceState parent_obj;
CPUState *cs;
@@ -323,33 +360,38 @@ typedef struct XiveTCTX {
uint8_t regs[XIVE_TM_RING_COUNT * XIVE_TM_RING_SIZE];
XivePresenter *xptr;
-} XiveTCTX;
+};
+
+static inline uint32_t xive_tctx_word2(uint8_t *ring)
+{
+ return *((uint32_t *) &ring[TM_WORD2]);
+}
/*
* XIVE Router
*/
typedef struct XiveFabric XiveFabric;
-typedef struct XiveRouter {
+struct XiveRouter {
SysBusDevice parent;
XiveFabric *xfb;
-} XiveRouter;
+};
#define TYPE_XIVE_ROUTER "xive-router"
-#define XIVE_ROUTER(obj) \
- OBJECT_CHECK(XiveRouter, (obj), TYPE_XIVE_ROUTER)
-#define XIVE_ROUTER_CLASS(klass) \
- OBJECT_CLASS_CHECK(XiveRouterClass, (klass), TYPE_XIVE_ROUTER)
-#define XIVE_ROUTER_GET_CLASS(obj) \
- OBJECT_GET_CLASS(XiveRouterClass, (obj), TYPE_XIVE_ROUTER)
-
-typedef struct XiveRouterClass {
+OBJECT_DECLARE_TYPE(XiveRouter, XiveRouterClass,
+ XIVE_ROUTER)
+
+struct XiveRouterClass {
SysBusDeviceClass parent;
/* XIVE table accessors */
int (*get_eas)(XiveRouter *xrtr, uint8_t eas_blk, uint32_t eas_idx,
XiveEAS *eas);
+ int (*get_pq)(XiveRouter *xrtr, uint8_t eas_blk, uint32_t eas_idx,
+ uint8_t *pq);
+ int (*set_pq)(XiveRouter *xrtr, uint8_t eas_blk, uint32_t eas_idx,
+ uint8_t *pq);
int (*get_end)(XiveRouter *xrtr, uint8_t end_blk, uint32_t end_idx,
XiveEND *end);
int (*write_end)(XiveRouter *xrtr, uint8_t end_blk, uint32_t end_idx,
@@ -359,7 +401,8 @@ typedef struct XiveRouterClass {
int (*write_nvt)(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx,
XiveNVT *nvt, uint8_t word_number);
uint8_t (*get_block_id)(XiveRouter *xrtr);
-} XiveRouterClass;
+ void (*end_notify)(XiveRouter *xrtr, XiveEAS *eas);
+};
int xive_router_get_eas(XiveRouter *xrtr, uint8_t eas_blk, uint32_t eas_idx,
XiveEAS *eas);
@@ -371,7 +414,8 @@ int xive_router_get_nvt(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx,
XiveNVT *nvt);
int xive_router_write_nvt(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx,
XiveNVT *nvt, uint8_t word_number);
-void xive_router_notify(XiveNotifier *xn, uint32_t lisn);
+void xive_router_notify(XiveNotifier *xn, uint32_t lisn, bool pq_checked);
+void xive_router_end_notify(XiveRouter *xrtr, XiveEAS *eas);
/*
* XIVE Presenter
@@ -385,23 +429,30 @@ typedef struct XiveTCTXMatch {
#define TYPE_XIVE_PRESENTER "xive-presenter"
#define XIVE_PRESENTER(obj) \
INTERFACE_CHECK(XivePresenter, (obj), TYPE_XIVE_PRESENTER)
-#define XIVE_PRESENTER_CLASS(klass) \
- OBJECT_CLASS_CHECK(XivePresenterClass, (klass), TYPE_XIVE_PRESENTER)
-#define XIVE_PRESENTER_GET_CLASS(obj) \
- OBJECT_GET_CLASS(XivePresenterClass, (obj), TYPE_XIVE_PRESENTER)
+typedef struct XivePresenterClass XivePresenterClass;
+DECLARE_CLASS_CHECKERS(XivePresenterClass, XIVE_PRESENTER,
+ TYPE_XIVE_PRESENTER)
-typedef struct XivePresenterClass {
+#define XIVE_PRESENTER_GEN1_TIMA_OS 0x1
+
+struct XivePresenterClass {
InterfaceClass parent;
int (*match_nvt)(XivePresenter *xptr, uint8_t format,
uint8_t nvt_blk, uint32_t nvt_idx,
bool cam_ignore, uint8_t priority,
uint32_t logic_serv, XiveTCTXMatch *match);
-} XivePresenterClass;
+ bool (*in_kernel)(const XivePresenter *xptr);
+ uint32_t (*get_config)(XivePresenter *xptr);
+};
int xive_presenter_tctx_match(XivePresenter *xptr, XiveTCTX *tctx,
uint8_t format,
uint8_t nvt_blk, uint32_t nvt_idx,
bool cam_ignore, uint32_t logic_serv);
+bool xive_presenter_notify(XiveFabric *xfb, uint8_t format,
+ uint8_t nvt_blk, uint32_t nvt_idx,
+ bool cam_ignore, uint8_t priority,
+ uint32_t logic_serv);
/*
* XIVE Fabric (Interface between Interrupt Controller and Machine)
@@ -410,28 +461,26 @@ int xive_presenter_tctx_match(XivePresenter *xptr, XiveTCTX *tctx,
#define TYPE_XIVE_FABRIC "xive-fabric"
#define XIVE_FABRIC(obj) \
INTERFACE_CHECK(XiveFabric, (obj), TYPE_XIVE_FABRIC)
-#define XIVE_FABRIC_CLASS(klass) \
- OBJECT_CLASS_CHECK(XiveFabricClass, (klass), TYPE_XIVE_FABRIC)
-#define XIVE_FABRIC_GET_CLASS(obj) \
- OBJECT_GET_CLASS(XiveFabricClass, (obj), TYPE_XIVE_FABRIC)
+typedef struct XiveFabricClass XiveFabricClass;
+DECLARE_CLASS_CHECKERS(XiveFabricClass, XIVE_FABRIC,
+ TYPE_XIVE_FABRIC)
-typedef struct XiveFabricClass {
+struct XiveFabricClass {
InterfaceClass parent;
int (*match_nvt)(XiveFabric *xfb, uint8_t format,
uint8_t nvt_blk, uint32_t nvt_idx,
bool cam_ignore, uint8_t priority,
uint32_t logic_serv, XiveTCTXMatch *match);
-} XiveFabricClass;
+};
/*
* XIVE END ESBs
*/
#define TYPE_XIVE_END_SOURCE "xive-end-source"
-#define XIVE_END_SOURCE(obj) \
- OBJECT_CHECK(XiveENDSource, (obj), TYPE_XIVE_END_SOURCE)
+OBJECT_DECLARE_SIMPLE_TYPE(XiveENDSource, XIVE_END_SOURCE)
-typedef struct XiveENDSource {
+struct XiveENDSource {
DeviceState parent;
uint32_t nr_ends;
@@ -441,7 +490,7 @@ typedef struct XiveENDSource {
MemoryRegion esb_mmio;
XiveRouter *xrtr;
-} XiveENDSource;
+};
/*
* For legacy compatibility, the exceptions define up to 256 different
@@ -451,6 +500,17 @@ typedef struct XiveENDSource {
#define XIVE_PRIORITY_MAX 7
/*
+ * Convert a priority number to an Interrupt Pending Buffer (IPB)
+ * register, which indicates a pending interrupt at the priority
+ * corresponding to the bit number
+ */
+static inline uint8_t xive_priority_to_ipb(uint8_t priority)
+{
+ return priority > XIVE_PRIORITY_MAX ?
+ 0 : 1 << (XIVE_PRIORITY_MAX - priority);
+}
+
+/*
* XIVE Thread Interrupt Management Aera (TIMA)
*
* This region gives access to the registers of the thread interrupt
@@ -473,6 +533,7 @@ Object *xive_tctx_create(Object *cpu, XivePresenter *xptr, Error **errp);
void xive_tctx_reset(XiveTCTX *tctx);
void xive_tctx_destroy(XiveTCTX *tctx);
void xive_tctx_ipb_update(XiveTCTX *tctx, uint8_t ring, uint8_t ipb);
+void xive_tctx_reset_os_signal(XiveTCTX *tctx);
/*
* KVM XIVE device helpers
@@ -480,9 +541,9 @@ void xive_tctx_ipb_update(XiveTCTX *tctx, uint8_t ring, uint8_t ipb);
int kvmppc_xive_source_reset_one(XiveSource *xsrc, int srcno, Error **errp);
void kvmppc_xive_source_set_irq(void *opaque, int srcno, int val);
-void kvmppc_xive_cpu_connect(XiveTCTX *tctx, Error **errp);
-void kvmppc_xive_cpu_synchronize_state(XiveTCTX *tctx, Error **errp);
-void kvmppc_xive_cpu_get_state(XiveTCTX *tctx, Error **errp);
-void kvmppc_xive_cpu_set_state(XiveTCTX *tctx, Error **errp);
+int kvmppc_xive_cpu_connect(XiveTCTX *tctx, Error **errp);
+int kvmppc_xive_cpu_synchronize_state(XiveTCTX *tctx, Error **errp);
+int kvmppc_xive_cpu_get_state(XiveTCTX *tctx, Error **errp);
+int kvmppc_xive_cpu_set_state(XiveTCTX *tctx, Error **errp);
#endif /* PPC_XIVE_H */
diff --git a/include/hw/ppc/xive2.h b/include/hw/ppc/xive2.h
new file mode 100644
index 0000000000..ab68f8d157
--- /dev/null
+++ b/include/hw/ppc/xive2.h
@@ -0,0 +1,111 @@
+/*
+ * QEMU PowerPC XIVE2 interrupt controller model (POWER10)
+ *
+ * Copyright (c) 2019-2022, IBM Corporation.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef PPC_XIVE2_H
+#define PPC_XIVE2_H
+
+#include "hw/ppc/xive.h"
+#include "hw/ppc/xive2_regs.h"
+#include "hw/sysbus.h"
+
+/*
+ * XIVE2 Router (POWER10)
+ */
+typedef struct Xive2Router {
+ SysBusDevice parent;
+
+ XiveFabric *xfb;
+} Xive2Router;
+
+#define TYPE_XIVE2_ROUTER "xive2-router"
+OBJECT_DECLARE_TYPE(Xive2Router, Xive2RouterClass, XIVE2_ROUTER);
+
+/*
+ * Configuration flags
+ */
+
+#define XIVE2_GEN1_TIMA_OS 0x00000001
+#define XIVE2_VP_SAVE_RESTORE 0x00000002
+#define XIVE2_THREADID_8BITS 0x00000004
+
+typedef struct Xive2RouterClass {
+ SysBusDeviceClass parent;
+
+ /* XIVE table accessors */
+ int (*get_eas)(Xive2Router *xrtr, uint8_t eas_blk, uint32_t eas_idx,
+ Xive2Eas *eas);
+ int (*get_pq)(Xive2Router *xrtr, uint8_t eas_blk, uint32_t eas_idx,
+ uint8_t *pq);
+ int (*set_pq)(Xive2Router *xrtr, uint8_t eas_blk, uint32_t eas_idx,
+ uint8_t *pq);
+ int (*get_end)(Xive2Router *xrtr, uint8_t end_blk, uint32_t end_idx,
+ Xive2End *end);
+ int (*write_end)(Xive2Router *xrtr, uint8_t end_blk, uint32_t end_idx,
+ Xive2End *end, uint8_t word_number);
+ int (*get_nvp)(Xive2Router *xrtr, uint8_t nvp_blk, uint32_t nvp_idx,
+ Xive2Nvp *nvp);
+ int (*write_nvp)(Xive2Router *xrtr, uint8_t nvp_blk, uint32_t nvp_idx,
+ Xive2Nvp *nvp, uint8_t word_number);
+ uint8_t (*get_block_id)(Xive2Router *xrtr);
+ uint32_t (*get_config)(Xive2Router *xrtr);
+} Xive2RouterClass;
+
+int xive2_router_get_eas(Xive2Router *xrtr, uint8_t eas_blk, uint32_t eas_idx,
+ Xive2Eas *eas);
+int xive2_router_get_end(Xive2Router *xrtr, uint8_t end_blk, uint32_t end_idx,
+ Xive2End *end);
+int xive2_router_write_end(Xive2Router *xrtr, uint8_t end_blk, uint32_t end_idx,
+ Xive2End *end, uint8_t word_number);
+int xive2_router_get_nvp(Xive2Router *xrtr, uint8_t nvp_blk, uint32_t nvp_idx,
+ Xive2Nvp *nvp);
+int xive2_router_write_nvp(Xive2Router *xrtr, uint8_t nvp_blk, uint32_t nvp_idx,
+ Xive2Nvp *nvp, uint8_t word_number);
+uint32_t xive2_router_get_config(Xive2Router *xrtr);
+
+void xive2_router_notify(XiveNotifier *xn, uint32_t lisn, bool pq_checked);
+
+/*
+ * XIVE2 Presenter (POWER10)
+ */
+
+int xive2_presenter_tctx_match(XivePresenter *xptr, XiveTCTX *tctx,
+ uint8_t format,
+ uint8_t nvt_blk, uint32_t nvt_idx,
+ bool cam_ignore, uint32_t logic_serv);
+
+/*
+ * XIVE2 END ESBs (POWER10)
+ */
+
+#define TYPE_XIVE2_END_SOURCE "xive2-end-source"
+OBJECT_DECLARE_SIMPLE_TYPE(Xive2EndSource, XIVE2_END_SOURCE)
+
+typedef struct Xive2EndSource {
+ DeviceState parent;
+
+ uint32_t nr_ends;
+
+ /* ESB memory region */
+ uint32_t esb_shift;
+ MemoryRegion esb_mmio;
+
+ Xive2Router *xrtr;
+} Xive2EndSource;
+
+/*
+ * XIVE2 Thread Interrupt Management Area (POWER10)
+ */
+
+void xive2_tm_push_os_ctx(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset,
+ uint64_t value, unsigned size);
+uint64_t xive2_tm_pull_os_ctx(XivePresenter *xptr, XiveTCTX *tctx,
+ hwaddr offset, unsigned size);
+
+#endif /* PPC_XIVE2_H */
diff --git a/include/hw/ppc/xive2_regs.h b/include/hw/ppc/xive2_regs.h
new file mode 100644
index 0000000000..816f5d0e84
--- /dev/null
+++ b/include/hw/ppc/xive2_regs.h
@@ -0,0 +1,212 @@
+/*
+ * QEMU PowerPC XIVE2 internal structure definitions (POWER10)
+ *
+ * Copyright (c) 2019-2022, IBM Corporation.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+
+#ifndef PPC_XIVE2_REGS_H
+#define PPC_XIVE2_REGS_H
+
+#include "qemu/bswap.h"
+
+/*
+ * Thread Interrupt Management Area (TIMA)
+ *
+ * In Gen1 mode (P9 compat mode) word 2 is the same. However in Gen2
+ * mode (P10), the CAM line is slightly different as the VP space was
+ * increased.
+ */
+#define TM2_QW0W2_VU PPC_BIT32(0)
+#define TM2_QW0W2_LOGIC_SERV PPC_BITMASK32(4, 31)
+#define TM2_QW1W2_VO PPC_BIT32(0)
+#define TM2_QW1W2_HO PPC_BIT32(1)
+#define TM2_QW1W2_OS_CAM PPC_BITMASK32(4, 31)
+#define TM2_QW2W2_VP PPC_BIT32(0)
+#define TM2_QW2W2_HP PPC_BIT32(1)
+#define TM2_QW2W2_POOL_CAM PPC_BITMASK32(4, 31)
+#define TM2_QW3W2_VT PPC_BIT32(0)
+#define TM2_QW3W2_HT PPC_BIT32(1)
+#define TM2_QW3W2_LP PPC_BIT32(6)
+#define TM2_QW3W2_LE PPC_BIT32(7)
+
+/*
+ * Event Assignment Structure (EAS)
+ */
+
+typedef struct Xive2Eas {
+ uint64_t w;
+#define EAS2_VALID PPC_BIT(0)
+#define EAS2_END_BLOCK PPC_BITMASK(4, 7) /* Destination EQ block# */
+#define EAS2_END_INDEX PPC_BITMASK(8, 31) /* Destination EQ index */
+#define EAS2_MASKED PPC_BIT(32) /* Masked */
+#define EAS2_END_DATA PPC_BITMASK(33, 63) /* written to the EQ */
+} Xive2Eas;
+
+#define xive2_eas_is_valid(eas) (be64_to_cpu((eas)->w) & EAS2_VALID)
+#define xive2_eas_is_masked(eas) (be64_to_cpu((eas)->w) & EAS2_MASKED)
+
+void xive2_eas_pic_print_info(Xive2Eas *eas, uint32_t lisn, Monitor *mon);
+
+/*
+ * Event Notifification Descriptor (END)
+ */
+
+typedef struct Xive2End {
+ uint32_t w0;
+#define END2_W0_VALID PPC_BIT32(0) /* "v" bit */
+#define END2_W0_ENQUEUE PPC_BIT32(5) /* "q" bit */
+#define END2_W0_UCOND_NOTIFY PPC_BIT32(6) /* "n" bit */
+#define END2_W0_SILENT_ESCALATE PPC_BIT32(7) /* "s" bit */
+#define END2_W0_BACKLOG PPC_BIT32(8) /* "b" bit */
+#define END2_W0_PRECL_ESC_CTL PPC_BIT32(9) /* "p" bit */
+#define END2_W0_UNCOND_ESCALATE PPC_BIT32(10) /* "u" bit */
+#define END2_W0_ESCALATE_CTL PPC_BIT32(11) /* "e" bit */
+#define END2_W0_ADAPTIVE_ESC PPC_BIT32(12) /* "a" bit */
+#define END2_W0_ESCALATE_END PPC_BIT32(13) /* "N" bit */
+#define END2_W0_FIRMWARE1 PPC_BIT32(16) /* Owned by FW */
+#define END2_W0_FIRMWARE2 PPC_BIT32(17) /* Owned by FW */
+#define END2_W0_AEC_SIZE PPC_BITMASK32(18, 19)
+#define END2_W0_AEG_SIZE PPC_BITMASK32(20, 23)
+#define END2_W0_EQ_VG_PREDICT PPC_BITMASK32(24, 31) /* Owned by HW */
+ uint32_t w1;
+#define END2_W1_ESn PPC_BITMASK32(0, 1)
+#define END2_W1_ESn_P PPC_BIT32(0)
+#define END2_W1_ESn_Q PPC_BIT32(1)
+#define END2_W1_ESe PPC_BITMASK32(2, 3)
+#define END2_W1_ESe_P PPC_BIT32(2)
+#define END2_W1_ESe_Q PPC_BIT32(3)
+#define END2_W1_GEN_FLIPPED PPC_BIT32(8)
+#define END2_W1_GENERATION PPC_BIT32(9)
+#define END2_W1_PAGE_OFF PPC_BITMASK32(10, 31)
+ uint32_t w2;
+#define END2_W2_RESERVED PPC_BITMASK32(4, 7)
+#define END2_W2_EQ_ADDR_HI PPC_BITMASK32(8, 31)
+ uint32_t w3;
+#define END2_W3_EQ_ADDR_LO PPC_BITMASK32(0, 24)
+#define END2_W3_QSIZE PPC_BITMASK32(28, 31)
+ uint32_t w4;
+#define END2_W4_END_BLOCK PPC_BITMASK32(4, 7)
+#define END2_W4_ESC_END_INDEX PPC_BITMASK32(8, 31)
+#define END2_W4_ESB_BLOCK PPC_BITMASK32(0, 3)
+#define END2_W4_ESC_ESB_INDEX PPC_BITMASK32(4, 31)
+ uint32_t w5;
+#define END2_W5_ESC_END_DATA PPC_BITMASK32(1, 31)
+ uint32_t w6;
+#define END2_W6_FORMAT_BIT PPC_BIT32(0)
+#define END2_W6_IGNORE PPC_BIT32(1)
+#define END2_W6_VP_BLOCK PPC_BITMASK32(4, 7)
+#define END2_W6_VP_OFFSET PPC_BITMASK32(8, 31)
+#define END2_W6_VP_OFFSET_GEN1 PPC_BITMASK32(13, 31)
+ uint32_t w7;
+#define END2_W7_TOPO PPC_BITMASK32(0, 3) /* Owned by HW */
+#define END2_W7_F0_PRIORITY PPC_BITMASK32(8, 15)
+#define END2_W7_F1_LOG_SERVER_ID PPC_BITMASK32(4, 31)
+} Xive2End;
+
+#define xive2_end_is_valid(end) (be32_to_cpu((end)->w0) & END2_W0_VALID)
+#define xive2_end_is_enqueue(end) (be32_to_cpu((end)->w0) & END2_W0_ENQUEUE)
+#define xive2_end_is_notify(end) \
+ (be32_to_cpu((end)->w0) & END2_W0_UCOND_NOTIFY)
+#define xive2_end_is_backlog(end) (be32_to_cpu((end)->w0) & END2_W0_BACKLOG)
+#define xive2_end_is_escalate(end) \
+ (be32_to_cpu((end)->w0) & END2_W0_ESCALATE_CTL)
+#define xive2_end_is_uncond_escalation(end) \
+ (be32_to_cpu((end)->w0) & END2_W0_UNCOND_ESCALATE)
+#define xive2_end_is_silent_escalation(end) \
+ (be32_to_cpu((end)->w0) & END2_W0_SILENT_ESCALATE)
+#define xive2_end_is_escalate_end(end) \
+ (be32_to_cpu((end)->w0) & END2_W0_ESCALATE_END)
+#define xive2_end_is_firmware1(end) \
+ (be32_to_cpu((end)->w0) & END2_W0_FIRMWARE1)
+#define xive2_end_is_firmware2(end) \
+ (be32_to_cpu((end)->w0) & END2_W0_FIRMWARE2)
+
+static inline uint64_t xive2_end_qaddr(Xive2End *end)
+{
+ return ((uint64_t) be32_to_cpu(end->w2) & END2_W2_EQ_ADDR_HI) << 32 |
+ (be32_to_cpu(end->w3) & END2_W3_EQ_ADDR_LO);
+}
+
+void xive2_end_pic_print_info(Xive2End *end, uint32_t end_idx, Monitor *mon);
+void xive2_end_queue_pic_print_info(Xive2End *end, uint32_t width,
+ Monitor *mon);
+void xive2_end_eas_pic_print_info(Xive2End *end, uint32_t end_idx,
+ Monitor *mon);
+
+/*
+ * Notification Virtual Processor (NVP)
+ */
+typedef struct Xive2Nvp {
+ uint32_t w0;
+#define NVP2_W0_VALID PPC_BIT32(0)
+#define NVP2_W0_HW PPC_BIT32(7)
+#define NVP2_W0_ESC_END PPC_BIT32(25) /* 'N' bit 0:ESB 1:END */
+ uint32_t w1;
+#define NVP2_W1_CO PPC_BIT32(13)
+#define NVP2_W1_CO_PRIV PPC_BITMASK32(14, 15)
+#define NVP2_W1_CO_THRID_VALID PPC_BIT32(16)
+#define NVP2_W1_CO_THRID PPC_BITMASK32(17, 31)
+ uint32_t w2;
+#define NVP2_W2_CPPR PPC_BITMASK32(0, 7)
+#define NVP2_W2_IPB PPC_BITMASK32(8, 15)
+#define NVP2_W2_LSMFB PPC_BITMASK32(16, 23)
+ uint32_t w3;
+ uint32_t w4;
+#define NVP2_W4_ESC_ESB_BLOCK PPC_BITMASK32(0, 3) /* N:0 */
+#define NVP2_W4_ESC_ESB_INDEX PPC_BITMASK32(4, 31) /* N:0 */
+#define NVP2_W4_ESC_END_BLOCK PPC_BITMASK32(4, 7) /* N:1 */
+#define NVP2_W4_ESC_END_INDEX PPC_BITMASK32(8, 31) /* N:1 */
+ uint32_t w5;
+#define NVP2_W5_PSIZE PPC_BITMASK32(0, 1)
+#define NVP2_W5_VP_END_BLOCK PPC_BITMASK32(4, 7)
+#define NVP2_W5_VP_END_INDEX PPC_BITMASK32(8, 31)
+ uint32_t w6;
+ uint32_t w7;
+} Xive2Nvp;
+
+#define xive2_nvp_is_valid(nvp) (be32_to_cpu((nvp)->w0) & NVP2_W0_VALID)
+#define xive2_nvp_is_hw(nvp) (be32_to_cpu((nvp)->w0) & NVP2_W0_HW)
+#define xive2_nvp_is_co(nvp) (be32_to_cpu((nvp)->w1) & NVP2_W1_CO)
+
+/*
+ * The VP number space in a block is defined by the END2_W6_VP_OFFSET
+ * field of the XIVE END. When running in Gen1 mode (P9 compat mode),
+ * the VP space is reduced to (1 << 19) VPs per block
+ */
+#define XIVE2_NVP_SHIFT 24
+#define XIVE2_NVP_COUNT (1 << XIVE2_NVP_SHIFT)
+
+static inline uint32_t xive2_nvp_cam_line(uint8_t nvp_blk, uint32_t nvp_idx)
+{
+ return (nvp_blk << XIVE2_NVP_SHIFT) | nvp_idx;
+}
+
+static inline uint32_t xive2_nvp_idx(uint32_t cam_line)
+{
+ return cam_line & ((1 << XIVE2_NVP_SHIFT) - 1);
+}
+
+static inline uint32_t xive2_nvp_blk(uint32_t cam_line)
+{
+ return (cam_line >> XIVE2_NVP_SHIFT) & 0xf;
+}
+
+/*
+ * Notification Virtual Group or Crowd (NVG/NVC)
+ */
+typedef struct Xive2Nvgc {
+ uint32_t w0;
+#define NVGC2_W0_VALID PPC_BIT32(0)
+ uint32_t w1;
+ uint32_t w2;
+ uint32_t w3;
+ uint32_t w4;
+ uint32_t w5;
+ uint32_t w6;
+ uint32_t w7;
+} Xive2Nvgc;
+
+#endif /* PPC_XIVE2_REGS_H */
diff --git a/include/hw/ppc/xive_regs.h b/include/hw/ppc/xive_regs.h
index 7879692825..4a3c9badd3 100644
--- a/include/hw/ppc/xive_regs.h
+++ b/include/hw/ppc/xive_regs.h
@@ -48,6 +48,22 @@
#define TM_SHIFT 16
+/*
+ * TIMA addresses are 12-bits (4k page).
+ * The MSB indicates a special op with side effect, which can be
+ * refined with bit 10 (see below).
+ * The registers, logically grouped in 4 rings (a quad-word each), are
+ * defined on the 6 LSBs (offset below 0x40)
+ * In between, we can add a cache line index from 0...3 (ie, 0, 0x80,
+ * 0x100, 0x180) to select a specific snooper. Those 'snoop port
+ * address' bits should be dropped when processing the operations as
+ * they are all equivalent.
+ */
+#define TM_ADDRESS_MASK 0xC3F
+#define TM_SPECIAL_OP 0x800
+#define TM_RING_OFFSET 0x30
+#define TM_REG_OFFSET 0x3F
+
/* TM register offsets */
#define TM_QW0_USER 0x000 /* All rings */
#define TM_QW1_OS 0x010 /* Ring 0..2 */
@@ -236,6 +252,8 @@ typedef struct XiveEND {
(be32_to_cpu((end)->w0) & END_W0_UNCOND_ESCALATE)
#define xive_end_is_silent_escalation(end) \
(be32_to_cpu((end)->w0) & END_W0_SILENT_ESCALATE)
+#define xive_end_is_firmware(end) \
+ (be32_to_cpu((end)->w0) & END_W0_FIRMWARE)
static inline uint64_t xive_end_qaddr(XiveEND *end)
{
diff --git a/include/hw/ptimer.h b/include/hw/ptimer.h
index 412763fffb..4dc02b0de4 100644
--- a/include/hw/ptimer.h
+++ b/include/hw/ptimer.h
@@ -33,9 +33,17 @@
* to stderr when the guest attempts to enable the timer.
*/
-/* The default ptimer policy retains backward compatibility with the legacy
- * timers. Custom policies are adjusting the default one. Consider providing
- * a correct policy for your timer.
+/*
+ * The 'legacy' ptimer policy retains backward compatibility with the
+ * traditional ptimer behaviour from before policy flags were introduced.
+ * It has several weird behaviours which don't match typical hardware
+ * timer behaviour. For a new device using ptimers, you should not
+ * use PTIMER_POLICY_LEGACY, but instead check the actual behaviour
+ * that you need and specify the right set of policy flags to get that.
+ *
+ * If you are overhauling an existing device that uses PTIMER_POLICY_LEGACY
+ * and are in a position to check or test the real hardware behaviour,
+ * consider updating it to specify the right policy flags.
*
* The rough edges of the default policy:
* - Starting to run with a period = 0 emits error message and stops the
@@ -54,7 +62,7 @@
* since the last period, effectively restarting the timer with a
* counter = counter value at the moment of change (.i.e. one less).
*/
-#define PTIMER_POLICY_DEFAULT 0
+#define PTIMER_POLICY_LEGACY 0
/* Periodic timer counter stays with "0" for a one period before wrapping
* around. */
@@ -166,6 +174,28 @@ void ptimer_transaction_commit(ptimer_state *s);
void ptimer_set_period(ptimer_state *s, int64_t period);
/**
+ * ptimer_set_period_from_clock - Set counter increment from a Clock
+ * @s: ptimer to configure
+ * @clk: pointer to Clock object to take period from
+ * @divisor: value to scale the clock frequency down by
+ *
+ * If the ptimer is being driven from a Clock, this is the preferred
+ * way to tell the ptimer about the period, because it avoids any
+ * possible rounding errors that might happen if the internal
+ * representation of the Clock period was converted to either a period
+ * in ns or a frequency in Hz.
+ *
+ * If the ptimer should run at the same frequency as the clock,
+ * pass 1 as the @divisor; if the ptimer should run at half the
+ * frequency, pass 2, and so on.
+ *
+ * This function will assert if it is called outside a
+ * ptimer_transaction_begin/commit block.
+ */
+void ptimer_set_period_from_clock(ptimer_state *s, const Clock *clock,
+ unsigned int divisor);
+
+/**
* ptimer_set_freq - Set counter frequency in Hz
* @s: ptimer to configure
* @freq: counter frequency in Hz
diff --git a/include/hw/qdev-clock.h b/include/hw/qdev-clock.h
index a340f65ff9..ffa0f7ba09 100644
--- a/include/hw/qdev-clock.h
+++ b/include/hw/qdev-clock.h
@@ -22,6 +22,8 @@
* @name: the name of the clock (can't be NULL).
* @callback: optional callback to be called on update or NULL.
* @opaque: argument for the callback
+ * @events: the events the callback should be called for
+ * (logical OR of ClockEvent enum values)
* @returns: a pointer to the newly added clock
*
* Add an input clock to device @dev as a clock named @name.
@@ -29,7 +31,8 @@
* The callback will be called with @opaque as opaque parameter.
*/
Clock *qdev_init_clock_in(DeviceState *dev, const char *name,
- ClockCallback *callback, void *opaque);
+ ClockCallback *callback, void *opaque,
+ unsigned int events);
/**
* qdev_init_clock_out:
@@ -70,12 +73,10 @@ Clock *qdev_get_clock_out(DeviceState *dev, const char *name);
*
* Set the source clock of input clock @name of device @dev to @source.
* @source period update will be propagated to @name clock.
+ *
+ * Must be called before @dev is realized.
*/
-static inline void qdev_connect_clock_in(DeviceState *dev, const char *name,
- Clock *source)
-{
- clock_set_source(qdev_get_clock_in(dev, name), source);
-}
+void qdev_connect_clock_in(DeviceState *dev, const char *name, Clock *source);
/**
* qdev_alias_clock:
@@ -107,6 +108,7 @@ void qdev_finalize_clocklist(DeviceState *dev);
* @output: indicates whether the clock is input or output
* @callback: for inputs, optional callback to be called on clock's update
* with device as opaque
+ * @callback_events: mask of ClockEvent values for when callback is called
* @offset: optional offset to store the ClockIn or ClockOut pointer in device
* state structure (0 means unused)
*/
@@ -114,6 +116,7 @@ struct ClockPortInitElem {
const char *name;
bool is_output;
ClockCallback *callback;
+ unsigned int callback_events;
size_t offset;
};
@@ -121,10 +124,11 @@ struct ClockPortInitElem {
(offsetof(devstate, field) + \
type_check(Clock *, typeof_field(devstate, field)))
-#define QDEV_CLOCK(out_not_in, devstate, field, cb) { \
+#define QDEV_CLOCK(out_not_in, devstate, field, cb, cbevents) { \
.name = (stringify(field)), \
.is_output = out_not_in, \
.callback = cb, \
+ .callback_events = cbevents, \
.offset = clock_offset_value(devstate, field), \
}
@@ -135,14 +139,15 @@ struct ClockPortInitElem {
* @field: a field in @_devstate (must be Clock*)
* @callback: (for input only) callback (or NULL) to be called with the device
* state as argument
+ * @cbevents: (for input only) ClockEvent mask for when callback is called
*
* The name of the clock will be derived from @field
*/
-#define QDEV_CLOCK_IN(devstate, field, callback) \
- QDEV_CLOCK(false, devstate, field, callback)
+#define QDEV_CLOCK_IN(devstate, field, callback, cbevents) \
+ QDEV_CLOCK(false, devstate, field, callback, cbevents)
#define QDEV_CLOCK_OUT(devstate, field) \
- QDEV_CLOCK(true, devstate, field, NULL)
+ QDEV_CLOCK(true, devstate, field, NULL, 0)
#define QDEV_CLOCK_END { .name = NULL }
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index ea3f73a282..9228e96c87 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -1,20 +1,80 @@
#ifndef QDEV_CORE_H
#define QDEV_CORE_H
+#include "qemu/atomic.h"
#include "qemu/queue.h"
#include "qemu/bitmap.h"
+#include "qemu/rcu.h"
+#include "qemu/rcu_queue.h"
#include "qom/object.h"
#include "hw/hotplug.h"
#include "hw/resettable.h"
+/**
+ * DOC: The QEMU Device API
+ *
+ * All modern devices should represented as a derived QOM class of
+ * TYPE_DEVICE. The device API introduces the additional methods of
+ * @realize and @unrealize to represent additional stages in a device
+ * objects life cycle.
+ *
+ * Realization
+ * -----------
+ *
+ * Devices are constructed in two stages:
+ *
+ * 1) object instantiation via object_initialize() and
+ * 2) device realization via the #DeviceState.realized property
+ *
+ * The former may not fail (and must not abort or exit, since it is called
+ * during device introspection already), and the latter may return error
+ * information to the caller and must be re-entrant.
+ * Trivial field initializations should go into #TypeInfo.instance_init.
+ * Operations depending on @props static properties should go into @realize.
+ * After successful realization, setting static properties will fail.
+ *
+ * As an interim step, the #DeviceState.realized property can also be
+ * set with qdev_realize(). In the future, devices will propagate this
+ * state change to their children and along busses they expose. The
+ * point in time will be deferred to machine creation, so that values
+ * set in @realize will not be introspectable beforehand. Therefore
+ * devices must not create children during @realize; they should
+ * initialize them via object_initialize() in their own
+ * #TypeInfo.instance_init and forward the realization events
+ * appropriately.
+ *
+ * Any type may override the @realize and/or @unrealize callbacks but needs
+ * to call the parent type's implementation if keeping their functionality
+ * is desired. Refer to QOM documentation for further discussion and examples.
+ *
+ * .. note::
+ * Since TYPE_DEVICE doesn't implement @realize and @unrealize, types
+ * derived directly from it need not call their parent's @realize and
+ * @unrealize. For other types consult the documentation and
+ * implementation of the respective parent types.
+ *
+ * Hiding a device
+ * ---------------
+ *
+ * To hide a device, a DeviceListener function hide_device() needs to
+ * be registered. It can be used to defer adding a device and
+ * therefore hide it from the guest. The handler registering to this
+ * DeviceListener can save the QOpts passed to it for re-using it
+ * later. It must return if it wants the device to be hidden or
+ * visible. When the handler function decides the device shall be
+ * visible it will be added with qdev_device_add() and realized as any
+ * other device. Otherwise qdev_device_add() will return early without
+ * adding the device. The guest will not see a "hidden" device until
+ * it was marked visible and qdev_device_add called again.
+ *
+ */
+
enum {
DEV_NVECTORS_UNSPECIFIED = -1,
};
#define TYPE_DEVICE "device"
-#define DEVICE(obj) OBJECT_CHECK(DeviceState, (obj), TYPE_DEVICE)
-#define DEVICE_CLASS(klass) OBJECT_CLASS_CHECK(DeviceClass, (klass), TYPE_DEVICE)
-#define DEVICE_GET_CLASS(obj) OBJECT_GET_CLASS(DeviceClass, (obj), TYPE_DEVICE)
+OBJECT_DECLARE_TYPE(DeviceState, DeviceClass, DEVICE)
typedef enum DeviceCategory {
DEVICE_CATEGORY_BRIDGE,
@@ -26,6 +86,7 @@ typedef enum DeviceCategory {
DEVICE_CATEGORY_SOUND,
DEVICE_CATEGORY_MISC,
DEVICE_CATEGORY_CPU,
+ DEVICE_CATEGORY_WATCHDOG,
DEVICE_CATEGORY_MAX
} DeviceCategory;
@@ -36,7 +97,7 @@ typedef void (*BusRealize)(BusState *bus, Error **errp);
typedef void (*BusUnrealize)(BusState *bus);
/**
- * DeviceClass:
+ * struct DeviceClass - The base class for all devices.
* @props: Properties accessing state fields.
* @realize: Callback function invoked when the #DeviceState:realized
* property is changed to %true.
@@ -45,71 +106,37 @@ typedef void (*BusUnrealize)(BusState *bus);
* @hotpluggable: indicates if #DeviceClass is hotpluggable, available
* as readonly "hotpluggable" property of #DeviceState instance
*
- * # Realization #
- * Devices are constructed in two stages,
- * 1) object instantiation via object_initialize() and
- * 2) device realization via #DeviceState:realized property.
- * The former may not fail (and must not abort or exit, since it is called
- * during device introspection already), and the latter may return error
- * information to the caller and must be re-entrant.
- * Trivial field initializations should go into #TypeInfo.instance_init.
- * Operations depending on @props static properties should go into @realize.
- * After successful realization, setting static properties will fail.
- *
- * As an interim step, the #DeviceState:realized property can also be
- * set with qdev_realize().
- * In the future, devices will propagate this state change to their children
- * and along busses they expose.
- * The point in time will be deferred to machine creation, so that values
- * set in @realize will not be introspectable beforehand. Therefore devices
- * must not create children during @realize; they should initialize them via
- * object_initialize() in their own #TypeInfo.instance_init and forward the
- * realization events appropriately.
- *
- * Any type may override the @realize and/or @unrealize callbacks but needs
- * to call the parent type's implementation if keeping their functionality
- * is desired. Refer to QOM documentation for further discussion and examples.
- *
- * <note>
- * <para>
- * Since TYPE_DEVICE doesn't implement @realize and @unrealize, types
- * derived directly from it need not call their parent's @realize and
- * @unrealize.
- * For other types consult the documentation and implementation of the
- * respective parent types.
- * </para>
- * </note>
- *
- * # Hiding a device #
- * To hide a device, a DeviceListener function should_be_hidden() needs to
- * be registered.
- * It can be used to defer adding a device and therefore hide it from the
- * guest. The handler registering to this DeviceListener can save the QOpts
- * passed to it for re-using it later and must return that it wants the device
- * to be/remain hidden or not. When the handler function decides the device
- * shall not be hidden it will be added in qdev_device_add() and
- * realized as any other device. Otherwise qdev_device_add() will return early
- * without adding the device. The guest will not see a "hidden" device
- * until it was marked don't hide and qdev_device_add called again.
- *
- */
-typedef struct DeviceClass {
- /*< private >*/
+ */
+struct DeviceClass {
+ /* private: */
ObjectClass parent_class;
- /*< public >*/
+ /* public: */
+
+ /**
+ * @categories: device categories device belongs to
+ */
DECLARE_BITMAP(categories, DEVICE_CATEGORY_MAX);
+ /**
+ * @fw_name: name used to identify device to firmware interfaces
+ */
const char *fw_name;
+ /**
+ * @desc: human readable description of device
+ */
const char *desc;
- /*
- * The underscore at the end ensures a compile-time error if someone
- * assigns to dc->props instead of using device_class_set_props.
+ /**
+ * @props_: properties associated with device, should only be
+ * assigned by using device_class_set_props(). The underscore
+ * ensures a compile-time error if someone attempts to assign
+ * dc->props directly.
*/
Property *props_;
- /*
- * Can this device be instantiated with -device / device_add?
+ /**
+ * @user_creatable: Can user instantiate with -device / device_add?
+ *
* All devices should support instantiation with device_add, and
* this flag should not exist. But we're not there, yet. Some
* devices fail to instantiate with cryptic error messages.
@@ -117,27 +144,37 @@ typedef struct DeviceClass {
* behavior would be cruel; clearing this flag will protect them.
* It should never be cleared without a comment explaining why it
* is cleared.
+ *
* TODO remove once we're there
*/
bool user_creatable;
bool hotpluggable;
/* callbacks */
- /*
- * Reset method here is deprecated and replaced by methods in the
- * resettable class interface to implement a multi-phase reset.
+ /**
+ * @reset: deprecated device reset method pointer
+ *
+ * Modern code should use the ResettableClass interface to
+ * implement a multi-phase reset.
+ *
* TODO: remove once every reset callback is unused
*/
DeviceReset reset;
DeviceRealize realize;
DeviceUnrealize unrealize;
- /* device state */
+ /**
+ * @vmsd: device state serialisation description for
+ * migration/save/restore
+ */
const VMStateDescription *vmsd;
- /* Private to qdev / bus. */
+ /**
+ * @bus_type: bus type
+ * private: to qdev / bus.
+ */
const char *bus_type;
-} DeviceClass;
+};
typedef struct NamedGPIOList NamedGPIOList;
@@ -160,52 +197,123 @@ struct NamedClockList {
QLIST_ENTRY(NamedClockList) node;
};
+typedef struct {
+ bool engaged_in_io;
+} MemReentrancyGuard;
+
+
+typedef QLIST_HEAD(, NamedGPIOList) NamedGPIOListHead;
+typedef QLIST_HEAD(, NamedClockList) NamedClockListHead;
+typedef QLIST_HEAD(, BusState) BusStateHead;
+
/**
- * DeviceState:
- * @realized: Indicates whether the device has been fully constructed.
- * @reset: ResettableState for the device; handled by Resettable interface.
+ * struct DeviceState - common device state, accessed with qdev helpers
*
* This structure should not be accessed directly. We declare it here
* so that it can be embedded in individual device state structures.
*/
struct DeviceState {
- /*< private >*/
+ /* private: */
Object parent_obj;
- /*< public >*/
+ /* public: */
- const char *id;
+ /**
+ * @id: global device id
+ */
+ char *id;
+ /**
+ * @canonical_path: canonical path of realized device in the QOM tree
+ */
char *canonical_path;
+ /**
+ * @realized: has device been realized?
+ */
bool realized;
+ /**
+ * @pending_deleted_event: track pending deletion events during unplug
+ */
bool pending_deleted_event;
- QemuOpts *opts;
+ /**
+ * @pending_deleted_expires_ms: optional timeout for deletion events
+ */
+ int64_t pending_deleted_expires_ms;
+ /**
+ * @opts: QDict of options for the device
+ */
+ QDict *opts;
+ /**
+ * @hotplugged: was device added after PHASE_MACHINE_READY?
+ */
int hotplugged;
+ /**
+ * @allow_unplug_during_migration: can device be unplugged during migration
+ */
bool allow_unplug_during_migration;
+ /**
+ * @parent_bus: bus this device belongs to
+ */
BusState *parent_bus;
- QLIST_HEAD(, NamedGPIOList) gpios;
- QLIST_HEAD(, NamedClockList) clocks;
- QLIST_HEAD(, BusState) child_bus;
+ /**
+ * @gpios: QLIST of named GPIOs the device provides.
+ */
+ NamedGPIOListHead gpios;
+ /**
+ * @clocks: QLIST of named clocks the device provides.
+ */
+ NamedClockListHead clocks;
+ /**
+ * @child_bus: QLIST of child buses
+ */
+ BusStateHead child_bus;
+ /**
+ * @num_child_bus: number of @child_bus entries
+ */
int num_child_bus;
+ /**
+ * @instance_id_alias: device alias for handling legacy migration setups
+ */
int instance_id_alias;
+ /**
+ * @alias_required_for_version: indicates @instance_id_alias is
+ * needed for migration
+ */
int alias_required_for_version;
+ /**
+ * @reset: ResettableState for the device; handled by Resettable interface.
+ */
ResettableState reset;
+ /**
+ * @unplug_blockers: list of reasons to block unplugging of device
+ */
+ GSList *unplug_blockers;
+ /**
+ * @mem_reentrancy_guard: Is the device currently in mmio/pio/dma?
+ *
+ * Used to prevent re-entrancy confusing things.
+ */
+ MemReentrancyGuard mem_reentrancy_guard;
};
struct DeviceListener {
void (*realize)(DeviceListener *listener, DeviceState *dev);
void (*unrealize)(DeviceListener *listener, DeviceState *dev);
/*
- * This callback is called upon init of the DeviceState and allows to
- * inform qdev that a device should be hidden, depending on the device
- * opts, for example, to hide a standby device.
+ * This callback is called upon init of the DeviceState and
+ * informs qdev if a device should be visible or hidden. We can
+ * hide a failover device depending for example on the device
+ * opts.
+ *
+ * On errors, it returns false and errp is set. Device creation
+ * should fail in this case.
*/
- int (*should_be_hidden)(DeviceListener *listener, QemuOpts *device_opts);
+ bool (*hide_device)(DeviceListener *listener, const QDict *device_opts,
+ bool from_json, Error **errp);
QTAILQ_ENTRY(DeviceListener) link;
};
#define TYPE_BUS "bus"
-#define BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_BUS)
-#define BUS_CLASS(klass) OBJECT_CLASS_CHECK(BusClass, (klass), TYPE_BUS)
-#define BUS_GET_CLASS(obj) OBJECT_GET_CLASS(BusClass, (obj), TYPE_BUS)
+DECLARE_OBJ_CHECKERS(BusState, BusClass,
+ BUS, TYPE_BUS)
struct BusClass {
ObjectClass parent_class;
@@ -213,13 +321,22 @@ struct BusClass {
/* FIXME first arg should be BusState */
void (*print_dev)(Monitor *mon, DeviceState *dev, int indent);
char *(*get_dev_path)(DeviceState *dev);
+
/*
* This callback is used to create Open Firmware device path in accordance
* with OF spec http://forthworks.com/standards/of1275.pdf. Individual bus
* bindings can be found at http://playground.sun.com/1275/bindings/.
*/
char *(*get_fw_dev_path)(DeviceState *dev);
- void (*reset)(BusState *bus);
+
+ /*
+ * Return whether the device can be added to @bus,
+ * based on the address that was set (via device properties)
+ * before realize. If not, on return @errp contains the
+ * human-readable error message.
+ */
+ bool (*check_address)(BusState *bus, DeviceState *dev, Error **errp);
+
BusRealize realize;
BusUnrealize unrealize;
@@ -230,6 +347,7 @@ struct BusClass {
};
typedef struct BusChild {
+ struct rcu_head rcu;
DeviceState *child;
int index;
QTAILQ_ENTRY(BusChild) sibling;
@@ -237,63 +355,50 @@ typedef struct BusChild {
#define QDEV_HOTPLUG_HANDLER_PROPERTY "hotplug-handler"
+typedef QTAILQ_HEAD(, BusChild) BusChildHead;
+typedef QLIST_ENTRY(BusState) BusStateEntry;
+
/**
- * BusState:
+ * struct BusState:
+ * @obj: parent object
+ * @parent: parent Device
+ * @name: name of bus
* @hotplug_handler: link to a hotplug handler associated with bus.
- * @reset: ResettableState for the bus; handled by Resettable interface.
+ * @max_index: max number of child buses
+ * @realized: is the bus itself realized?
+ * @full: is the bus full?
+ * @num_children: current number of child buses
*/
struct BusState {
+ /* private: */
Object obj;
+ /* public: */
DeviceState *parent;
char *name;
HotplugHandler *hotplug_handler;
int max_index;
bool realized;
+ bool full;
int num_children;
- QTAILQ_HEAD(, BusChild) children;
- QLIST_ENTRY(BusState) sibling;
- ResettableState reset;
-};
-
-/**
- * Property:
- * @set_default: true if the default value should be set from @defval,
- * in which case @info->set_default_value must not be NULL
- * (if false then no default value is set by the property system
- * and the field retains whatever value it was given by instance_init).
- * @defval: default value for the property. This is used only if @set_default
- * is true.
- */
-struct Property {
- const char *name;
- const PropertyInfo *info;
- ptrdiff_t offset;
- uint8_t bitnr;
- bool set_default;
- union {
- int64_t i;
- uint64_t u;
- } defval;
- int arrayoffset;
- const PropertyInfo *arrayinfo;
- int arrayfieldsize;
- const char *link_type;
-};
-struct PropertyInfo {
- const char *name;
- const char *description;
- const QEnumLookup *enum_table;
- int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
- void (*set_default_value)(ObjectProperty *op, const Property *prop);
- void (*create)(ObjectClass *oc, Property *prop);
- ObjectPropertyAccessor *get;
- ObjectPropertyAccessor *set;
- ObjectPropertyRelease *release;
+ /**
+ * @children: an RCU protected QTAILQ, thus readers must use RCU
+ * to access it, and writers must hold the big qemu lock
+ */
+ BusChildHead children;
+ /**
+ * @sibling: next bus
+ */
+ BusStateEntry sibling;
+ /**
+ * @reset: ResettableState for the bus; handled by Resettable interface.
+ */
+ ResettableState reset;
};
/**
- * GlobalProperty:
+ * typedef GlobalProperty - a global property type
+ *
* @used: Set to true if property was used when initializing a device.
* @optional: If set to true, GlobalProperty will be skipped without errors
* if the property doesn't exist.
@@ -327,17 +432,35 @@ compat_props_add(GPtrArray *arr,
* This only allocates the memory and initializes the device state
* structure, ready for the caller to set properties if they wish.
* The device still needs to be realized.
- * The returned object has a reference count of 1.
+ *
+ * Return: a derived DeviceState object with a reference count of 1.
*/
DeviceState *qdev_new(const char *name);
+
/**
* qdev_try_new: Try to create a device on the heap
* @name: device type to create
*
* This is like qdev_new(), except it returns %NULL when type @name
* does not exist, rather than asserting.
+ *
+ * Return: a derived DeviceState object with a reference count of 1 or
+ * NULL if type @name does not exist.
*/
DeviceState *qdev_try_new(const char *name);
+
+/**
+ * qdev_is_realized() - check if device is realized
+ * @dev: The device to check.
+ *
+ * Context: May be called outside big qemu lock.
+ * Return: true if the device has been fully constructed, false otherwise.
+ */
+static inline bool qdev_is_realized(DeviceState *dev)
+{
+ return qatomic_load_acquire(&dev->realized);
+}
+
/**
* qdev_realize: Realize @dev.
* @dev: device to realize
@@ -349,13 +472,14 @@ DeviceState *qdev_try_new(const char *name);
* @dev must not be plugged into a bus already.
* If @bus, plug @dev into @bus. This takes a reference to @dev.
* If @dev has no QOM parent, make one up, taking another reference.
- * On success, return true.
- * On failure, store an error through @errp and return false.
*
* If you created @dev using qdev_new(), you probably want to use
* qdev_realize_and_unref() instead.
+ *
+ * Return: true on success, else false setting @errp with error
*/
bool qdev_realize(DeviceState *dev, BusState *bus, Error **errp);
+
/**
* qdev_realize_and_unref: Realize @dev and drop a reference
* @dev: device to realize
@@ -379,8 +503,11 @@ bool qdev_realize(DeviceState *dev, BusState *bus, Error **errp);
* for the only reference to the child device to be held by the parent
* via the child<> property, and so the reference-count-drop done here
* would be incorrect. For that use case you want qdev_realize().
+ *
+ * Return: true on success, else false setting @errp with error
*/
bool qdev_realize_and_unref(DeviceState *dev, BusState *bus, Error **errp);
+
/**
* qdev_unrealize: Unrealize a device
* @dev: device to unrealize
@@ -390,7 +517,7 @@ bool qdev_realize_and_unref(DeviceState *dev, BusState *bus, Error **errp);
*
* - unrealize any child buses by calling qbus_unrealize()
* (this will recursively unrealize any devices on those buses)
- * - call the the unrealize method of @dev
+ * - call the unrealize method of @dev
*
* The device can then be freed by causing its reference count to go
* to zero.
@@ -406,16 +533,16 @@ void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
HotplugHandler *qdev_get_bus_hotplug_handler(DeviceState *dev);
HotplugHandler *qdev_get_machine_hotplug_handler(DeviceState *dev);
bool qdev_hotplug_allowed(DeviceState *dev, Error **errp);
+
/**
- * qdev_get_hotplug_handler: Get handler responsible for device wiring
- *
- * Find HOTPLUG_HANDLER for @dev that provides [pre|un]plug callbacks for it.
+ * qdev_get_hotplug_handler() - Get handler responsible for device wiring
+ * @dev: the device we want the HOTPLUG_HANDLER for.
*
* Note: in case @dev has a parent bus, it will be returned as handler unless
* machine handler overrides it.
*
- * Returns: pointer to object that implements TYPE_HOTPLUG_HANDLER interface
- * or NULL if there aren't any.
+ * Return: pointer to object that implements TYPE_HOTPLUG_HANDLER interface
+ * or NULL if there aren't any.
*/
HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev);
void qdev_unplug(DeviceState *dev, Error **errp);
@@ -425,6 +552,50 @@ void qdev_machine_creation_done(void);
bool qdev_machine_modified(void);
/**
+ * qdev_add_unplug_blocker: Add an unplug blocker to a device
+ *
+ * @dev: Device to be blocked from unplug
+ * @reason: Reason for blocking
+ */
+void qdev_add_unplug_blocker(DeviceState *dev, Error *reason);
+
+/**
+ * qdev_del_unplug_blocker: Remove an unplug blocker from a device
+ *
+ * @dev: Device to be unblocked
+ * @reason: Pointer to the Error used with qdev_add_unplug_blocker.
+ * Used as a handle to lookup the blocker for deletion.
+ */
+void qdev_del_unplug_blocker(DeviceState *dev, Error *reason);
+
+/**
+ * qdev_unplug_blocked: Confirm if a device is blocked from unplug
+ *
+ * @dev: Device to be tested
+ * @errp: The reasons why the device is blocked, if any
+ *
+ * Returns: true (also setting @errp) if device is blocked from unplug,
+ * false otherwise
+ */
+bool qdev_unplug_blocked(DeviceState *dev, Error **errp);
+
+/**
+ * typedef GpioPolarity - Polarity of a GPIO line
+ *
+ * GPIO lines use either positive (active-high) logic,
+ * or negative (active-low) logic.
+ *
+ * In active-high logic (%GPIO_POLARITY_ACTIVE_HIGH), a pin is
+ * active when the voltage on the pin is high (relative to ground);
+ * whereas in active-low logic (%GPIO_POLARITY_ACTIVE_LOW), a pin
+ * is active when the voltage on the pin is low (or grounded).
+ */
+typedef enum {
+ GPIO_POLARITY_ACTIVE_LOW,
+ GPIO_POLARITY_ACTIVE_HIGH
+} GpioPolarity;
+
+/**
* qdev_get_gpio_in: Get one of a device's anonymous input GPIO lines
* @dev: Device whose GPIO we want
* @n: Number of the anonymous GPIO line (which must be in range)
@@ -441,8 +612,11 @@ bool qdev_machine_modified(void);
* connect another device's output GPIO line to this input.
*
* For named input GPIO lines, use qdev_get_gpio_in_named().
+ *
+ * Return: qemu_irq corresponding to anonymous input GPIO line
*/
qemu_irq qdev_get_gpio_in(DeviceState *dev, int n);
+
/**
* qdev_get_gpio_in_named: Get one of a device's named input GPIO lines
* @dev: Device whose GPIO we want
@@ -457,6 +631,8 @@ qemu_irq qdev_get_gpio_in(DeviceState *dev, int n);
* array); this function will assert() if passed an invalid name or index.
*
* For anonymous input GPIO lines, use qdev_get_gpio_in().
+ *
+ * Return: qemu_irq corresponding to named input GPIO line
*/
qemu_irq qdev_get_gpio_in_named(DeviceState *dev, const char *name, int n);
@@ -481,7 +657,7 @@ qemu_irq qdev_get_gpio_in_named(DeviceState *dev, const char *name, int n);
* qemu_irqs at once, or to connect multiple outbound GPIOs to the
* same qemu_irq. (Warning: there is no assertion or other guard to
* catch this error: the model will just not do the right thing.)
- * Instead, for fan-out you can use the TYPE_IRQ_SPLIT device: connect
+ * Instead, for fan-out you can use the TYPE_SPLIT_IRQ device: connect
* a device's outbound GPIO to the splitter's input, and connect each
* of the splitter's outputs to a different device. For fan-in you
* can use the TYPE_OR_IRQ device, which is a model of a logical OR
@@ -490,12 +666,14 @@ qemu_irq qdev_get_gpio_in_named(DeviceState *dev, const char *name, int n);
* For named output GPIO lines, use qdev_connect_gpio_out_named().
*/
void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin);
+
/**
- * qdev_connect_gpio_out: Connect one of a device's anonymous output GPIO lines
+ * qdev_connect_gpio_out_named: Connect one of a device's named output
+ * GPIO lines
* @dev: Device whose GPIO to connect
* @name: Name of the output GPIO array
* @n: Number of the anonymous output GPIO line (which must be in range)
- * @pin: qemu_irq to connect the output line to
+ * @input_pin: qemu_irq to connect the output line to
*
* This function connects an anonymous output GPIO line on a device
* up to an arbitrary qemu_irq, so that when the device asserts that
@@ -513,10 +691,11 @@ void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin);
* qemu_irqs at once, or to connect multiple outbound GPIOs to the
* same qemu_irq; see qdev_connect_gpio_out() for details.
*
- * For named output GPIO lines, use qdev_connect_gpio_out_named().
+ * For anonymous output GPIO lines, use qdev_connect_gpio_out().
*/
void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n,
- qemu_irq pin);
+ qemu_irq input_pin);
+
/**
* qdev_get_gpio_out_connector: Get the qemu_irq connected to an output GPIO
* @dev: Device whose output GPIO we are interested in
@@ -532,8 +711,11 @@ void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n,
*
* You probably don't need to use this function -- it is used only
* by the platform-bus subsystem.
+ *
+ * Return: qemu_irq associated with GPIO or NULL if un-wired.
*/
qemu_irq qdev_get_gpio_out_connector(DeviceState *dev, const char *name, int n);
+
/**
* qdev_intercept_gpio_out: Intercept an existing GPIO connection
* @dev: Device to intercept the outbound GPIO line from
@@ -541,14 +723,17 @@ qemu_irq qdev_get_gpio_out_connector(DeviceState *dev, const char *name, int n);
* @name: Name of the output GPIO array
* @n: Number of the GPIO line in the array
*
- * This function is provided only for use by the qtest testing framework
- * and is not suitable for use in non-testing parts of QEMU.
+ * .. note::
+ * This function is provided only for use by the qtest testing framework
+ * and is not suitable for use in non-testing parts of QEMU.
*
* This function breaks an existing connection of an outbound GPIO
* line from @dev, and replaces it with the new qemu_irq @icpt, as if
* ``qdev_connect_gpio_out_named(dev, icpt, name, n)`` had been called.
* The previously connected qemu_irq is returned, so it can be restored
* by a second call to qdev_intercept_gpio_out() if desired.
+ *
+ * Return: old disconnected qemu_irq if one existed
*/
qemu_irq qdev_intercept_gpio_out(DeviceState *dev, qemu_irq icpt,
const char *name, int n);
@@ -575,6 +760,7 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
* hold of an input GPIO line to manipulate it.
*/
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n);
+
/**
* qdev_init_gpio_out: create an array of anonymous output GPIO lines
* @dev: Device to create output GPIOs for
@@ -597,10 +783,15 @@ void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n);
*
* See qdev_connect_gpio_out() for how code that uses such a device
* can connect to one of its output GPIO lines.
+ *
+ * There is no need to release the @pins allocated array because it
+ * will be automatically released when @dev calls its instance_finalize()
+ * handler.
*/
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n);
+
/**
- * qdev_init_gpio_out: create an array of named output GPIO lines
+ * qdev_init_gpio_out_named: create an array of named output GPIO lines
* @dev: Device to create output GPIOs for
* @pins: Pointer to qemu_irq or qemu_irq array for the GPIO lines
* @name: Name to give this array of GPIO lines
@@ -612,10 +803,9 @@ void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n);
*/
void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins,
const char *name, int n);
+
/**
- * qdev_init_gpio_in_named_with_opaque: create an array of input GPIO lines
- * for the specified device
- *
+ * qdev_init_gpio_in_named_with_opaque() - create an array of input GPIO lines
* @dev: Device to create input GPIOs for
* @handler: Function to call when GPIO line value is set
* @opaque: Opaque data pointer to pass to @handler
@@ -628,8 +818,11 @@ void qdev_init_gpio_in_named_with_opaque(DeviceState *dev,
const char *name, int n);
/**
- * qdev_init_gpio_in_named: create an array of input GPIO lines
- * for the specified device
+ * qdev_init_gpio_in_named() - create an array of input GPIO lines
+ * @dev: device to add array to
+ * @handler: a &typedef qemu_irq_handler function to call when GPIO is set
+ * @name: Name of the GPIO input (must be unique for this device)
+ * @n: Number of GPIO lines in this input set
*
* Like qdev_init_gpio_in_named_with_opaque(), but the opaque pointer
* passed to the handler is @dev (which is the most commonly desired behaviour).
@@ -663,7 +856,7 @@ static inline void qdev_init_gpio_in_named(DeviceState *dev,
void qdev_pass_gpios(DeviceState *dev, DeviceState *container,
const char *name);
-BusState *qdev_get_parent_bus(DeviceState *dev);
+BusState *qdev_get_parent_bus(const DeviceState *dev);
/*** BUS API. ***/
@@ -673,9 +866,9 @@ DeviceState *qdev_find_recursive(BusState *bus, const char *id);
typedef int (qbus_walkerfn)(BusState *bus, void *opaque);
typedef int (qdev_walkerfn)(DeviceState *dev, void *opaque);
-void qbus_create_inplace(void *bus, size_t size, const char *typename,
- DeviceState *parent, const char *name);
-BusState *qbus_create(const char *typename, DeviceState *parent, const char *name);
+void qbus_init(void *bus, size_t size, const char *typename,
+ DeviceState *parent, const char *name);
+BusState *qbus_new(const char *typename, DeviceState *parent, const char *name);
bool qbus_realize(BusState *bus, Error **errp);
void qbus_unrealize(BusState *bus);
@@ -692,40 +885,17 @@ int qdev_walk_children(DeviceState *dev,
void *opaque);
/**
- * @qdev_reset_all:
- * Reset @dev. See @qbus_reset_all() for more details.
- *
- * Note: This function is deprecated and will be removed when it becomes unused.
- * Please use device_cold_reset() now.
- */
-void qdev_reset_all(DeviceState *dev);
-void qdev_reset_all_fn(void *opaque);
-
-/**
- * @qbus_reset_all:
- * @bus: Bus to be reset.
+ * device_cold_reset() - perform a recursive cold reset on a device
+ * @dev: device to reset.
*
- * Reset @bus and perform a bus-level ("hard") reset of all devices connected
- * to it, including recursive processing of all buses below @bus itself. A
- * hard reset means that qbus_reset_all will reset all state of the device.
- * For PCI devices, for example, this will include the base address registers
- * or configuration space.
- *
- * Note: This function is deprecated and will be removed when it becomes unused.
- * Please use bus_cold_reset() now.
- */
-void qbus_reset_all(BusState *bus);
-void qbus_reset_all_fn(void *opaque);
-
-/**
- * device_cold_reset:
* Reset device @dev and perform a recursive processing using the resettable
* interface. It triggers a RESET_TYPE_COLD.
*/
void device_cold_reset(DeviceState *dev);
/**
- * bus_cold_reset:
+ * bus_cold_reset() - perform a recursive cold reset on a bus
+ * @bus: bus to reset
*
* Reset bus @bus and perform a recursive processing using the resettable
* interface. It triggers a RESET_TYPE_COLD.
@@ -733,14 +903,18 @@ void device_cold_reset(DeviceState *dev);
void bus_cold_reset(BusState *bus);
/**
- * device_is_in_reset:
- * Return true if the device @dev is currently being reset.
+ * device_is_in_reset() - check device reset state
+ * @dev: device to check
+ *
+ * Return: true if the device @dev is currently being reset.
*/
bool device_is_in_reset(DeviceState *dev);
/**
- * bus_is_in_reset:
- * Return true if the bus @bus is currently being reset.
+ * bus_is_in_reset() - check bus reset state
+ * @bus: bus to check
+ *
+ * Return: true if the bus @bus is currently being reset.
*/
bool bus_is_in_reset(BusState *bus);
@@ -751,35 +925,61 @@ char *qdev_get_fw_dev_path(DeviceState *dev);
char *qdev_get_own_fw_dev_path_from_handler(BusState *bus, DeviceState *dev);
/**
- * @qdev_machine_init
+ * device_class_set_props(): add a set of properties to an device
+ * @dc: the parent DeviceClass all devices inherit
+ * @props: an array of properties, terminate by DEFINE_PROP_END_OF_LIST()
*
- * Initialize platform devices before machine init. This is a hack until full
- * support for composition is added.
+ * This will add a set of properties to the object. It will fault if
+ * you attempt to add an existing property defined by a parent class.
+ * To modify an inherited property you need to use????
*/
-void qdev_machine_init(void);
-
-/**
- * device_legacy_reset:
- *
- * Reset a single device (by calling the reset method).
- * Note: This function is deprecated and will be removed when it becomes unused.
- * Please use device_cold_reset() now.
- */
-void device_legacy_reset(DeviceState *dev);
-
void device_class_set_props(DeviceClass *dc, Property *props);
/**
- * device_class_set_parent_reset:
+ * device_class_set_parent_reset() - legacy set device reset handlers
+ * @dc: device class
+ * @dev_reset: function pointer to reset handler
+ * @parent_reset: function pointer to parents reset handler
+ *
+ * Modern code should use the ResettableClass interface to
+ * implement a multi-phase reset instead.
+ *
* TODO: remove the function when DeviceClass's reset method
* is not used anymore.
*/
void device_class_set_parent_reset(DeviceClass *dc,
DeviceReset dev_reset,
DeviceReset *parent_reset);
+
+/**
+ * device_class_set_parent_realize() - set up for chaining realize fns
+ * @dc: The device class
+ * @dev_realize: the device realize function
+ * @parent_realize: somewhere to save the parents realize function
+ *
+ * This is intended to be used when the new realize function will
+ * eventually call its parent realization function during creation.
+ * This requires storing the function call somewhere (usually in the
+ * instance structure) so you can eventually call
+ * dc->parent_realize(dev, errp)
+ */
void device_class_set_parent_realize(DeviceClass *dc,
DeviceRealize dev_realize,
DeviceRealize *parent_realize);
+
+
+/**
+ * device_class_set_parent_unrealize() - set up for chaining unrealize fns
+ * @dc: The device class
+ * @dev_unrealize: the device realize function
+ * @parent_unrealize: somewhere to save the parents unrealize function
+ *
+ * This is intended to be used when the new unrealize function will
+ * eventually call its parent unrealization function during the
+ * unrealize phase. This requires storing the function call somewhere
+ * (usually in the instance structure) so you can eventually call
+ * dc->parent_unrealize(dev);
+ */
void device_class_set_parent_unrealize(DeviceClass *dc,
DeviceUnrealize dev_unrealize,
DeviceUnrealize *parent_unrealize);
@@ -788,12 +988,26 @@ const VMStateDescription *qdev_get_vmsd(DeviceState *dev);
const char *qdev_fw_name(DeviceState *dev);
+void qdev_assert_realized_properly(void);
Object *qdev_get_machine(void);
+/**
+ * qdev_get_human_name() - Return a human-readable name for a device
+ * @dev: The device. Must be a valid and non-NULL pointer.
+ *
+ * .. note::
+ * This function is intended for user friendly error messages.
+ *
+ * Returns: A newly allocated string containing the device id if not null,
+ * else the object canonical path.
+ *
+ * Use g_free() to free it.
+ */
+char *qdev_get_human_name(DeviceState *dev);
+
/* FIXME: make this a link<> */
-void qdev_set_parent_bus(DeviceState *dev, BusState *bus);
+bool qdev_set_parent_bus(DeviceState *dev, BusState *bus, Error **errp);
-extern bool qdev_hotplug;
extern bool qdev_hot_removed;
char *qdev_get_dev_path(DeviceState *dev);
@@ -803,20 +1017,93 @@ void qbus_set_bus_hotplug_handler(BusState *bus);
static inline bool qbus_is_hotpluggable(BusState *bus)
{
- return bus->hotplug_handler;
+ HotplugHandler *plug_handler = bus->hotplug_handler;
+ bool ret = !!plug_handler;
+
+ if (plug_handler) {
+ HotplugHandlerClass *hdc;
+
+ hdc = HOTPLUG_HANDLER_GET_CLASS(plug_handler);
+ if (hdc->is_hotpluggable_bus) {
+ ret = hdc->is_hotpluggable_bus(plug_handler, bus);
+ }
+ }
+ return ret;
+}
+
+/**
+ * qbus_mark_full: Mark this bus as full, so no more devices can be attached
+ * @bus: Bus to mark as full
+ *
+ * By default, QEMU will allow devices to be plugged into a bus up
+ * to the bus class's device count limit. Calling this function
+ * marks a particular bus as full, so that no more devices can be
+ * plugged into it. In particular this means that the bus will not
+ * be considered as a candidate for plugging in devices created by
+ * the user on the commandline or via the monitor.
+ * If a machine has multiple buses of a given type, such as I2C,
+ * where some of those buses in the real hardware are used only for
+ * internal devices and some are exposed via expansion ports, you
+ * can use this function to mark the internal-only buses as full
+ * after you have created all their internal devices. Then user
+ * created devices will appear on the expansion-port bus where
+ * guest software expects them.
+ */
+static inline void qbus_mark_full(BusState *bus)
+{
+ bus->full = true;
}
void device_listener_register(DeviceListener *listener);
void device_listener_unregister(DeviceListener *listener);
/**
- * @qdev_should_hide_device:
- * @opts: QemuOpts as passed on cmdline.
+ * qdev_should_hide_device() - check if device should be hidden
*
- * Check if a device should be added.
- * When a device is added via qdev_device_add() this will be called,
- * and return if the device should be added now or not.
+ * @opts: options QDict
+ * @from_json: true if @opts entries are typed, false for all strings
+ * @errp: pointer to error object
+ *
+ * When a device is added via qdev_device_add() this will be called.
+ *
+ * Return: if the device should be added now or not.
*/
-bool qdev_should_hide_device(QemuOpts *opts);
+bool qdev_should_hide_device(const QDict *opts, bool from_json, Error **errp);
+
+typedef enum MachineInitPhase {
+ /* current_machine is NULL. */
+ PHASE_NO_MACHINE,
+
+ /* current_machine is not NULL, but current_machine->accel is NULL. */
+ PHASE_MACHINE_CREATED,
+
+ /*
+ * current_machine->accel is not NULL, but the machine properties have
+ * not been validated and machine_class->init has not yet been called.
+ */
+ PHASE_ACCEL_CREATED,
+
+ /*
+ * Late backend objects have been created and initialized.
+ */
+ PHASE_LATE_BACKENDS_CREATED,
+
+ /*
+ * machine_class->init has been called, thus creating any embedded
+ * devices and validating machine properties. Devices created at
+ * this time are considered to be cold-plugged.
+ */
+ PHASE_MACHINE_INITIALIZED,
+
+ /*
+ * QEMU is ready to start CPUs and devices created at this time
+ * are considered to be hot-plugged. The monitor is not restricted
+ * to "preconfig" commands.
+ */
+ PHASE_MACHINE_READY,
+} MachineInitPhase;
+
+bool phase_check(MachineInitPhase phase);
+void phase_advance(MachineInitPhase phase);
#endif
diff --git a/include/hw/qdev-properties-system.h b/include/hw/qdev-properties-system.h
new file mode 100644
index 0000000000..438f65389f
--- /dev/null
+++ b/include/hw/qdev-properties-system.h
@@ -0,0 +1,97 @@
+#ifndef HW_QDEV_PROPERTIES_SYSTEM_H
+#define HW_QDEV_PROPERTIES_SYSTEM_H
+
+#include "hw/qdev-properties.h"
+
+extern const PropertyInfo qdev_prop_chr;
+extern const PropertyInfo qdev_prop_macaddr;
+extern const PropertyInfo qdev_prop_reserved_region;
+extern const PropertyInfo qdev_prop_multifd_compression;
+extern const PropertyInfo qdev_prop_mig_mode;
+extern const PropertyInfo qdev_prop_granule_mode;
+extern const PropertyInfo qdev_prop_zero_page_detection;
+extern const PropertyInfo qdev_prop_losttickpolicy;
+extern const PropertyInfo qdev_prop_blockdev_on_error;
+extern const PropertyInfo qdev_prop_bios_chs_trans;
+extern const PropertyInfo qdev_prop_fdc_drive_type;
+extern const PropertyInfo qdev_prop_drive;
+extern const PropertyInfo qdev_prop_drive_iothread;
+extern const PropertyInfo qdev_prop_netdev;
+extern const PropertyInfo qdev_prop_pci_devfn;
+extern const PropertyInfo qdev_prop_blocksize;
+extern const PropertyInfo qdev_prop_pci_host_devaddr;
+extern const PropertyInfo qdev_prop_uuid;
+extern const PropertyInfo qdev_prop_audiodev;
+extern const PropertyInfo qdev_prop_off_auto_pcibar;
+extern const PropertyInfo qdev_prop_pcie_link_speed;
+extern const PropertyInfo qdev_prop_pcie_link_width;
+extern const PropertyInfo qdev_prop_cpus390entitlement;
+extern const PropertyInfo qdev_prop_iothread_vq_mapping_list;
+
+#define DEFINE_PROP_PCI_DEVFN(_n, _s, _f, _d) \
+ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_pci_devfn, int32_t)
+
+#define DEFINE_PROP_CHR(_n, _s, _f) \
+ DEFINE_PROP(_n, _s, _f, qdev_prop_chr, CharBackend)
+#define DEFINE_PROP_NETDEV(_n, _s, _f) \
+ DEFINE_PROP(_n, _s, _f, qdev_prop_netdev, NICPeers)
+#define DEFINE_PROP_DRIVE(_n, _s, _f) \
+ DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockBackend *)
+#define DEFINE_PROP_DRIVE_IOTHREAD(_n, _s, _f) \
+ DEFINE_PROP(_n, _s, _f, qdev_prop_drive_iothread, BlockBackend *)
+#define DEFINE_PROP_MACADDR(_n, _s, _f) \
+ DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr)
+#define DEFINE_PROP_RESERVED_REGION(_n, _s, _f) \
+ DEFINE_PROP(_n, _s, _f, qdev_prop_reserved_region, ReservedRegion)
+#define DEFINE_PROP_MULTIFD_COMPRESSION(_n, _s, _f, _d) \
+ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_multifd_compression, \
+ MultiFDCompression)
+#define DEFINE_PROP_MIG_MODE(_n, _s, _f, _d) \
+ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_mig_mode, \
+ MigMode)
+#define DEFINE_PROP_GRANULE_MODE(_n, _s, _f, _d) \
+ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_granule_mode, GranuleMode)
+#define DEFINE_PROP_ZERO_PAGE_DETECTION(_n, _s, _f, _d) \
+ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_zero_page_detection, \
+ ZeroPageDetection)
+#define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \
+ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_losttickpolicy, \
+ LostTickPolicy)
+#define DEFINE_PROP_BLOCKDEV_ON_ERROR(_n, _s, _f, _d) \
+ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_blockdev_on_error, \
+ BlockdevOnError)
+#define DEFINE_PROP_BIOS_CHS_TRANS(_n, _s, _f, _d) \
+ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_bios_chs_trans, int)
+#define DEFINE_PROP_BLOCKSIZE(_n, _s, _f) \
+ DEFINE_PROP_UNSIGNED(_n, _s, _f, 0, qdev_prop_blocksize, uint32_t)
+#define DEFINE_PROP_PCI_HOST_DEVADDR(_n, _s, _f) \
+ DEFINE_PROP(_n, _s, _f, qdev_prop_pci_host_devaddr, PCIHostDeviceAddress)
+#define DEFINE_PROP_OFF_AUTO_PCIBAR(_n, _s, _f, _d) \
+ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_off_auto_pcibar, \
+ OffAutoPCIBAR)
+#define DEFINE_PROP_PCIE_LINK_SPEED(_n, _s, _f, _d) \
+ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_pcie_link_speed, \
+ PCIExpLinkSpeed)
+#define DEFINE_PROP_PCIE_LINK_WIDTH(_n, _s, _f, _d) \
+ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_pcie_link_width, \
+ PCIExpLinkWidth)
+
+#define DEFINE_PROP_UUID(_name, _state, _field) \
+ DEFINE_PROP(_name, _state, _field, qdev_prop_uuid, QemuUUID, \
+ .set_default = true)
+
+#define DEFINE_PROP_AUDIODEV(_n, _s, _f) \
+ DEFINE_PROP(_n, _s, _f, qdev_prop_audiodev, QEMUSoundCard)
+
+#define DEFINE_PROP_UUID_NODEFAULT(_name, _state, _field) \
+ DEFINE_PROP(_name, _state, _field, qdev_prop_uuid, QemuUUID)
+
+#define DEFINE_PROP_CPUS390ENTITLEMENT(_n, _s, _f, _d) \
+ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_cpus390entitlement, \
+ CpuS390Entitlement)
+
+#define DEFINE_PROP_IOTHREAD_VQ_MAPPING_LIST(_name, _state, _field) \
+ DEFINE_PROP(_name, _state, _field, qdev_prop_iothread_vq_mapping_list, \
+ IOThreadVirtQueueMappingList *)
+
+#endif
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index 8f3a98cba6..09aa04ca1e 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -3,113 +3,117 @@
#include "hw/qdev-core.h"
+/**
+ * Property:
+ * @set_default: true if the default value should be set from @defval,
+ * in which case @info->set_default_value must not be NULL
+ * (if false then no default value is set by the property system
+ * and the field retains whatever value it was given by instance_init).
+ * @defval: default value for the property. This is used only if @set_default
+ * is true.
+ */
+struct Property {
+ const char *name;
+ const PropertyInfo *info;
+ ptrdiff_t offset;
+ uint8_t bitnr;
+ uint64_t bitmask;
+ bool set_default;
+ union {
+ int64_t i;
+ uint64_t u;
+ } defval;
+ int arrayoffset;
+ const PropertyInfo *arrayinfo;
+ int arrayfieldsize;
+ const char *link_type;
+};
+
+struct PropertyInfo {
+ const char *name;
+ const char *description;
+ const QEnumLookup *enum_table;
+ bool realized_set_allowed; /* allow setting property on realized device */
+ int (*print)(Object *obj, Property *prop, char *dest, size_t len);
+ void (*set_default_value)(ObjectProperty *op, const Property *prop);
+ ObjectProperty *(*create)(ObjectClass *oc, const char *name,
+ Property *prop);
+ ObjectPropertyAccessor *get;
+ ObjectPropertyAccessor *set;
+ ObjectPropertyRelease *release;
+};
+
+
/*** qdev-properties.c ***/
extern const PropertyInfo qdev_prop_bit;
extern const PropertyInfo qdev_prop_bit64;
extern const PropertyInfo qdev_prop_bool;
+extern const PropertyInfo qdev_prop_enum;
extern const PropertyInfo qdev_prop_uint8;
extern const PropertyInfo qdev_prop_uint16;
extern const PropertyInfo qdev_prop_uint32;
extern const PropertyInfo qdev_prop_int32;
extern const PropertyInfo qdev_prop_uint64;
+extern const PropertyInfo qdev_prop_uint64_checkmask;
extern const PropertyInfo qdev_prop_int64;
extern const PropertyInfo qdev_prop_size;
extern const PropertyInfo qdev_prop_string;
-extern const PropertyInfo qdev_prop_chr;
-extern const PropertyInfo qdev_prop_tpm;
-extern const PropertyInfo qdev_prop_macaddr;
-extern const PropertyInfo qdev_prop_reserved_region;
extern const PropertyInfo qdev_prop_on_off_auto;
-extern const PropertyInfo qdev_prop_multifd_compression;
-extern const PropertyInfo qdev_prop_losttickpolicy;
-extern const PropertyInfo qdev_prop_blockdev_on_error;
-extern const PropertyInfo qdev_prop_bios_chs_trans;
-extern const PropertyInfo qdev_prop_fdc_drive_type;
-extern const PropertyInfo qdev_prop_drive;
-extern const PropertyInfo qdev_prop_drive_iothread;
-extern const PropertyInfo qdev_prop_netdev;
-extern const PropertyInfo qdev_prop_pci_devfn;
extern const PropertyInfo qdev_prop_size32;
-extern const PropertyInfo qdev_prop_blocksize;
-extern const PropertyInfo qdev_prop_pci_host_devaddr;
-extern const PropertyInfo qdev_prop_uuid;
-extern const PropertyInfo qdev_prop_arraylen;
-extern const PropertyInfo qdev_prop_audiodev;
+extern const PropertyInfo qdev_prop_array;
extern const PropertyInfo qdev_prop_link;
-extern const PropertyInfo qdev_prop_off_auto_pcibar;
-extern const PropertyInfo qdev_prop_pcie_link_speed;
-extern const PropertyInfo qdev_prop_pcie_link_width;
-#define DEFINE_PROP(_name, _state, _field, _prop, _type) { \
+#define DEFINE_PROP(_name, _state, _field, _prop, _type, ...) { \
.name = (_name), \
.info = &(_prop), \
.offset = offsetof(_state, _field) \
+ type_check(_type, typeof_field(_state, _field)), \
+ __VA_ARGS__ \
}
-#define DEFINE_PROP_SIGNED(_name, _state, _field, _defval, _prop, _type) { \
- .name = (_name), \
- .info = &(_prop), \
- .offset = offsetof(_state, _field) \
- + type_check(_type,typeof_field(_state, _field)), \
- .set_default = true, \
- .defval.i = (_type)_defval, \
- }
+#define DEFINE_PROP_SIGNED(_name, _state, _field, _defval, _prop, _type) \
+ DEFINE_PROP(_name, _state, _field, _prop, _type, \
+ .set_default = true, \
+ .defval.i = (_type)_defval)
-#define DEFINE_PROP_SIGNED_NODEFAULT(_name, _state, _field, _prop, _type) { \
- .name = (_name), \
- .info = &(_prop), \
- .offset = offsetof(_state, _field) \
- + type_check(_type, typeof_field(_state, _field)), \
- }
+#define DEFINE_PROP_SIGNED_NODEFAULT(_name, _state, _field, _prop, _type) \
+ DEFINE_PROP(_name, _state, _field, _prop, _type)
-#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) { \
- .name = (_name), \
- .info = &(qdev_prop_bit), \
- .bitnr = (_bit), \
- .offset = offsetof(_state, _field) \
- + type_check(uint32_t,typeof_field(_state, _field)), \
- .set_default = true, \
- .defval.u = (bool)_defval, \
- }
+#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) \
+ DEFINE_PROP(_name, _state, _field, qdev_prop_bit, uint32_t, \
+ .bitnr = (_bit), \
+ .set_default = true, \
+ .defval.u = (bool)_defval)
-#define DEFINE_PROP_UNSIGNED(_name, _state, _field, _defval, _prop, _type) { \
- .name = (_name), \
- .info = &(_prop), \
- .offset = offsetof(_state, _field) \
- + type_check(_type, typeof_field(_state, _field)), \
- .set_default = true, \
- .defval.u = (_type)_defval, \
- }
+#define DEFINE_PROP_UNSIGNED(_name, _state, _field, _defval, _prop, _type) \
+ DEFINE_PROP(_name, _state, _field, _prop, _type, \
+ .set_default = true, \
+ .defval.u = (_type)_defval)
-#define DEFINE_PROP_UNSIGNED_NODEFAULT(_name, _state, _field, _prop, _type) { \
- .name = (_name), \
- .info = &(_prop), \
- .offset = offsetof(_state, _field) \
- + type_check(_type, typeof_field(_state, _field)), \
- }
+#define DEFINE_PROP_UNSIGNED_NODEFAULT(_name, _state, _field, _prop, _type) \
+ DEFINE_PROP(_name, _state, _field, _prop, _type)
-#define DEFINE_PROP_BIT64(_name, _state, _field, _bit, _defval) { \
- .name = (_name), \
- .info = &(qdev_prop_bit64), \
- .bitnr = (_bit), \
- .offset = offsetof(_state, _field) \
- + type_check(uint64_t, typeof_field(_state, _field)), \
- .set_default = true, \
- .defval.u = (bool)_defval, \
- }
+#define DEFINE_PROP_BIT64(_name, _state, _field, _bit, _defval) \
+ DEFINE_PROP(_name, _state, _field, qdev_prop_bit64, uint64_t, \
+ .bitnr = (_bit), \
+ .set_default = true, \
+ .defval.u = (bool)_defval)
-#define DEFINE_PROP_BOOL(_name, _state, _field, _defval) { \
- .name = (_name), \
- .info = &(qdev_prop_bool), \
- .offset = offsetof(_state, _field) \
- + type_check(bool, typeof_field(_state, _field)), \
- .set_default = true, \
- .defval.u = (bool)_defval, \
- }
+#define DEFINE_PROP_BOOL(_name, _state, _field, _defval) \
+ DEFINE_PROP(_name, _state, _field, qdev_prop_bool, bool, \
+ .set_default = true, \
+ .defval.u = (bool)_defval)
-#define PROP_ARRAY_LEN_PREFIX "len-"
+/**
+ * The DEFINE_PROP_UINT64_CHECKMASK macro checks a user-supplied value
+ * against corresponding bitmask, rejects the value if it violates.
+ * The default value is set in instance_init().
+ */
+#define DEFINE_PROP_UINT64_CHECKMASK(_name, _state, _field, _bitmask) \
+ DEFINE_PROP(_name, _state, _field, qdev_prop_uint64_checkmask, uint64_t, \
+ .bitmask = (_bitmask), \
+ .set_default = false)
/**
* DEFINE_PROP_ARRAY:
@@ -121,40 +125,30 @@ extern const PropertyInfo qdev_prop_pcie_link_width;
* @_arrayprop: PropertyInfo defining what property the array elements have
* @_arraytype: C type of the array elements
*
- * Define device properties for a variable-length array _name. A
- * static property "len-arrayname" is defined. When the device creator
- * sets this property to the desired length of array, further dynamic
- * properties "arrayname[0]", "arrayname[1]", ... are defined so the
- * device creator can set the array element values. Setting the
- * "len-arrayname" property more than once is an error.
+ * Define device properties for a variable-length array _name. The array is
+ * represented as a list in the visitor interface.
+ *
+ * @_arraytype is required to be movable with memcpy().
*
- * When the array length is set, the @_field member of the device
+ * When the array property is set, the @_field member of the device
* struct is set to the array length, and @_arrayfield is set to point
- * to (zero-initialised) memory allocated for the array. For a zero
- * length array, @_field will be set to 0 and @_arrayfield to NULL.
+ * to the memory allocated for the array.
+ *
* It is the responsibility of the device deinit code to free the
* @_arrayfield memory.
*/
#define DEFINE_PROP_ARRAY(_name, _state, _field, \
- _arrayfield, _arrayprop, _arraytype) { \
- .name = (PROP_ARRAY_LEN_PREFIX _name), \
- .info = &(qdev_prop_arraylen), \
- .set_default = true, \
- .defval.u = 0, \
- .offset = offsetof(_state, _field) \
- + type_check(uint32_t, typeof_field(_state, _field)), \
- .arrayinfo = &(_arrayprop), \
- .arrayfieldsize = sizeof(_arraytype), \
- .arrayoffset = offsetof(_state, _arrayfield), \
- }
+ _arrayfield, _arrayprop, _arraytype) \
+ DEFINE_PROP(_name, _state, _field, qdev_prop_array, uint32_t, \
+ .set_default = true, \
+ .defval.u = 0, \
+ .arrayinfo = &(_arrayprop), \
+ .arrayfieldsize = sizeof(_arraytype), \
+ .arrayoffset = offsetof(_state, _arrayfield))
-#define DEFINE_PROP_LINK(_name, _state, _field, _type, _ptr_type) { \
- .name = (_name), \
- .info = &(qdev_prop_link), \
- .offset = offsetof(_state, _field) \
- + type_check(_ptr_type, typeof_field(_state, _field)), \
- .link_type = _type, \
- }
+#define DEFINE_PROP_LINK(_name, _state, _field, _type, _ptr_type) \
+ DEFINE_PROP(_name, _state, _field, qdev_prop_link, _ptr_type, \
+ .link_type = _type)
#define DEFINE_PROP_UINT8(_n, _s, _f, _d) \
DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, qdev_prop_uint8, uint8_t)
@@ -170,74 +164,20 @@ extern const PropertyInfo qdev_prop_pcie_link_width;
DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_int64, int64_t)
#define DEFINE_PROP_SIZE(_n, _s, _f, _d) \
DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, qdev_prop_size, uint64_t)
-#define DEFINE_PROP_PCI_DEVFN(_n, _s, _f, _d) \
- DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_pci_devfn, int32_t)
-
-#define DEFINE_PROP_CHR(_n, _s, _f) \
- DEFINE_PROP(_n, _s, _f, qdev_prop_chr, CharBackend)
#define DEFINE_PROP_STRING(_n, _s, _f) \
DEFINE_PROP(_n, _s, _f, qdev_prop_string, char*)
-#define DEFINE_PROP_NETDEV(_n, _s, _f) \
- DEFINE_PROP(_n, _s, _f, qdev_prop_netdev, NICPeers)
-#define DEFINE_PROP_DRIVE(_n, _s, _f) \
- DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockBackend *)
-#define DEFINE_PROP_DRIVE_IOTHREAD(_n, _s, _f) \
- DEFINE_PROP(_n, _s, _f, qdev_prop_drive_iothread, BlockBackend *)
-#define DEFINE_PROP_MACADDR(_n, _s, _f) \
- DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr)
-#define DEFINE_PROP_RESERVED_REGION(_n, _s, _f) \
- DEFINE_PROP(_n, _s, _f, qdev_prop_reserved_region, ReservedRegion)
#define DEFINE_PROP_ON_OFF_AUTO(_n, _s, _f, _d) \
DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_on_off_auto, OnOffAuto)
-#define DEFINE_PROP_MULTIFD_COMPRESSION(_n, _s, _f, _d) \
- DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_multifd_compression, \
- MultiFDCompression)
-#define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \
- DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_losttickpolicy, \
- LostTickPolicy)
-#define DEFINE_PROP_BLOCKDEV_ON_ERROR(_n, _s, _f, _d) \
- DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_blockdev_on_error, \
- BlockdevOnError)
-#define DEFINE_PROP_BIOS_CHS_TRANS(_n, _s, _f, _d) \
- DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_bios_chs_trans, int)
#define DEFINE_PROP_SIZE32(_n, _s, _f, _d) \
DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, qdev_prop_size32, uint32_t)
-#define DEFINE_PROP_BLOCKSIZE(_n, _s, _f) \
- DEFINE_PROP_UNSIGNED(_n, _s, _f, 0, qdev_prop_blocksize, uint32_t)
-#define DEFINE_PROP_PCI_HOST_DEVADDR(_n, _s, _f) \
- DEFINE_PROP(_n, _s, _f, qdev_prop_pci_host_devaddr, PCIHostDeviceAddress)
-#define DEFINE_PROP_OFF_AUTO_PCIBAR(_n, _s, _f, _d) \
- DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_off_auto_pcibar, \
- OffAutoPCIBAR)
-#define DEFINE_PROP_PCIE_LINK_SPEED(_n, _s, _f, _d) \
- DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_pcie_link_speed, \
- PCIExpLinkSpeed)
-#define DEFINE_PROP_PCIE_LINK_WIDTH(_n, _s, _f, _d) \
- DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_pcie_link_width, \
- PCIExpLinkWidth)
-
-#define DEFINE_PROP_UUID(_name, _state, _field) { \
- .name = (_name), \
- .info = &qdev_prop_uuid, \
- .offset = offsetof(_state, _field) \
- + type_check(QemuUUID, typeof_field(_state, _field)), \
- .set_default = true, \
- }
-#define DEFINE_PROP_AUDIODEV(_n, _s, _f) \
- DEFINE_PROP(_n, _s, _f, qdev_prop_audiodev, QEMUSoundCard)
-
-#define DEFINE_PROP_UUID_NODEFAULT(_name, _state, _field) { \
- .name = (_name), \
- .info = &qdev_prop_uuid, \
- .offset = offsetof(_state, _field) \
- + type_check(QemuUUID, typeof_field(_state, _field)), \
- }
#define DEFINE_PROP_END_OF_LIST() \
{}
/*
* Set properties between creation and realization.
+ *
+ * Returns: %true on success, %false on error.
*/
bool qdev_prop_set_drive_err(DeviceState *dev, const char *name,
BlockBackend *value, Error **errp);
@@ -261,15 +201,18 @@ void qdev_prop_set_macaddr(DeviceState *dev, const char *name,
const uint8_t *value);
void qdev_prop_set_enum(DeviceState *dev, const char *name, int value);
-void *qdev_get_prop_ptr(DeviceState *dev, Property *prop);
+/* Takes ownership of @values */
+void qdev_prop_set_array(DeviceState *dev, const char *name, QList *values);
+
+void *object_field_prop_ptr(Object *obj, Property *prop);
void qdev_prop_register_global(GlobalProperty *prop);
-const GlobalProperty *qdev_find_global_prop(DeviceState *dev,
+const GlobalProperty *qdev_find_global_prop(Object *obj,
const char *name);
int qdev_prop_check_globals(void);
void qdev_prop_set_globals(DeviceState *dev);
-void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
- Property *prop, const char *value);
+void error_set_from_qdev_prop_error(Error **errp, int ret, Object *obj,
+ const char *name, const char *value);
/**
* qdev_property_add_static:
@@ -287,8 +230,8 @@ void qdev_property_add_static(DeviceState *dev, Property *prop);
* @target: Device which has properties to be aliased
* @source: Object to add alias properties to
*
- * Add alias properties to the @source object for all qdev properties on
- * the @target DeviceState.
+ * Add alias properties to the @source object for all properties on the @target
+ * DeviceState.
*
* This is useful when @target is an internal implementation object
* owned by @source, and you want to expose all the properties of that
diff --git a/include/hw/rdma/rdma.h b/include/hw/rdma/rdma.h
deleted file mode 100644
index 68290fb58c..0000000000
--- a/include/hw/rdma/rdma.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * RDMA device interface
- *
- * Copyright (C) 2019 Oracle
- * Copyright (C) 2019 Red Hat Inc
- *
- * Authors:
- * Yuval Shaia <yuval.shaia@oracle.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-
-#ifndef RDMA_H
-#define RDMA_H
-
-#include "qom/object.h"
-
-#define INTERFACE_RDMA_PROVIDER "rdma"
-
-#define INTERFACE_RDMA_PROVIDER_CLASS(klass) \
- OBJECT_CLASS_CHECK(RdmaProviderClass, (klass), \
- INTERFACE_RDMA_PROVIDER)
-#define RDMA_PROVIDER_GET_CLASS(obj) \
- OBJECT_GET_CLASS(RdmaProviderClass, (obj), \
- INTERFACE_RDMA_PROVIDER)
-#define RDMA_PROVIDER(obj) \
- INTERFACE_CHECK(RdmaProvider, (obj), \
- INTERFACE_RDMA_PROVIDER)
-
-typedef struct RdmaProvider RdmaProvider;
-
-typedef struct RdmaProviderClass {
- InterfaceClass parent;
-
- void (*print_statistics)(Monitor *mon, RdmaProvider *obj);
-} RdmaProviderClass;
-
-#endif
diff --git a/include/hw/register.h b/include/hw/register.h
index 5d2c565ae0..6a076cfcdf 100644
--- a/include/hw/register.h
+++ b/include/hw/register.h
@@ -14,6 +14,7 @@
#include "hw/qdev-core.h"
#include "exec/memory.h"
#include "hw/registerfields.h"
+#include "qom/object.h"
typedef struct RegisterInfo RegisterInfo;
typedef struct RegisterAccessInfo RegisterAccessInfo;
@@ -86,8 +87,9 @@ struct RegisterInfo {
void *opaque;
};
-#define TYPE_REGISTER "qemu,register"
-#define REGISTER(obj) OBJECT_CHECK(RegisterInfo, (obj), TYPE_REGISTER)
+#define TYPE_REGISTER "qemu-register"
+DECLARE_INSTANCE_CHECKER(RegisterInfo, REGISTER,
+ TYPE_REGISTER)
/**
* This structure is used to group all of the individual registers which are
@@ -181,6 +183,7 @@ uint64_t register_read_memory(void *opaque, hwaddr addr, unsigned size);
* @data: Array to use for register data, must already be allocated
* @ops: Memory region ops to access registers.
* @debug enabled: turn on/off verbose debug information
+ * @memory_size: Size of the memory region
* returns: A structure containing all of the registers and an initialized
* memory region (r_array->mem) the caller should add to a container.
*/
@@ -201,6 +204,14 @@ RegisterInfoArray *register_init_block32(DeviceState *owner,
bool debug_enabled,
uint64_t memory_size);
+RegisterInfoArray *register_init_block64(DeviceState *owner,
+ const RegisterAccessInfo *rae,
+ int num, RegisterInfo *ri,
+ uint64_t *data,
+ const MemoryRegionOps *ops,
+ bool debug_enabled,
+ uint64_t memory_size);
+
/**
* This function should be called to cleanup the registers that were initialized
* when calling register_init_block32(). This function should only be called
diff --git a/include/hw/registerfields.h b/include/hw/registerfields.h
index 93fa4a84c2..1330ca77de 100644
--- a/include/hw/registerfields.h
+++ b/include/hw/registerfields.h
@@ -30,6 +30,10 @@
enum { A_ ## reg = (addr) }; \
enum { R_ ## reg = (addr) / 2 };
+#define REG64(reg, addr) \
+ enum { A_ ## reg = (addr) }; \
+ enum { R_ ## reg = (addr) / 8 };
+
/* Define SHIFT, LENGTH and MASK constants for a field within a register */
/* This macro will define R_FOO_BAR_MASK, R_FOO_BAR_SHIFT and R_FOO_BAR_LENGTH
@@ -55,9 +59,24 @@
extract64((storage), R_ ## reg ## _ ## field ## _SHIFT, \
R_ ## reg ## _ ## field ## _LENGTH)
+#define FIELD_SEX8(storage, reg, field) \
+ sextract8((storage), R_ ## reg ## _ ## field ## _SHIFT, \
+ R_ ## reg ## _ ## field ## _LENGTH)
+#define FIELD_SEX16(storage, reg, field) \
+ sextract16((storage), R_ ## reg ## _ ## field ## _SHIFT, \
+ R_ ## reg ## _ ## field ## _LENGTH)
+#define FIELD_SEX32(storage, reg, field) \
+ sextract32((storage), R_ ## reg ## _ ## field ## _SHIFT, \
+ R_ ## reg ## _ ## field ## _LENGTH)
+#define FIELD_SEX64(storage, reg, field) \
+ sextract64((storage), R_ ## reg ## _ ## field ## _SHIFT, \
+ R_ ## reg ## _ ## field ## _LENGTH)
+
/* Extract a field from an array of registers */
#define ARRAY_FIELD_EX32(regs, reg, field) \
FIELD_EX32((regs)[R_ ## reg], reg, field)
+#define ARRAY_FIELD_EX64(regs, reg, field) \
+ FIELD_EX64((regs)[R_ ## reg], reg, field)
/* Deposit a register field.
* Assigning values larger then the target field will result in
@@ -89,7 +108,40 @@
_d; })
#define FIELD_DP64(storage, reg, field, val) ({ \
struct { \
- unsigned int v:R_ ## reg ## _ ## field ## _LENGTH; \
+ uint64_t v:R_ ## reg ## _ ## field ## _LENGTH; \
+ } _v = { .v = val }; \
+ uint64_t _d; \
+ _d = deposit64((storage), R_ ## reg ## _ ## field ## _SHIFT, \
+ R_ ## reg ## _ ## field ## _LENGTH, _v.v); \
+ _d; })
+
+#define FIELD_SDP8(storage, reg, field, val) ({ \
+ struct { \
+ signed int v:R_ ## reg ## _ ## field ## _LENGTH; \
+ } _v = { .v = val }; \
+ uint8_t _d; \
+ _d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \
+ R_ ## reg ## _ ## field ## _LENGTH, _v.v); \
+ _d; })
+#define FIELD_SDP16(storage, reg, field, val) ({ \
+ struct { \
+ signed int v:R_ ## reg ## _ ## field ## _LENGTH; \
+ } _v = { .v = val }; \
+ uint16_t _d; \
+ _d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \
+ R_ ## reg ## _ ## field ## _LENGTH, _v.v); \
+ _d; })
+#define FIELD_SDP32(storage, reg, field, val) ({ \
+ struct { \
+ signed int v:R_ ## reg ## _ ## field ## _LENGTH; \
+ } _v = { .v = val }; \
+ uint32_t _d; \
+ _d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \
+ R_ ## reg ## _ ## field ## _LENGTH, _v.v); \
+ _d; })
+#define FIELD_SDP64(storage, reg, field, val) ({ \
+ struct { \
+ int64_t v:R_ ## reg ## _ ## field ## _LENGTH; \
} _v = { .v = val }; \
uint64_t _d; \
_d = deposit64((storage), R_ ## reg ## _ ## field ## _SHIFT, \
@@ -99,5 +151,77 @@
/* Deposit a field to array of registers. */
#define ARRAY_FIELD_DP32(regs, reg, field, val) \
(regs)[R_ ## reg] = FIELD_DP32((regs)[R_ ## reg], reg, field, val);
+#define ARRAY_FIELD_DP64(regs, reg, field, val) \
+ (regs)[R_ ## reg] = FIELD_DP64((regs)[R_ ## reg], reg, field, val);
+
+
+/*
+ * These macros can be used for defining and extracting fields that have the
+ * same bit position across multiple registers.
+ */
+
+/* Define shared SHIFT, LENGTH, and MASK constants */
+#define SHARED_FIELD(name, shift, length) \
+ enum { name ## _ ## SHIFT = (shift)}; \
+ enum { name ## _ ## LENGTH = (length)}; \
+ enum { name ## _ ## MASK = MAKE_64BIT_MASK(shift, length)};
+
+/* Extract a shared field */
+#define SHARED_FIELD_EX8(storage, field) \
+ extract8((storage), field ## _SHIFT, field ## _LENGTH)
+
+#define SHARED_FIELD_EX16(storage, field) \
+ extract16((storage), field ## _SHIFT, field ## _LENGTH)
+
+#define SHARED_FIELD_EX32(storage, field) \
+ extract32((storage), field ## _SHIFT, field ## _LENGTH)
+
+#define SHARED_FIELD_EX64(storage, field) \
+ extract64((storage), field ## _SHIFT, field ## _LENGTH)
+
+/* Extract a shared field from a register array */
+#define SHARED_ARRAY_FIELD_EX32(regs, offset, field) \
+ SHARED_FIELD_EX32((regs)[(offset)], field)
+#define SHARED_ARRAY_FIELD_EX64(regs, offset, field) \
+ SHARED_FIELD_EX64((regs)[(offset)], field)
+
+/* Deposit a shared field */
+#define SHARED_FIELD_DP8(storage, field, val) ({ \
+ struct { \
+ unsigned int v:field ## _LENGTH; \
+ } _v = { .v = val }; \
+ uint8_t _d; \
+ _d = deposit32((storage), field ## _SHIFT, field ## _LENGTH, _v.v); \
+ _d; })
+
+#define SHARED_FIELD_DP16(storage, field, val) ({ \
+ struct { \
+ unsigned int v:field ## _LENGTH; \
+ } _v = { .v = val }; \
+ uint16_t _d; \
+ _d = deposit32((storage), field ## _SHIFT, field ## _LENGTH, _v.v); \
+ _d; })
+
+#define SHARED_FIELD_DP32(storage, field, val) ({ \
+ struct { \
+ unsigned int v:field ## _LENGTH; \
+ } _v = { .v = val }; \
+ uint32_t _d; \
+ _d = deposit32((storage), field ## _SHIFT, field ## _LENGTH, _v.v); \
+ _d; })
+
+#define SHARED_FIELD_DP64(storage, field, val) ({ \
+ struct { \
+ uint64_t v:field ## _LENGTH; \
+ } _v = { .v = val }; \
+ uint64_t _d; \
+ _d = deposit64((storage), field ## _SHIFT, field ## _LENGTH, _v.v); \
+ _d; })
+
+/* Deposit a shared field to a register array */
+#define SHARED_ARRAY_FIELD_DP32(regs, offset, field, val) \
+ (regs)[(offset)] = SHARED_FIELD_DP32((regs)[(offset)], field, val);
+#define SHARED_ARRAY_FIELD_DP64(regs, offset, field, val) \
+ (regs)[(offset)] = SHARED_FIELD_DP64((regs)[(offset)], field, val);
#endif
diff --git a/include/hw/remote/iohub.h b/include/hw/remote/iohub.h
new file mode 100644
index 0000000000..6a8444f9a9
--- /dev/null
+++ b/include/hw/remote/iohub.h
@@ -0,0 +1,42 @@
+/*
+ * IO Hub for remote device
+ *
+ * Copyright © 2018, 2021 Oracle and/or its affiliates.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef REMOTE_IOHUB_H
+#define REMOTE_IOHUB_H
+
+#include "hw/pci/pci_device.h"
+#include "qemu/event_notifier.h"
+#include "qemu/thread-posix.h"
+#include "hw/remote/mpqemu-link.h"
+
+#define REMOTE_IOHUB_NB_PIRQS PCI_DEVFN_MAX
+
+typedef struct ResampleToken {
+ void *iohub;
+ int pirq;
+} ResampleToken;
+
+typedef struct RemoteIOHubState {
+ PCIDevice d;
+ EventNotifier irqfds[REMOTE_IOHUB_NB_PIRQS];
+ EventNotifier resamplefds[REMOTE_IOHUB_NB_PIRQS];
+ unsigned int irq_level[REMOTE_IOHUB_NB_PIRQS];
+ ResampleToken token[REMOTE_IOHUB_NB_PIRQS];
+ QemuMutex irq_level_lock[REMOTE_IOHUB_NB_PIRQS];
+} RemoteIOHubState;
+
+int remote_iohub_map_irq(PCIDevice *pci_dev, int intx);
+void remote_iohub_set_irq(void *opaque, int pirq, int level);
+void process_set_irqfd_msg(PCIDevice *pci_dev, MPQemuMsg *msg);
+
+void remote_iohub_init(RemoteIOHubState *iohub);
+void remote_iohub_finalize(RemoteIOHubState *iohub);
+
+#endif
diff --git a/include/hw/remote/iommu.h b/include/hw/remote/iommu.h
new file mode 100644
index 0000000000..33b68a8f4b
--- /dev/null
+++ b/include/hw/remote/iommu.h
@@ -0,0 +1,40 @@
+/**
+ * Copyright © 2022 Oracle and/or its affiliates.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef REMOTE_IOMMU_H
+#define REMOTE_IOMMU_H
+
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci.h"
+
+#ifndef INT2VOIDP
+#define INT2VOIDP(i) (void *)(uintptr_t)(i)
+#endif
+
+typedef struct RemoteIommuElem {
+ MemoryRegion *mr;
+
+ AddressSpace as;
+} RemoteIommuElem;
+
+#define TYPE_REMOTE_IOMMU "x-remote-iommu"
+OBJECT_DECLARE_SIMPLE_TYPE(RemoteIommu, REMOTE_IOMMU)
+
+struct RemoteIommu {
+ Object parent;
+
+ GHashTable *elem_by_devfn;
+
+ QemuMutex lock;
+};
+
+void remote_iommu_setup(PCIBus *pci_bus);
+
+void remote_iommu_unplug_dev(PCIDevice *pci_dev);
+
+#endif
diff --git a/include/hw/remote/machine.h b/include/hw/remote/machine.h
new file mode 100644
index 0000000000..ac32fda387
--- /dev/null
+++ b/include/hw/remote/machine.h
@@ -0,0 +1,42 @@
+/*
+ * Remote machine configuration
+ *
+ * Copyright © 2018, 2021 Oracle and/or its affiliates.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef REMOTE_MACHINE_H
+#define REMOTE_MACHINE_H
+
+#include "qom/object.h"
+#include "hw/boards.h"
+#include "hw/pci-host/remote.h"
+#include "io/channel.h"
+#include "hw/remote/iohub.h"
+
+struct RemoteMachineState {
+ MachineState parent_obj;
+
+ RemotePCIHost *host;
+ RemoteIOHubState iohub;
+
+ bool vfio_user;
+
+ bool auto_shutdown;
+};
+
+/* Used to pass to co-routine device and ioc. */
+typedef struct RemoteCommDev {
+ PCIDevice *dev;
+ QIOChannel *ioc;
+} RemoteCommDev;
+
+#define TYPE_REMOTE_MACHINE "x-remote-machine"
+OBJECT_DECLARE_SIMPLE_TYPE(RemoteMachineState, REMOTE_MACHINE)
+
+void coroutine_fn mpqemu_remote_msg_loop_co(void *data);
+
+#endif
diff --git a/include/hw/remote/memory.h b/include/hw/remote/memory.h
new file mode 100644
index 0000000000..bc2e30945f
--- /dev/null
+++ b/include/hw/remote/memory.h
@@ -0,0 +1,19 @@
+/*
+ * Memory manager for remote device
+ *
+ * Copyright © 2018, 2021 Oracle and/or its affiliates.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef REMOTE_MEMORY_H
+#define REMOTE_MEMORY_H
+
+#include "exec/hwaddr.h"
+#include "hw/remote/mpqemu-link.h"
+
+void remote_sysmem_reconfig(MPQemuMsg *msg, Error **errp);
+
+#endif
diff --git a/include/hw/remote/mpqemu-link.h b/include/hw/remote/mpqemu-link.h
new file mode 100644
index 0000000000..4ec0915885
--- /dev/null
+++ b/include/hw/remote/mpqemu-link.h
@@ -0,0 +1,99 @@
+/*
+ * Communication channel between QEMU and remote device process
+ *
+ * Copyright © 2018, 2021 Oracle and/or its affiliates.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef MPQEMU_LINK_H
+#define MPQEMU_LINK_H
+
+#include "qom/object.h"
+#include "qemu/thread.h"
+#include "io/channel.h"
+#include "exec/hwaddr.h"
+#include "io/channel-socket.h"
+#include "hw/remote/proxy.h"
+
+#define REMOTE_MAX_FDS 8
+
+#define MPQEMU_MSG_HDR_SIZE offsetof(MPQemuMsg, data.u64)
+
+/**
+ * MPQemuCmd:
+ *
+ * MPQemuCmd enum type to specify the command to be executed on the remote
+ * device.
+ *
+ * This uses a private protocol between QEMU and the remote process. vfio-user
+ * protocol would supersede this in the future.
+ *
+ */
+typedef enum {
+ MPQEMU_CMD_SYNC_SYSMEM,
+ MPQEMU_CMD_RET,
+ MPQEMU_CMD_PCI_CFGWRITE,
+ MPQEMU_CMD_PCI_CFGREAD,
+ MPQEMU_CMD_BAR_WRITE,
+ MPQEMU_CMD_BAR_READ,
+ MPQEMU_CMD_SET_IRQFD,
+ MPQEMU_CMD_DEVICE_RESET,
+ MPQEMU_CMD_MAX,
+} MPQemuCmd;
+
+typedef struct {
+ hwaddr gpas[REMOTE_MAX_FDS];
+ uint64_t sizes[REMOTE_MAX_FDS];
+ off_t offsets[REMOTE_MAX_FDS];
+} SyncSysmemMsg;
+
+typedef struct {
+ uint32_t addr;
+ uint32_t val;
+ int len;
+} PciConfDataMsg;
+
+typedef struct {
+ hwaddr addr;
+ uint64_t val;
+ unsigned size;
+ bool memory;
+} BarAccessMsg;
+
+/**
+ * MPQemuMsg:
+ * @cmd: The remote command
+ * @size: Size of the data to be shared
+ * @data: Structured data
+ * @fds: File descriptors to be shared with remote device
+ *
+ * MPQemuMsg Format of the message sent to the remote device from QEMU.
+ *
+ */
+
+typedef struct {
+ int cmd;
+ size_t size;
+
+ union {
+ uint64_t u64;
+ PciConfDataMsg pci_conf_data;
+ SyncSysmemMsg sync_sysmem;
+ BarAccessMsg bar_access;
+ } data;
+
+ int fds[REMOTE_MAX_FDS];
+ int num_fds;
+} MPQemuMsg;
+
+bool mpqemu_msg_send(MPQemuMsg *msg, QIOChannel *ioc, Error **errp);
+bool mpqemu_msg_recv(MPQemuMsg *msg, QIOChannel *ioc, Error **errp);
+
+uint64_t mpqemu_msg_send_and_await_reply(MPQemuMsg *msg, PCIProxyDev *pdev,
+ Error **errp);
+bool mpqemu_msg_valid(MPQemuMsg *msg);
+
+#endif
diff --git a/include/hw/remote/proxy-memory-listener.h b/include/hw/remote/proxy-memory-listener.h
new file mode 100644
index 0000000000..c4f3efb928
--- /dev/null
+++ b/include/hw/remote/proxy-memory-listener.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright © 2018, 2021 Oracle and/or its affiliates.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef PROXY_MEMORY_LISTENER_H
+#define PROXY_MEMORY_LISTENER_H
+
+#include "exec/memory.h"
+#include "io/channel.h"
+
+typedef struct ProxyMemoryListener {
+ MemoryListener listener;
+
+ int n_mr_sections;
+ MemoryRegionSection *mr_sections;
+
+ QIOChannel *ioc;
+} ProxyMemoryListener;
+
+void proxy_memory_listener_configure(ProxyMemoryListener *proxy_listener,
+ QIOChannel *ioc);
+void proxy_memory_listener_deconfigure(ProxyMemoryListener *proxy_listener);
+
+#endif
diff --git a/include/hw/remote/proxy.h b/include/hw/remote/proxy.h
new file mode 100644
index 0000000000..0cfd9665be
--- /dev/null
+++ b/include/hw/remote/proxy.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright © 2018, 2021 Oracle and/or its affiliates.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef PROXY_H
+#define PROXY_H
+
+#include "hw/pci/pci_device.h"
+#include "io/channel.h"
+#include "hw/remote/proxy-memory-listener.h"
+#include "qemu/event_notifier.h"
+
+#define TYPE_PCI_PROXY_DEV "x-pci-proxy-dev"
+OBJECT_DECLARE_SIMPLE_TYPE(PCIProxyDev, PCI_PROXY_DEV)
+
+typedef struct ProxyMemoryRegion {
+ PCIProxyDev *dev;
+ MemoryRegion mr;
+ bool memory;
+ bool present;
+ uint8_t type;
+} ProxyMemoryRegion;
+
+struct PCIProxyDev {
+ PCIDevice parent_dev;
+ char *fd;
+
+ /*
+ * Mutex used to protect the QIOChannel fd from
+ * the concurrent access by the VCPUs since proxy
+ * blocks while awaiting for the replies from the
+ * process remote.
+ */
+ QemuMutex io_mutex;
+ QIOChannel *ioc;
+ Error *migration_blocker;
+ ProxyMemoryListener proxy_listener;
+ int virq;
+ EventNotifier intr;
+ EventNotifier resample;
+ ProxyMemoryRegion region[PCI_NUM_REGIONS];
+};
+
+#endif /* PROXY_H */
diff --git a/include/hw/remote/vfio-user-obj.h b/include/hw/remote/vfio-user-obj.h
new file mode 100644
index 0000000000..87ab78b875
--- /dev/null
+++ b/include/hw/remote/vfio-user-obj.h
@@ -0,0 +1,6 @@
+#ifndef VFIO_USER_OBJ_H
+#define VFIO_USER_OBJ_H
+
+void vfu_object_set_bus_irq(PCIBus *pci_bus);
+
+#endif
diff --git a/include/hw/resettable.h b/include/hw/resettable.h
index f4c4bab0ef..bdcd1276b6 100644
--- a/include/hw/resettable.h
+++ b/include/hw/resettable.h
@@ -17,11 +17,10 @@
#define TYPE_RESETTABLE_INTERFACE "resettable"
-#define RESETTABLE_CLASS(class) \
- OBJECT_CLASS_CHECK(ResettableClass, (class), TYPE_RESETTABLE_INTERFACE)
+typedef struct ResettableClass ResettableClass;
+DECLARE_CLASS_CHECKERS(ResettableClass, RESETTABLE,
+ TYPE_RESETTABLE_INTERFACE)
-#define RESETTABLE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(ResettableClass, (obj), TYPE_RESETTABLE_INTERFACE)
typedef struct ResettableState ResettableState;
@@ -119,7 +118,7 @@ typedef struct ResettablePhases {
ResettableHoldPhase hold;
ResettableExitPhase exit;
} ResettablePhases;
-typedef struct ResettableClass {
+struct ResettableClass {
InterfaceClass parent_class;
/* Phase methods */
@@ -133,7 +132,7 @@ typedef struct ResettableClass {
/* Hierarchy handling method */
ResettableChildForeach child_foreach;
-} ResettableClass;
+};
/**
* ResettableState:
diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
index 451338780a..a2e4ae9cb0 100644
--- a/include/hw/riscv/boot.h
+++ b/include/hw/riscv/boot.h
@@ -22,25 +22,45 @@
#include "exec/cpu-defs.h"
#include "hw/loader.h"
+#include "hw/riscv/riscv_hart.h"
-void riscv_find_and_load_firmware(MachineState *machine,
- const char *default_machine_firmware,
- hwaddr firmware_load_addr,
- symbol_fn_t sym_cb);
-char *riscv_find_firmware(const char *firmware_filename);
+#define RISCV32_BIOS_BIN "opensbi-riscv32-generic-fw_dynamic.bin"
+#define RISCV64_BIOS_BIN "opensbi-riscv64-generic-fw_dynamic.bin"
+
+bool riscv_is_32bit(RISCVHartArrayState *harts);
+
+char *riscv_plic_hart_config_string(int hart_count);
+
+target_ulong riscv_calc_kernel_start_addr(RISCVHartArrayState *harts,
+ target_ulong firmware_end_addr);
+target_ulong riscv_find_and_load_firmware(MachineState *machine,
+ const char *default_machine_firmware,
+ hwaddr firmware_load_addr,
+ symbol_fn_t sym_cb);
+const char *riscv_default_firmware_name(RISCVHartArrayState *harts);
+char *riscv_find_firmware(const char *firmware_filename,
+ const char *default_machine_firmware);
target_ulong riscv_load_firmware(const char *firmware_filename,
hwaddr firmware_load_addr,
symbol_fn_t sym_cb);
-target_ulong riscv_load_kernel(const char *kernel_filename,
+target_ulong riscv_load_kernel(MachineState *machine,
+ RISCVHartArrayState *harts,
+ target_ulong firmware_end_addr,
+ bool load_initrd,
symbol_fn_t sym_cb);
-hwaddr riscv_load_initrd(const char *filename, uint64_t mem_size,
- uint64_t kernel_entry, hwaddr *start);
-uint32_t riscv_load_fdt(hwaddr dram_start, uint64_t dram_size, void *fdt);
-void riscv_setup_rom_reset_vec(hwaddr saddr, hwaddr rom_base,
- hwaddr rom_size, uint64_t kernel_entry,
- uint32_t fdt_load_addr, void *fdt);
-void riscv_rom_copy_firmware_info(hwaddr rom_base, hwaddr rom_size,
+uint64_t riscv_compute_fdt_addr(hwaddr dram_start, uint64_t dram_size,
+ MachineState *ms);
+void riscv_load_fdt(hwaddr fdt_addr, void *fdt);
+void riscv_setup_rom_reset_vec(MachineState *machine, RISCVHartArrayState *harts,
+ hwaddr saddr,
+ hwaddr rom_base, hwaddr rom_size,
+ uint64_t kernel_entry,
+ uint64_t fdt_load_addr);
+void riscv_rom_copy_firmware_info(MachineState *machine, hwaddr rom_base,
+ hwaddr rom_size,
uint32_t reset_vec_size,
uint64_t kernel_entry);
+void riscv_setup_direct_kernel(hwaddr kernel_addr, hwaddr fdt_addr);
+void riscv_setup_firmware_boot(MachineState *machine);
#endif /* RISCV_BOOT_H */
diff --git a/include/hw/riscv/boot_opensbi.h b/include/hw/riscv/boot_opensbi.h
index 0d5ddd6c3d..1b749663dc 100644
--- a/include/hw/riscv/boot_opensbi.h
+++ b/include/hw/riscv/boot_opensbi.h
@@ -4,8 +4,11 @@
*
* Based on include/sbi/{fw_dynamic.h,sbi_scratch.h} from the OpenSBI project.
*/
-#ifndef OPENSBI_H
-#define OPENSBI_H
+
+#ifndef RISCV_BOOT_OPENSBI_H
+#define RISCV_BOOT_OPENSBI_H
+
+#include "exec/cpu-defs.h"
/** Expected value of info magic ('OSBI' ascii string in hex) */
#define FW_DYNAMIC_INFO_MAGIC_VALUE 0x4942534f
diff --git a/include/hw/riscv/microchip_pfsoc.h b/include/hw/riscv/microchip_pfsoc.h
new file mode 100644
index 0000000000..daef086da6
--- /dev/null
+++ b/include/hw/riscv/microchip_pfsoc.h
@@ -0,0 +1,168 @@
+/*
+ * Microchip PolarFire SoC machine interface
+ *
+ * Copyright (c) 2020 Wind River Systems, Inc.
+ *
+ * Author:
+ * Bin Meng <bin.meng@windriver.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_MICROCHIP_PFSOC_H
+#define HW_MICROCHIP_PFSOC_H
+
+#include "hw/boards.h"
+#include "hw/char/mchp_pfsoc_mmuart.h"
+#include "hw/cpu/cluster.h"
+#include "hw/dma/sifive_pdma.h"
+#include "hw/misc/mchp_pfsoc_dmc.h"
+#include "hw/misc/mchp_pfsoc_ioscb.h"
+#include "hw/misc/mchp_pfsoc_sysreg.h"
+#include "hw/net/cadence_gem.h"
+#include "hw/sd/cadence_sdhci.h"
+#include "hw/riscv/riscv_hart.h"
+
+typedef struct MicrochipPFSoCState {
+ /*< private >*/
+ DeviceState parent_obj;
+
+ /*< public >*/
+ CPUClusterState e_cluster;
+ CPUClusterState u_cluster;
+ RISCVHartArrayState e_cpus;
+ RISCVHartArrayState u_cpus;
+ DeviceState *plic;
+ MchpPfSoCDdrSgmiiPhyState ddr_sgmii_phy;
+ MchpPfSoCDdrCfgState ddr_cfg;
+ MchpPfSoCIoscbState ioscb;
+ MchpPfSoCMMUartState *serial0;
+ MchpPfSoCMMUartState *serial1;
+ MchpPfSoCMMUartState *serial2;
+ MchpPfSoCMMUartState *serial3;
+ MchpPfSoCMMUartState *serial4;
+ MchpPfSoCSysregState sysreg;
+ SiFivePDMAState dma;
+ CadenceGEMState gem0;
+ CadenceGEMState gem1;
+ CadenceSDHCIState sdhci;
+} MicrochipPFSoCState;
+
+#define TYPE_MICROCHIP_PFSOC "microchip.pfsoc"
+#define MICROCHIP_PFSOC(obj) \
+ OBJECT_CHECK(MicrochipPFSoCState, (obj), TYPE_MICROCHIP_PFSOC)
+
+typedef struct MicrochipIcicleKitState {
+ /*< private >*/
+ MachineState parent_obj;
+
+ /*< public >*/
+ MicrochipPFSoCState soc;
+} MicrochipIcicleKitState;
+
+#define TYPE_MICROCHIP_ICICLE_KIT_MACHINE \
+ MACHINE_TYPE_NAME("microchip-icicle-kit")
+#define MICROCHIP_ICICLE_KIT_MACHINE(obj) \
+ OBJECT_CHECK(MicrochipIcicleKitState, (obj), \
+ TYPE_MICROCHIP_ICICLE_KIT_MACHINE)
+
+enum {
+ MICROCHIP_PFSOC_RSVD0,
+ MICROCHIP_PFSOC_DEBUG,
+ MICROCHIP_PFSOC_E51_DTIM,
+ MICROCHIP_PFSOC_BUSERR_UNIT0,
+ MICROCHIP_PFSOC_BUSERR_UNIT1,
+ MICROCHIP_PFSOC_BUSERR_UNIT2,
+ MICROCHIP_PFSOC_BUSERR_UNIT3,
+ MICROCHIP_PFSOC_BUSERR_UNIT4,
+ MICROCHIP_PFSOC_CLINT,
+ MICROCHIP_PFSOC_L2CC,
+ MICROCHIP_PFSOC_DMA,
+ MICROCHIP_PFSOC_L2LIM,
+ MICROCHIP_PFSOC_PLIC,
+ MICROCHIP_PFSOC_MMUART0,
+ MICROCHIP_PFSOC_WDOG0,
+ MICROCHIP_PFSOC_SYSREG,
+ MICROCHIP_PFSOC_AXISW,
+ MICROCHIP_PFSOC_MPUCFG,
+ MICROCHIP_PFSOC_FMETER,
+ MICROCHIP_PFSOC_DDR_SGMII_PHY,
+ MICROCHIP_PFSOC_EMMC_SD,
+ MICROCHIP_PFSOC_DDR_CFG,
+ MICROCHIP_PFSOC_MMUART1,
+ MICROCHIP_PFSOC_MMUART2,
+ MICROCHIP_PFSOC_MMUART3,
+ MICROCHIP_PFSOC_MMUART4,
+ MICROCHIP_PFSOC_WDOG1,
+ MICROCHIP_PFSOC_WDOG2,
+ MICROCHIP_PFSOC_WDOG3,
+ MICROCHIP_PFSOC_WDOG4,
+ MICROCHIP_PFSOC_SPI0,
+ MICROCHIP_PFSOC_SPI1,
+ MICROCHIP_PFSOC_I2C0,
+ MICROCHIP_PFSOC_I2C1,
+ MICROCHIP_PFSOC_CAN0,
+ MICROCHIP_PFSOC_CAN1,
+ MICROCHIP_PFSOC_GEM0,
+ MICROCHIP_PFSOC_GEM1,
+ MICROCHIP_PFSOC_GPIO0,
+ MICROCHIP_PFSOC_GPIO1,
+ MICROCHIP_PFSOC_GPIO2,
+ MICROCHIP_PFSOC_RTC,
+ MICROCHIP_PFSOC_ENVM_CFG,
+ MICROCHIP_PFSOC_ENVM_DATA,
+ MICROCHIP_PFSOC_USB,
+ MICROCHIP_PFSOC_QSPI_XIP,
+ MICROCHIP_PFSOC_IOSCB,
+ MICROCHIP_PFSOC_FABRIC_FIC0,
+ MICROCHIP_PFSOC_FABRIC_FIC1,
+ MICROCHIP_PFSOC_FABRIC_FIC3,
+ MICROCHIP_PFSOC_DRAM_LO,
+ MICROCHIP_PFSOC_DRAM_LO_ALIAS,
+ MICROCHIP_PFSOC_DRAM_HI,
+ MICROCHIP_PFSOC_DRAM_HI_ALIAS
+};
+
+enum {
+ MICROCHIP_PFSOC_DMA_IRQ0 = 5,
+ MICROCHIP_PFSOC_DMA_IRQ1 = 6,
+ MICROCHIP_PFSOC_DMA_IRQ2 = 7,
+ MICROCHIP_PFSOC_DMA_IRQ3 = 8,
+ MICROCHIP_PFSOC_DMA_IRQ4 = 9,
+ MICROCHIP_PFSOC_DMA_IRQ5 = 10,
+ MICROCHIP_PFSOC_DMA_IRQ6 = 11,
+ MICROCHIP_PFSOC_DMA_IRQ7 = 12,
+ MICROCHIP_PFSOC_GEM0_IRQ = 64,
+ MICROCHIP_PFSOC_GEM1_IRQ = 70,
+ MICROCHIP_PFSOC_EMMC_SD_IRQ = 88,
+ MICROCHIP_PFSOC_MMUART0_IRQ = 90,
+ MICROCHIP_PFSOC_MMUART1_IRQ = 91,
+ MICROCHIP_PFSOC_MMUART2_IRQ = 92,
+ MICROCHIP_PFSOC_MMUART3_IRQ = 93,
+ MICROCHIP_PFSOC_MMUART4_IRQ = 94,
+ MICROCHIP_PFSOC_MAILBOX_IRQ = 96,
+};
+
+#define MICROCHIP_PFSOC_MANAGEMENT_CPU_COUNT 1
+#define MICROCHIP_PFSOC_COMPUTE_CPU_COUNT 4
+
+#define MICROCHIP_PFSOC_PLIC_NUM_SOURCES 187
+#define MICROCHIP_PFSOC_PLIC_NUM_PRIORITIES 7
+#define MICROCHIP_PFSOC_PLIC_PRIORITY_BASE 0x00
+#define MICROCHIP_PFSOC_PLIC_PENDING_BASE 0x1000
+#define MICROCHIP_PFSOC_PLIC_ENABLE_BASE 0x2000
+#define MICROCHIP_PFSOC_PLIC_ENABLE_STRIDE 0x80
+#define MICROCHIP_PFSOC_PLIC_CONTEXT_BASE 0x200000
+#define MICROCHIP_PFSOC_PLIC_CONTEXT_STRIDE 0x1000
+
+#endif /* HW_MICROCHIP_PFSOC_H */
diff --git a/include/hw/riscv/numa.h b/include/hw/riscv/numa.h
new file mode 100644
index 0000000000..8f5280211d
--- /dev/null
+++ b/include/hw/riscv/numa.h
@@ -0,0 +1,114 @@
+/*
+ * QEMU RISC-V NUMA Helper
+ *
+ * Copyright (c) 2020 Western Digital Corporation or its affiliates.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef RISCV_NUMA_H
+#define RISCV_NUMA_H
+
+#include "hw/boards.h"
+#include "hw/sysbus.h"
+#include "sysemu/numa.h"
+
+/**
+ * riscv_socket_count:
+ * @ms: pointer to machine state
+ *
+ * Returns: number of sockets for a numa system and 1 for a non-numa system
+ */
+int riscv_socket_count(const MachineState *ms);
+
+/**
+ * riscv_socket_first_hartid:
+ * @ms: pointer to machine state
+ * @socket_id: socket index
+ *
+ * Returns: first hartid for a valid socket and -1 for an invalid socket
+ */
+int riscv_socket_first_hartid(const MachineState *ms, int socket_id);
+
+/**
+ * riscv_socket_last_hartid:
+ * @ms: pointer to machine state
+ * @socket_id: socket index
+ *
+ * Returns: last hartid for a valid socket and -1 for an invalid socket
+ */
+int riscv_socket_last_hartid(const MachineState *ms, int socket_id);
+
+/**
+ * riscv_socket_hart_count:
+ * @ms: pointer to machine state
+ * @socket_id: socket index
+ *
+ * Returns: number of harts for a valid socket and -1 for an invalid socket
+ */
+int riscv_socket_hart_count(const MachineState *ms, int socket_id);
+
+/**
+ * riscv_socket_mem_offset:
+ * @ms: pointer to machine state
+ * @socket_id: socket index
+ *
+ * Returns: offset of ram belonging to given socket
+ */
+uint64_t riscv_socket_mem_offset(const MachineState *ms, int socket_id);
+
+/**
+ * riscv_socket_mem_size:
+ * @ms: pointer to machine state
+ * @socket_id: socket index
+ *
+ * Returns: size of ram belonging to given socket
+ */
+uint64_t riscv_socket_mem_size(const MachineState *ms, int socket_id);
+
+/**
+ * riscv_socket_check_hartids:
+ * @ms: pointer to machine state
+ * @socket_id: socket index
+ *
+ * Returns: true if hardids belonging to given socket are contiguous else false
+ */
+bool riscv_socket_check_hartids(const MachineState *ms, int socket_id);
+
+/**
+ * riscv_socket_fdt_write_id:
+ * @ms: pointer to machine state
+ * @socket_id: socket index
+ *
+ * Write NUMA node-id FDT property in MachineState->fdt
+ */
+void riscv_socket_fdt_write_id(const MachineState *ms, const char *node_name,
+ int socket_id);
+
+/**
+ * riscv_socket_fdt_write_distance_matrix:
+ * @ms: pointer to machine state
+ * @socket_id: socket index
+ *
+ * Write NUMA distance matrix in MachineState->fdt
+ */
+void riscv_socket_fdt_write_distance_matrix(const MachineState *ms);
+
+CpuInstanceProperties
+riscv_numa_cpu_index_to_props(MachineState *ms, unsigned cpu_index);
+
+int64_t riscv_numa_get_default_cpu_node_id(const MachineState *ms, int idx);
+
+const CPUArchIdList *riscv_numa_possible_cpu_arch_ids(MachineState *ms);
+
+#endif /* RISCV_NUMA_H */
diff --git a/include/hw/riscv/opentitan.h b/include/hw/riscv/opentitan.h
index 8f29b9cbbf..609473d07b 100644
--- a/include/hw/riscv/opentitan.h
+++ b/include/hw/riscv/opentitan.h
@@ -20,65 +20,103 @@
#define HW_OPENTITAN_H
#include "hw/riscv/riscv_hart.h"
-#include "hw/intc/ibex_plic.h"
+#include "hw/intc/sifive_plic.h"
#include "hw/char/ibex_uart.h"
+#include "hw/timer/ibex_timer.h"
+#include "hw/ssi/ibex_spi_host.h"
+#include "hw/boards.h"
+#include "qom/object.h"
#define TYPE_RISCV_IBEX_SOC "riscv.lowrisc.ibex.soc"
-#define RISCV_IBEX_SOC(obj) \
- OBJECT_CHECK(LowRISCIbexSoCState, (obj), TYPE_RISCV_IBEX_SOC)
+OBJECT_DECLARE_SIMPLE_TYPE(LowRISCIbexSoCState, RISCV_IBEX_SOC)
-typedef struct LowRISCIbexSoCState {
+enum {
+ OPENTITAN_SPI_HOST0,
+ OPENTITAN_SPI_HOST1,
+ OPENTITAN_NUM_SPI_HOSTS,
+};
+
+struct LowRISCIbexSoCState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
RISCVHartArrayState cpus;
- IbexPlicState plic;
+ SiFivePLICState plic;
IbexUartState uart;
+ IbexTimerState timer;
+ IbexSPIHostState spi_host[OPENTITAN_NUM_SPI_HOSTS];
+
+ uint32_t resetvec;
MemoryRegion flash_mem;
MemoryRegion rom;
-} LowRISCIbexSoCState;
+ MemoryRegion flash_alias;
+};
+
+#define TYPE_OPENTITAN_MACHINE MACHINE_TYPE_NAME("opentitan")
+OBJECT_DECLARE_SIMPLE_TYPE(OpenTitanState, OPENTITAN_MACHINE)
typedef struct OpenTitanState {
/*< private >*/
- SysBusDevice parent_obj;
+ MachineState parent_obj;
/*< public >*/
LowRISCIbexSoCState soc;
} OpenTitanState;
enum {
- IBEX_ROM,
- IBEX_RAM,
- IBEX_FLASH,
- IBEX_UART,
- IBEX_GPIO,
- IBEX_SPI,
- IBEX_FLASH_CTRL,
- IBEX_RV_TIMER,
- IBEX_AES,
- IBEX_HMAC,
- IBEX_PLIC,
- IBEX_PWRMGR,
- IBEX_RSTMGR,
- IBEX_CLKMGR,
- IBEX_PINMUX,
- IBEX_ALERT_HANDLER,
- IBEX_NMI_GEN,
- IBEX_USBDEV,
- IBEX_PADCTRL,
+ IBEX_DEV_ROM,
+ IBEX_DEV_RAM,
+ IBEX_DEV_FLASH,
+ IBEX_DEV_FLASH_VIRTUAL,
+ IBEX_DEV_UART,
+ IBEX_DEV_SPI_DEVICE,
+ IBEX_DEV_SPI_HOST0,
+ IBEX_DEV_SPI_HOST1,
+ IBEX_DEV_GPIO,
+ IBEX_DEV_I2C,
+ IBEX_DEV_PATTGEN,
+ IBEX_DEV_TIMER,
+ IBEX_DEV_SENSOR_CTRL,
+ IBEX_DEV_OTP_CTRL,
+ IBEX_DEV_LC_CTRL,
+ IBEX_DEV_PWRMGR,
+ IBEX_DEV_RSTMGR,
+ IBEX_DEV_CLKMGR,
+ IBEX_DEV_PINMUX,
+ IBEX_DEV_AON_TIMER,
+ IBEX_DEV_USBDEV,
+ IBEX_DEV_FLASH_CTRL,
+ IBEX_DEV_PLIC,
+ IBEX_DEV_AES,
+ IBEX_DEV_HMAC,
+ IBEX_DEV_KMAC,
+ IBEX_DEV_KEYMGR,
+ IBEX_DEV_CSRNG,
+ IBEX_DEV_ENTROPY,
+ IBEX_DEV_EDNO,
+ IBEX_DEV_EDN1,
+ IBEX_DEV_ALERT_HANDLER,
+ IBEX_DEV_SRAM_CTRL,
+ IBEX_DEV_OTBN,
+ IBEX_DEV_IBEX_CFG,
};
enum {
- IBEX_UART_RX_PARITY_ERR_IRQ = 0x28,
- IBEX_UART_RX_TIMEOUT_IRQ = 0x27,
- IBEX_UART_RX_BREAK_ERR_IRQ = 0x26,
- IBEX_UART_RX_FRAME_ERR_IRQ = 0x25,
- IBEX_UART_RX_OVERFLOW_IRQ = 0x24,
- IBEX_UART_TX_EMPTY_IRQ = 0x23,
- IBEX_UART_RX_WATERMARK_IRQ = 0x22,
- IBEX_UART_TX_WATERMARK_IRQ = 0x21,
+ IBEX_UART0_TX_WATERMARK_IRQ = 1,
+ IBEX_UART0_RX_WATERMARK_IRQ = 2,
+ IBEX_UART0_TX_EMPTY_IRQ = 3,
+ IBEX_UART0_RX_OVERFLOW_IRQ = 4,
+ IBEX_UART0_RX_FRAME_ERR_IRQ = 5,
+ IBEX_UART0_RX_BREAK_ERR_IRQ = 6,
+ IBEX_UART0_RX_TIMEOUT_IRQ = 7,
+ IBEX_UART0_RX_PARITY_ERR_IRQ = 8,
+ IBEX_TIMER_TIMEREXPIRED0_0 = 124,
+ IBEX_SPI_HOST0_ERR_IRQ = 131,
+ IBEX_SPI_HOST0_SPI_EVENT_IRQ = 132,
+ IBEX_SPI_HOST1_ERR_IRQ = 133,
+ IBEX_SPI_HOST1_SPI_EVENT_IRQ = 134,
};
#endif
diff --git a/include/hw/riscv/riscv_hart.h b/include/hw/riscv/riscv_hart.h
index c75856fa73..912b4a2682 100644
--- a/include/hw/riscv/riscv_hart.h
+++ b/include/hw/riscv/riscv_hart.h
@@ -3,7 +3,7 @@
*
* Copyright (c) 2017 SiFive, Inc.
*
- * Holds the state of a heterogenous array of RISC-V harts
+ * Holds the state of a heterogeneous array of RISC-V harts
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -23,13 +23,13 @@
#include "hw/sysbus.h"
#include "target/riscv/cpu.h"
+#include "qom/object.h"
#define TYPE_RISCV_HART_ARRAY "riscv.hart_array"
-#define RISCV_HART_ARRAY(obj) \
- OBJECT_CHECK(RISCVHartArrayState, (obj), TYPE_RISCV_HART_ARRAY)
+OBJECT_DECLARE_SIMPLE_TYPE(RISCVHartArrayState, RISCV_HART_ARRAY)
-typedef struct RISCVHartArrayState {
+struct RISCVHartArrayState {
/*< private >*/
SysBusDevice parent_obj;
@@ -37,7 +37,8 @@ typedef struct RISCVHartArrayState {
uint32_t num_harts;
uint32_t hartid_base;
char *cpu_type;
+ uint64_t resetvec;
RISCVCPU *harts;
-} RISCVHartArrayState;
+};
#endif
diff --git a/include/hw/riscv/shakti_c.h b/include/hw/riscv/shakti_c.h
new file mode 100644
index 0000000000..539fe1156d
--- /dev/null
+++ b/include/hw/riscv/shakti_c.h
@@ -0,0 +1,75 @@
+/*
+ * Shakti C-class SoC emulation
+ *
+ * Copyright (c) 2021 Vijai Kumar K <vijai@behindbytes.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_SHAKTI_C_H
+#define HW_SHAKTI_C_H
+
+#include "hw/riscv/riscv_hart.h"
+#include "hw/boards.h"
+#include "hw/char/shakti_uart.h"
+
+#define TYPE_RISCV_SHAKTI_SOC "riscv.shakti.cclass.soc"
+#define RISCV_SHAKTI_SOC(obj) \
+ OBJECT_CHECK(ShaktiCSoCState, (obj), TYPE_RISCV_SHAKTI_SOC)
+
+typedef struct ShaktiCSoCState {
+ /*< private >*/
+ DeviceState parent_obj;
+
+ /*< public >*/
+ RISCVHartArrayState cpus;
+ DeviceState *plic;
+ ShaktiUartState uart;
+ MemoryRegion rom;
+
+} ShaktiCSoCState;
+
+#define TYPE_RISCV_SHAKTI_MACHINE MACHINE_TYPE_NAME("shakti_c")
+#define RISCV_SHAKTI_MACHINE(obj) \
+ OBJECT_CHECK(ShaktiCMachineState, (obj), TYPE_RISCV_SHAKTI_MACHINE)
+typedef struct ShaktiCMachineState {
+ /*< private >*/
+ MachineState parent_obj;
+
+ /*< public >*/
+ ShaktiCSoCState soc;
+} ShaktiCMachineState;
+
+enum {
+ SHAKTI_C_ROM,
+ SHAKTI_C_RAM,
+ SHAKTI_C_UART,
+ SHAKTI_C_GPIO,
+ SHAKTI_C_PLIC,
+ SHAKTI_C_CLINT,
+ SHAKTI_C_I2C,
+};
+
+#define SHAKTI_C_PLIC_HART_CONFIG "MS"
+/* Including Interrupt ID 0 (no interrupt)*/
+#define SHAKTI_C_PLIC_NUM_SOURCES 28
+/* Excluding Priority 0 */
+#define SHAKTI_C_PLIC_NUM_PRIORITIES 2
+#define SHAKTI_C_PLIC_PRIORITY_BASE 0x00
+#define SHAKTI_C_PLIC_PENDING_BASE 0x1000
+#define SHAKTI_C_PLIC_ENABLE_BASE 0x2000
+#define SHAKTI_C_PLIC_ENABLE_STRIDE 0x80
+#define SHAKTI_C_PLIC_CONTEXT_BASE 0x200000
+#define SHAKTI_C_PLIC_CONTEXT_STRIDE 0x1000
+
+#endif
diff --git a/include/hw/riscv/sifive_clint.h b/include/hw/riscv/sifive_clint.h
deleted file mode 100644
index 4a720bfece..0000000000
--- a/include/hw/riscv/sifive_clint.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * SiFive CLINT (Core Local Interruptor) interface
- *
- * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
- * Copyright (c) 2017 SiFive, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2 or later, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef HW_SIFIVE_CLINT_H
-#define HW_SIFIVE_CLINT_H
-
-#include "hw/sysbus.h"
-
-#define TYPE_SIFIVE_CLINT "riscv.sifive.clint"
-
-#define SIFIVE_CLINT(obj) \
- OBJECT_CHECK(SiFiveCLINTState, (obj), TYPE_SIFIVE_CLINT)
-
-typedef struct SiFiveCLINTState {
- /*< private >*/
- SysBusDevice parent_obj;
-
- /*< public >*/
- MemoryRegion mmio;
- uint32_t num_harts;
- uint32_t sip_base;
- uint32_t timecmp_base;
- uint32_t time_base;
- uint32_t aperture_size;
-} SiFiveCLINTState;
-
-DeviceState *sifive_clint_create(hwaddr addr, hwaddr size, uint32_t num_harts,
- uint32_t sip_base, uint32_t timecmp_base, uint32_t time_base,
- bool provide_rdtime);
-
-enum {
- SIFIVE_SIP_BASE = 0x0,
- SIFIVE_TIMECMP_BASE = 0x4000,
- SIFIVE_TIME_BASE = 0xBFF8
-};
-
-enum {
- SIFIVE_CLINT_TIMEBASE_FREQ = 10000000
-};
-
-#endif
diff --git a/include/hw/riscv/sifive_e.h b/include/hw/riscv/sifive_e.h
index 637414130b..31180a680e 100644
--- a/include/hw/riscv/sifive_e.h
+++ b/include/hw/riscv/sifive_e.h
@@ -21,7 +21,9 @@
#include "hw/riscv/riscv_hart.h"
#include "hw/riscv/sifive_cpu.h"
-#include "hw/riscv/sifive_gpio.h"
+#include "hw/gpio/sifive_gpio.h"
+#include "hw/misc/sifive_e_aon.h"
+#include "hw/boards.h"
#define TYPE_RISCV_E_SOC "riscv.sifive.e.soc"
#define RISCV_E_SOC(obj) \
@@ -34,6 +36,7 @@ typedef struct SiFiveESoCState {
/*< public >*/
RISCVHartArrayState cpus;
DeviceState *plic;
+ SiFiveEAONState aon;
SIFIVEGPIOState gpio;
MemoryRegion xip_mem;
MemoryRegion mask_rom;
@@ -41,7 +44,7 @@ typedef struct SiFiveESoCState {
typedef struct SiFiveEState {
/*< private >*/
- SysBusDevice parent_obj;
+ MachineState parent_obj;
/*< public >*/
SiFiveESoCState soc;
@@ -53,37 +56,43 @@ typedef struct SiFiveEState {
OBJECT_CHECK(SiFiveEState, (obj), TYPE_RISCV_E_MACHINE)
enum {
- SIFIVE_E_DEBUG,
- SIFIVE_E_MROM,
- SIFIVE_E_OTP,
- SIFIVE_E_CLINT,
- SIFIVE_E_PLIC,
- SIFIVE_E_AON,
- SIFIVE_E_PRCI,
- SIFIVE_E_OTP_CTRL,
- SIFIVE_E_GPIO0,
- SIFIVE_E_UART0,
- SIFIVE_E_QSPI0,
- SIFIVE_E_PWM0,
- SIFIVE_E_UART1,
- SIFIVE_E_QSPI1,
- SIFIVE_E_PWM1,
- SIFIVE_E_QSPI2,
- SIFIVE_E_PWM2,
- SIFIVE_E_XIP,
- SIFIVE_E_DTIM
+ SIFIVE_E_DEV_DEBUG,
+ SIFIVE_E_DEV_MROM,
+ SIFIVE_E_DEV_OTP,
+ SIFIVE_E_DEV_CLINT,
+ SIFIVE_E_DEV_PLIC,
+ SIFIVE_E_DEV_AON,
+ SIFIVE_E_DEV_PRCI,
+ SIFIVE_E_DEV_OTP_CTRL,
+ SIFIVE_E_DEV_GPIO0,
+ SIFIVE_E_DEV_UART0,
+ SIFIVE_E_DEV_QSPI0,
+ SIFIVE_E_DEV_PWM0,
+ SIFIVE_E_DEV_UART1,
+ SIFIVE_E_DEV_QSPI1,
+ SIFIVE_E_DEV_PWM1,
+ SIFIVE_E_DEV_QSPI2,
+ SIFIVE_E_DEV_PWM2,
+ SIFIVE_E_DEV_XIP,
+ SIFIVE_E_DEV_DTIM
};
enum {
- SIFIVE_E_UART0_IRQ = 3,
- SIFIVE_E_UART1_IRQ = 4,
- SIFIVE_E_GPIO0_IRQ0 = 8
+ SIFIVE_E_AON_WDT_IRQ = 1,
+ SIFIVE_E_UART0_IRQ = 3,
+ SIFIVE_E_UART1_IRQ = 4,
+ SIFIVE_E_GPIO0_IRQ0 = 8
};
#define SIFIVE_E_PLIC_HART_CONFIG "M"
-#define SIFIVE_E_PLIC_NUM_SOURCES 127
+/*
+ * Freedom E310 G002 and G003 supports 52 interrupt sources while
+ * Freedom E310 G000 supports 51 interrupt sources. We use the value
+ * of G002 and G003, so it is 53 (including interrupt source 0).
+ */
+#define SIFIVE_E_PLIC_NUM_SOURCES 53
#define SIFIVE_E_PLIC_NUM_PRIORITIES 7
-#define SIFIVE_E_PLIC_PRIORITY_BASE 0x04
+#define SIFIVE_E_PLIC_PRIORITY_BASE 0x00
#define SIFIVE_E_PLIC_PENDING_BASE 0x1000
#define SIFIVE_E_PLIC_ENABLE_BASE 0x2000
#define SIFIVE_E_PLIC_ENABLE_STRIDE 0x80
diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h
index aba4d0181f..0696f85942 100644
--- a/include/hw/riscv/sifive_u.h
+++ b/include/hw/riscv/sifive_u.h
@@ -19,12 +19,17 @@
#ifndef HW_SIFIVE_U_H
#define HW_SIFIVE_U_H
+#include "hw/boards.h"
+#include "hw/cpu/cluster.h"
+#include "hw/dma/sifive_pdma.h"
#include "hw/net/cadence_gem.h"
#include "hw/riscv/riscv_hart.h"
#include "hw/riscv/sifive_cpu.h"
-#include "hw/riscv/sifive_gpio.h"
-#include "hw/riscv/sifive_u_prci.h"
-#include "hw/riscv/sifive_u_otp.h"
+#include "hw/gpio/sifive_gpio.h"
+#include "hw/misc/sifive_u_otp.h"
+#include "hw/misc/sifive_u_prci.h"
+#include "hw/ssi/sifive_spi.h"
+#include "hw/timer/sifive_pwm.h"
#define TYPE_RISCV_U_SOC "riscv.sifive.u.soc"
#define RISCV_U_SOC(obj) \
@@ -43,9 +48,14 @@ typedef struct SiFiveUSoCState {
SiFiveUPRCIState prci;
SIFIVEGPIOState gpio;
SiFiveUOTPState otp;
+ SiFivePDMAState dma;
+ SiFiveSPIState spi0;
+ SiFiveSPIState spi2;
CadenceGEMState gem;
+ SiFivePwmState pwm[2];
uint32_t serial;
+ char *cpu_type;
} SiFiveUSoCState;
#define TYPE_RISCV_U_MACHINE MACHINE_TYPE_NAME("sifive_u")
@@ -58,8 +68,6 @@ typedef struct SiFiveUState {
/*< public >*/
SiFiveUSoCState soc;
-
- void *fdt;
int fdt_size;
bool start_in_flash;
@@ -68,26 +76,36 @@ typedef struct SiFiveUState {
} SiFiveUState;
enum {
- SIFIVE_U_DEBUG,
- SIFIVE_U_MROM,
- SIFIVE_U_CLINT,
- SIFIVE_U_L2LIM,
- SIFIVE_U_PLIC,
- SIFIVE_U_PRCI,
- SIFIVE_U_UART0,
- SIFIVE_U_UART1,
- SIFIVE_U_GPIO,
- SIFIVE_U_OTP,
- SIFIVE_U_DMC,
- SIFIVE_U_FLASH0,
- SIFIVE_U_DRAM,
- SIFIVE_U_GEM,
- SIFIVE_U_GEM_MGMT
+ SIFIVE_U_DEV_DEBUG,
+ SIFIVE_U_DEV_MROM,
+ SIFIVE_U_DEV_CLINT,
+ SIFIVE_U_DEV_L2CC,
+ SIFIVE_U_DEV_PDMA,
+ SIFIVE_U_DEV_L2LIM,
+ SIFIVE_U_DEV_PLIC,
+ SIFIVE_U_DEV_PRCI,
+ SIFIVE_U_DEV_UART0,
+ SIFIVE_U_DEV_UART1,
+ SIFIVE_U_DEV_GPIO,
+ SIFIVE_U_DEV_QSPI0,
+ SIFIVE_U_DEV_QSPI2,
+ SIFIVE_U_DEV_OTP,
+ SIFIVE_U_DEV_DMC,
+ SIFIVE_U_DEV_FLASH0,
+ SIFIVE_U_DEV_DRAM,
+ SIFIVE_U_DEV_GEM,
+ SIFIVE_U_DEV_GEM_MGMT,
+ SIFIVE_U_DEV_PWM0,
+ SIFIVE_U_DEV_PWM1
};
enum {
+ SIFIVE_U_L2CC_IRQ0 = 1,
+ SIFIVE_U_L2CC_IRQ1 = 2,
+ SIFIVE_U_L2CC_IRQ2 = 3,
SIFIVE_U_UART0_IRQ = 4,
SIFIVE_U_UART1_IRQ = 5,
+ SIFIVE_U_QSPI2_IRQ = 6,
SIFIVE_U_GPIO_IRQ0 = 7,
SIFIVE_U_GPIO_IRQ1 = 8,
SIFIVE_U_GPIO_IRQ2 = 9,
@@ -104,7 +122,24 @@ enum {
SIFIVE_U_GPIO_IRQ13 = 20,
SIFIVE_U_GPIO_IRQ14 = 21,
SIFIVE_U_GPIO_IRQ15 = 22,
- SIFIVE_U_GEM_IRQ = 0x35
+ SIFIVE_U_PDMA_IRQ0 = 23,
+ SIFIVE_U_PDMA_IRQ1 = 24,
+ SIFIVE_U_PDMA_IRQ2 = 25,
+ SIFIVE_U_PDMA_IRQ3 = 26,
+ SIFIVE_U_PDMA_IRQ4 = 27,
+ SIFIVE_U_PDMA_IRQ5 = 28,
+ SIFIVE_U_PDMA_IRQ6 = 29,
+ SIFIVE_U_PDMA_IRQ7 = 30,
+ SIFIVE_U_PWM0_IRQ0 = 42,
+ SIFIVE_U_PWM0_IRQ1 = 43,
+ SIFIVE_U_PWM0_IRQ2 = 44,
+ SIFIVE_U_PWM0_IRQ3 = 45,
+ SIFIVE_U_PWM1_IRQ0 = 46,
+ SIFIVE_U_PWM1_IRQ1 = 47,
+ SIFIVE_U_PWM1_IRQ2 = 48,
+ SIFIVE_U_PWM1_IRQ3 = 49,
+ SIFIVE_U_QSPI0_IRQ = 51,
+ SIFIVE_U_GEM_IRQ = 53
};
enum {
@@ -121,10 +156,9 @@ enum {
#define SIFIVE_U_MANAGEMENT_CPU_COUNT 1
#define SIFIVE_U_COMPUTE_CPU_COUNT 4
-#define SIFIVE_U_PLIC_HART_CONFIG "MS"
#define SIFIVE_U_PLIC_NUM_SOURCES 54
#define SIFIVE_U_PLIC_NUM_PRIORITIES 7
-#define SIFIVE_U_PLIC_PRIORITY_BASE 0x04
+#define SIFIVE_U_PLIC_PRIORITY_BASE 0x00
#define SIFIVE_U_PLIC_PENDING_BASE 0x1000
#define SIFIVE_U_PLIC_ENABLE_BASE 0x2000
#define SIFIVE_U_PLIC_ENABLE_STRIDE 0x80
diff --git a/include/hw/riscv/spike.h b/include/hw/riscv/spike.h
index 1cd72b85d6..0c2a223763 100644
--- a/include/hw/riscv/spike.h
+++ b/include/hw/riscv/spike.h
@@ -19,29 +19,31 @@
#ifndef HW_RISCV_SPIKE_H
#define HW_RISCV_SPIKE_H
+#include "hw/boards.h"
#include "hw/riscv/riscv_hart.h"
#include "hw/sysbus.h"
-typedef struct {
+#define SPIKE_CPUS_MAX 8
+#define SPIKE_SOCKETS_MAX 8
+
+#define TYPE_SPIKE_MACHINE MACHINE_TYPE_NAME("spike")
+typedef struct SpikeState SpikeState;
+DECLARE_INSTANCE_CHECKER(SpikeState, SPIKE_MACHINE,
+ TYPE_SPIKE_MACHINE)
+
+struct SpikeState {
/*< private >*/
- SysBusDevice parent_obj;
+ MachineState parent;
/*< public >*/
- RISCVHartArrayState soc;
- void *fdt;
- int fdt_size;
-} SpikeState;
+ RISCVHartArrayState soc[SPIKE_SOCKETS_MAX];
+};
enum {
SPIKE_MROM,
+ SPIKE_HTIF,
SPIKE_CLINT,
SPIKE_DRAM
};
-#if defined(TARGET_RISCV32)
-#define SPIKE_V1_10_0_CPU TYPE_RISCV_CPU_BASE32
-#elif defined(TARGET_RISCV64)
-#define SPIKE_V1_10_0_CPU TYPE_RISCV_CPU_BASE64
-#endif
-
#endif
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
index e69355efaf..3db839160f 100644
--- a/include/hw/riscv/virt.h
+++ b/include/hw/riscv/virt.h
@@ -19,26 +19,50 @@
#ifndef HW_RISCV_VIRT_H
#define HW_RISCV_VIRT_H
+#include "hw/boards.h"
#include "hw/riscv/riscv_hart.h"
#include "hw/sysbus.h"
#include "hw/block/flash.h"
+#include "hw/intc/riscv_imsic.h"
+
+#define VIRT_CPUS_MAX_BITS 9
+#define VIRT_CPUS_MAX (1 << VIRT_CPUS_MAX_BITS)
+#define VIRT_SOCKETS_MAX_BITS 2
+#define VIRT_SOCKETS_MAX (1 << VIRT_SOCKETS_MAX_BITS)
#define TYPE_RISCV_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
-#define RISCV_VIRT_MACHINE(obj) \
- OBJECT_CHECK(RISCVVirtState, (obj), TYPE_RISCV_VIRT_MACHINE)
+typedef struct RISCVVirtState RISCVVirtState;
+DECLARE_INSTANCE_CHECKER(RISCVVirtState, RISCV_VIRT_MACHINE,
+ TYPE_RISCV_VIRT_MACHINE)
+
+typedef enum RISCVVirtAIAType {
+ VIRT_AIA_TYPE_NONE = 0,
+ VIRT_AIA_TYPE_APLIC,
+ VIRT_AIA_TYPE_APLIC_IMSIC,
+} RISCVVirtAIAType;
-typedef struct {
+struct RISCVVirtState {
/*< private >*/
MachineState parent;
/*< public >*/
- RISCVHartArrayState soc;
- DeviceState *plic;
+ Notifier machine_done;
+ DeviceState *platform_bus_dev;
+ RISCVHartArrayState soc[VIRT_SOCKETS_MAX];
+ DeviceState *irqchip[VIRT_SOCKETS_MAX];
PFlashCFI01 *flash[2];
+ FWCfgState *fw_cfg;
- void *fdt;
int fdt_size;
-} RISCVVirtState;
+ bool have_aclint;
+ RISCVVirtAIAType aia_type;
+ int aia_guests;
+ char *oem_id;
+ char *oem_table_id;
+ OnOffAuto acpi;
+ const MemMapEntry *memmap;
+ struct GPEXHost *gpex_host;
+};
enum {
VIRT_DEBUG,
@@ -46,13 +70,20 @@ enum {
VIRT_TEST,
VIRT_RTC,
VIRT_CLINT,
+ VIRT_ACLINT_SSWI,
VIRT_PLIC,
+ VIRT_APLIC_M,
+ VIRT_APLIC_S,
VIRT_UART0,
VIRT_VIRTIO,
+ VIRT_FW_CFG,
+ VIRT_IMSIC_M,
+ VIRT_IMSIC_S,
VIRT_FLASH,
VIRT_DRAM,
VIRT_PCIE_MMIO,
VIRT_PCIE_PIO,
+ VIRT_PLATFORM_BUS,
VIRT_PCIE_ECAM
};
@@ -62,30 +93,64 @@ enum {
VIRTIO_IRQ = 1, /* 1 to 8 */
VIRTIO_COUNT = 8,
PCIE_IRQ = 0x20, /* 32 to 35 */
- VIRTIO_NDEV = 0x35 /* Arbitrary maximum number of interrupts */
+ VIRT_PLATFORM_BUS_IRQ = 64, /* 64 to 95 */
};
-#define VIRT_PLIC_HART_CONFIG "MS"
-#define VIRT_PLIC_NUM_SOURCES 127
-#define VIRT_PLIC_NUM_PRIORITIES 7
-#define VIRT_PLIC_PRIORITY_BASE 0x04
+#define VIRT_PLATFORM_BUS_NUM_IRQS 32
+
+#define VIRT_IRQCHIP_NUM_MSIS 255
+#define VIRT_IRQCHIP_NUM_SOURCES 96
+#define VIRT_IRQCHIP_NUM_PRIO_BITS 3
+#define VIRT_IRQCHIP_MAX_GUESTS_BITS 3
+#define VIRT_IRQCHIP_MAX_GUESTS ((1U << VIRT_IRQCHIP_MAX_GUESTS_BITS) - 1U)
+
+#define VIRT_PLIC_PRIORITY_BASE 0x00
#define VIRT_PLIC_PENDING_BASE 0x1000
#define VIRT_PLIC_ENABLE_BASE 0x2000
#define VIRT_PLIC_ENABLE_STRIDE 0x80
#define VIRT_PLIC_CONTEXT_BASE 0x200000
#define VIRT_PLIC_CONTEXT_STRIDE 0x1000
+#define VIRT_PLIC_SIZE(__num_context) \
+ (VIRT_PLIC_CONTEXT_BASE + (__num_context) * VIRT_PLIC_CONTEXT_STRIDE)
#define FDT_PCI_ADDR_CELLS 3
#define FDT_PCI_INT_CELLS 1
#define FDT_PLIC_ADDR_CELLS 0
#define FDT_PLIC_INT_CELLS 1
-#define FDT_INT_MAP_WIDTH (FDT_PCI_ADDR_CELLS + FDT_PCI_INT_CELLS + 1 + \
- FDT_PLIC_ADDR_CELLS + FDT_PLIC_INT_CELLS)
+#define FDT_APLIC_INT_CELLS 2
+#define FDT_IMSIC_INT_CELLS 0
+#define FDT_MAX_INT_CELLS 2
+#define FDT_MAX_INT_MAP_WIDTH (FDT_PCI_ADDR_CELLS + FDT_PCI_INT_CELLS + \
+ 1 + FDT_MAX_INT_CELLS)
+#define FDT_PLIC_INT_MAP_WIDTH (FDT_PCI_ADDR_CELLS + FDT_PCI_INT_CELLS + \
+ 1 + FDT_PLIC_INT_CELLS)
+#define FDT_APLIC_INT_MAP_WIDTH (FDT_PCI_ADDR_CELLS + FDT_PCI_INT_CELLS + \
+ 1 + FDT_APLIC_INT_CELLS)
+
+bool virt_is_acpi_enabled(RISCVVirtState *s);
+void virt_acpi_setup(RISCVVirtState *vms);
+uint32_t imsic_num_bits(uint32_t count);
+
+/*
+ * The virt machine physical address space used by some of the devices
+ * namely ACLINT, PLIC, APLIC, and IMSIC depend on number of Sockets,
+ * number of CPUs, and number of IMSIC guest files.
+ *
+ * Various limits defined by VIRT_SOCKETS_MAX_BITS, VIRT_CPUS_MAX_BITS,
+ * and VIRT_IRQCHIP_MAX_GUESTS_BITS are tuned for maximum utilization
+ * of virt machine physical address space.
+ */
+
+#define VIRT_IMSIC_GROUP_MAX_SIZE (1U << IMSIC_MMIO_GROUP_MIN_SHIFT)
+#if VIRT_IMSIC_GROUP_MAX_SIZE < \
+ IMSIC_GROUP_SIZE(VIRT_CPUS_MAX_BITS, VIRT_IRQCHIP_MAX_GUESTS_BITS)
+#error "Can't accommodate single IMSIC group in address space"
+#endif
-#if defined(TARGET_RISCV32)
-#define VIRT_CPU TYPE_RISCV_CPU_BASE32
-#elif defined(TARGET_RISCV64)
-#define VIRT_CPU TYPE_RISCV_CPU_BASE64
+#define VIRT_IMSIC_MAX_SIZE (VIRT_SOCKETS_MAX * \
+ VIRT_IMSIC_GROUP_MAX_SIZE)
+#if 0x4000000 < VIRT_IMSIC_MAX_SIZE
+#error "Can't accommodate all IMSIC groups in address space"
#endif
#endif
diff --git a/include/hw/rtc/allwinner-rtc.h b/include/hw/rtc/allwinner-rtc.h
index 7893f74795..bf415431cd 100644
--- a/include/hw/rtc/allwinner-rtc.h
+++ b/include/hw/rtc/allwinner-rtc.h
@@ -60,19 +60,14 @@
* @{
*/
-#define AW_RTC(obj) \
- OBJECT_CHECK(AwRtcState, (obj), TYPE_AW_RTC)
-#define AW_RTC_CLASS(klass) \
- OBJECT_CLASS_CHECK(AwRtcClass, (klass), TYPE_AW_RTC)
-#define AW_RTC_GET_CLASS(obj) \
- OBJECT_GET_CLASS(AwRtcClass, (obj), TYPE_AW_RTC)
+OBJECT_DECLARE_TYPE(AwRtcState, AwRtcClass, AW_RTC)
/** @} */
/**
* Allwinner RTC per-object instance state.
*/
-typedef struct AwRtcState {
+struct AwRtcState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -92,7 +87,7 @@ typedef struct AwRtcState {
/** Array of hardware registers */
uint32_t regs[AW_RTC_REGS_NUM];
-} AwRtcState;
+};
/**
* Allwinner RTC class-level struct.
@@ -101,7 +96,7 @@ typedef struct AwRtcState {
* such that the generic code can use this struct to support
* all devices.
*/
-typedef struct AwRtcClass {
+struct AwRtcClass {
/*< private >*/
SysBusDeviceClass parent_class;
/*< public >*/
@@ -129,6 +124,6 @@ typedef struct AwRtcClass {
*/
bool (*write)(AwRtcState *s, uint32_t offset, uint32_t data);
-} AwRtcClass;
+};
#endif /* HW_MISC_ALLWINNER_RTC_H */
diff --git a/include/hw/rtc/aspeed_rtc.h b/include/hw/rtc/aspeed_rtc.h
index b94a710268..596dfebb46 100644
--- a/include/hw/rtc/aspeed_rtc.h
+++ b/include/hw/rtc/aspeed_rtc.h
@@ -9,19 +9,20 @@
#define HW_RTC_ASPEED_RTC_H
#include "hw/sysbus.h"
+#include "qom/object.h"
-typedef struct AspeedRtcState {
+struct AspeedRtcState {
SysBusDevice parent_obj;
MemoryRegion iomem;
qemu_irq irq;
uint32_t reg[0x18];
- int offset;
+ int64_t offset;
-} AspeedRtcState;
+};
#define TYPE_ASPEED_RTC "aspeed.rtc"
-#define ASPEED_RTC(obj) OBJECT_CHECK(AspeedRtcState, (obj), TYPE_ASPEED_RTC)
+OBJECT_DECLARE_SIMPLE_TYPE(AspeedRtcState, ASPEED_RTC)
#endif /* HW_RTC_ASPEED_RTC_H */
diff --git a/include/hw/rtc/goldfish_rtc.h b/include/hw/rtc/goldfish_rtc.h
index 9bd8924f5f..162be33863 100644
--- a/include/hw/rtc/goldfish_rtc.h
+++ b/include/hw/rtc/goldfish_rtc.h
@@ -23,12 +23,12 @@
#define HW_RTC_GOLDFISH_RTC_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_GOLDFISH_RTC "goldfish_rtc"
-#define GOLDFISH_RTC(obj) \
- OBJECT_CHECK(GoldfishRTCState, (obj), TYPE_GOLDFISH_RTC)
+OBJECT_DECLARE_SIMPLE_TYPE(GoldfishRTCState, GOLDFISH_RTC)
-typedef struct GoldfishRTCState {
+struct GoldfishRTCState {
SysBusDevice parent_obj;
MemoryRegion iomem;
@@ -42,6 +42,8 @@ typedef struct GoldfishRTCState {
uint32_t irq_pending;
uint32_t irq_enabled;
uint32_t time_high;
-} GoldfishRTCState;
+
+ bool big_endian;
+};
#endif
diff --git a/include/hw/rtc/m48t59.h b/include/hw/rtc/m48t59.h
index e7ea4e8761..c14937476c 100644
--- a/include/hw/rtc/m48t59.h
+++ b/include/hw/rtc/m48t59.h
@@ -31,27 +31,20 @@
#define TYPE_NVRAM "nvram"
-#define NVRAM_CLASS(klass) \
- OBJECT_CLASS_CHECK(NvramClass, (klass), TYPE_NVRAM)
-#define NVRAM_GET_CLASS(obj) \
- OBJECT_GET_CLASS(NvramClass, (obj), TYPE_NVRAM)
+typedef struct NvramClass NvramClass;
+DECLARE_CLASS_CHECKERS(NvramClass, NVRAM,
+ TYPE_NVRAM)
#define NVRAM(obj) \
INTERFACE_CHECK(Nvram, (obj), TYPE_NVRAM)
typedef struct Nvram Nvram;
-typedef struct NvramClass {
+struct NvramClass {
InterfaceClass parent;
uint32_t (*read)(Nvram *obj, uint32_t addr);
void (*write)(Nvram *obj, uint32_t addr, uint32_t val);
void (*toggle_lock)(Nvram *obj, int lock);
-} NvramClass;
+};
-Nvram *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size,
- int base_year, int type);
-Nvram *m48t59_init(qemu_irq IRQ, hwaddr mem_base,
- uint32_t io_base, uint16_t size, int base_year,
- int type);
-
-#endif /* HW_M48T59_H */
+#endif /* HW_RTC_M48T59_H */
diff --git a/include/hw/rtc/mc146818rtc.h b/include/hw/rtc/mc146818rtc.h
index 3713181b56..97cec0b3e8 100644
--- a/include/hw/rtc/mc146818rtc.h
+++ b/include/hw/rtc/mc146818rtc.h
@@ -9,21 +9,24 @@
#ifndef HW_RTC_MC146818RTC_H
#define HW_RTC_MC146818RTC_H
-#include "qapi/qapi-types-misc.h"
+#include "qapi/qapi-types-machine.h"
#include "qemu/queue.h"
#include "qemu/timer.h"
#include "hw/isa/isa.h"
+#include "qom/object.h"
#define TYPE_MC146818_RTC "mc146818rtc"
-#define MC146818_RTC(obj) OBJECT_CHECK(RTCState, (obj), TYPE_MC146818_RTC)
+OBJECT_DECLARE_SIMPLE_TYPE(MC146818RtcState, MC146818_RTC)
-typedef struct RTCState {
+struct MC146818RtcState {
ISADevice parent_obj;
MemoryRegion io;
MemoryRegion coalesced_io;
uint8_t cmos_data[128];
uint8_t cmos_index;
+ uint8_t isairq;
+ uint16_t io_base;
int32_t base_year;
uint64_t base_rtc;
uint64_t last_update;
@@ -43,15 +46,15 @@ typedef struct RTCState {
Notifier clock_reset_notifier;
LostTickPolicy lost_tick_policy;
Notifier suspend_notifier;
- QLIST_ENTRY(RTCState) link;
-} RTCState;
+ QLIST_ENTRY(MC146818RtcState) link;
+};
#define RTC_ISA_IRQ 8
-#define RTC_ISA_BASE 0x70
-ISADevice *mc146818_rtc_init(ISABus *bus, int base_year,
- qemu_irq intercept_irq);
-void rtc_set_memory(ISADevice *dev, int addr, int val);
-int rtc_get_memory(ISADevice *dev, int addr);
+MC146818RtcState *mc146818_rtc_init(ISABus *bus, int base_year,
+ qemu_irq intercept_irq);
+void mc146818rtc_set_cmos_data(MC146818RtcState *s, int addr, int val);
+int mc146818rtc_get_cmos_data(MC146818RtcState *s, int addr);
+void qmp_rtc_reset_reinjection(Error **errp);
-#endif /* MC146818RTC_H */
+#endif /* HW_RTC_MC146818RTC_H */
diff --git a/include/hw/rtc/pl031.h b/include/hw/rtc/pl031.h
index e3cb1d646f..9fd4be1abb 100644
--- a/include/hw/rtc/pl031.h
+++ b/include/hw/rtc/pl031.h
@@ -16,11 +16,12 @@
#include "hw/sysbus.h"
#include "qemu/timer.h"
+#include "qom/object.h"
#define TYPE_PL031 "pl031"
-#define PL031(obj) OBJECT_CHECK(PL031State, (obj), TYPE_PL031)
+OBJECT_DECLARE_SIMPLE_TYPE(PL031State, PL031)
-typedef struct PL031State {
+struct PL031State {
SysBusDevice parent_obj;
MemoryRegion iomem;
@@ -42,6 +43,6 @@ typedef struct PL031State {
uint32_t cr;
uint32_t im;
uint32_t is;
-} PL031State;
+};
#endif
diff --git a/include/hw/rtc/sun4v-rtc.h b/include/hw/rtc/sun4v-rtc.h
index fd868f6ed2..26a9eb6196 100644
--- a/include/hw/rtc/sun4v-rtc.h
+++ b/include/hw/rtc/sun4v-rtc.h
@@ -5,12 +5,12 @@
*
* Copyright (c) 2016 Artyom Tarasenko
*
- * This code is licensed under the GNU GPL v3 or (at your option) any later
+ * This code is licensed under the GNU GPL v2 or (at your option) any later
* version.
*/
-#ifndef HW_RTC_SUN4V
-#define HW_RTC_SUN4V
+#ifndef HW_RTC_SUN4V_RTC_H
+#define HW_RTC_SUN4V_RTC_H
#include "exec/hwaddr.h"
diff --git a/include/hw/rtc/xlnx-zynqmp-rtc.h b/include/hw/rtc/xlnx-zynqmp-rtc.h
index 6fa1cb2f43..f0c6a2d78a 100644
--- a/include/hw/rtc/xlnx-zynqmp-rtc.h
+++ b/include/hw/rtc/xlnx-zynqmp-rtc.h
@@ -24,16 +24,16 @@
* THE SOFTWARE.
*/
-#ifndef HW_RTC_XLNX_ZYNQMP_H
-#define HW_RTC_XLNX_ZYNQMP_H
+#ifndef HW_RTC_XLNX_ZYNQMP_RTC_H
+#define HW_RTC_XLNX_ZYNQMP_RTC_H
#include "hw/register.h"
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_XLNX_ZYNQMP_RTC "xlnx-zynmp.rtc"
-#define XLNX_ZYNQMP_RTC(obj) \
- OBJECT_CHECK(XlnxZynqMPRTC, (obj), TYPE_XLNX_ZYNQMP_RTC)
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPRTC, XLNX_ZYNQMP_RTC)
REG32(SET_TIME_WRITE, 0x0)
REG32(SET_TIME_READ, 0x4)
@@ -77,7 +77,7 @@ REG32(SAFETY_CHK, 0x50)
#define XLNX_ZYNQMP_RTC_R_MAX (R_SAFETY_CHK + 1)
-typedef struct XlnxZynqMPRTC {
+struct XlnxZynqMPRTC {
SysBusDevice parent_obj;
MemoryRegion iomem;
qemu_irq irq_rtc_int;
@@ -87,6 +87,6 @@ typedef struct XlnxZynqMPRTC {
uint32_t regs[XLNX_ZYNQMP_RTC_R_MAX];
RegisterInfo regs_info[XLNX_ZYNQMP_RTC_R_MAX];
-} XlnxZynqMPRTC;
+};
#endif
diff --git a/include/hw/rx/rx62n.h b/include/hw/rx/rx62n.h
index aa94758c27..766fe0e435 100644
--- a/include/hw/rx/rx62n.h
+++ b/include/hw/rx/rx62n.h
@@ -21,18 +21,20 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef HW_RX_RX62N_MCU_H
-#define HW_RX_RX62N_MCU_H
+#ifndef HW_RX_RX62N_H
+#define HW_RX_RX62N_H
#include "target/rx/cpu.h"
#include "hw/intc/rx_icu.h"
#include "hw/timer/renesas_tmr.h"
#include "hw/timer/renesas_cmt.h"
#include "hw/char/renesas_sci.h"
-#include "qemu/units.h"
+#include "qom/object.h"
#define TYPE_RX62N_MCU "rx62n-mcu"
-#define RX62N_MCU(obj) OBJECT_CHECK(RX62NState, (obj), TYPE_RX62N_MCU)
+typedef struct RX62NState RX62NState;
+DECLARE_INSTANCE_CHECKER(RX62NState, RX62N_MCU,
+ TYPE_RX62N_MCU)
#define TYPE_R5F562N7_MCU "r5f562n7-mcu"
#define TYPE_R5F562N8_MCU "r5f562n8-mcu"
@@ -45,7 +47,7 @@
#define RX62N_NR_CMT 2
#define RX62N_NR_SCI 6
-typedef struct RX62NState {
+struct RX62NState {
/*< private >*/
DeviceState parent_obj;
/*< public >*/
@@ -65,12 +67,11 @@ typedef struct RX62NState {
MemoryRegion iomem2;
MemoryRegion iomem3;
MemoryRegion c_flash;
- qemu_irq irq[NR_IRQS];
/* Input Clock (XTAL) frequency */
uint32_t xtal_freq_hz;
/* Peripheral Module Clock frequency */
uint32_t pclk_freq_hz;
-} RX62NState;
+};
#endif
diff --git a/include/hw/s390x/3270-ccw.h b/include/hw/s390x/3270-ccw.h
index 9d1d18e2bd..1439882294 100644
--- a/include/hw/s390x/3270-ccw.h
+++ b/include/hw/s390x/3270-ccw.h
@@ -16,6 +16,7 @@
#include "hw/sysbus.h"
#include "hw/s390x/css.h"
#include "hw/s390x/ccw-device.h"
+#include "qom/object.h"
#define EMULATED_CCW_3270_CU_TYPE 0x3270
#define EMULATED_CCW_3270_CHPID_TYPE 0x1a
@@ -30,23 +31,18 @@
#define TC_EWRITEA 0x0d /* Erase write alternate */
#define TC_WRITESF 0x11 /* Write structured field */
-#define EMULATED_CCW_3270(obj) \
- OBJECT_CHECK(EmulatedCcw3270Device, (obj), TYPE_EMULATED_CCW_3270)
-#define EMULATED_CCW_3270_CLASS(klass) \
- OBJECT_CLASS_CHECK(EmulatedCcw3270Class, (klass), TYPE_EMULATED_CCW_3270)
-#define EMULATED_CCW_3270_GET_CLASS(obj) \
- OBJECT_GET_CLASS(EmulatedCcw3270Class, (obj), TYPE_EMULATED_CCW_3270)
+OBJECT_DECLARE_TYPE(EmulatedCcw3270Device, EmulatedCcw3270Class, EMULATED_CCW_3270)
-typedef struct EmulatedCcw3270Device {
+struct EmulatedCcw3270Device {
CcwDevice parent_obj;
-} EmulatedCcw3270Device;
+};
-typedef struct EmulatedCcw3270Class {
+struct EmulatedCcw3270Class {
CCWDeviceClass parent_class;
void (*init)(EmulatedCcw3270Device *, Error **);
int (*read_payload_3270)(EmulatedCcw3270Device *);
int (*write_payload_3270)(EmulatedCcw3270Device *, uint8_t);
-} EmulatedCcw3270Class;
+};
#endif
diff --git a/include/hw/s390x/ap-device.h b/include/hw/s390x/ap-device.h
index 8df9cd2954..e502745de5 100644
--- a/include/hw/s390x/ap-device.h
+++ b/include/hw/s390x/ap-device.h
@@ -12,14 +12,16 @@
#define HW_S390X_AP_DEVICE_H
#include "hw/qdev-core.h"
+#include "qom/object.h"
-#define AP_DEVICE_TYPE "ap-device"
+#define TYPE_AP_DEVICE "ap-device"
-typedef struct APDevice {
+struct APDevice {
DeviceState parent_obj;
-} APDevice;
+};
+typedef struct APDevice APDevice;
-#define AP_DEVICE(obj) \
- OBJECT_CHECK(APDevice, (obj), AP_DEVICE_TYPE)
+DECLARE_INSTANCE_CHECKER(APDevice, AP_DEVICE,
+ TYPE_AP_DEVICE)
#endif /* HW_S390X_AP_DEVICE_H */
diff --git a/include/hw/s390x/cpu-topology.h b/include/hw/s390x/cpu-topology.h
new file mode 100644
index 0000000000..c064f427e9
--- /dev/null
+++ b/include/hw/s390x/cpu-topology.h
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * CPU Topology
+ *
+ * Copyright IBM Corp. 2022, 2023
+ * Author(s): Pierre Morel <pmorel@linux.ibm.com>
+ *
+ */
+#ifndef HW_S390X_CPU_TOPOLOGY_H
+#define HW_S390X_CPU_TOPOLOGY_H
+
+#ifndef CONFIG_USER_ONLY
+
+#include "qemu/queue.h"
+#include "hw/boards.h"
+#include "qapi/qapi-types-machine-target.h"
+
+#define S390_TOPOLOGY_CPU_IFL 0x03
+
+typedef struct S390TopologyId {
+ uint8_t sentinel;
+ uint8_t drawer;
+ uint8_t book;
+ uint8_t socket;
+ uint8_t type;
+ uint8_t vertical:1;
+ uint8_t entitlement:2;
+ uint8_t dedicated;
+ uint8_t origin;
+} S390TopologyId;
+
+typedef struct S390TopologyEntry {
+ QTAILQ_ENTRY(S390TopologyEntry) next;
+ S390TopologyId id;
+ uint64_t mask;
+} S390TopologyEntry;
+
+typedef struct S390Topology {
+ uint8_t *cores_per_socket;
+ CpuS390Polarization polarization;
+} S390Topology;
+
+typedef QTAILQ_HEAD(, S390TopologyEntry) S390TopologyList;
+
+#ifdef CONFIG_KVM
+bool s390_has_topology(void);
+void s390_topology_setup_cpu(MachineState *ms, S390CPU *cpu, Error **errp);
+void s390_topology_reset(void);
+#else
+static inline bool s390_has_topology(void)
+{
+ return false;
+}
+static inline void s390_topology_setup_cpu(MachineState *ms,
+ S390CPU *cpu,
+ Error **errp) {}
+static inline void s390_topology_reset(void)
+{
+ /* Unreachable, CPU topology not implemented for TCG */
+ assert(false);
+}
+#endif
+
+extern S390Topology s390_topology;
+
+static inline int s390_std_socket(int n, CpuTopology *smp)
+{
+ return (n / smp->cores) % smp->sockets;
+}
+
+static inline int s390_std_book(int n, CpuTopology *smp)
+{
+ return (n / (smp->cores * smp->sockets)) % smp->books;
+}
+
+static inline int s390_std_drawer(int n, CpuTopology *smp)
+{
+ return (n / (smp->cores * smp->sockets * smp->books)) % smp->drawers;
+}
+
+#endif /* CONFIG_USER_ONLY */
+
+#endif
diff --git a/include/hw/s390x/css-bridge.h b/include/hw/s390x/css-bridge.h
index f7ed2d9a03..deb606d71f 100644
--- a/include/hw/s390x/css-bridge.h
+++ b/include/hw/s390x/css-bridge.h
@@ -17,23 +17,21 @@
#include "hw/sysbus.h"
/* virtual css bridge */
-typedef struct VirtualCssBridge {
+struct VirtualCssBridge {
SysBusDevice sysbus_dev;
bool css_dev_path;
-} VirtualCssBridge;
+};
#define TYPE_VIRTUAL_CSS_BRIDGE "virtual-css-bridge"
-#define VIRTUAL_CSS_BRIDGE(obj) \
- OBJECT_CHECK(VirtualCssBridge, (obj), TYPE_VIRTUAL_CSS_BRIDGE)
+OBJECT_DECLARE_SIMPLE_TYPE(VirtualCssBridge, VIRTUAL_CSS_BRIDGE)
/* virtual css bus type */
-typedef struct VirtualCssBus {
+struct VirtualCssBus {
BusState parent_obj;
-} VirtualCssBus;
+};
#define TYPE_VIRTUAL_CSS_BUS "virtual-css-bus"
-#define VIRTUAL_CSS_BUS(obj) \
- OBJECT_CHECK(VirtualCssBus, (obj), TYPE_VIRTUAL_CSS_BUS)
+OBJECT_DECLARE_SIMPLE_TYPE(VirtualCssBus, VIRTUAL_CSS_BUS)
VirtualCssBus *virtual_css_bus_init(void);
#endif
diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h
index 08c869ab0a..ba72ee3dd2 100644
--- a/include/hw/s390x/css.h
+++ b/include/hw/s390x/css.h
@@ -12,7 +12,6 @@
#ifndef CSS_H
#define CSS_H
-#include "cpu.h"
#include "hw/s390x/adapter.h"
#include "hw/s390x/s390_flic.h"
#include "hw/s390x/ioinst.h"
@@ -133,19 +132,22 @@ struct SubchDev {
bool ccw_fmt_1;
bool thinint_active;
uint8_t ccw_no_data_cnt;
- uint16_t migrated_schid; /* used for missmatch detection */
+ uint16_t migrated_schid; /* used for mismatch detection */
CcwDataStream cds;
/* transport-provided data: */
int (*ccw_cb) (SubchDev *, CCW1);
void (*disable_cb)(SubchDev *);
IOInstEnding (*do_subchannel_work) (SubchDev *);
+ void (*irb_cb)(SubchDev *, IRB *);
SenseId id;
void *driver_data;
+ ESW esw;
};
static inline void sch_gen_unit_exception(SubchDev *sch)
{
- sch->curr_status.scsw.ctrl &= ~SCSW_ACTL_START_PEND;
+ sch->curr_status.scsw.ctrl &= ~(SCSW_ACTL_DEVICE_ACTIVE |
+ SCSW_ACTL_SUBCH_ACTIVE);
sch->curr_status.scsw.ctrl |= SCSW_STCTL_PRIMARY |
SCSW_STCTL_SECONDARY |
SCSW_STCTL_ALERT |
@@ -202,6 +204,7 @@ int css_sch_build_schib(SubchDev *sch, CssDevId *dev_id);
unsigned int css_find_free_chpid(uint8_t cssid);
uint16_t css_build_subchannel_id(SubchDev *sch);
void copy_scsw_to_guest(SCSW *dest, const SCSW *src);
+void copy_esw_to_guest(ESW *dest, const ESW *src);
void css_inject_io_interrupt(SubchDev *sch);
void css_reset(void);
void css_reset_sch(SubchDev *sch);
@@ -216,6 +219,8 @@ void css_clear_sei_pending(void);
IOInstEnding s390_ccw_cmd_request(SubchDev *sch);
IOInstEnding do_subchannel_work_virtual(SubchDev *sub);
IOInstEnding do_subchannel_work_passthrough(SubchDev *sub);
+void build_irb_passthrough(SubchDev *sch, IRB *irb);
+void build_irb_virtual(SubchDev *sch, IRB *irb);
int s390_ccw_halt(SubchDev *sch);
int s390_ccw_clear(SubchDev *sch);
@@ -228,17 +233,11 @@ typedef enum {
} CssIoAdapterType;
void css_adapter_interrupt(CssIoAdapterType type, uint8_t isc);
-int css_do_sic(CPUS390XState *env, uint8_t isc, uint16_t mode);
+int css_do_sic(S390CPU *cpu, uint8_t isc, uint16_t mode);
uint32_t css_get_adapter_id(CssIoAdapterType type, uint8_t isc);
void css_register_io_adapters(CssIoAdapterType type, bool swap, bool maskable,
uint8_t flags, Error **errp);
-#ifndef CONFIG_KVM
-#define S390_ADAPTER_SUPPRESSIBLE 0x01
-#else
-#define S390_ADAPTER_SUPPRESSIBLE KVM_S390_ADAPTER_SUPPRESSIBLE
-#endif
-
#ifndef CONFIG_USER_ONLY
SubchDev *css_find_subch(uint8_t m, uint8_t cssid, uint8_t ssid,
uint16_t schid);
diff --git a/include/hw/s390x/event-facility.h b/include/hw/s390x/event-facility.h
index 700a610f33..3ffd575d8f 100644
--- a/include/hw/s390x/event-facility.h
+++ b/include/hw/s390x/event-facility.h
@@ -18,6 +18,7 @@
#include "qemu/thread.h"
#include "hw/qdev-core.h"
#include "hw/s390x/sclp.h"
+#include "qom/object.h"
/* SCLP event types */
#define SCLP_EVENT_OPRTNS_COMMAND 0x01
@@ -41,12 +42,8 @@
#define SCLP_SELECTIVE_READ 0x01
#define TYPE_SCLP_EVENT "s390-sclp-event-type"
-#define SCLP_EVENT(obj) \
- OBJECT_CHECK(SCLPEvent, (obj), TYPE_SCLP_EVENT)
-#define SCLP_EVENT_CLASS(klass) \
- OBJECT_CLASS_CHECK(SCLPEventClass, (klass), TYPE_SCLP_EVENT)
-#define SCLP_EVENT_GET_CLASS(obj) \
- OBJECT_GET_CLASS(SCLPEventClass, (obj), TYPE_SCLP_EVENT)
+OBJECT_DECLARE_TYPE(SCLPEvent, SCLPEventClass,
+ SCLP_EVENT)
#define TYPE_SCLP_CPU_HOTPLUG "sclp-cpu-hotplug"
#define TYPE_SCLP_QUIESCE "sclpquiesce"
@@ -169,13 +166,13 @@ typedef struct ReadEventData {
};
} QEMU_PACKED ReadEventData;
-typedef struct SCLPEvent {
+struct SCLPEvent {
DeviceState qdev;
bool event_pending;
char *name;
-} SCLPEvent;
+};
-typedef struct SCLPEventClass {
+struct SCLPEventClass {
DeviceClass parent_class;
int (*init)(SCLPEvent *event);
@@ -192,23 +189,19 @@ typedef struct SCLPEventClass {
/* can we handle this event type? */
bool (*can_handle_event)(uint8_t type);
-} SCLPEventClass;
+};
#define TYPE_SCLP_EVENT_FACILITY "s390-sclp-event-facility"
-#define EVENT_FACILITY(obj) \
- OBJECT_CHECK(SCLPEventFacility, (obj), TYPE_SCLP_EVENT_FACILITY)
-#define EVENT_FACILITY_CLASS(klass) \
- OBJECT_CLASS_CHECK(SCLPEventFacilityClass, (klass), \
- TYPE_SCLP_EVENT_FACILITY)
-#define EVENT_FACILITY_GET_CLASS(obj) \
- OBJECT_GET_CLASS(SCLPEventFacilityClass, (obj), \
- TYPE_SCLP_EVENT_FACILITY)
-
-typedef struct SCLPEventFacilityClass {
+typedef struct SCLPEventFacility SCLPEventFacility;
+typedef struct SCLPEventFacilityClass SCLPEventFacilityClass;
+DECLARE_OBJ_CHECKERS(SCLPEventFacility, SCLPEventFacilityClass,
+ EVENT_FACILITY, TYPE_SCLP_EVENT_FACILITY)
+
+struct SCLPEventFacilityClass {
SysBusDeviceClass parent_class;
void (*command_handler)(SCLPEventFacility *ef, SCCB *sccb, uint64_t code);
bool (*event_pending)(SCLPEventFacility *ef);
-} SCLPEventFacilityClass;
+};
BusState *sclp_get_event_facility_bus(void);
diff --git a/include/hw/s390x/ioinst.h b/include/hw/s390x/ioinst.h
index c6737a30d4..ea8d0f2444 100644
--- a/include/hw/s390x/ioinst.h
+++ b/include/hw/s390x/ioinst.h
@@ -107,7 +107,7 @@ QEMU_BUILD_BUG_MSG(sizeof(PMCW) != 28, "size of PMCW is wrong");
#define PMCW_FLAGS_MASK_MP 0x0004
#define PMCW_FLAGS_MASK_TF 0x0002
#define PMCW_FLAGS_MASK_DNV 0x0001
-#define PMCW_FLAGS_MASK_INVALID 0x0700
+#define PMCW_FLAGS_MASK_INVALID 0xc300
#define PMCW_CHARS_MASK_ST 0x00e00000
#define PMCW_CHARS_MASK_MBFC 0x00000004
@@ -123,10 +123,20 @@ typedef struct SCHIB {
uint8_t mda[4];
} QEMU_PACKED SCHIB;
+/* format-0 extended-status word */
+typedef struct ESW {
+ uint32_t word0; /* subchannel logout for format 0 */
+ uint32_t erw;
+ uint64_t word2; /* failing-storage address for format 0 */
+ uint32_t word4; /* secondary-CCW address for format 0 */
+} QEMU_PACKED ESW;
+
+#define ESW_ERW_SENSE 0x01000000
+
/* interruption response block */
typedef struct IRB {
SCSW scsw;
- uint32_t esw[5];
+ ESW esw;
uint32_t ecw[8];
uint32_t emw[8];
} IRB;
diff --git a/include/hw/s390x/pv.h b/include/hw/s390x/pv.h
deleted file mode 100644
index aee758bc2d..0000000000
--- a/include/hw/s390x/pv.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Protected Virtualization header
- *
- * Copyright IBM Corp. 2020
- * Author(s):
- * Janosch Frank <frankja@linux.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or (at
- * your option) any later version. See the COPYING file in the top-level
- * directory.
- */
-#ifndef HW_S390_PV_H
-#define HW_S390_PV_H
-
-#ifdef CONFIG_KVM
-#include "cpu.h"
-#include "hw/s390x/s390-virtio-ccw.h"
-
-static inline bool s390_is_pv(void)
-{
- static S390CcwMachineState *ccw;
- Object *obj;
-
- if (ccw) {
- return ccw->pv;
- }
-
- /* we have to bail out for the "none" machine */
- obj = object_dynamic_cast(qdev_get_machine(),
- TYPE_S390_CCW_MACHINE);
- if (!obj) {
- return false;
- }
- ccw = S390_CCW_MACHINE(obj);
- return ccw->pv;
-}
-
-int s390_pv_vm_enable(void);
-void s390_pv_vm_disable(void);
-int s390_pv_set_sec_parms(uint64_t origin, uint64_t length);
-int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak);
-void s390_pv_prep_reset(void);
-int s390_pv_verify(void);
-void s390_pv_unshare(void);
-void s390_pv_inject_reset_error(CPUState *cs);
-#else /* CONFIG_KVM */
-static inline bool s390_is_pv(void) { return false; }
-static inline int s390_pv_vm_enable(void) { return 0; }
-static inline void s390_pv_vm_disable(void) {}
-static inline int s390_pv_set_sec_parms(uint64_t origin, uint64_t length) { return 0; }
-static inline int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak) { return 0; }
-static inline void s390_pv_prep_reset(void) {}
-static inline int s390_pv_verify(void) { return 0; }
-static inline void s390_pv_unshare(void) {}
-static inline void s390_pv_inject_reset_error(CPUState *cs) {};
-#endif /* CONFIG_KVM */
-
-#endif /* HW_S390_PV_H */
diff --git a/include/hw/s390x/s390-ccw.h b/include/hw/s390x/s390-ccw.h
index d8e08b5f4c..2c807ee3a1 100644
--- a/include/hw/s390x/s390-ccw.h
+++ b/include/hw/s390x/s390-ccw.h
@@ -14,23 +14,22 @@
#define HW_S390_CCW_H
#include "hw/s390x/ccw-device.h"
+#include "qom/object.h"
#define TYPE_S390_CCW "s390-ccw"
-#define S390_CCW_DEVICE(obj) \
- OBJECT_CHECK(S390CCWDevice, (obj), TYPE_S390_CCW)
-#define S390_CCW_DEVICE_CLASS(klass) \
- OBJECT_CLASS_CHECK(S390CCWDeviceClass, (klass), TYPE_S390_CCW)
-#define S390_CCW_DEVICE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(S390CCWDeviceClass, (obj), TYPE_S390_CCW)
+typedef struct S390CCWDevice S390CCWDevice;
+typedef struct S390CCWDeviceClass S390CCWDeviceClass;
+DECLARE_OBJ_CHECKERS(S390CCWDevice, S390CCWDeviceClass,
+ S390_CCW_DEVICE, TYPE_S390_CCW)
-typedef struct S390CCWDevice {
+struct S390CCWDevice {
CcwDevice parent_obj;
CssDevId hostid;
char *mdevid;
int32_t bootindex;
-} S390CCWDevice;
+};
-typedef struct S390CCWDeviceClass {
+struct S390CCWDeviceClass {
CCWDeviceClass parent_class;
void (*realize)(S390CCWDevice *dev, char *sysfsdev, Error **errp);
void (*unrealize)(S390CCWDevice *dev);
@@ -38,6 +37,6 @@ typedef struct S390CCWDeviceClass {
int (*handle_halt) (SubchDev *sch);
int (*handle_clear) (SubchDev *sch);
IOInstEnding (*handle_store) (SubchDev *sch);
-} S390CCWDeviceClass;
+};
#endif
diff --git a/include/hw/s390x/s390-pci-bus.h b/include/hw/s390x/s390-pci-bus.h
new file mode 100644
index 0000000000..2c43ea123f
--- /dev/null
+++ b/include/hw/s390x/s390-pci-bus.h
@@ -0,0 +1,406 @@
+/*
+ * s390 PCI BUS definitions
+ *
+ * Copyright 2014 IBM Corp.
+ * Author(s): Frank Blaschka <frank.blaschka@de.ibm.com>
+ * Hong Bo Li <lihbbj@cn.ibm.com>
+ * Yi Min Zhao <zyimin@cn.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#ifndef HW_S390_PCI_BUS_H
+#define HW_S390_PCI_BUS_H
+
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "hw/s390x/sclp.h"
+#include "hw/s390x/s390_flic.h"
+#include "hw/s390x/css.h"
+#include "hw/s390x/s390-pci-clp.h"
+#include "qom/object.h"
+
+#define TYPE_S390_PCI_HOST_BRIDGE "s390-pcihost"
+#define TYPE_S390_PCI_BUS "s390-pcibus"
+#define TYPE_S390_PCI_DEVICE "zpci"
+#define TYPE_S390_PCI_IOMMU "s390-pci-iommu"
+#define TYPE_S390_IOMMU_MEMORY_REGION "s390-iommu-memory-region"
+#define FH_MASK_ENABLE 0x80000000
+#define FH_MASK_INSTANCE 0x7f000000
+#define FH_MASK_SHM 0x00ff0000
+#define FH_MASK_INDEX 0x0000ffff
+#define FH_SHM_VFIO 0x00010000
+#define FH_SHM_EMUL 0x00020000
+#define ZPCI_MAX_FID 0xffffffff
+#define ZPCI_MAX_UID 0xffff
+#define UID_UNDEFINED 0
+#define UID_CHECKING_ENABLED 0x01
+#define ZPCI_DTSM 0x40
+
+/* zPCI Function Types */
+#define ZPCI_PFT_ISM 5
+
+OBJECT_DECLARE_SIMPLE_TYPE(S390pciState, S390_PCI_HOST_BRIDGE)
+OBJECT_DECLARE_SIMPLE_TYPE(S390PCIBus, S390_PCI_BUS)
+OBJECT_DECLARE_SIMPLE_TYPE(S390PCIBusDevice, S390_PCI_DEVICE)
+OBJECT_DECLARE_SIMPLE_TYPE(S390PCIIOMMU, S390_PCI_IOMMU)
+
+#define HP_EVENT_TO_CONFIGURED 0x0301
+#define HP_EVENT_RESERVED_TO_STANDBY 0x0302
+#define HP_EVENT_DECONFIGURE_REQUEST 0x0303
+#define HP_EVENT_CONFIGURED_TO_STBRES 0x0304
+#define HP_EVENT_STANDBY_TO_RESERVED 0x0308
+
+#define ERR_EVENT_INVALAS 0x1
+#define ERR_EVENT_OORANGE 0x2
+#define ERR_EVENT_INVALTF 0x3
+#define ERR_EVENT_TPROTE 0x4
+#define ERR_EVENT_APROTE 0x5
+#define ERR_EVENT_KEYE 0x6
+#define ERR_EVENT_INVALTE 0x7
+#define ERR_EVENT_INVALTL 0x8
+#define ERR_EVENT_TT 0x9
+#define ERR_EVENT_INVALMS 0xa
+#define ERR_EVENT_SERR 0xb
+#define ERR_EVENT_NOMSI 0x10
+#define ERR_EVENT_INVALBV 0x11
+#define ERR_EVENT_AIBV 0x12
+#define ERR_EVENT_AIRERR 0x13
+#define ERR_EVENT_FMBA 0x2a
+#define ERR_EVENT_FMBUP 0x2b
+#define ERR_EVENT_FMBPRO 0x2c
+#define ERR_EVENT_CCONF 0x30
+#define ERR_EVENT_SERVAC 0x3a
+#define ERR_EVENT_PERMERR 0x3b
+
+#define ERR_EVENT_Q_BIT 0x2
+#define ERR_EVENT_MVN_OFFSET 16
+
+#define ZPCI_MSI_VEC_BITS 11
+#define ZPCI_MSI_VEC_MASK 0x7ff
+
+#define ZPCI_MSI_ADDR 0xfe00000000000000ULL
+#define ZPCI_SDMA_ADDR 0x100000000ULL
+#define ZPCI_EDMA_ADDR 0x1ffffffffffffffULL
+
+#define PAGE_DEFAULT_ACC 0
+#define PAGE_DEFAULT_KEY (PAGE_DEFAULT_ACC << 4)
+
+/* I/O Translation Anchor (IOTA) */
+enum ZpciIoatDtype {
+ ZPCI_IOTA_STO = 0,
+ ZPCI_IOTA_RTTO = 1,
+ ZPCI_IOTA_RSTO = 2,
+ ZPCI_IOTA_RFTO = 3,
+ ZPCI_IOTA_PFAA = 4,
+ ZPCI_IOTA_IOPFAA = 5,
+ ZPCI_IOTA_IOPTO = 7
+};
+
+#define ZPCI_IOTA_IOT_ENABLED 0x800ULL
+#define ZPCI_IOTA_DT_ST (ZPCI_IOTA_STO << 2)
+#define ZPCI_IOTA_DT_RT (ZPCI_IOTA_RTTO << 2)
+#define ZPCI_IOTA_DT_RS (ZPCI_IOTA_RSTO << 2)
+#define ZPCI_IOTA_DT_RF (ZPCI_IOTA_RFTO << 2)
+#define ZPCI_IOTA_DT_PF (ZPCI_IOTA_PFAA << 2)
+#define ZPCI_IOTA_FS_4K 0
+#define ZPCI_IOTA_FS_1M 1
+#define ZPCI_IOTA_FS_2G 2
+#define ZPCI_KEY (PAGE_DEFAULT_KEY << 5)
+
+#define ZPCI_IOTA_STO_FLAG (ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_ST)
+#define ZPCI_IOTA_RTTO_FLAG (ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_RT)
+#define ZPCI_IOTA_RSTO_FLAG (ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_RS)
+#define ZPCI_IOTA_RFTO_FLAG (ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_RF)
+#define ZPCI_IOTA_RFAA_FLAG (ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY |\
+ ZPCI_IOTA_DT_PF | ZPCI_IOTA_FS_2G)
+
+/* I/O Region and segment tables */
+#define ZPCI_INDEX_MASK 0x7ffULL
+
+#define ZPCI_TABLE_TYPE_MASK 0xc
+#define ZPCI_TABLE_TYPE_RFX 0xc
+#define ZPCI_TABLE_TYPE_RSX 0x8
+#define ZPCI_TABLE_TYPE_RTX 0x4
+#define ZPCI_TABLE_TYPE_SX 0x0
+
+#define ZPCI_TABLE_LEN_RFX 0x3
+#define ZPCI_TABLE_LEN_RSX 0x3
+#define ZPCI_TABLE_LEN_RTX 0x3
+
+#define ZPCI_TABLE_OFFSET_MASK 0xc0
+#define ZPCI_TABLE_SIZE 0x4000
+#define ZPCI_TABLE_ALIGN ZPCI_TABLE_SIZE
+#define ZPCI_TABLE_ENTRY_SIZE (sizeof(unsigned long))
+#define ZPCI_TABLE_ENTRIES (ZPCI_TABLE_SIZE / ZPCI_TABLE_ENTRY_SIZE)
+
+#define ZPCI_TABLE_BITS 11
+#define ZPCI_PT_BITS 8
+#define ZPCI_ST_SHIFT (ZPCI_PT_BITS + TARGET_PAGE_BITS)
+#define ZPCI_RT_SHIFT (ZPCI_ST_SHIFT + ZPCI_TABLE_BITS)
+
+#define ZPCI_RTE_FLAG_MASK 0x3fffULL
+#define ZPCI_RTE_ADDR_MASK (~ZPCI_RTE_FLAG_MASK)
+#define ZPCI_STE_FLAG_MASK 0x7ffULL
+#define ZPCI_STE_ADDR_MASK (~ZPCI_STE_FLAG_MASK)
+
+#define ZPCI_SFAA_MASK (~((1ULL << 20) - 1))
+
+/* I/O Page tables */
+#define ZPCI_PTE_VALID_MASK 0x400
+#define ZPCI_PTE_INVALID 0x400
+#define ZPCI_PTE_VALID 0x000
+#define ZPCI_PT_SIZE 0x800
+#define ZPCI_PT_ALIGN ZPCI_PT_SIZE
+#define ZPCI_PT_ENTRIES (ZPCI_PT_SIZE / ZPCI_TABLE_ENTRY_SIZE)
+#define ZPCI_PT_MASK (ZPCI_PT_ENTRIES - 1)
+
+#define ZPCI_PTE_FLAG_MASK 0xfffULL
+#define ZPCI_PTE_ADDR_MASK (~ZPCI_PTE_FLAG_MASK)
+
+/* Shared bits */
+#define ZPCI_TABLE_VALID 0x00
+#define ZPCI_TABLE_INVALID 0x20
+#define ZPCI_TABLE_PROTECTED 0x200
+#define ZPCI_TABLE_UNPROTECTED 0x000
+#define ZPCI_TABLE_FC 0x400
+
+#define ZPCI_TABLE_VALID_MASK 0x20
+#define ZPCI_TABLE_PROT_MASK 0x200
+
+#define ZPCI_ETT_RT 1
+#define ZPCI_ETT_ST 0
+#define ZPCI_ETT_PT -1
+
+/* PCI Function States
+ *
+ * reserved: default; device has just been plugged or is in progress of being
+ * unplugged
+ * standby: device is present but not configured; transition from any
+ * configured state/to this state via sclp configure/deconfigure
+ *
+ * The following states make up the "configured" meta-state:
+ * disabled: device is configured but not enabled; transition between this
+ * state and enabled via clp enable/disable
+ * enabled: device is ready for use; transition to disabled via clp disable;
+ * may enter an error state
+ * blocked: ignore all DMA and interrupts; transition back to enabled or from
+ * error state via mpcifc
+ * error: an error occurred; transition back to enabled via mpcifc
+ * permanent error: an unrecoverable error occurred; transition to standby via
+ * sclp deconfigure
+ */
+typedef enum {
+ ZPCI_FS_RESERVED,
+ ZPCI_FS_STANDBY,
+ ZPCI_FS_DISABLED,
+ ZPCI_FS_ENABLED,
+ ZPCI_FS_BLOCKED,
+ ZPCI_FS_ERROR,
+ ZPCI_FS_PERMANENT_ERROR,
+} ZpciState;
+
+typedef struct SeiContainer {
+ QTAILQ_ENTRY(SeiContainer) link;
+ uint32_t fid;
+ uint32_t fh;
+ uint8_t cc;
+ uint16_t pec;
+ uint64_t faddr;
+ uint32_t e;
+} SeiContainer;
+
+typedef struct PciCcdfErr {
+ uint32_t reserved1;
+ uint32_t fh;
+ uint32_t fid;
+ uint32_t e;
+ uint64_t faddr;
+ uint32_t reserved3;
+ uint16_t reserved4;
+ uint16_t pec;
+} QEMU_PACKED PciCcdfErr;
+
+typedef struct PciCcdfAvail {
+ uint32_t reserved1;
+ uint32_t fh;
+ uint32_t fid;
+ uint32_t reserved2;
+ uint32_t reserved3;
+ uint32_t reserved4;
+ uint32_t reserved5;
+ uint16_t reserved6;
+ uint16_t pec;
+} QEMU_PACKED PciCcdfAvail;
+
+typedef struct ChscSeiNt2Res {
+ uint16_t length;
+ uint16_t code;
+ uint16_t reserved1;
+ uint8_t reserved2;
+ uint8_t nt;
+ uint8_t flags;
+ uint8_t reserved3;
+ uint8_t reserved4;
+ uint8_t cc;
+ uint32_t reserved5[13];
+ uint8_t ccdf[4016];
+} QEMU_PACKED ChscSeiNt2Res;
+
+typedef struct S390MsixInfo {
+ uint8_t table_bar;
+ uint8_t pba_bar;
+ uint16_t entries;
+ uint32_t table_offset;
+ uint32_t pba_offset;
+} S390MsixInfo;
+
+typedef struct S390IOTLBEntry {
+ uint64_t iova;
+ uint64_t translated_addr;
+ uint64_t len;
+ uint64_t perm;
+} S390IOTLBEntry;
+
+typedef struct S390PCIDMACount {
+ int id;
+ int users;
+ uint32_t avail;
+ QTAILQ_ENTRY(S390PCIDMACount) link;
+} S390PCIDMACount;
+
+struct S390PCIIOMMU {
+ Object parent_obj;
+ S390PCIBusDevice *pbdev;
+ AddressSpace as;
+ MemoryRegion mr;
+ IOMMUMemoryRegion iommu_mr;
+ bool enabled;
+ uint64_t g_iota;
+ uint64_t pba;
+ uint64_t pal;
+ uint64_t max_dma_limit;
+ GHashTable *iotlb;
+ S390PCIDMACount *dma_limit;
+};
+
+typedef struct S390PCIIOMMUTable {
+ uint64_t key;
+ S390PCIIOMMU *iommu[PCI_SLOT_MAX];
+} S390PCIIOMMUTable;
+
+/* Function Measurement Block */
+#define DEFAULT_MUI 4000
+#define UPDATE_U_BIT 0x1ULL
+#define FMBK_MASK 0xfULL
+
+typedef struct ZpciFmbFmt0 {
+ uint64_t dma_rbytes;
+ uint64_t dma_wbytes;
+} ZpciFmbFmt0;
+
+#define ZPCI_FMB_CNT_LD 0
+#define ZPCI_FMB_CNT_ST 1
+#define ZPCI_FMB_CNT_STB 2
+#define ZPCI_FMB_CNT_RPCIT 3
+#define ZPCI_FMB_CNT_MAX 4
+
+#define ZPCI_FMB_FORMAT 0
+
+typedef struct ZpciFmb {
+ uint32_t format;
+ uint32_t sample;
+ uint64_t last_update;
+ uint64_t counter[ZPCI_FMB_CNT_MAX];
+ ZpciFmbFmt0 fmt0;
+} ZpciFmb;
+QEMU_BUILD_BUG_MSG(offsetof(ZpciFmb, fmt0) != 48, "padding in ZpciFmb");
+
+#define ZPCI_DEFAULT_FN_GRP 0xFF
+#define ZPCI_SIM_GRP_START 0xF0
+typedef struct S390PCIGroup {
+ ClpRspQueryPciGrp zpci_group;
+ int id;
+ int host_id;
+ QTAILQ_ENTRY(S390PCIGroup) link;
+} S390PCIGroup;
+S390PCIGroup *s390_group_create(int id, int host_id);
+S390PCIGroup *s390_group_find(int id);
+S390PCIGroup *s390_group_find_host_sim(int host_id);
+
+struct S390PCIBusDevice {
+ DeviceState qdev;
+ PCIDevice *pdev;
+ ZpciState state;
+ char *target;
+ uint16_t uid;
+ uint32_t idx;
+ uint32_t fh;
+ uint32_t fid;
+ bool fid_defined;
+ uint64_t fmb_addr;
+ ZpciFmb fmb;
+ QEMUTimer *fmb_timer;
+ uint8_t isc;
+ uint16_t noi;
+ uint16_t maxstbl;
+ uint8_t sum;
+ uint8_t pft;
+ S390PCIGroup *pci_group;
+ ClpRspQueryPci zpci_fn;
+ S390MsixInfo msix;
+ AdapterRoutes routes;
+ S390PCIIOMMU *iommu;
+ MemoryRegion msix_notify_mr;
+ IndAddr *summary_ind;
+ IndAddr *indicator;
+ Notifier shutdown_notifier;
+ bool pci_unplug_request_processed;
+ bool unplug_requested;
+ bool interp;
+ bool forwarding_assist;
+ bool aif;
+ QTAILQ_ENTRY(S390PCIBusDevice) link;
+};
+
+struct S390PCIBus {
+ BusState qbus;
+};
+
+struct S390pciState {
+ PCIHostState parent_obj;
+ uint32_t next_idx;
+ int bus_no;
+ S390PCIBus *bus;
+ GHashTable *iommu_table;
+ GHashTable *zpci_table;
+ QTAILQ_HEAD(, SeiContainer) pending_sei;
+ QTAILQ_HEAD(, S390PCIBusDevice) zpci_devs;
+ QTAILQ_HEAD(, S390PCIDMACount) zpci_dma_limit;
+ QTAILQ_HEAD(, S390PCIGroup) zpci_groups;
+ uint8_t next_sim_grp;
+};
+
+S390pciState *s390_get_phb(void);
+int pci_chsc_sei_nt2_get_event(void *res);
+int pci_chsc_sei_nt2_have_event(void);
+void s390_pci_sclp_configure(SCCB *sccb);
+void s390_pci_sclp_deconfigure(SCCB *sccb);
+void s390_pci_iommu_enable(S390PCIIOMMU *iommu);
+void s390_pci_iommu_disable(S390PCIIOMMU *iommu);
+void s390_pci_generate_error_event(uint16_t pec, uint32_t fh, uint32_t fid,
+ uint64_t faddr, uint32_t e);
+uint16_t s390_guest_io_table_walk(uint64_t g_iota, hwaddr addr,
+ S390IOTLBEntry *entry);
+S390PCIBusDevice *s390_pci_find_dev_by_idx(S390pciState *s, uint32_t idx);
+S390PCIBusDevice *s390_pci_find_dev_by_fh(S390pciState *s, uint32_t fh);
+S390PCIBusDevice *s390_pci_find_dev_by_fid(S390pciState *s, uint32_t fid);
+S390PCIBusDevice *s390_pci_find_dev_by_target(S390pciState *s,
+ const char *target);
+S390PCIBusDevice *s390_pci_find_next_avail_dev(S390pciState *s,
+ S390PCIBusDevice *pbdev);
+void s390_pci_ism_reset(void);
+
+#endif
diff --git a/include/hw/s390x/s390-pci-clp.h b/include/hw/s390x/s390-pci-clp.h
new file mode 100644
index 0000000000..03b7f9ba5f
--- /dev/null
+++ b/include/hw/s390x/s390-pci-clp.h
@@ -0,0 +1,216 @@
+/*
+ * s390 CLP instruction definitions
+ *
+ * Copyright 2019 IBM Corp.
+ * Author(s): Pierre Morel <pmorel@de.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#ifndef HW_S390_PCI_CLP_H
+#define HW_S390_PCI_CLP_H
+
+/* CLP common request & response block size */
+#define CLP_BLK_SIZE 4096
+#define PCI_BAR_COUNT 6
+#define PCI_MAX_FUNCTIONS 4096
+
+typedef struct ClpReqHdr {
+ uint16_t len;
+ uint16_t cmd;
+} QEMU_PACKED ClpReqHdr;
+
+typedef struct ClpRspHdr {
+ uint16_t len;
+ uint16_t rsp;
+} QEMU_PACKED ClpRspHdr;
+
+/* CLP Response Codes */
+#define CLP_RC_OK 0x0010 /* Command request successfully */
+#define CLP_RC_CMD 0x0020 /* Command code not recognized */
+#define CLP_RC_PERM 0x0030 /* Command not authorized */
+#define CLP_RC_FMT 0x0040 /* Invalid command request format */
+#define CLP_RC_LEN 0x0050 /* Invalid command request length */
+#define CLP_RC_8K 0x0060 /* Command requires 8K LPCB */
+#define CLP_RC_RESNOT0 0x0070 /* Reserved field not zero */
+#define CLP_RC_NODATA 0x0080 /* No data available */
+#define CLP_RC_FC_UNKNOWN 0x0100 /* Function code not recognized */
+
+/*
+ * Call Logical Processor - Command Codes
+ */
+#define CLP_LIST_PCI 0x0002
+#define CLP_QUERY_PCI_FN 0x0003
+#define CLP_QUERY_PCI_FNGRP 0x0004
+#define CLP_SET_PCI_FN 0x0005
+
+/* PCI function handle list entry */
+typedef struct ClpFhListEntry {
+ uint16_t device_id;
+ uint16_t vendor_id;
+#define CLP_FHLIST_MASK_CONFIG 0x80000000
+ uint32_t config;
+ uint32_t fid;
+ uint32_t fh;
+} QEMU_PACKED ClpFhListEntry;
+
+#define CLP_RC_SETPCIFN_FH 0x0101 /* Invalid PCI fn handle */
+#define CLP_RC_SETPCIFN_FHOP 0x0102 /* Fn handle not valid for op */
+#define CLP_RC_SETPCIFN_DMAAS 0x0103 /* Invalid DMA addr space */
+#define CLP_RC_SETPCIFN_RES 0x0104 /* Insufficient resources */
+#define CLP_RC_SETPCIFN_ALRDY 0x0105 /* Fn already in requested state */
+#define CLP_RC_SETPCIFN_ERR 0x0106 /* Fn in permanent error state */
+#define CLP_RC_SETPCIFN_RECPND 0x0107 /* Error recovery pending */
+#define CLP_RC_SETPCIFN_BUSY 0x0108 /* Fn busy */
+#define CLP_RC_LISTPCI_BADRT 0x010a /* Resume token not recognized */
+#define CLP_RC_QUERYPCIFG_PFGID 0x010b /* Unrecognized PFGID */
+
+/* request or response block header length */
+#define LIST_PCI_HDR_LEN 32
+
+/* Number of function handles fitting in response block */
+#define CLP_FH_LIST_NR_ENTRIES \
+ ((CLP_BLK_SIZE - 2 * LIST_PCI_HDR_LEN) \
+ / sizeof(ClpFhListEntry))
+
+#define CLP_SET_ENABLE_PCI_FN 0 /* Yes, 0 enables it */
+#define CLP_SET_DISABLE_PCI_FN 1 /* Yes, 1 disables it */
+
+#define CLP_UTIL_STR_LEN 64
+#define CLP_PFIP_NR_SEGMENTS 4
+
+#define CLP_MASK_FMT 0xf0000000
+
+/* List PCI functions request */
+typedef struct ClpReqListPci {
+ ClpReqHdr hdr;
+ uint32_t fmt;
+ uint64_t reserved1;
+ uint64_t resume_token;
+ uint64_t reserved2;
+} QEMU_PACKED ClpReqListPci;
+
+/* List PCI functions response */
+typedef struct ClpRspListPci {
+ ClpRspHdr hdr;
+ uint32_t fmt;
+ uint64_t reserved1;
+ uint64_t resume_token;
+ uint32_t mdd;
+ uint16_t max_fn;
+ uint8_t flags;
+ uint8_t entry_size;
+ ClpFhListEntry fh_list[CLP_FH_LIST_NR_ENTRIES];
+} QEMU_PACKED ClpRspListPci;
+
+/* Query PCI function request */
+typedef struct ClpReqQueryPci {
+ ClpReqHdr hdr;
+ uint32_t fmt;
+ uint64_t reserved1;
+ uint32_t fh; /* function handle */
+ uint32_t reserved2;
+ uint64_t reserved3;
+} QEMU_PACKED ClpReqQueryPci;
+
+/* Query PCI function response */
+typedef struct ClpRspQueryPci {
+ ClpRspHdr hdr;
+ uint32_t fmt;
+ uint64_t reserved1;
+ uint16_t vfn; /* virtual fn number */
+#define CLP_RSP_QPCI_MASK_UTIL 0x01
+ uint8_t flags;
+ uint8_t pfgid;
+ uint32_t fid; /* pci function id */
+ uint8_t bar_size[PCI_BAR_COUNT];
+ uint16_t pchid;
+ uint32_t bar[PCI_BAR_COUNT];
+ uint8_t pfip[CLP_PFIP_NR_SEGMENTS];
+ uint16_t reserved2;
+ uint8_t fmbl;
+ uint8_t pft;
+ uint64_t sdma; /* start dma as */
+ uint64_t edma; /* end dma as */
+ uint32_t reserved3[11];
+ uint32_t uid;
+ uint8_t util_str[CLP_UTIL_STR_LEN]; /* utility string */
+} QEMU_PACKED ClpRspQueryPci;
+
+/* Query PCI function group request */
+typedef struct ClpReqQueryPciGrp {
+ ClpReqHdr hdr;
+ uint32_t fmt;
+ uint64_t reserved1;
+ uint8_t reserved2[3];
+ uint8_t g;
+ uint32_t reserved3;
+ uint64_t reserved4;
+} QEMU_PACKED ClpReqQueryPciGrp;
+
+/* Query PCI function group response */
+typedef struct ClpRspQueryPciGrp {
+ ClpRspHdr hdr;
+ uint32_t fmt;
+ uint64_t reserved1;
+#define CLP_RSP_QPCIG_MASK_NOI 0xfff
+ uint16_t i;
+ uint8_t version;
+#define CLP_RSP_QPCIG_MASK_FRAME 0x2
+#define CLP_RSP_QPCIG_MASK_REFRESH 0x1
+ uint8_t fr;
+ uint16_t maxstbl;
+ uint16_t mui;
+ uint8_t dtsm;
+ uint8_t reserved3[7];
+ uint64_t dasm; /* dma address space mask */
+ uint64_t msia; /* MSI address */
+ uint64_t reserved4;
+ uint64_t reserved5;
+} QEMU_PACKED ClpRspQueryPciGrp;
+
+/* Set PCI function request */
+typedef struct ClpReqSetPci {
+ ClpReqHdr hdr;
+ uint32_t fmt;
+ uint64_t reserved1;
+ uint32_t fh; /* function handle */
+ uint16_t reserved2;
+ uint8_t oc; /* operation controls */
+ uint8_t ndas; /* number of dma spaces */
+ uint64_t reserved3;
+} QEMU_PACKED ClpReqSetPci;
+
+/* Set PCI function response */
+typedef struct ClpRspSetPci {
+ ClpRspHdr hdr;
+ uint32_t fmt;
+ uint64_t reserved1;
+ uint32_t fh; /* function handle */
+ uint32_t reserved3;
+ uint64_t reserved4;
+} QEMU_PACKED ClpRspSetPci;
+
+typedef struct ClpReqRspListPci {
+ ClpReqListPci request;
+ ClpRspListPci response;
+} QEMU_PACKED ClpReqRspListPci;
+
+typedef struct ClpReqRspSetPci {
+ ClpReqSetPci request;
+ ClpRspSetPci response;
+} QEMU_PACKED ClpReqRspSetPci;
+
+typedef struct ClpReqRspQueryPci {
+ ClpReqQueryPci request;
+ ClpRspQueryPci response;
+} QEMU_PACKED ClpReqRspQueryPci;
+
+typedef struct ClpReqRspQueryPciGrp {
+ ClpReqQueryPciGrp request;
+ ClpRspQueryPciGrp response;
+} QEMU_PACKED ClpReqRspQueryPciGrp;
+
+#endif
diff --git a/include/hw/s390x/s390-pci-inst.h b/include/hw/s390x/s390-pci-inst.h
new file mode 100644
index 0000000000..a55c448aad
--- /dev/null
+++ b/include/hw/s390x/s390-pci-inst.h
@@ -0,0 +1,119 @@
+/*
+ * s390 PCI instruction definitions
+ *
+ * Copyright 2014 IBM Corp.
+ * Author(s): Frank Blaschka <frank.blaschka@de.ibm.com>
+ * Hong Bo Li <lihbbj@cn.ibm.com>
+ * Yi Min Zhao <zyimin@cn.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#ifndef HW_S390_PCI_INST_H
+#define HW_S390_PCI_INST_H
+
+#include "s390-pci-bus.h"
+#include "sysemu/dma.h"
+
+/* Load/Store status codes */
+#define ZPCI_PCI_ST_FUNC_NOT_ENABLED 4
+#define ZPCI_PCI_ST_FUNC_IN_ERR 8
+#define ZPCI_PCI_ST_BLOCKED 12
+#define ZPCI_PCI_ST_INSUF_RES 16
+#define ZPCI_PCI_ST_INVAL_AS 20
+#define ZPCI_PCI_ST_FUNC_ALREADY_ENABLED 24
+#define ZPCI_PCI_ST_DMA_AS_NOT_ENABLED 28
+#define ZPCI_PCI_ST_2ND_OP_IN_INV_AS 36
+#define ZPCI_PCI_ST_FUNC_NOT_AVAIL 40
+#define ZPCI_PCI_ST_ALREADY_IN_RQ_STATE 44
+
+/* Load/Store return codes */
+#define ZPCI_PCI_LS_OK 0
+#define ZPCI_PCI_LS_ERR 1
+#define ZPCI_PCI_LS_BUSY 2
+#define ZPCI_PCI_LS_INVAL_HANDLE 3
+
+/* Modify PCI status codes */
+#define ZPCI_MOD_ST_RES_NOT_AVAIL 4
+#define ZPCI_MOD_ST_INSUF_RES 16
+#define ZPCI_MOD_ST_SEQUENCE 24
+#define ZPCI_MOD_ST_DMAAS_INVAL 28
+#define ZPCI_MOD_ST_FRAME_INVAL 32
+#define ZPCI_MOD_ST_ERROR_RECOVER 40
+
+/* Modify PCI Function Controls */
+#define ZPCI_MOD_FC_REG_INT 2
+#define ZPCI_MOD_FC_DEREG_INT 3
+#define ZPCI_MOD_FC_REG_IOAT 4
+#define ZPCI_MOD_FC_DEREG_IOAT 5
+#define ZPCI_MOD_FC_REREG_IOAT 6
+#define ZPCI_MOD_FC_RESET_ERROR 7
+#define ZPCI_MOD_FC_RESET_BLOCK 9
+#define ZPCI_MOD_FC_SET_MEASURE 10
+
+/* Store PCI Function Controls status codes */
+#define ZPCI_STPCIFC_ST_PERM_ERROR 8
+#define ZPCI_STPCIFC_ST_INVAL_DMAAS 28
+#define ZPCI_STPCIFC_ST_ERROR_RECOVER 40
+
+/* Refresh PCI Translations status codes */
+#define ZPCI_RPCIT_ST_INSUFF_RES 16
+
+/* FIB function controls */
+#define ZPCI_FIB_FC_ENABLED 0x80
+#define ZPCI_FIB_FC_ERROR 0x40
+#define ZPCI_FIB_FC_LS_BLOCKED 0x20
+#define ZPCI_FIB_FC_DMAAS_REG 0x10
+
+/* FIB function controls */
+#define ZPCI_FIB_FC_ENABLED 0x80
+#define ZPCI_FIB_FC_ERROR 0x40
+#define ZPCI_FIB_FC_LS_BLOCKED 0x20
+#define ZPCI_FIB_FC_DMAAS_REG 0x10
+
+/* Function Information Block */
+typedef struct ZpciFib {
+ uint8_t fmt; /* format */
+ uint8_t reserved1[7];
+ uint8_t fc; /* function controls */
+ uint8_t reserved2;
+ uint16_t reserved3;
+ uint32_t reserved4;
+ uint64_t pba; /* PCI base address */
+ uint64_t pal; /* PCI address limit */
+ uint64_t iota; /* I/O Translation Anchor */
+#define FIB_DATA_ISC(x) (((x) >> 28) & 0x7)
+#define FIB_DATA_NOI(x) (((x) >> 16) & 0xfff)
+#define FIB_DATA_AIBVO(x) (((x) >> 8) & 0x3f)
+#define FIB_DATA_SUM(x) (((x) >> 7) & 0x1)
+#define FIB_DATA_AISBO(x) ((x) & 0x3f)
+ uint32_t data;
+ uint32_t reserved5;
+ uint64_t aibv; /* Adapter int bit vector address */
+ uint64_t aisb; /* Adapter int summary bit address */
+ uint64_t fmb_addr; /* Function measurement address and key */
+ uint32_t reserved6;
+ uint32_t gd;
+} QEMU_PACKED ZpciFib;
+
+int pci_dereg_irqs(S390PCIBusDevice *pbdev);
+void pci_dereg_ioat(S390PCIIOMMU *iommu);
+int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra);
+int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra);
+int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra);
+int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra);
+int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,
+ uint8_t ar, uintptr_t ra);
+int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar,
+ uintptr_t ra);
+int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar,
+ uintptr_t ra);
+void fmb_timer_free(S390PCIBusDevice *pbdev);
+
+#define ZPCI_IO_BAR_MIN 0
+#define ZPCI_IO_BAR_MAX 5
+#define ZPCI_CONFIG_BAR 15
+
+#endif
diff --git a/include/hw/s390x/s390-pci-kvm.h b/include/hw/s390x/s390-pci-kvm.h
new file mode 100644
index 0000000000..933814a402
--- /dev/null
+++ b/include/hw/s390x/s390-pci-kvm.h
@@ -0,0 +1,38 @@
+/*
+ * s390 PCI KVM interfaces
+ *
+ * Copyright 2022 IBM Corp.
+ * Author(s): Matthew Rosato <mjrosato@linux.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#ifndef HW_S390_PCI_KVM_H
+#define HW_S390_PCI_KVM_H
+
+#include "hw/s390x/s390-pci-bus.h"
+#include "hw/s390x/s390-pci-inst.h"
+
+#ifdef CONFIG_KVM
+bool s390_pci_kvm_interp_allowed(void);
+int s390_pci_kvm_aif_enable(S390PCIBusDevice *pbdev, ZpciFib *fib, bool assist);
+int s390_pci_kvm_aif_disable(S390PCIBusDevice *pbdev);
+#else
+static inline bool s390_pci_kvm_interp_allowed(void)
+{
+ return false;
+}
+static inline int s390_pci_kvm_aif_enable(S390PCIBusDevice *pbdev, ZpciFib *fib,
+ bool assist)
+{
+ return -EINVAL;
+}
+static inline int s390_pci_kvm_aif_disable(S390PCIBusDevice *pbdev)
+{
+ return -EINVAL;
+}
+#endif
+
+#endif
diff --git a/include/hw/s390x/s390-pci-vfio.h b/include/hw/s390x/s390-pci-vfio.h
new file mode 100644
index 0000000000..ae1b126ff7
--- /dev/null
+++ b/include/hw/s390x/s390-pci-vfio.h
@@ -0,0 +1,44 @@
+/*
+ * s390 vfio-pci interfaces
+ *
+ * Copyright 2020 IBM Corp.
+ * Author(s): Matthew Rosato <mjrosato@linux.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#ifndef HW_S390_PCI_VFIO_H
+#define HW_S390_PCI_VFIO_H
+
+#include "hw/s390x/s390-pci-bus.h"
+#include CONFIG_DEVICES
+
+#ifdef CONFIG_VFIO
+bool s390_pci_update_dma_avail(int fd, unsigned int *avail);
+S390PCIDMACount *s390_pci_start_dma_count(S390pciState *s,
+ S390PCIBusDevice *pbdev);
+void s390_pci_end_dma_count(S390pciState *s, S390PCIDMACount *cnt);
+bool s390_pci_get_host_fh(S390PCIBusDevice *pbdev, uint32_t *fh);
+void s390_pci_get_clp_info(S390PCIBusDevice *pbdev);
+#else
+static inline bool s390_pci_update_dma_avail(int fd, unsigned int *avail)
+{
+ return false;
+}
+static inline S390PCIDMACount *s390_pci_start_dma_count(S390pciState *s,
+ S390PCIBusDevice *pbdev)
+{
+ return NULL;
+}
+static inline void s390_pci_end_dma_count(S390pciState *s,
+ S390PCIDMACount *cnt) { }
+static inline bool s390_pci_get_host_fh(S390PCIBusDevice *pbdev, uint32_t *fh)
+{
+ return false;
+}
+static inline void s390_pci_get_clp_info(S390PCIBusDevice *pbdev) { }
+#endif
+
+#endif
diff --git a/include/hw/s390x/s390-virtio-ccw.h b/include/hw/s390x/s390-virtio-ccw.h
index cd1dccc6e3..c1d46e78af 100644
--- a/include/hw/s390x/s390-virtio-ccw.h
+++ b/include/hw/s390x/s390-virtio-ccw.h
@@ -12,16 +12,14 @@
#define HW_S390X_S390_VIRTIO_CCW_H
#include "hw/boards.h"
+#include "qom/object.h"
#define TYPE_S390_CCW_MACHINE "s390-ccw-machine"
-#define S390_CCW_MACHINE(obj) \
- OBJECT_CHECK(S390CcwMachineState, (obj), TYPE_S390_CCW_MACHINE)
+OBJECT_DECLARE_TYPE(S390CcwMachineState, S390CcwMachineClass, S390_CCW_MACHINE)
-#define S390_MACHINE_CLASS(klass) \
- OBJECT_CLASS_CHECK(S390CcwMachineClass, (klass), TYPE_S390_CCW_MACHINE)
-typedef struct S390CcwMachineState {
+struct S390CcwMachineState {
/*< private >*/
MachineState parent_obj;
@@ -30,9 +28,15 @@ typedef struct S390CcwMachineState {
bool dea_key_wrap;
bool pv;
uint8_t loadparm[8];
-} S390CcwMachineState;
+};
-typedef struct S390CcwMachineClass {
+#define S390_PTF_REASON_NONE (0x00 << 8)
+#define S390_PTF_REASON_DONE (0x01 << 8)
+#define S390_PTF_REASON_BUSY (0x02 << 8)
+#define S390_TOPO_FC_MASK 0xffUL
+void s390_handle_ptf(S390CPU *cpu, uint8_t r1, uintptr_t ra);
+
+struct S390CcwMachineClass {
/*< private >*/
MachineClass parent_class;
@@ -41,7 +45,8 @@ typedef struct S390CcwMachineClass {
bool cpu_model_allowed;
bool css_migration_enabled;
bool hpage_1m_allowed;
-} S390CcwMachineClass;
+ int max_threads;
+};
/* runtime-instrumentation allowed by the machine */
bool ri_allowed(void);
diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h
index 4687ecfe83..3907a13d07 100644
--- a/include/hw/s390x/s390_flic.h
+++ b/include/hw/s390x/s390_flic.h
@@ -17,6 +17,7 @@
#include "hw/s390x/adapter.h"
#include "hw/virtio/virtio.h"
#include "qemu/queue.h"
+#include "qom/object.h"
/*
* Reserve enough gsis to accommodate all virtio devices.
@@ -38,22 +39,18 @@ extern const VMStateDescription vmstate_adapter_routes;
VMSTATE_STRUCT(_f, _s, 1, vmstate_adapter_routes, AdapterRoutes)
#define TYPE_S390_FLIC_COMMON "s390-flic"
-#define S390_FLIC_COMMON(obj) \
- OBJECT_CHECK(S390FLICState, (obj), TYPE_S390_FLIC_COMMON)
+OBJECT_DECLARE_TYPE(S390FLICState, S390FLICStateClass,
+ S390_FLIC_COMMON)
-typedef struct S390FLICState {
+struct S390FLICState {
SysBusDevice parent_obj;
/* to limit AdapterRoutes.num_routes for compat */
uint32_t adapter_routes_max_batch;
bool ais_supported;
-} S390FLICState;
+};
-#define S390_FLIC_COMMON_CLASS(klass) \
- OBJECT_CLASS_CHECK(S390FLICStateClass, (klass), TYPE_S390_FLIC_COMMON)
-#define S390_FLIC_COMMON_GET_CLASS(obj) \
- OBJECT_GET_CLASS(S390FLICStateClass, (obj), TYPE_S390_FLIC_COMMON)
-typedef struct S390FLICStateClass {
+struct S390FLICStateClass {
DeviceClass parent_class;
int (*register_io_adapter)(S390FLICState *fs, uint32_t id, uint8_t isc,
@@ -72,15 +69,15 @@ typedef struct S390FLICStateClass {
uint16_t subchannel_nr, uint32_t io_int_parm,
uint32_t io_int_word);
void (*inject_crw_mchk)(S390FLICState *fs);
-} S390FLICStateClass;
+};
#define TYPE_KVM_S390_FLIC "s390-flic-kvm"
-#define KVM_S390_FLIC(obj) \
- OBJECT_CHECK(KVMS390FLICState, (obj), TYPE_KVM_S390_FLIC)
+typedef struct KVMS390FLICState KVMS390FLICState;
+DECLARE_INSTANCE_CHECKER(KVMS390FLICState, KVM_S390_FLIC,
+ TYPE_KVM_S390_FLIC)
#define TYPE_QEMU_S390_FLIC "s390-flic-qemu"
-#define QEMU_S390_FLIC(obj) \
- OBJECT_CHECK(QEMUS390FLICState, (obj), TYPE_QEMU_S390_FLIC)
+OBJECT_DECLARE_SIMPLE_TYPE(QEMUS390FLICState, QEMU_S390_FLIC)
#define SIC_IRQ_MODE_ALL 0
#define SIC_IRQ_MODE_SINGLE 1
@@ -114,14 +111,14 @@ typedef struct QEMUS390FlicIO {
QLIST_ENTRY(QEMUS390FlicIO) next;
} QEMUS390FlicIO;
-typedef struct QEMUS390FLICState {
+struct QEMUS390FLICState {
S390FLICState parent_obj;
uint32_t pending;
uint32_t service_param;
uint8_t simm;
uint8_t nimm;
QLIST_HEAD(, QEMUS390FlicIO) io[8];
-} QEMUS390FLICState;
+};
uint32_t qemu_s390_flic_dequeue_service(QEMUS390FLICState *flic);
QEMUS390FlicIO *qemu_s390_flic_dequeue_io(QEMUS390FLICState *flic,
@@ -137,6 +134,9 @@ void s390_flic_init(void);
S390FLICState *s390_get_flic(void);
QEMUS390FLICState *s390_get_qemu_flic(S390FLICState *fs);
S390FLICStateClass *s390_get_flic_class(S390FLICState *fs);
+void s390_crw_mchk(void);
+void s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr,
+ uint32_t io_int_parm, uint32_t io_int_word);
bool ais_needed(void *opaque);
#endif /* HW_S390_FLIC_H */
diff --git a/include/hw/s390x/sclp.h b/include/hw/s390x/sclp.h
index 822eff4396..b405a387b6 100644
--- a/include/hw/s390x/sclp.h
+++ b/include/hw/s390x/sclp.h
@@ -16,6 +16,7 @@
#include "hw/sysbus.h"
#include "target/s390x/cpu-qom.h"
+#include "qom/object.h"
#define SCLP_CMD_CODE_MASK 0xffff00ff
@@ -37,10 +38,8 @@
#define MAX_STORAGE_INCREMENTS 1020
/* CPU hotplug SCLP codes */
-#define SCLP_HAS_CPU_INFO 0x0C00000000000000ULL
+#define SCLP_HAS_CPU_INFO 0x0800000000000000ULL
#define SCLP_CMDW_READ_CPU_INFO 0x00010001
-#define SCLP_CMDW_CONFIGURE_CPU 0x00110001
-#define SCLP_CMDW_DECONFIGURE_CPU 0x00100001
/* SCLP PCI codes */
#define SCLP_HAS_IOA_RECONFIG 0x0000000040000000ULL
@@ -86,7 +85,7 @@
* - we work on a private copy of the SCCB, since there are several length
* fields, that would cause a security nightmare if we allow the guest to
* alter the structure while we parse it. We cannot use ldl_p and friends
- * either without doing pointer arithmetics
+ * either without doing pointer arithmetic
* So we have to double check that all users of sclp data structures use the
* right endianness wrappers.
*/
@@ -110,11 +109,14 @@ typedef struct CPUEntry {
uint8_t reserved1;
} QEMU_PACKED CPUEntry;
+#define SCLP_READ_SCP_INFO_FIXED_CPU_OFFSET 128
+#define SCLP_READ_SCP_INFO_MNEST 4
typedef struct ReadInfo {
SCCBHeader h;
uint16_t rnmax;
uint8_t rnsize;
- uint8_t _reserved1[16 - 11]; /* 11-15 */
+ uint8_t _reserved1[15 - 11]; /* 11-14 */
+ uint8_t stsi_parm; /* 15-15 */
uint16_t entries_cpu; /* 16-17 */
uint16_t offset_cpu; /* 18-19 */
uint8_t _reserved2[24 - 20]; /* 20-23 */
@@ -132,7 +134,15 @@ typedef struct ReadInfo {
uint16_t highest_cpu;
uint8_t _reserved5[124 - 122]; /* 122-123 */
uint32_t hmfai;
+ uint8_t _reserved7[134 - 128]; /* 128-133 */
+ uint8_t fac134;
+ uint8_t _reserved8[144 - 135]; /* 135-143 */
struct CPUEntry entries[];
+ /*
+ * When the Extended-Length SCCB (ELS) feature is enabled the
+ * start of the entries field begins at an offset denoted by the
+ * offset_cpu field, otherwise it's at an offset of 128.
+ */
} QEMU_PACKED ReadInfo;
typedef struct ReadCpuInfo {
@@ -177,26 +187,25 @@ typedef struct IoaCfgSccb {
typedef struct SCCB {
SCCBHeader h;
- char data[SCCB_DATA_LEN];
+ char data[];
} QEMU_PACKED SCCB;
#define TYPE_SCLP "sclp"
-#define SCLP(obj) OBJECT_CHECK(SCLPDevice, (obj), TYPE_SCLP)
-#define SCLP_CLASS(oc) OBJECT_CLASS_CHECK(SCLPDeviceClass, (oc), TYPE_SCLP)
-#define SCLP_GET_CLASS(obj) OBJECT_GET_CLASS(SCLPDeviceClass, (obj), TYPE_SCLP)
+OBJECT_DECLARE_TYPE(SCLPDevice, SCLPDeviceClass,
+ SCLP)
-typedef struct SCLPEventFacility SCLPEventFacility;
+struct SCLPEventFacility;
-typedef struct SCLPDevice {
+struct SCLPDevice {
/* private */
DeviceState parent_obj;
- SCLPEventFacility *event_facility;
+ struct SCLPEventFacility *event_facility;
int increment_size;
/* public */
-} SCLPDevice;
+};
-typedef struct SCLPDeviceClass {
+struct SCLPDeviceClass {
/* private */
DeviceClass parent_class;
void (*read_SCP_info)(SCLPDevice *sclp, SCCB *sccb);
@@ -205,7 +214,7 @@ typedef struct SCLPDeviceClass {
/* public */
void (*execute)(SCLPDevice *sclp, SCCB *sccb, uint32_t code);
void (*service_interrupt)(SCLPDevice *sclp, uint32_t sccb);
-} SCLPDeviceClass;
+};
static inline int sccb_data_len(SCCB *sccb)
{
@@ -216,8 +225,7 @@ static inline int sccb_data_len(SCCB *sccb)
void s390_sclp_init(void);
void sclp_service_interrupt(uint32_t sccb);
void raise_irq_cpu_hotplug(void);
-int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code);
-int sclp_service_call_protected(CPUS390XState *env, uint64_t sccb,
- uint32_t code);
+int sclp_service_call(S390CPU *cpu, uint64_t sccb, uint32_t code);
+int sclp_service_call_protected(S390CPU *cpu, uint64_t sccb, uint32_t code);
#endif
diff --git a/include/hw/s390x/storage-attributes.h b/include/hw/s390x/storage-attributes.h
index 4f7c6c0877..8921a04d51 100644
--- a/include/hw/s390x/storage-attributes.h
+++ b/include/hw/s390x/storage-attributes.h
@@ -14,26 +14,22 @@
#include "hw/qdev-core.h"
#include "monitor/monitor.h"
+#include "qom/object.h"
#define TYPE_S390_STATTRIB "s390-storage_attributes"
#define TYPE_QEMU_S390_STATTRIB "s390-storage_attributes-qemu"
#define TYPE_KVM_S390_STATTRIB "s390-storage_attributes-kvm"
-#define S390_STATTRIB(obj) \
- OBJECT_CHECK(S390StAttribState, (obj), TYPE_S390_STATTRIB)
+OBJECT_DECLARE_TYPE(S390StAttribState, S390StAttribClass, S390_STATTRIB)
-typedef struct S390StAttribState {
+struct S390StAttribState {
DeviceState parent_obj;
uint64_t migration_cur_gfn;
bool migration_enabled;
-} S390StAttribState;
+};
-#define S390_STATTRIB_CLASS(klass) \
- OBJECT_CLASS_CHECK(S390StAttribClass, (klass), TYPE_S390_STATTRIB)
-#define S390_STATTRIB_GET_CLASS(obj) \
- OBJECT_GET_CLASS(S390StAttribClass, (obj), TYPE_S390_STATTRIB)
-typedef struct S390StAttribClass {
+struct S390StAttribClass {
DeviceClass parent_class;
/* Return value: < 0 on error, or new count */
int (*get_stattr)(S390StAttribState *sa, uint64_t *start_gfn,
@@ -43,26 +39,28 @@ typedef struct S390StAttribClass {
int (*set_stattr)(S390StAttribState *sa, uint64_t start_gfn,
uint32_t count, uint8_t *values);
void (*synchronize)(S390StAttribState *sa);
- int (*set_migrationmode)(S390StAttribState *sa, bool value);
+ int (*set_migrationmode)(S390StAttribState *sa, bool value, Error **errp);
int (*get_active)(S390StAttribState *sa);
long long (*get_dirtycount)(S390StAttribState *sa);
-} S390StAttribClass;
+};
-#define QEMU_S390_STATTRIB(obj) \
- OBJECT_CHECK(QEMUS390StAttribState, (obj), TYPE_QEMU_S390_STATTRIB)
+typedef struct QEMUS390StAttribState QEMUS390StAttribState;
+DECLARE_INSTANCE_CHECKER(QEMUS390StAttribState, QEMU_S390_STATTRIB,
+ TYPE_QEMU_S390_STATTRIB)
-typedef struct QEMUS390StAttribState {
+struct QEMUS390StAttribState {
S390StAttribState parent_obj;
-} QEMUS390StAttribState;
+};
-#define KVM_S390_STATTRIB(obj) \
- OBJECT_CHECK(KVMS390StAttribState, (obj), TYPE_KVM_S390_STATTRIB)
+typedef struct KVMS390StAttribState KVMS390StAttribState;
+DECLARE_INSTANCE_CHECKER(KVMS390StAttribState, KVM_S390_STATTRIB,
+ TYPE_KVM_S390_STATTRIB)
-typedef struct KVMS390StAttribState {
+struct KVMS390StAttribState {
S390StAttribState parent_obj;
uint64_t still_dirty;
uint8_t *incoming_buffer;
-} KVMS390StAttribState;
+};
void s390_stattrib_init(void);
diff --git a/include/hw/s390x/storage-keys.h b/include/hw/s390x/storage-keys.h
index 3f1ae7e778..aa2ec2aae5 100644
--- a/include/hw/s390x/storage-keys.h
+++ b/include/hw/s390x/storage-keys.h
@@ -14,41 +14,101 @@
#include "hw/qdev-core.h"
#include "monitor/monitor.h"
+#include "qom/object.h"
#define TYPE_S390_SKEYS "s390-skeys"
-#define S390_SKEYS(obj) \
- OBJECT_CHECK(S390SKeysState, (obj), TYPE_S390_SKEYS)
+OBJECT_DECLARE_TYPE(S390SKeysState, S390SKeysClass, S390_SKEYS)
-typedef struct S390SKeysState {
+struct S390SKeysState {
DeviceState parent_obj;
bool migration_enabled;
-} S390SKeysState;
+};
-#define S390_SKEYS_CLASS(klass) \
- OBJECT_CLASS_CHECK(S390SKeysClass, (klass), TYPE_S390_SKEYS)
-#define S390_SKEYS_GET_CLASS(obj) \
- OBJECT_GET_CLASS(S390SKeysClass, (obj), TYPE_S390_SKEYS)
-typedef struct S390SKeysClass {
+struct S390SKeysClass {
DeviceClass parent_class;
- int (*skeys_enabled)(S390SKeysState *ks);
+
+ /**
+ * @skeys_are_enabled:
+ *
+ * Check whether storage keys are enabled. If not enabled, they were not
+ * enabled lazily either by the guest via a storage key instruction or
+ * by the host during migration.
+ *
+ * If disabled, everything not explicitly triggered by the guest,
+ * such as outgoing migration or dirty/change tracking, should not touch
+ * storage keys and should not lazily enable it.
+ *
+ * @ks: the #S390SKeysState
+ *
+ * Returns false if not enabled and true if enabled.
+ */
+ bool (*skeys_are_enabled)(S390SKeysState *ks);
+
+ /**
+ * @enable_skeys:
+ *
+ * Lazily enable storage keys. If this function is not implemented,
+ * setting a storage key will lazily enable storage keys implicitly
+ * instead. TCG guests have to make sure to flush the TLB of all CPUs
+ * if storage keys were not enabled before this call.
+ *
+ * @ks: the #S390SKeysState
+ *
+ * Returns false if not enabled before this call, and true if already
+ * enabled.
+ */
+ bool (*enable_skeys)(S390SKeysState *ks);
+
+ /**
+ * @get_skeys:
+ *
+ * Get storage keys for the given PFN range. This call will fail if
+ * storage keys have not been lazily enabled yet.
+ *
+ * Callers have to validate that a GFN is valid before this call.
+ *
+ * @ks: the #S390SKeysState
+ * @start_gfn: the start GFN to get storage keys for
+ * @count: the number of storage keys to get
+ * @keys: the byte array where storage keys will be stored to
+ *
+ * Returns 0 on success, returns an error if getting a storage key failed.
+ */
int (*get_skeys)(S390SKeysState *ks, uint64_t start_gfn, uint64_t count,
uint8_t *keys);
+ /**
+ * @set_skeys:
+ *
+ * Set storage keys for the given PFN range. This call will fail if
+ * storage keys have not been lazily enabled yet and implicit
+ * enablement is not supported.
+ *
+ * Callers have to validate that a GFN is valid before this call.
+ *
+ * @ks: the #S390SKeysState
+ * @start_gfn: the start GFN to set storage keys for
+ * @count: the number of storage keys to set
+ * @keys: the byte array where storage keys will be read from
+ *
+ * Returns 0 on success, returns an error if setting a storage key failed.
+ */
int (*set_skeys)(S390SKeysState *ks, uint64_t start_gfn, uint64_t count,
uint8_t *keys);
-} S390SKeysClass;
+};
#define TYPE_KVM_S390_SKEYS "s390-skeys-kvm"
#define TYPE_QEMU_S390_SKEYS "s390-skeys-qemu"
-#define QEMU_S390_SKEYS(obj) \
- OBJECT_CHECK(QEMUS390SKeysState, (obj), TYPE_QEMU_S390_SKEYS)
+typedef struct QEMUS390SKeysState QEMUS390SKeysState;
+DECLARE_INSTANCE_CHECKER(QEMUS390SKeysState, QEMU_S390_SKEYS,
+ TYPE_QEMU_S390_SKEYS)
-typedef struct QEMUS390SKeysState {
+struct QEMUS390SKeysState {
S390SKeysState parent_obj;
uint8_t *keydata;
uint32_t key_count;
-} QEMUS390SKeysState;
+};
void s390_skeys_init(void);
diff --git a/include/hw/s390x/tod.h b/include/hw/s390x/tod.h
index 4251623f7f..0935e85089 100644
--- a/include/hw/s390x/tod.h
+++ b/include/hw/s390x/tod.h
@@ -12,7 +12,8 @@
#define HW_S390_TOD_H
#include "hw/qdev-core.h"
-#include "target/s390x/s390-tod.h"
+#include "tcg/s390-tod.h"
+#include "qom/object.h"
typedef struct S390TOD {
uint8_t high;
@@ -20,15 +21,11 @@ typedef struct S390TOD {
} S390TOD;
#define TYPE_S390_TOD "s390-tod"
-#define S390_TOD(obj) OBJECT_CHECK(S390TODState, (obj), TYPE_S390_TOD)
-#define S390_TOD_CLASS(oc) OBJECT_CLASS_CHECK(S390TODClass, (oc), \
- TYPE_S390_TOD)
-#define S390_TOD_GET_CLASS(obj) OBJECT_GET_CLASS(S390TODClass, (obj), \
- TYPE_S390_TOD)
+OBJECT_DECLARE_TYPE(S390TODState, S390TODClass, S390_TOD)
#define TYPE_KVM_S390_TOD TYPE_S390_TOD "-kvm"
#define TYPE_QEMU_S390_TOD TYPE_S390_TOD "-qemu"
-typedef struct S390TODState {
+struct S390TODState {
/* private */
DeviceState parent_obj;
@@ -39,9 +36,9 @@ typedef struct S390TODState {
S390TOD base;
/* Used by KVM to remember if the TOD is stopped and base is valid. */
bool stopped;
-} S390TODState;
+};
-typedef struct S390TODClass {
+struct S390TODClass {
/* private */
DeviceClass parent_class;
void (*parent_realize)(DeviceState *dev, Error **errp);
@@ -49,7 +46,7 @@ typedef struct S390TODClass {
/* public */
void (*get)(const S390TODState *td, S390TOD *tod, Error **errp);
void (*set)(S390TODState *td, const S390TOD *tod, Error **errp);
-} S390TODClass;
+};
void s390_init_tod(void);
S390TODState *s390_get_todstate(void);
diff --git a/include/hw/s390x/vfio-ccw.h b/include/hw/s390x/vfio-ccw.h
index ee5250d0d7..4209d27657 100644
--- a/include/hw/s390x/vfio-ccw.h
+++ b/include/hw/s390x/vfio-ccw.h
@@ -17,12 +17,9 @@
#include "hw/vfio/vfio-common.h"
#include "hw/s390x/s390-ccw.h"
#include "hw/s390x/ccw-device.h"
+#include "qom/object.h"
#define TYPE_VFIO_CCW "vfio-ccw"
-#define VFIO_CCW(obj) \
- OBJECT_CHECK(VFIOCCWDevice, (obj), TYPE_VFIO_CCW)
-
-#define TYPE_VFIO_CCW "vfio-ccw"
-typedef struct VFIOCCWDevice VFIOCCWDevice;
+OBJECT_DECLARE_SIMPLE_TYPE(VFIOCCWDevice, VFIO_CCW)
#endif
diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h
index 6ba47dac41..533d856aa3 100644
--- a/include/hw/scsi/esp.h
+++ b/include/hw/scsi/esp.h
@@ -3,50 +3,45 @@
#include "hw/scsi/scsi.h"
#include "hw/sysbus.h"
+#include "qemu/fifo8.h"
+#include "qom/object.h"
/* esp.c */
#define ESP_MAX_DEVS 7
typedef void (*ESPDMAMemoryReadWriteFunc)(void *opaque, uint8_t *buf, int len);
#define ESP_REGS 16
-#define TI_BUFSZ 16
-#define ESP_CMDBUF_SZ 32
+#define ESP_FIFO_SZ 16
+#define ESP_CMDFIFO_SZ 32
typedef struct ESPState ESPState;
-enum pdma_origin_id {
- PDMA,
- TI,
- CMD,
- ASYNC,
-};
+#define TYPE_ESP "esp"
+OBJECT_DECLARE_SIMPLE_TYPE(ESPState, ESP)
struct ESPState {
+ DeviceState parent_obj;
+
uint8_t rregs[ESP_REGS];
uint8_t wregs[ESP_REGS];
qemu_irq irq;
- qemu_irq irq_data;
+ qemu_irq drq_irq;
+ bool drq_state;
uint8_t chip_id;
bool tchi_written;
int32_t ti_size;
- uint32_t ti_rptr, ti_wptr;
uint32_t status;
- uint32_t deferred_status;
- bool deferred_complete;
uint32_t dma;
- uint8_t ti_buf[TI_BUFSZ];
+ Fifo8 fifo;
SCSIBus bus;
SCSIDevice *current_dev;
SCSIRequest *current_req;
- uint8_t cmdbuf[ESP_CMDBUF_SZ];
- uint32_t cmdlen;
+ Fifo8 cmdfifo;
+ uint8_t cmdfifo_cdb_offset;
+ uint8_t lun;
uint32_t do_cmd;
- /* The amount of data left in the current DMA transfer. */
- uint32_t dma_left;
- /* The size of the current DMA transfer. Zero if no transfer is in
- progress. */
- uint32_t dma_counter;
+ bool data_ready;
int dma_enabled;
uint32_t async_len;
@@ -56,18 +51,25 @@ struct ESPState {
ESPDMAMemoryReadWriteFunc dma_memory_write;
void *dma_opaque;
void (*dma_cb)(ESPState *s);
- uint8_t pdma_buf[32];
- int pdma_origin;
- uint32_t pdma_len;
- uint32_t pdma_start;
- uint32_t pdma_cur;
- void (*pdma_cb)(ESPState *s);
+
+ uint8_t mig_version_id;
+
+ /* Legacy fields for vmstate_esp version < 5 */
+ uint32_t mig_dma_left;
+ uint32_t mig_deferred_status;
+ bool mig_deferred_complete;
+ uint32_t mig_ti_rptr, mig_ti_wptr;
+ uint8_t mig_ti_buf[ESP_FIFO_SZ];
+ uint8_t mig_cmdbuf[ESP_CMDFIFO_SZ];
+ uint32_t mig_cmdlen;
+
+ uint8_t mig_ti_cmd;
};
-#define TYPE_ESP "esp"
-#define ESP_STATE(obj) OBJECT_CHECK(SysBusESPState, (obj), TYPE_ESP)
+#define TYPE_SYSBUS_ESP "sysbus-esp"
+OBJECT_DECLARE_SIMPLE_TYPE(SysBusESPState, SYSBUS_ESP)
-typedef struct {
+struct SysBusESPState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -76,7 +78,7 @@ typedef struct {
MemoryRegion pdma;
uint32_t it_shift;
ESPState esp;
-} SysBusESPState;
+};
#define ESP_TCLO 0x0
#define ESP_TCMID 0x1
@@ -141,6 +143,7 @@ typedef struct {
#define INTR_RST 0x80
#define SEQ_0 0x0
+#define SEQ_MO 0x1
#define SEQ_CD 0x4
#define CFG1_RESREPT 0x40
@@ -150,11 +153,12 @@ typedef struct {
void esp_dma_enable(ESPState *s, int irq, int level);
void esp_request_cancelled(SCSIRequest *req);
-void esp_command_complete(SCSIRequest *req, uint32_t status, size_t resid);
+void esp_command_complete(SCSIRequest *req, size_t resid);
void esp_transfer_data(SCSIRequest *req, uint32_t len);
void esp_hard_reset(ESPState *s);
uint64_t esp_reg_read(ESPState *s, uint32_t saddr);
void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val);
extern const VMStateDescription vmstate_esp;
+int esp_pre_save(void *opaque);
#endif
diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
index 2fc23e44ba..c3d5e17e38 100644
--- a/include/hw/scsi/scsi.h
+++ b/include/hw/scsi/scsi.h
@@ -6,8 +6,9 @@
#include "hw/qdev-core.h"
#include "scsi/utils.h"
#include "qemu/notify.h"
+#include "qom/object.h"
-#define MAX_SCSI_DEVS 255
+#define MAX_SCSI_DEVS 255
typedef struct SCSIBus SCSIBus;
typedef struct SCSIBusInfo SCSIBusInfo;
@@ -17,6 +18,7 @@ typedef struct SCSIReqOps SCSIReqOps;
#define SCSI_SENSE_BUF_SIZE_OLD 96
#define SCSI_SENSE_BUF_SIZE 252
+#define DEFAULT_IO_TIMEOUT 30
struct SCSIRequest {
SCSIBus *bus;
@@ -25,9 +27,10 @@ struct SCSIRequest {
uint32_t refcount;
uint32_t tag;
uint32_t lun;
- uint32_t status;
+ int16_t status;
+ int16_t host_status;
void *hba_private;
- size_t resid;
+ uint64_t residual;
SCSICommand cmd;
NotifierList cancel_notifiers;
@@ -49,36 +52,36 @@ struct SCSIRequest {
};
#define TYPE_SCSI_DEVICE "scsi-device"
-#define SCSI_DEVICE(obj) \
- OBJECT_CHECK(SCSIDevice, (obj), TYPE_SCSI_DEVICE)
-#define SCSI_DEVICE_CLASS(klass) \
- OBJECT_CLASS_CHECK(SCSIDeviceClass, (klass), TYPE_SCSI_DEVICE)
-#define SCSI_DEVICE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(SCSIDeviceClass, (obj), TYPE_SCSI_DEVICE)
-
-typedef struct SCSIDeviceClass {
+OBJECT_DECLARE_TYPE(SCSIDevice, SCSIDeviceClass, SCSI_DEVICE)
+
+struct SCSIDeviceClass {
DeviceClass parent_class;
void (*realize)(SCSIDevice *dev, Error **errp);
void (*unrealize)(SCSIDevice *dev);
int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
- void *hba_private);
+ size_t buf_len, void *hba_private);
SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun,
uint8_t *buf, void *hba_private);
void (*unit_attention_reported)(SCSIDevice *s);
-} SCSIDeviceClass;
+};
struct SCSIDevice
{
DeviceState qdev;
VMChangeStateEntry *vmsentry;
- QEMUBH *bh;
uint32_t id;
BlockConf conf;
SCSISense unit_attention;
bool sense_is_ua;
uint8_t sense[SCSI_SENSE_BUF_SIZE];
uint32_t sense_len;
+
+ /*
+ * The requests list is only accessed from the AioContext that executes
+ * requests or from the main loop when IOThread processing is stopped.
+ */
QTAILQ_HEAD(, SCSIRequest) requests;
+
uint32_t channel;
uint32_t lun;
int blocksize;
@@ -88,6 +91,7 @@ struct SCSIDevice
uint64_t port_wwn;
int scsi_version;
int default_scsi_version;
+ uint32_t io_timeout;
bool needs_vpd_bl_emulation;
bool hba_supports_iothread;
};
@@ -109,6 +113,7 @@ int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num);
/* scsi-bus.c */
struct SCSIReqOps {
size_t size;
+ void (*init_req)(SCSIRequest *req);
void (*free_req)(SCSIRequest *req);
int32_t (*send_command)(SCSIRequest *req, uint8_t *buf);
void (*read_data)(SCSIRequest *req);
@@ -123,9 +128,10 @@ struct SCSIBusInfo {
int tcq;
int max_channel, max_target, max_lun;
int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
- void *hba_private);
+ size_t buf_len, void *hba_private);
void (*transfer_data)(SCSIRequest *req, uint32_t arg);
- void (*complete)(SCSIRequest *req, uint32_t arg, size_t resid);
+ void (*fail)(SCSIRequest *req);
+ void (*complete)(SCSIRequest *req, size_t residual);
void (*cancel)(SCSIRequest *req);
void (*change)(SCSIBus *bus, SCSIDevice *dev, SCSISense sense);
QEMUSGList *(*get_sg_list)(SCSIRequest *req);
@@ -133,10 +139,20 @@ struct SCSIBusInfo {
void (*save_request)(QEMUFile *f, SCSIRequest *req);
void *(*load_request)(QEMUFile *f, SCSIRequest *req);
void (*free_request)(SCSIBus *bus, void *priv);
+
+ /*
+ * Temporarily stop submitting new requests between drained_begin() and
+ * drained_end(). Called from the main loop thread with the BQL held.
+ *
+ * Implement these callbacks if request processing is triggered by a file
+ * descriptor like an EventNotifier. Otherwise set them to NULL.
+ */
+ void (*drained_begin)(SCSIBus *bus);
+ void (*drained_end)(SCSIBus *bus);
};
#define TYPE_SCSI_BUS "SCSI"
-#define SCSI_BUS(obj) OBJECT_CHECK(SCSIBus, (obj), TYPE_SCSI_BUS)
+OBJECT_DECLARE_SIMPLE_TYPE(SCSIBus, SCSI_BUS)
struct SCSIBus {
BusState qbus;
@@ -144,10 +160,38 @@ struct SCSIBus {
SCSISense unit_attention;
const SCSIBusInfo *info;
+
+ int drain_count; /* protected by BQL */
};
-void scsi_bus_new(SCSIBus *bus, size_t bus_size, DeviceState *host,
- const SCSIBusInfo *info, const char *bus_name);
+/**
+ * scsi_bus_init_named: Initialize a SCSI bus with the specified name
+ * @bus: SCSIBus object to initialize
+ * @bus_size: size of @bus object
+ * @host: Device which owns the bus (generally the SCSI controller)
+ * @info: structure defining callbacks etc for the controller
+ * @bus_name: Name to use for this bus
+ *
+ * This in-place initializes @bus as a new SCSI bus with a name
+ * provided by the caller. It is the caller's responsibility to make
+ * sure that name does not clash with the name of any other bus in the
+ * system. Unless you need the new bus to have a specific name, you
+ * should use scsi_bus_init() instead.
+ */
+void scsi_bus_init_named(SCSIBus *bus, size_t bus_size, DeviceState *host,
+ const SCSIBusInfo *info, const char *bus_name);
+
+/**
+ * scsi_bus_init: Initialize a SCSI bus
+ *
+ * This in-place-initializes @bus as a new SCSI bus and gives it
+ * an automatically generated unique name.
+ */
+static inline void scsi_bus_init(SCSIBus *bus, size_t bus_size,
+ DeviceState *host, const SCSIBusInfo *info)
+{
+ scsi_bus_init_named(bus, bus_size, host, info, NULL);
+}
static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
{
@@ -155,36 +199,37 @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
}
SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
- int unit, bool removable, int bootindex,
- bool share_rw,
- BlockdevOnError rerror,
- BlockdevOnError werror,
+ int unit, bool removable, BlockConf *conf,
const char *serial, Error **errp);
+void scsi_bus_set_ua(SCSIBus *bus, SCSISense sense);
void scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
-void scsi_legacy_handle_cmdline(void);
SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
uint32_t tag, uint32_t lun, void *hba_private);
SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
- uint8_t *buf, void *hba_private);
+ uint8_t *buf, size_t buf_len, void *hba_private);
int32_t scsi_req_enqueue(SCSIRequest *req);
SCSIRequest *scsi_req_ref(SCSIRequest *req);
void scsi_req_unref(SCSIRequest *req);
int scsi_bus_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
- void *hba_private);
-int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf);
+ size_t buf_len, void *hba_private);
+int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
+ size_t buf_len);
void scsi_req_build_sense(SCSIRequest *req, SCSISense sense);
void scsi_req_print(SCSIRequest *req);
void scsi_req_continue(SCSIRequest *req);
void scsi_req_data(SCSIRequest *req, int len);
void scsi_req_complete(SCSIRequest *req, int status);
+void scsi_req_complete_failed(SCSIRequest *req, int host_status);
uint8_t *scsi_req_get_buf(SCSIRequest *req);
int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len);
void scsi_req_cancel_complete(SCSIRequest *req);
void scsi_req_cancel(SCSIRequest *req);
void scsi_req_cancel_async(SCSIRequest *req, Notifier *notifier);
void scsi_req_retry(SCSIRequest *req);
+void scsi_device_drained_begin(SCSIDevice *sdev);
+void scsi_device_drained_end(SCSIDevice *sdev);
void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense);
void scsi_device_set_ua(SCSIDevice *sdev, SCSISense sense);
void scsi_device_report_change(SCSIDevice *dev, SCSISense sense);
@@ -192,10 +237,17 @@ void scsi_device_unit_attention_reported(SCSIDevice *dev);
void scsi_generic_read_device_inquiry(SCSIDevice *dev);
int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed);
int scsi_SG_IO_FROM_DEV(BlockBackend *blk, uint8_t *cmd, uint8_t cmd_size,
- uint8_t *buf, uint8_t buf_size);
+ uint8_t *buf, uint8_t buf_size, uint32_t timeout);
SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun);
+SCSIDevice *scsi_device_get(SCSIBus *bus, int channel, int target, int lun);
/* scsi-generic.c. */
extern const SCSIReqOps scsi_generic_req_ops;
+/* scsi-disk.c */
+#define SCSI_DISK_QUIRK_MODE_PAGE_APPLE_VENDOR 0
+#define SCSI_DISK_QUIRK_MODE_SENSE_ROM_USE_DBD 1
+#define SCSI_DISK_QUIRK_MODE_PAGE_VENDOR_SPECIFIC_APPLE 2
+#define SCSI_DISK_QUIRK_MODE_PAGE_TRUNCATED 3
+
#endif
diff --git a/include/hw/sd/allwinner-sdhost.h b/include/hw/sd/allwinner-sdhost.h
index d94606a853..1b951177dd 100644
--- a/include/hw/sd/allwinner-sdhost.h
+++ b/include/hw/sd/allwinner-sdhost.h
@@ -38,6 +38,12 @@
/** Allwinner sun5i family and newer (A13, H2+, H3, etc) */
#define TYPE_AW_SDHOST_SUN5I TYPE_AW_SDHOST "-sun5i"
+/** Allwinner sun50i-a64 */
+#define TYPE_AW_SDHOST_SUN50I_A64 TYPE_AW_SDHOST "-sun50i-a64"
+
+/** Allwinner sun50i-a64 emmc */
+#define TYPE_AW_SDHOST_SUN50I_A64_EMMC TYPE_AW_SDHOST "-sun50i-a64-emmc"
+
/** @} */
/**
@@ -45,19 +51,14 @@
* @{
*/
-#define AW_SDHOST(obj) \
- OBJECT_CHECK(AwSdHostState, (obj), TYPE_AW_SDHOST)
-#define AW_SDHOST_CLASS(klass) \
- OBJECT_CLASS_CHECK(AwSdHostClass, (klass), TYPE_AW_SDHOST)
-#define AW_SDHOST_GET_CLASS(obj) \
- OBJECT_GET_CLASS(AwSdHostClass, (obj), TYPE_AW_SDHOST)
+OBJECT_DECLARE_TYPE(AwSdHostState, AwSdHostClass, AW_SDHOST)
/** @} */
/**
* Allwinner SD Host Controller object instance state.
*/
-typedef struct AwSdHostState {
+struct AwSdHostState {
/*< private >*/
SysBusDevice busdev;
/*< public >*/
@@ -71,6 +72,12 @@ typedef struct AwSdHostState {
/** Interrupt output signal to notify CPU */
qemu_irq irq;
+ /** Memory region where DMA transfers are done */
+ MemoryRegion *dma_mr;
+
+ /** Address space used internally for DMA transfers */
+ AddressSpace dma_as;
+
/** Number of bytes left in current DMA transfer */
uint32_t transfer_cnt;
@@ -109,11 +116,12 @@ typedef struct AwSdHostState {
uint32_t startbit_detect; /**< eMMC DDR Start Bit Detection Control */
uint32_t response_crc; /**< Response CRC */
uint32_t data_crc[8]; /**< Data CRC */
+ uint32_t sample_delay; /**< Sample delay control */
uint32_t status_crc; /**< Status CRC */
/** @} */
-} AwSdHostState;
+};
/**
* Allwinner SD Host Controller class-level struct.
@@ -122,14 +130,17 @@ typedef struct AwSdHostState {
* such that the generic code can use this struct to support
* all devices.
*/
-typedef struct AwSdHostClass {
+struct AwSdHostClass {
/*< private >*/
SysBusDeviceClass parent_class;
/*< public >*/
/** Maximum buffer size in bytes per DMA descriptor */
size_t max_desc_size;
+ bool is_sun4i;
-} AwSdHostClass;
+ /** does the IP block support autocalibration? */
+ bool can_calibrate;
+};
#endif /* HW_SD_ALLWINNER_SDHOST_H */
diff --git a/include/hw/sd/aspeed_sdhci.h b/include/hw/sd/aspeed_sdhci.h
index dffbb46946..057bc5f3d1 100644
--- a/include/hw/sd/aspeed_sdhci.h
+++ b/include/hw/sd/aspeed_sdhci.h
@@ -3,24 +3,24 @@
* Eddie James <eajames@linux.ibm.com>
*
* Copyright (C) 2019 IBM Corp
- * SPDX-License-Identifer: GPL-2.0-or-later
+ * SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef ASPEED_SDHCI_H
#define ASPEED_SDHCI_H
#include "hw/sd/sdhci.h"
+#include "qom/object.h"
#define TYPE_ASPEED_SDHCI "aspeed.sdhci"
-#define ASPEED_SDHCI(obj) OBJECT_CHECK(AspeedSDHCIState, (obj), \
- TYPE_ASPEED_SDHCI)
+OBJECT_DECLARE_SIMPLE_TYPE(AspeedSDHCIState, ASPEED_SDHCI)
#define ASPEED_SDHCI_CAPABILITIES 0x01E80080
#define ASPEED_SDHCI_NUM_SLOTS 2
#define ASPEED_SDHCI_NUM_REGS (ASPEED_SDHCI_REG_SIZE / sizeof(uint32_t))
#define ASPEED_SDHCI_REG_SIZE 0x100
-typedef struct AspeedSDHCIState {
+struct AspeedSDHCIState {
SysBusDevice parent;
SDHCIState slots[ASPEED_SDHCI_NUM_SLOTS];
@@ -30,6 +30,6 @@ typedef struct AspeedSDHCIState {
qemu_irq irq;
uint32_t regs[ASPEED_SDHCI_NUM_REGS];
-} AspeedSDHCIState;
+};
#endif /* ASPEED_SDHCI_H */
diff --git a/include/hw/sd/bcm2835_sdhost.h b/include/hw/sd/bcm2835_sdhost.h
index 7520dd6507..f6bca5c397 100644
--- a/include/hw/sd/bcm2835_sdhost.h
+++ b/include/hw/sd/bcm2835_sdhost.h
@@ -16,14 +16,14 @@
#include "hw/sysbus.h"
#include "hw/sd/sd.h"
+#include "qom/object.h"
#define TYPE_BCM2835_SDHOST "bcm2835-sdhost"
-#define BCM2835_SDHOST(obj) \
- OBJECT_CHECK(BCM2835SDHostState, (obj), TYPE_BCM2835_SDHOST)
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835SDHostState, BCM2835_SDHOST)
#define BCM2835_SDHOST_FIFO_LEN 16
-typedef struct {
+struct BCM2835SDHostState {
SysBusDevice busdev;
SDBus sdbus;
MemoryRegion iomem;
@@ -43,6 +43,6 @@ typedef struct {
uint32_t datacnt;
qemu_irq irq;
-} BCM2835SDHostState;
+};
#endif
diff --git a/include/hw/sd/cadence_sdhci.h b/include/hw/sd/cadence_sdhci.h
new file mode 100644
index 0000000000..cd8288b7d8
--- /dev/null
+++ b/include/hw/sd/cadence_sdhci.h
@@ -0,0 +1,47 @@
+/*
+ * Cadence SDHCI emulation
+ *
+ * Copyright (c) 2020 Wind River Systems, Inc.
+ *
+ * Author:
+ * Bin Meng <bin.meng@windriver.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CADENCE_SDHCI_H
+#define CADENCE_SDHCI_H
+
+#include "hw/sd/sdhci.h"
+
+#define CADENCE_SDHCI_REG_SIZE 0x100
+#define CADENCE_SDHCI_NUM_REGS (CADENCE_SDHCI_REG_SIZE / sizeof(uint32_t))
+
+typedef struct CadenceSDHCIState {
+ SysBusDevice parent;
+
+ MemoryRegion container;
+ MemoryRegion iomem;
+ BusState *bus;
+
+ uint32_t regs[CADENCE_SDHCI_NUM_REGS];
+
+ SDHCIState sdhci;
+} CadenceSDHCIState;
+
+#define TYPE_CADENCE_SDHCI "cadence.sdhci"
+#define CADENCE_SDHCI(obj) OBJECT_CHECK(CadenceSDHCIState, (obj), \
+ TYPE_CADENCE_SDHCI)
+
+#endif /* CADENCE_SDHCI_H */
diff --git a/include/hw/sd/npcm7xx_sdhci.h b/include/hw/sd/npcm7xx_sdhci.h
new file mode 100644
index 0000000000..ad8002f766
--- /dev/null
+++ b/include/hw/sd/npcm7xx_sdhci.h
@@ -0,0 +1,65 @@
+/*
+ * NPCM7xx SD-3.0 / eMMC-4.51 Host Controller
+ *
+ * Copyright (c) 2021 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef NPCM7XX_SDHCI_H
+#define NPCM7XX_SDHCI_H
+
+#include "hw/sd/sdhci.h"
+#include "qom/object.h"
+
+#define TYPE_NPCM7XX_SDHCI "npcm7xx.sdhci"
+#define NPCM7XX_PRSTVALS_SIZE 6
+#define NPCM7XX_PRSTVALS 0x60
+#define NPCM7XX_PRSTVALS_0 0x0
+#define NPCM7XX_PRSTVALS_1 0x2
+#define NPCM7XX_PRSTVALS_2 0x4
+#define NPCM7XX_PRSTVALS_3 0x6
+#define NPCM7XX_PRSTVALS_4 0x8
+#define NPCM7XX_PRSTVALS_5 0xA
+#define NPCM7XX_BOOTTOCTRL 0x10
+#define NPCM7XX_SDHCI_REGSIZE 0x20
+
+#define NPCM7XX_PRSNTS_RESET 0x04A00000
+#define NPCM7XX_BLKGAP_RESET 0x80
+#define NPCM7XX_CAPAB_RESET 0x0100200161EE0399
+#define NPCM7XX_MAXCURR_RESET 0x0000000000000005
+#define NPCM7XX_HCVER_RESET 0x1002
+
+#define NPCM7XX_PRSTVALS_0_RESET 0x0040
+#define NPCM7XX_PRSTVALS_1_RESET 0x0001
+#define NPCM7XX_PRSTVALS_3_RESET 0x0001
+
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxSDHCIState, NPCM7XX_SDHCI)
+
+typedef struct NPCM7xxRegs {
+ /* Preset Values Register Field, read-only */
+ uint16_t prstvals[NPCM7XX_PRSTVALS_SIZE];
+ /* Boot Timeout Control Register, read-write */
+ uint32_t boottoctrl;
+} NPCM7xxRegisters;
+
+struct NPCM7xxSDHCIState {
+ SysBusDevice parent;
+
+ MemoryRegion container;
+ MemoryRegion iomem;
+ BusState *bus;
+ NPCM7xxRegisters regs;
+
+ SDHCIState sdhci;
+};
+
+#endif /* NPCM7XX_SDHCI_H */
diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
index a84b8e274a..2c8748fb9b 100644
--- a/include/hw/sd/sd.h
+++ b/include/hw/sd/sd.h
@@ -31,28 +31,29 @@
#define HW_SD_H
#include "hw/qdev-core.h"
-
-#define OUT_OF_RANGE (1 << 31)
-#define ADDRESS_ERROR (1 << 30)
-#define BLOCK_LEN_ERROR (1 << 29)
-#define ERASE_SEQ_ERROR (1 << 28)
-#define ERASE_PARAM (1 << 27)
-#define WP_VIOLATION (1 << 26)
-#define CARD_IS_LOCKED (1 << 25)
-#define LOCK_UNLOCK_FAILED (1 << 24)
-#define COM_CRC_ERROR (1 << 23)
-#define ILLEGAL_COMMAND (1 << 22)
-#define CARD_ECC_FAILED (1 << 21)
-#define CC_ERROR (1 << 20)
-#define SD_ERROR (1 << 19)
-#define CID_CSD_OVERWRITE (1 << 16)
-#define WP_ERASE_SKIP (1 << 15)
-#define CARD_ECC_DISABLED (1 << 14)
-#define ERASE_RESET (1 << 13)
-#define CURRENT_STATE (7 << 9)
-#define READY_FOR_DATA (1 << 8)
-#define APP_CMD (1 << 5)
-#define AKE_SEQ_ERROR (1 << 3)
+#include "qom/object.h"
+
+#define OUT_OF_RANGE (1 << 31)
+#define ADDRESS_ERROR (1 << 30)
+#define BLOCK_LEN_ERROR (1 << 29)
+#define ERASE_SEQ_ERROR (1 << 28)
+#define ERASE_PARAM (1 << 27)
+#define WP_VIOLATION (1 << 26)
+#define CARD_IS_LOCKED (1 << 25)
+#define LOCK_UNLOCK_FAILED (1 << 24)
+#define COM_CRC_ERROR (1 << 23)
+#define ILLEGAL_COMMAND (1 << 22)
+#define CARD_ECC_FAILED (1 << 21)
+#define CC_ERROR (1 << 20)
+#define SD_ERROR (1 << 19)
+#define CID_CSD_OVERWRITE (1 << 16)
+#define WP_ERASE_SKIP (1 << 15)
+#define CARD_ECC_DISABLED (1 << 14)
+#define ERASE_RESET (1 << 13)
+#define CURRENT_STATE (7 << 9)
+#define READY_FOR_DATA (1 << 8)
+#define APP_CMD (1 << 5)
+#define AKE_SEQ_ERROR (1 << 3)
enum SDPhySpecificationVersion {
SD_PHY_SPECv1_10_VERS = 1,
@@ -76,10 +77,10 @@ typedef enum {
typedef enum {
sd_none = -1,
- sd_bc = 0, /* broadcast -- no response */
- sd_bcr, /* broadcast with response */
- sd_ac, /* addressed -- no data transfer */
- sd_adtc, /* addressed with data transfer */
+ sd_bc = 0, /* broadcast -- no response */
+ sd_bcr, /* broadcast with response */
+ sd_ac, /* addressed -- no data transfer */
+ sd_adtc, /* addressed with data transfer */
} sd_cmd_type_t;
typedef struct {
@@ -88,24 +89,37 @@ typedef struct {
uint8_t crc;
} SDRequest;
-typedef struct SDState SDState;
-typedef struct SDBus SDBus;
#define TYPE_SD_CARD "sd-card"
-#define SD_CARD(obj) OBJECT_CHECK(SDState, (obj), TYPE_SD_CARD)
-#define SD_CARD_CLASS(klass) \
- OBJECT_CLASS_CHECK(SDCardClass, (klass), TYPE_SD_CARD)
-#define SD_CARD_GET_CLASS(obj) \
- OBJECT_GET_CLASS(SDCardClass, (obj), TYPE_SD_CARD)
+OBJECT_DECLARE_TYPE(SDState, SDCardClass, SD_CARD)
-typedef struct {
+#define TYPE_SD_CARD_SPI "sd-card-spi"
+DECLARE_INSTANCE_CHECKER(SDState, SD_CARD_SPI, TYPE_SD_CARD_SPI)
+
+struct SDCardClass {
/*< private >*/
DeviceClass parent_class;
/*< public >*/
int (*do_command)(SDState *sd, SDRequest *req, uint8_t *response);
- void (*write_data)(SDState *sd, uint8_t value);
- uint8_t (*read_data)(SDState *sd);
+ /**
+ * Write a byte to a SD card.
+ * @sd: card
+ * @value: byte to write
+ *
+ * Write a byte on the data lines of a SD card.
+ */
+ void (*write_byte)(SDState *sd, uint8_t value);
+ /**
+ * Read a byte from a SD card.
+ * @sd: card
+ *
+ * Read a byte from the data lines of a SD card.
+ *
+ * Return: byte value read
+ */
+ uint8_t (*read_byte)(SDState *sd);
+ bool (*receive_ready)(SDState *sd);
bool (*data_ready)(SDState *sd);
void (*set_voltage)(SDState *sd, uint16_t millivolts);
uint8_t (*get_dat_lines)(SDState *sd);
@@ -113,18 +127,19 @@ typedef struct {
void (*enable)(SDState *sd, bool enable);
bool (*get_inserted)(SDState *sd);
bool (*get_readonly)(SDState *sd);
-} SDCardClass;
+
+ const struct SDProto *proto;
+};
#define TYPE_SD_BUS "sd-bus"
-#define SD_BUS(obj) OBJECT_CHECK(SDBus, (obj), TYPE_SD_BUS)
-#define SD_BUS_CLASS(klass) OBJECT_CLASS_CHECK(SDBusClass, (klass), TYPE_SD_BUS)
-#define SD_BUS_GET_CLASS(obj) OBJECT_GET_CLASS(SDBusClass, (obj), TYPE_SD_BUS)
+OBJECT_DECLARE_TYPE(SDBus, SDBusClass,
+ SD_BUS)
struct SDBus {
BusState qbus;
};
-typedef struct {
+struct SDBusClass {
/*< private >*/
BusClass parent_class;
/*< public >*/
@@ -134,24 +149,7 @@ typedef struct {
*/
void (*set_inserted)(DeviceState *dev, bool inserted);
void (*set_readonly)(DeviceState *dev, bool readonly);
-} SDBusClass;
-
-/* Legacy functions to be used only by non-qdevified callers */
-SDState *sd_init(BlockBackend *bs, bool is_spi);
-int sd_do_command(SDState *sd, SDRequest *req,
- uint8_t *response);
-void sd_write_data(SDState *sd, uint8_t value);
-uint8_t sd_read_data(SDState *sd);
-void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert);
-bool sd_data_ready(SDState *sd);
-/* sd_enable should not be used -- it is only used on the nseries boards,
- * where it is part of a broken implementation of the MMC card slot switch
- * (there should be two card slots which are multiplexed to a single MMC
- * controller, but instead we model it with one card and controller and
- * disable the card when the second slot is selected, so it looks like the
- * second slot is always empty).
- */
-void sd_enable(SDState *sd, bool enable);
+};
/* Functions to be used by qdevified callers (working via
* an SDBus rather than directly with SDState)
@@ -160,8 +158,42 @@ void sdbus_set_voltage(SDBus *sdbus, uint16_t millivolts);
uint8_t sdbus_get_dat_lines(SDBus *sdbus);
bool sdbus_get_cmd_line(SDBus *sdbus);
int sdbus_do_command(SDBus *sd, SDRequest *req, uint8_t *response);
-void sdbus_write_data(SDBus *sd, uint8_t value);
-uint8_t sdbus_read_data(SDBus *sd);
+/**
+ * Write a byte to a SD bus.
+ * @sd: bus
+ * @value: byte to write
+ *
+ * Write a byte on the data lines of a SD bus.
+ */
+void sdbus_write_byte(SDBus *sd, uint8_t value);
+/**
+ * Read a byte from a SD bus.
+ * @sd: bus
+ *
+ * Read a byte from the data lines of a SD bus.
+ *
+ * Return: byte value read
+ */
+uint8_t sdbus_read_byte(SDBus *sd);
+/**
+ * Write data to a SD bus.
+ * @sdbus: bus
+ * @buf: data to write
+ * @length: number of bytes to write
+ *
+ * Write multiple bytes of data on the data lines of a SD bus.
+ */
+void sdbus_write_data(SDBus *sdbus, const void *buf, size_t length);
+/**
+ * Read data from a SD bus.
+ * @sdbus: bus
+ * @buf: buffer to read data into
+ * @length: number of bytes to read
+ *
+ * Read multiple bytes of data on the data lines of a SD bus.
+ */
+void sdbus_read_data(SDBus *sdbus, void *buf, size_t length);
+bool sdbus_receive_ready(SDBus *sd);
bool sdbus_data_ready(SDBus *sd);
bool sdbus_get_inserted(SDBus *sd);
bool sdbus_get_readonly(SDBus *sd);
diff --git a/include/hw/sd/sdcard_legacy.h b/include/hw/sd/sdcard_legacy.h
new file mode 100644
index 0000000000..0dc3889555
--- /dev/null
+++ b/include/hw/sd/sdcard_legacy.h
@@ -0,0 +1,50 @@
+/*
+ * SD Memory Card emulation (deprecated legacy API)
+ *
+ * Copyright (c) 2006 Andrzej Zaborowski <balrog@zabor.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef HW_SDCARD_LEGACY_H
+#define HW_SDCARD_LEGACY_H
+
+#include "hw/sd/sd.h"
+
+/* Legacy functions to be used only by non-qdevified callers */
+SDState *sd_init(BlockBackend *blk, bool is_spi);
+int sd_do_command(SDState *card, SDRequest *request, uint8_t *response);
+void sd_write_byte(SDState *card, uint8_t value);
+uint8_t sd_read_byte(SDState *card);
+void sd_set_cb(SDState *card, qemu_irq readonly, qemu_irq insert);
+
+/* sd_enable should not be used -- it is only used on the nseries boards,
+ * where it is part of a broken implementation of the MMC card slot switch
+ * (there should be two card slots which are multiplexed to a single MMC
+ * controller, but instead we model it with one card and controller and
+ * disable the card when the second slot is selected, so it looks like the
+ * second slot is always empty).
+ */
+void sd_enable(SDState *card, bool enable);
+
+#endif /* HW_SDCARD_LEGACY_H */
diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
index 5d9275f3d6..6cd2822f1d 100644
--- a/include/hw/sd/sdhci.h
+++ b/include/hw/sd/sdhci.h
@@ -25,12 +25,13 @@
#ifndef SDHCI_H
#define SDHCI_H
-#include "hw/pci/pci.h"
+#include "hw/pci/pci_device.h"
#include "hw/sysbus.h"
#include "hw/sd/sd.h"
+#include "qom/object.h"
/* SD/MMC host controller state */
-typedef struct SDHCIState {
+struct SDHCIState {
/*< private >*/
union {
PCIDevice pcidev;
@@ -95,10 +96,12 @@ typedef struct SDHCIState {
/* Configurable properties */
bool pending_insert_quirk; /* Quirk for Raspberry Pi card insert int */
uint32_t quirks;
+ uint8_t endianness;
uint8_t sd_spec_version;
uint8_t uhs_mode;
uint8_t vendor; /* For vendor specific functionality */
-} SDHCIState;
+};
+typedef struct SDHCIState SDHCIState;
#define SDHCI_VENDOR_NONE 0
#define SDHCI_VENDOR_IMX 1
@@ -113,11 +116,12 @@ typedef struct SDHCIState {
#define SDHCI_QUIRK_NO_BUSY_IRQ BIT(14)
#define TYPE_PCI_SDHCI "sdhci-pci"
-#define PCI_SDHCI(obj) OBJECT_CHECK(SDHCIState, (obj), TYPE_PCI_SDHCI)
+DECLARE_INSTANCE_CHECKER(SDHCIState, PCI_SDHCI,
+ TYPE_PCI_SDHCI)
#define TYPE_SYSBUS_SDHCI "generic-sdhci"
-#define SYSBUS_SDHCI(obj) \
- OBJECT_CHECK(SDHCIState, (obj), TYPE_SYSBUS_SDHCI)
+DECLARE_INSTANCE_CHECKER(SDHCIState, SYSBUS_SDHCI,
+ TYPE_SYSBUS_SDHCI)
#define TYPE_IMX_USDHC "imx-usdhc"
diff --git a/include/hw/semihosting/console.h b/include/hw/semihosting/console.h
deleted file mode 100644
index 0238f540f4..0000000000
--- a/include/hw/semihosting/console.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Semihosting Console
- *
- * Copyright (c) 2019 Linaro Ltd
- *
- * SPDX-License-Identifier: GPL-2.0-or-later
- */
-
-#ifndef SEMIHOST_CONSOLE_H
-#define SEMIHOST_CONSOLE_H
-
-#include "cpu.h"
-
-/**
- * qemu_semihosting_console_outs:
- * @env: CPUArchState
- * @s: host address of null terminated guest string
- *
- * Send a null terminated guest string to the debug console. This may
- * be the remote gdb session if a softmmu guest is currently being
- * debugged.
- *
- * Returns: number of bytes written.
- */
-int qemu_semihosting_console_outs(CPUArchState *env, target_ulong s);
-
-/**
- * qemu_semihosting_console_outc:
- * @env: CPUArchState
- * @s: host address of null terminated guest string
- *
- * Send single character from guest memory to the debug console. This
- * may be the remote gdb session if a softmmu guest is currently being
- * debugged.
- *
- * Returns: nothing
- */
-void qemu_semihosting_console_outc(CPUArchState *env, target_ulong c);
-
-/**
- * qemu_semihosting_console_inc:
- * @env: CPUArchState
- *
- * Receive single character from debug console. This may be the remote
- * gdb session if a softmmu guest is currently being debugged. As this
- * call may block if no data is available we suspend the CPU and will
- * re-execute the instruction when data is there. Therefore two
- * conditions must be met:
- * - CPUState is synchronized before calling this function
- * - pc is only updated once the character is successfully returned
- *
- * Returns: character read OR cpu_loop_exit!
- */
-target_ulong qemu_semihosting_console_inc(CPUArchState *env);
-
-/**
- * qemu_semihosting_log_out:
- * @s: pointer to string
- * @len: length of string
- *
- * Send a string to the debug output. Unlike console_out these strings
- * can't be sent to a remote gdb instance as they don't exist in guest
- * memory.
- *
- * Returns: number of bytes written
- */
-int qemu_semihosting_log_out(const char *s, int len);
-
-#endif /* SEMIHOST_CONSOLE_H */
diff --git a/include/hw/semihosting/semihost.h b/include/hw/semihosting/semihost.h
deleted file mode 100644
index b8ce5117ae..0000000000
--- a/include/hw/semihosting/semihost.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Semihosting support
- *
- * Copyright (c) 2015 Imagination Technologies
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef SEMIHOST_H
-#define SEMIHOST_H
-
-typedef enum SemihostingTarget {
- SEMIHOSTING_TARGET_AUTO = 0,
- SEMIHOSTING_TARGET_NATIVE,
- SEMIHOSTING_TARGET_GDB
-} SemihostingTarget;
-
-#ifdef CONFIG_USER_ONLY
-static inline bool semihosting_enabled(void)
-{
- return true;
-}
-
-static inline SemihostingTarget semihosting_get_target(void)
-{
- return SEMIHOSTING_TARGET_AUTO;
-}
-
-static inline const char *semihosting_get_arg(int i)
-{
- return NULL;
-}
-
-static inline int semihosting_get_argc(void)
-{
- return 0;
-}
-
-static inline const char *semihosting_get_cmdline(void)
-{
- return NULL;
-}
-
-static inline Chardev *semihosting_get_chardev(void)
-{
- return NULL;
-}
-static inline void qemu_semihosting_console_init(void)
-{
-}
-#else /* !CONFIG_USER_ONLY */
-bool semihosting_enabled(void);
-SemihostingTarget semihosting_get_target(void);
-const char *semihosting_get_arg(int i);
-int semihosting_get_argc(void);
-const char *semihosting_get_cmdline(void);
-void semihosting_arg_fallback(const char *file, const char *cmd);
-Chardev *semihosting_get_chardev(void);
-/* for vl.c hooks */
-void qemu_semihosting_enable(void);
-int qemu_semihosting_config_options(const char *opt);
-void qemu_semihosting_connect_chardevs(void);
-void qemu_semihosting_console_init(void);
-#endif /* CONFIG_USER_ONLY */
-
-#endif /* SEMIHOST_H */
diff --git a/include/hw/sensor/emc141x_regs.h b/include/hw/sensor/emc141x_regs.h
new file mode 100644
index 0000000000..e509a43d55
--- /dev/null
+++ b/include/hw/sensor/emc141x_regs.h
@@ -0,0 +1,37 @@
+/*
+ * SMSC EMC141X temperature sensor.
+ *
+ * Browse the data sheet:
+ *
+ * http://ww1.microchip.com/downloads/en/DeviceDoc/20005274A.pdf
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later. See the COPYING file in the top-level directory.
+ */
+
+#ifndef EMC141X_REGS_H
+#define EMC141X_REGS_H
+
+#define EMC1413_DEVICE_ID 0x21
+#define EMC1414_DEVICE_ID 0x25
+#define MANUFACTURER_ID 0x5d
+#define REVISION 0x04
+
+/* the EMC141X registers */
+#define EMC141X_TEMP_HIGH0 0x00
+#define EMC141X_TEMP_HIGH1 0x01
+#define EMC141X_TEMP_HIGH2 0x23
+#define EMC141X_TEMP_HIGH3 0x2a
+#define EMC141X_TEMP_MAX_HIGH0 0x05
+#define EMC141X_TEMP_MIN_HIGH0 0x06
+#define EMC141X_TEMP_MAX_HIGH1 0x07
+#define EMC141X_TEMP_MIN_HIGH1 0x08
+#define EMC141X_TEMP_MAX_HIGH2 0x15
+#define EMC141X_TEMP_MIN_HIGH2 0x16
+#define EMC141X_TEMP_MAX_HIGH3 0x2c
+#define EMC141X_TEMP_MIN_HIGH3 0x2d
+#define EMC141X_DEVICE_ID 0xfd
+#define EMC141X_MANUFACTURER_ID 0xfe
+#define EMC141X_REVISION 0xff
+
+#endif
diff --git a/include/hw/sensor/isl_pmbus_vr.h b/include/hw/sensor/isl_pmbus_vr.h
new file mode 100644
index 0000000000..aa2c2767df
--- /dev/null
+++ b/include/hw/sensor/isl_pmbus_vr.h
@@ -0,0 +1,57 @@
+/*
+ * PMBus device for Renesas Digital Multiphase Voltage Regulators
+ *
+ * Copyright 2022 Google LLC
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_MISC_ISL_PMBUS_VR_H
+#define HW_MISC_ISL_PMBUS_VR_H
+
+#include "hw/i2c/pmbus_device.h"
+#include "qom/object.h"
+
+#define TYPE_ISL69259 "isl69259"
+#define TYPE_ISL69260 "isl69260"
+#define TYPE_RAA228000 "raa228000"
+#define TYPE_RAA229004 "raa229004"
+#define ISL_MAX_IC_DEVICE_ID_LEN 16
+
+struct ISLState {
+ PMBusDevice parent;
+
+ uint8_t ic_device_id[ISL_MAX_IC_DEVICE_ID_LEN];
+ uint8_t ic_device_id_len;
+};
+
+OBJECT_DECLARE_SIMPLE_TYPE(ISLState, ISL69260)
+
+#define ISL_CAPABILITY_DEFAULT 0x40
+#define ISL_OPERATION_DEFAULT 0x80
+#define ISL_ON_OFF_CONFIG_DEFAULT 0x16
+#define ISL_VOUT_MODE_DEFAULT 0x40
+#define ISL_VOUT_COMMAND_DEFAULT 0x0384
+#define ISL_VOUT_MAX_DEFAULT 0x08FC
+#define ISL_VOUT_MARGIN_HIGH_DEFAULT 0x0640
+#define ISL_VOUT_MARGIN_LOW_DEFAULT 0xFA
+#define ISL_VOUT_TRANSITION_RATE_DEFAULT 0x64
+#define ISL_VOUT_OV_FAULT_LIMIT_DEFAULT 0x076C
+#define ISL_OT_FAULT_LIMIT_DEFAULT 0x7D
+#define ISL_OT_WARN_LIMIT_DEFAULT 0x07D0
+#define ISL_VIN_OV_WARN_LIMIT_DEFAULT 0x36B0
+#define ISL_VIN_UV_WARN_LIMIT_DEFAULT 0x1F40
+#define ISL_IIN_OC_FAULT_LIMIT_DEFAULT 0x32
+#define ISL_TON_DELAY_DEFAULT 0x14
+#define ISL_TON_RISE_DEFAULT 0x01F4
+#define ISL_TOFF_FALL_DEFAULT 0x01F4
+#define ISL_REVISION_DEFAULT 0x33
+#define ISL_READ_VOUT_DEFAULT 1000
+#define ISL_READ_IOUT_DEFAULT 40
+#define ISL_READ_POUT_DEFAULT 4
+#define ISL_READ_TEMP_DEFAULT 25
+#define ISL_READ_VIN_DEFAULT 1100
+#define ISL_READ_IIN_DEFAULT 40
+#define ISL_READ_PIN_DEFAULT 4
+
+#endif
diff --git a/include/hw/sensor/tmp105.h b/include/hw/sensor/tmp105.h
new file mode 100644
index 0000000000..244e2989fe
--- /dev/null
+++ b/include/hw/sensor/tmp105.h
@@ -0,0 +1,55 @@
+/*
+ * Texas Instruments TMP105 Temperature Sensor
+ *
+ * Browse the data sheet:
+ *
+ * http://www.ti.com/lit/gpn/tmp105
+ *
+ * Copyright (C) 2012 Alex Horn <alex.horn@cs.ox.ac.uk>
+ * Copyright (C) 2008-2012 Andrzej Zaborowski <balrogg@gmail.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later. See the COPYING file in the top-level directory.
+ */
+#ifndef QEMU_TMP105_H
+#define QEMU_TMP105_H
+
+#include "hw/i2c/i2c.h"
+#include "hw/sensor/tmp105_regs.h"
+#include "qom/object.h"
+
+#define TYPE_TMP105 "tmp105"
+OBJECT_DECLARE_SIMPLE_TYPE(TMP105State, TMP105)
+
+/**
+ * TMP105State:
+ * @config: Bits 5 and 6 (value 32 and 64) determine the precision of the
+ * temperature. See Table 8 in the data sheet.
+ *
+ * @see_also: http://www.ti.com/lit/gpn/tmp105
+ */
+struct TMP105State {
+ /*< private >*/
+ I2CSlave i2c;
+ /*< public >*/
+
+ uint8_t len;
+ uint8_t buf[2];
+ qemu_irq pin;
+
+ uint8_t pointer;
+ uint8_t config;
+ int16_t temperature;
+ int16_t limit[2];
+ int faults;
+ uint8_t alarm;
+ /*
+ * The TMP105 initially looks for a temperature rising above T_high;
+ * once this is detected, the condition it looks for next is the
+ * temperature falling below T_low. This flag is false when initially
+ * looking for T_high, true when looking for T_low.
+ */
+ bool detect_falling;
+};
+
+#endif
diff --git a/include/hw/misc/tmp105_regs.h b/include/hw/sensor/tmp105_regs.h
index ef015ee5cf..ef015ee5cf 100644
--- a/include/hw/misc/tmp105_regs.h
+++ b/include/hw/sensor/tmp105_regs.h
diff --git a/include/hw/sh4/sh.h b/include/hw/sh4/sh.h
index 93f464bf4c..ec716cdd45 100644
--- a/include/hw/sh4/sh.h
+++ b/include/hw/sh4/sh.h
@@ -1,6 +1,31 @@
-#ifndef QEMU_SH_H
-#define QEMU_SH_H
-/* Definitions for SH board emulation. */
+/*
+ * Definitions for SH board emulation
+ *
+ * Copyright (c) 2005 Samuel Tardieu
+ *
+ * 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 (including the next
+ * paragraph) 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.
+ *
+ * SPDX-License-Identifier: MIT
+ */
+#ifndef QEMU_HW_SH_H
+#define QEMU_HW_SH_H
#include "hw/sh4/sh_intc.h"
#include "target/sh4/cpu-qom.h"
@@ -19,25 +44,18 @@ typedef struct {
uint16_t portbmask_trigger;
/* Return 0 if no action was taken */
int (*port_change_cb) (uint16_t porta, uint16_t portb,
- uint16_t * periph_pdtra,
- uint16_t * periph_portdira,
- uint16_t * periph_pdtrb,
- uint16_t * periph_portdirb);
+ uint16_t *periph_pdtra,
+ uint16_t *periph_portdira,
+ uint16_t *periph_pdtrb,
+ uint16_t *periph_portdirb);
} sh7750_io_device;
int sh7750_register_io_device(struct SH7750State *s,
- sh7750_io_device * device);
+ sh7750_io_device *device);
/* sh_serial.c */
+#define TYPE_SH_SERIAL "sh-serial"
#define SH_SERIAL_FEAT_SCIF (1 << 0)
-void sh_serial_init(MemoryRegion *sysmem,
- hwaddr base, int feat,
- uint32_t freq, Chardev *chr,
- qemu_irq eri_source,
- qemu_irq rxi_source,
- qemu_irq txi_source,
- qemu_irq tei_source,
- qemu_irq bri_source);
/* sh7750.c */
qemu_irq sh7750_irl(struct SH7750State *s);
diff --git a/include/hw/sh4/sh_intc.h b/include/hw/sh4/sh_intc.h
index 65f3425057..f62d5c5e13 100644
--- a/include/hw/sh4/sh_intc.h
+++ b/include/hw/sh4/sh_intc.h
@@ -58,7 +58,7 @@ struct intc_desc {
};
int sh_intc_get_pending_vector(struct intc_desc *desc, int imask);
-struct intc_source *sh_intc_source(struct intc_desc *desc, intc_enum id);
+
void sh_intc_toggle_source(struct intc_source *source,
int enable_adj, int assert_adj);
diff --git a/include/hw/i386/ich9.h b/include/hw/southbridge/ich9.h
index a98d10b252..fd01649d04 100644
--- a/include/hw/i386/ich9.h
+++ b/include/hw/southbridge/ich9.h
@@ -1,32 +1,24 @@
-#ifndef HW_ICH9_H
-#define HW_ICH9_H
+#ifndef HW_SOUTHBRIDGE_ICH9_H
+#define HW_SOUTHBRIDGE_ICH9_H
-#include "hw/isa/isa.h"
-#include "hw/sysbus.h"
-#include "hw/i386/pc.h"
#include "hw/isa/apm.h"
-#include "hw/pci/pci.h"
-#include "hw/pci/pcie_host.h"
-#include "hw/pci/pci_bridge.h"
-#include "hw/acpi/acpi.h"
#include "hw/acpi/ich9.h"
-#include "hw/pci/pci_bus.h"
-
-void ich9_lpc_set_irq(void *opaque, int irq_num, int level);
-int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx);
-PCIINTxRoute ich9_route_intx_pin_to_irq(void *opaque, int pirq_pin);
-void ich9_lpc_pm_init(PCIDevice *pci_lpc, bool smm_enabled);
-I2CBus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base);
+#include "hw/intc/ioapic.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_device.h"
+#include "hw/rtc/mc146818rtc.h"
+#include "exec/memory.h"
+#include "qemu/notify.h"
+#include "qom/object.h"
void ich9_generate_smi(void);
#define ICH9_CC_SIZE (16 * 1024) /* 16KB. Chipset configuration registers */
#define TYPE_ICH9_LPC_DEVICE "ICH9-LPC"
-#define ICH9_LPC_DEVICE(obj) \
- OBJECT_CHECK(ICH9LPCState, (obj), TYPE_ICH9_LPC_DEVICE)
+OBJECT_DECLARE_SIMPLE_TYPE(ICH9LPCState, ICH9_LPC_DEVICE)
-typedef struct ICH9LPCState {
+struct ICH9LPCState {
/* ICH9 LPC PCI to ISA bridge */
PCIDevice d;
@@ -39,6 +31,7 @@ typedef struct ICH9LPCState {
*/
uint8_t irr[PCI_SLOT_MAX][PCI_NUM_PINS];
+ MC146818RtcState rtc;
APMState apm;
ICH9LPCPMRegs pm;
uint32_t sci_level; /* track sci level */
@@ -71,15 +64,13 @@ typedef struct ICH9LPCState {
* triggers feature lockdown */
uint64_t smi_negotiated_features; /* guest-invisible, host endian */
- /* isa bus */
- ISABus *isa_bus;
MemoryRegion rcrb_mem; /* root complex register block */
Notifier machine_ready;
- qemu_irq gsi[GSI_NUM_PINS];
-} ICH9LPCState;
+ qemu_irq gsi[IOAPIC_NUM_PINS];
+};
-#define Q35_MASK(bit, ms_bit, ls_bit) \
+#define ICH9_MASK(bit, ms_bit, ls_bit) \
((uint##bit##_t)(((1ULL << ((ms_bit) + 1)) - 1) & ~((1ULL << ls_bit) - 1)))
/* ICH9: Chipset Configuration Registers */
@@ -141,12 +132,13 @@ typedef struct ICH9LPCState {
#define ICH9_LPC_NB_PIRQS 8 /* PCI A-H */
#define ICH9_LPC_PMBASE 0x40
-#define ICH9_LPC_PMBASE_BASE_ADDRESS_MASK Q35_MASK(32, 15, 7)
+#define ICH9_LPC_PMBASE_BASE_ADDRESS_MASK ICH9_MASK(32, 15, 7)
#define ICH9_LPC_PMBASE_RTE 0x1
#define ICH9_LPC_PMBASE_DEFAULT 0x1
+
#define ICH9_LPC_ACPI_CTRL 0x44
#define ICH9_LPC_ACPI_CTRL_ACPI_EN 0x80
-#define ICH9_LPC_ACPI_CTRL_SCI_IRQ_SEL_MASK Q35_MASK(8, 2, 0)
+#define ICH9_LPC_ACPI_CTRL_SCI_IRQ_SEL_MASK ICH9_MASK(8, 2, 0)
#define ICH9_LPC_ACPI_CTRL_9 0x0
#define ICH9_LPC_ACPI_CTRL_10 0x1
#define ICH9_LPC_ACPI_CTRL_11 0x2
@@ -165,7 +157,7 @@ typedef struct ICH9LPCState {
#define ICH9_LPC_PIRQH_ROUT 0x6b
#define ICH9_LPC_PIRQ_ROUT_IRQEN 0x80
-#define ICH9_LPC_PIRQ_ROUT_MASK Q35_MASK(8, 3, 0)
+#define ICH9_LPC_PIRQ_ROUT_MASK ICH9_MASK(8, 3, 0)
#define ICH9_LPC_PIRQ_ROUT_DEFAULT 0x80
#define ICH9_LPC_GEN_PMCON_1 0xa0
@@ -175,7 +167,7 @@ typedef struct ICH9LPCState {
#define ICH9_LPC_GEN_PMCON_LOCK 0xa6
#define ICH9_LPC_RCBA 0xf0
-#define ICH9_LPC_RCBA_BA_MASK Q35_MASK(32, 31, 14)
+#define ICH9_LPC_RCBA_BA_MASK ICH9_MASK(32, 31, 14)
#define ICH9_LPC_RCBA_EN 0x1
#define ICH9_LPC_RCBA_DEFAULT 0x0
@@ -215,7 +207,7 @@ typedef struct ICH9LPCState {
/* D31:F3 SMBus controller */
-#define TYPE_ICH9_SMB_DEVICE "ICH9 SMB"
+#define TYPE_ICH9_SMB_DEVICE "ICH9-SMB"
#define ICH9_A2_SMB_REVISION 0x02
#define ICH9_SMB_PI 0x00
@@ -245,7 +237,11 @@ typedef struct ICH9LPCState {
#define ICH9_SMB_HST_D1 0x06
#define ICH9_SMB_HOST_BLOCK_DB 0x07
+#define ICH9_LPC_SMI_NEGOTIATED_FEAT_PROP "x-smi-negotiated-features"
+
/* bit positions used in fw_cfg SMI feature negotiation */
#define ICH9_LPC_SMI_F_BROADCAST_BIT 0
+#define ICH9_LPC_SMI_F_CPU_HOTPLUG_BIT 1
+#define ICH9_LPC_SMI_F_CPU_HOT_UNPLUG_BIT 2
-#endif /* HW_ICH9_H */
+#endif /* HW_SOUTHBRIDGE_ICH9_H */
diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h
index 02bd741209..86709ba2e4 100644
--- a/include/hw/southbridge/piix.h
+++ b/include/hw/southbridge/piix.h
@@ -12,13 +12,11 @@
#ifndef HW_SOUTHBRIDGE_PIIX_H
#define HW_SOUTHBRIDGE_PIIX_H
-#include "hw/pci/pci.h"
-
-#define TYPE_PIIX4_PM "PIIX4_PM"
-
-I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
- qemu_irq sci_irq, qemu_irq smi_irq,
- int smm_enabled, DeviceState **piix4_pm);
+#include "hw/pci/pci_device.h"
+#include "hw/acpi/piix4.h"
+#include "hw/ide/pci.h"
+#include "hw/rtc/mc146818rtc.h"
+#include "hw/usb/hcd-uhci.h"
/* PIRQRC[A:D]: PIRQx Route Control Registers */
#define PIIX_PIRQCA 0x60
@@ -32,10 +30,9 @@ I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
*/
#define PIIX_RCR_IOPORT 0xcf9
-#define PIIX_NUM_PIC_IRQS 16 /* i8259 * 2 */
#define PIIX_NUM_PIRQS 4ULL /* PIRQ[A-D] */
-typedef struct PIIXState {
+struct PIIXState {
PCIDevice dev;
/*
@@ -44,30 +41,44 @@ typedef struct PIIXState {
* So one PIC level is tracked by PIIX_NUM_PIRQS bits.
*
* PIRQ is mapped to PIC pins, we track it by
- * PIIX_NUM_PIRQS * PIIX_NUM_PIC_IRQS = 64 bits with
+ * PIIX_NUM_PIRQS * ISA_NUM_IRQS = 64 bits with
* pic_irq * PIIX_NUM_PIRQS + pirq
*/
-#if PIIX_NUM_PIC_IRQS * PIIX_NUM_PIRQS > 64
+#if ISA_NUM_IRQS * PIIX_NUM_PIRQS > 64
#error "unable to encode pic state in 64bit in pic_levels."
#endif
uint64_t pic_levels;
- qemu_irq *pic;
+ qemu_irq cpu_intr;
+ qemu_irq isa_irqs_in[ISA_NUM_IRQS];
/* This member isn't used. Just for save/load compatibility */
int32_t pci_irq_levels_vmstate[PIIX_NUM_PIRQS];
+ MC146818RtcState rtc;
+ PCIIDEState ide;
+ UHCIState uhci;
+ PIIX4PMState pm;
+
+ uint32_t smb_io_base;
+
/* Reset Control Register contents */
uint8_t rcr;
/* IO memory region for Reset Control Register (PIIX_RCR_IOPORT) */
MemoryRegion rcr_mem;
-} PIIX3State;
-extern PCIDevice *piix4_dev;
+ bool has_acpi;
+ bool has_pic;
+ bool has_pit;
+ bool has_usb;
+ bool smm_enabled;
+};
-PIIX3State *piix3_create(PCIBus *pci_bus, ISABus **isa_bus);
+#define TYPE_PIIX_PCI_DEVICE "pci-piix"
+OBJECT_DECLARE_SIMPLE_TYPE(PIIXState, PIIX_PCI_DEVICE)
-DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus);
+#define TYPE_PIIX3_DEVICE "PIIX3"
+#define TYPE_PIIX4_PCI_DEVICE "piix4-isa"
#endif
diff --git a/include/hw/sparc/sparc32_dma.h b/include/hw/sparc/sparc32_dma.h
index ab42c5421b..cde8ec02cb 100644
--- a/include/hw/sparc/sparc32_dma.h
+++ b/include/hw/sparc/sparc32_dma.h
@@ -4,14 +4,13 @@
#include "hw/sysbus.h"
#include "hw/scsi/esp.h"
#include "hw/net/lance.h"
+#include "qom/object.h"
#define DMA_REGS 4
#define TYPE_SPARC32_DMA_DEVICE "sparc32-dma-device"
-#define SPARC32_DMA_DEVICE(obj) OBJECT_CHECK(DMADeviceState, (obj), \
- TYPE_SPARC32_DMA_DEVICE)
+OBJECT_DECLARE_SIMPLE_TYPE(DMADeviceState, SPARC32_DMA_DEVICE)
-typedef struct DMADeviceState DMADeviceState;
struct DMADeviceState {
SysBusDevice parent_obj;
@@ -24,37 +23,34 @@ struct DMADeviceState {
};
#define TYPE_SPARC32_ESPDMA_DEVICE "sparc32-espdma"
-#define SPARC32_ESPDMA_DEVICE(obj) OBJECT_CHECK(ESPDMADeviceState, (obj), \
- TYPE_SPARC32_ESPDMA_DEVICE)
+OBJECT_DECLARE_SIMPLE_TYPE(ESPDMADeviceState, SPARC32_ESPDMA_DEVICE)
-typedef struct ESPDMADeviceState {
+struct ESPDMADeviceState {
DMADeviceState parent_obj;
- SysBusESPState *esp;
-} ESPDMADeviceState;
+ SysBusESPState esp;
+};
#define TYPE_SPARC32_LEDMA_DEVICE "sparc32-ledma"
-#define SPARC32_LEDMA_DEVICE(obj) OBJECT_CHECK(LEDMADeviceState, (obj), \
- TYPE_SPARC32_LEDMA_DEVICE)
+OBJECT_DECLARE_SIMPLE_TYPE(LEDMADeviceState, SPARC32_LEDMA_DEVICE)
-typedef struct LEDMADeviceState {
+struct LEDMADeviceState {
DMADeviceState parent_obj;
- SysBusPCNetState *lance;
-} LEDMADeviceState;
+ SysBusPCNetState lance;
+};
#define TYPE_SPARC32_DMA "sparc32-dma"
-#define SPARC32_DMA(obj) OBJECT_CHECK(SPARC32DMAState, (obj), \
- TYPE_SPARC32_DMA)
+OBJECT_DECLARE_SIMPLE_TYPE(SPARC32DMAState, SPARC32_DMA)
-typedef struct SPARC32DMAState {
+struct SPARC32DMAState {
SysBusDevice parent_obj;
MemoryRegion dmamem;
MemoryRegion ledma_alias;
- ESPDMADeviceState *espdma;
- LEDMADeviceState *ledma;
-} SPARC32DMAState;
+ ESPDMADeviceState espdma;
+ LEDMADeviceState ledma;
+};
/* sparc32_dma.c */
void ledma_memory_read(void *opaque, hwaddr addr,
diff --git a/include/hw/sparc/sun4m_iommu.h b/include/hw/sparc/sun4m_iommu.h
index 482266c6a7..4e2ab34cde 100644
--- a/include/hw/sparc/sun4m_iommu.h
+++ b/include/hw/sparc/sun4m_iommu.h
@@ -26,10 +26,11 @@
#define SUN4M_IOMMU_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define IOMMU_NREGS (4 * 4096 / 4)
-typedef struct IOMMUState {
+struct IOMMUState {
SysBusDevice parent_obj;
AddressSpace iommu_as;
@@ -40,10 +41,12 @@ typedef struct IOMMUState {
hwaddr iostart;
qemu_irq irq;
uint32_t version;
-} IOMMUState;
+};
+typedef struct IOMMUState IOMMUState;
#define TYPE_SUN4M_IOMMU "sun4m-iommu"
-#define SUN4M_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4M_IOMMU)
+DECLARE_INSTANCE_CHECKER(IOMMUState, SUN4M_IOMMU,
+ TYPE_SUN4M_IOMMU)
#define TYPE_SUN4M_IOMMU_MEMORY_REGION "sun4m-iommu-memory-region"
diff --git a/include/hw/sparc/sun4u_iommu.h b/include/hw/sparc/sun4u_iommu.h
index 5472d489cf..f94566a72c 100644
--- a/include/hw/sparc/sun4u_iommu.h
+++ b/include/hw/sparc/sun4u_iommu.h
@@ -28,10 +28,11 @@
#define SUN4U_IOMMU_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define IOMMU_NREGS 3
-typedef struct IOMMUState {
+struct IOMMUState {
SysBusDevice parent_obj;
AddressSpace iommu_as;
@@ -39,10 +40,12 @@ typedef struct IOMMUState {
MemoryRegion iomem;
uint64_t regs[IOMMU_NREGS];
-} IOMMUState;
+};
+typedef struct IOMMUState IOMMUState;
#define TYPE_SUN4U_IOMMU "sun4u-iommu"
-#define SUN4U_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4U_IOMMU)
+DECLARE_INSTANCE_CHECKER(IOMMUState, SUN4U_IOMMU,
+ TYPE_SUN4U_IOMMU)
#define TYPE_SUN4U_IOMMU_MEMORY_REGION "sun4u-iommu-memory-region"
diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h
index 6fbbb238f1..8e1dda556b 100644
--- a/include/hw/ssi/aspeed_smc.h
+++ b/include/hw/ssi/aspeed_smc.h
@@ -27,71 +27,38 @@
#include "hw/ssi/ssi.h"
#include "hw/sysbus.h"
-
-typedef struct AspeedSegments {
- hwaddr addr;
- uint32_t size;
-} AspeedSegments;
+#include "qom/object.h"
struct AspeedSMCState;
-typedef struct AspeedSMCController {
- const char *name;
- uint8_t r_conf;
- uint8_t r_ce_ctrl;
- uint8_t r_ctrl0;
- uint8_t r_timings;
- uint8_t nregs_timings;
- uint8_t conf_enable_w0;
- uint8_t max_slaves;
- const AspeedSegments *segments;
- hwaddr flash_window_base;
- uint32_t flash_window_size;
- bool has_dma;
- hwaddr dma_flash_mask;
- hwaddr dma_dram_mask;
- uint32_t nregs;
- uint32_t (*segment_to_reg)(const struct AspeedSMCState *s,
- const AspeedSegments *seg);
- void (*reg_to_segment)(const struct AspeedSMCState *s, uint32_t reg,
- AspeedSegments *seg);
-} AspeedSMCController;
+struct AspeedSMCClass;
-typedef struct AspeedSMCFlash {
- struct AspeedSMCState *controller;
+#define TYPE_ASPEED_SMC_FLASH "aspeed.smc.flash"
+OBJECT_DECLARE_SIMPLE_TYPE(AspeedSMCFlash, ASPEED_SMC_FLASH)
+struct AspeedSMCFlash {
+ SysBusDevice parent_obj;
- uint8_t id;
- uint32_t size;
+ struct AspeedSMCState *controller;
+ struct AspeedSMCClass *asc;
+ uint8_t cs;
MemoryRegion mmio;
- DeviceState *flash;
-} AspeedSMCFlash;
+};
#define TYPE_ASPEED_SMC "aspeed.smc"
-#define ASPEED_SMC(obj) OBJECT_CHECK(AspeedSMCState, (obj), TYPE_ASPEED_SMC)
-#define ASPEED_SMC_CLASS(klass) \
- OBJECT_CLASS_CHECK(AspeedSMCClass, (klass), TYPE_ASPEED_SMC)
-#define ASPEED_SMC_GET_CLASS(obj) \
- OBJECT_GET_CLASS(AspeedSMCClass, (obj), TYPE_ASPEED_SMC)
-
-typedef struct AspeedSMCClass {
- SysBusDevice parent_obj;
- const AspeedSMCController *ctrl;
-} AspeedSMCClass;
+OBJECT_DECLARE_TYPE(AspeedSMCState, AspeedSMCClass, ASPEED_SMC)
#define ASPEED_SMC_R_MAX (0x100 / 4)
+#define ASPEED_SMC_CS_MAX 5
-typedef struct AspeedSMCState {
+struct AspeedSMCState {
SysBusDevice parent_obj;
- const AspeedSMCController *ctrl;
-
MemoryRegion mmio;
+ MemoryRegion mmio_flash_container;
MemoryRegion mmio_flash;
qemu_irq irq;
- int irqline;
- uint32_t num_cs;
qemu_irq *cs_lines;
bool inject_failure;
@@ -106,17 +73,46 @@ typedef struct AspeedSMCState {
uint8_t r_timings;
uint8_t conf_enable_w0;
- /* for DMA support */
- uint64_t sdram_base;
-
AddressSpace flash_as;
MemoryRegion *dram_mr;
AddressSpace dram_as;
- AspeedSMCFlash *flashes;
+ AspeedSMCFlash flashes[ASPEED_SMC_CS_MAX];
uint8_t snoop_index;
uint8_t snoop_dummies;
-} AspeedSMCState;
+};
+
+typedef struct AspeedSegments {
+ hwaddr addr;
+ uint32_t size;
+} AspeedSegments;
+
+struct AspeedSMCClass {
+ SysBusDeviceClass parent_obj;
+
+ uint8_t r_conf;
+ uint8_t r_ce_ctrl;
+ uint8_t r_ctrl0;
+ uint8_t r_timings;
+ uint8_t nregs_timings;
+ uint8_t conf_enable_w0;
+ uint8_t cs_num_max;
+ const uint32_t *resets;
+ const AspeedSegments *segments;
+ uint32_t segment_addr_mask;
+ hwaddr flash_window_base;
+ uint32_t flash_window_size;
+ uint32_t features;
+ hwaddr dma_flash_mask;
+ hwaddr dma_dram_mask;
+ uint32_t nregs;
+ uint32_t (*segment_to_reg)(const AspeedSMCState *s,
+ const AspeedSegments *seg);
+ void (*reg_to_segment)(const AspeedSMCState *s, uint32_t reg,
+ AspeedSegments *seg);
+ void (*dma_ctrl)(AspeedSMCState *s, uint32_t value);
+ int (*addr_width)(const AspeedSMCState *s);
+};
#endif /* ASPEED_SMC_H */
diff --git a/include/hw/ssi/bcm2835_spi.h b/include/hw/ssi/bcm2835_spi.h
new file mode 100644
index 0000000000..d3f8cec111
--- /dev/null
+++ b/include/hw/ssi/bcm2835_spi.h
@@ -0,0 +1,81 @@
+/*
+ * BCM2835 SPI Master Controller
+ *
+ * Copyright (c) 2024 Rayhan Faizel <rayhan.faizel@gmail.com>
+ *
+ * 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 "hw/sysbus.h"
+#include "hw/ssi/ssi.h"
+#include "qom/object.h"
+#include "qemu/fifo8.h"
+
+#define TYPE_BCM2835_SPI "bcm2835-spi"
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835SPIState, BCM2835_SPI)
+
+/*
+ * Though BCM2835 documentation says FIFOs have a capacity of 16,
+ * FIFOs are actually 16 words in size or effectively 64 bytes when operating
+ * in non DMA mode.
+ */
+#define FIFO_SIZE 64
+#define FIFO_SIZE_3_4 48
+
+#define RO_MASK 0x1f0000
+
+#define BCM2835_SPI_CS 0x00
+#define BCM2835_SPI_FIFO 0x04
+#define BCM2835_SPI_CLK 0x08
+#define BCM2835_SPI_DLEN 0x0c
+#define BCM2835_SPI_LTOH 0x10
+#define BCM2835_SPI_DC 0x14
+
+#define BCM2835_SPI_CS_RXF BIT(20)
+#define BCM2835_SPI_CS_RXR BIT(19)
+#define BCM2835_SPI_CS_TXD BIT(18)
+#define BCM2835_SPI_CS_RXD BIT(17)
+#define BCM2835_SPI_CS_DONE BIT(16)
+#define BCM2835_SPI_CS_LEN BIT(13)
+#define BCM2835_SPI_CS_REN BIT(12)
+#define BCM2835_SPI_CS_INTR BIT(10)
+#define BCM2835_SPI_CS_INTD BIT(9)
+#define BCM2835_SPI_CS_DMAEN BIT(8)
+#define BCM2835_SPI_CS_TA BIT(7)
+#define BCM2835_SPI_CLEAR_RX BIT(5)
+#define BCM2835_SPI_CLEAR_TX BIT(4)
+
+struct BCM2835SPIState {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /* <public> */
+ SSIBus *bus;
+ MemoryRegion iomem;
+ qemu_irq irq;
+
+ uint32_t cs;
+ uint32_t clk;
+ uint32_t dlen;
+ uint32_t ltoh;
+ uint32_t dc;
+
+ Fifo8 tx_fifo;
+ Fifo8 rx_fifo;
+};
diff --git a/include/hw/ssi/ibex_spi_host.h b/include/hw/ssi/ibex_spi_host.h
new file mode 100644
index 0000000000..5bd5557b9a
--- /dev/null
+++ b/include/hw/ssi/ibex_spi_host.h
@@ -0,0 +1,92 @@
+
+/*
+ * QEMU model of the Ibex SPI Controller
+ * SPEC Reference: https://docs.opentitan.org/hw/ip/spi_host/doc/
+ *
+ * Copyright (C) 2022 Western Digital
+ *
+ * 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.
+ */
+
+#ifndef IBEX_SPI_HOST_H
+#define IBEX_SPI_HOST_H
+
+#include "hw/sysbus.h"
+#include "hw/ssi/ssi.h"
+#include "qemu/fifo8.h"
+#include "qom/object.h"
+#include "qemu/timer.h"
+
+#define TYPE_IBEX_SPI_HOST "ibex-spi"
+#define IBEX_SPI_HOST(obj) \
+ OBJECT_CHECK(IbexSPIHostState, (obj), TYPE_IBEX_SPI_HOST)
+
+/* SPI Registers */
+#define IBEX_SPI_HOST_INTR_STATE (0x00 / 4) /* rw1c */
+#define IBEX_SPI_HOST_INTR_ENABLE (0x04 / 4) /* rw */
+#define IBEX_SPI_HOST_INTR_TEST (0x08 / 4) /* wo */
+#define IBEX_SPI_HOST_ALERT_TEST (0x0c / 4) /* wo */
+#define IBEX_SPI_HOST_CONTROL (0x10 / 4) /* rw */
+#define IBEX_SPI_HOST_STATUS (0x14 / 4) /* ro */
+#define IBEX_SPI_HOST_CONFIGOPTS (0x18 / 4) /* rw */
+#define IBEX_SPI_HOST_CSID (0x1c / 4) /* rw */
+#define IBEX_SPI_HOST_COMMAND (0x20 / 4) /* wo */
+/* RX/TX Modelled by FIFO */
+#define IBEX_SPI_HOST_RXDATA (0x24 / 4)
+#define IBEX_SPI_HOST_TXDATA (0x28 / 4)
+
+#define IBEX_SPI_HOST_ERROR_ENABLE (0x2c / 4) /* rw */
+#define IBEX_SPI_HOST_ERROR_STATUS (0x30 / 4) /* rw1c */
+#define IBEX_SPI_HOST_EVENT_ENABLE (0x34 / 4) /* rw */
+
+/* FIFO Len in Bytes */
+#define IBEX_SPI_HOST_TXFIFO_LEN 288
+#define IBEX_SPI_HOST_RXFIFO_LEN 256
+
+/* Max Register (Based on addr) */
+#define IBEX_SPI_HOST_MAX_REGS (IBEX_SPI_HOST_EVENT_ENABLE + 1)
+
+/* MISC */
+#define TX_INTERRUPT_TRIGGER_DELAY_NS 100
+#define BIDIRECTIONAL_TRANSFER 3
+
+typedef struct {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /* <public> */
+ MemoryRegion mmio;
+ uint32_t regs[IBEX_SPI_HOST_MAX_REGS];
+ /* Multi-reg that sets config opts per CS */
+ uint32_t *config_opts;
+ Fifo8 rx_fifo;
+ Fifo8 tx_fifo;
+ QEMUTimer *fifo_trigger_handle;
+
+ qemu_irq event;
+ qemu_irq host_err;
+ uint32_t num_cs;
+ qemu_irq *cs_lines;
+ SSIBus *ssi;
+
+ /* Used to track the init status, for replicating TXDATA ghost writes */
+ bool init_status;
+} IbexSPIHostState;
+
+#endif
diff --git a/include/hw/ssi/imx_spi.h b/include/hw/ssi/imx_spi.h
index 7103953581..eeaf49bbac 100644
--- a/include/hw/ssi/imx_spi.h
+++ b/include/hw/ssi/imx_spi.h
@@ -14,6 +14,7 @@
#include "hw/ssi/ssi.h"
#include "qemu/bitops.h"
#include "qemu/fifo32.h"
+#include "qom/object.h"
#define ECSPI_FIFO_SIZE 64
@@ -76,10 +77,13 @@
#define EXTRACT(value, name) extract32(value, name##_SHIFT, name##_LENGTH)
+/* number of chip selects supported */
+#define ECSPI_NUM_CS 4
+
#define TYPE_IMX_SPI "imx.spi"
-#define IMX_SPI(obj) OBJECT_CHECK(IMXSPIState, (obj), TYPE_IMX_SPI)
+OBJECT_DECLARE_SIMPLE_TYPE(IMXSPIState, IMX_SPI)
-typedef struct IMXSPIState {
+struct IMXSPIState {
/* <private> */
SysBusDevice parent_obj;
@@ -88,7 +92,7 @@ typedef struct IMXSPIState {
qemu_irq irq;
- qemu_irq cs_lines[4];
+ qemu_irq cs_lines[ECSPI_NUM_CS];
SSIBus *bus;
@@ -98,6 +102,6 @@ typedef struct IMXSPIState {
Fifo32 tx_fifo;
int16_t burst_length;
-} IMXSPIState;
+};
#endif /* IMX_SPI_H */
diff --git a/include/hw/ssi/mss-spi.h b/include/hw/ssi/mss-spi.h
index f0cf3243e0..ce6279c431 100644
--- a/include/hw/ssi/mss-spi.h
+++ b/include/hw/ssi/mss-spi.h
@@ -28,13 +28,14 @@
#include "hw/sysbus.h"
#include "hw/ssi/ssi.h"
#include "qemu/fifo32.h"
+#include "qom/object.h"
#define TYPE_MSS_SPI "mss-spi"
-#define MSS_SPI(obj) OBJECT_CHECK(MSSSpiState, (obj), TYPE_MSS_SPI)
+OBJECT_DECLARE_SIMPLE_TYPE(MSSSpiState, MSS_SPI)
#define R_SPI_MAX 16
-typedef struct MSSSpiState {
+struct MSSSpiState {
SysBusDevice parent_obj;
MemoryRegion mmio;
@@ -53,6 +54,6 @@ typedef struct MSSSpiState {
bool enabled;
uint32_t regs[R_SPI_MAX];
-} MSSSpiState;
+};
#endif /* HW_MSS_SPI_H */
diff --git a/include/hw/ssi/npcm7xx_fiu.h b/include/hw/ssi/npcm7xx_fiu.h
new file mode 100644
index 0000000000..a3a1704289
--- /dev/null
+++ b/include/hw/ssi/npcm7xx_fiu.h
@@ -0,0 +1,73 @@
+/*
+ * Nuvoton NPCM7xx Flash Interface Unit (FIU)
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_FIU_H
+#define NPCM7XX_FIU_H
+
+#include "hw/ssi/ssi.h"
+#include "hw/sysbus.h"
+
+/*
+ * Number of registers in our device state structure. Don't change this without
+ * incrementing the version_id in the vmstate.
+ */
+#define NPCM7XX_FIU_NR_REGS (0x7c / sizeof(uint32_t))
+
+typedef struct NPCM7xxFIUState NPCM7xxFIUState;
+
+/**
+ * struct NPCM7xxFIUFlash - Per-chipselect flash controller state.
+ * @direct_access: Memory region for direct flash access.
+ * @fiu: Pointer to flash controller shared state.
+ */
+typedef struct NPCM7xxFIUFlash {
+ MemoryRegion direct_access;
+ NPCM7xxFIUState *fiu;
+} NPCM7xxFIUFlash;
+
+/**
+ * NPCM7xxFIUState - Device state for one Flash Interface Unit.
+ * @parent: System bus device.
+ * @mmio: Memory region for register access.
+ * @cs_count: Number of flash chips that may be connected to this module.
+ * @active_cs: Currently active chip select, or -1 if no chip is selected.
+ * @cs_lines: GPIO lines that may be wired to flash chips.
+ * @flash: Array of @cs_count per-flash-chip state objects.
+ * @spi: The SPI bus mastered by this controller.
+ * @regs: Register contents.
+ *
+ * Each FIU has a shared bank of registers, and controls up to four chip
+ * selects. Each chip select has a dedicated memory region which may be used to
+ * read and write the flash connected to that chip select as if it were memory.
+ */
+struct NPCM7xxFIUState {
+ SysBusDevice parent;
+
+ MemoryRegion mmio;
+
+ int32_t cs_count;
+ int32_t active_cs;
+ qemu_irq *cs_lines;
+ NPCM7xxFIUFlash *flash;
+
+ SSIBus *spi;
+
+ uint32_t regs[NPCM7XX_FIU_NR_REGS];
+};
+
+#define TYPE_NPCM7XX_FIU "npcm7xx-fiu"
+#define NPCM7XX_FIU(obj) OBJECT_CHECK(NPCM7xxFIUState, (obj), TYPE_NPCM7XX_FIU)
+
+#endif /* NPCM7XX_FIU_H */
diff --git a/include/hw/ssi/npcm_pspi.h b/include/hw/ssi/npcm_pspi.h
new file mode 100644
index 0000000000..37cc784d96
--- /dev/null
+++ b/include/hw/ssi/npcm_pspi.h
@@ -0,0 +1,53 @@
+/*
+ * Nuvoton Peripheral SPI Module
+ *
+ * Copyright 2023 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM_PSPI_H
+#define NPCM_PSPI_H
+
+#include "hw/ssi/ssi.h"
+#include "hw/sysbus.h"
+
+/*
+ * Number of registers in our device state structure. Don't change this without
+ * incrementing the version_id in the vmstate.
+ */
+#define NPCM_PSPI_NR_REGS 3
+
+/**
+ * NPCMPSPIState - Device state for one Flash Interface Unit.
+ * @parent: System bus device.
+ * @mmio: Memory region for register access.
+ * @spi: The SPI bus mastered by this controller.
+ * @regs: Register contents.
+ * @irq: The interrupt request queue for this module.
+ *
+ * Each PSPI has a shared bank of registers, and controls up to four chip
+ * selects. Each chip select has a dedicated memory region which may be used to
+ * read and write the flash connected to that chip select as if it were memory.
+ */
+typedef struct NPCMPSPIState {
+ SysBusDevice parent;
+
+ MemoryRegion mmio;
+
+ SSIBus *spi;
+ uint16_t regs[NPCM_PSPI_NR_REGS];
+ qemu_irq irq;
+} NPCMPSPIState;
+
+#define TYPE_NPCM_PSPI "npcm-pspi"
+OBJECT_DECLARE_SIMPLE_TYPE(NPCMPSPIState, NPCM_PSPI)
+
+#endif /* NPCM_PSPI_H */
diff --git a/include/hw/ssi/pl022.h b/include/hw/ssi/pl022.h
index a080519366..25d58db5f3 100644
--- a/include/hw/ssi/pl022.h
+++ b/include/hw/ssi/pl022.h
@@ -9,9 +9,10 @@
* (at your option) any later version.
*/
-/* This is a model of the Arm PrimeCell PL022 synchronous serial port.
+/*
+ * This is a model of the Arm PrimeCell PL022 synchronous serial port.
* The PL022 TRM is:
- * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0194h/DDI0194H_ssp_pl022_trm.pdf
+ * https://developer.arm.com/documentation/ddi0194/latest
*
* QEMU interface:
* + sysbus IRQ: SSPINTR combined interrupt line
@@ -22,11 +23,12 @@
#define HW_SSI_PL022_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_PL022 "pl022"
-#define PL022(obj) OBJECT_CHECK(PL022State, (obj), TYPE_PL022)
+OBJECT_DECLARE_SIMPLE_TYPE(PL022State, PL022)
-typedef struct PL022State {
+struct PL022State {
SysBusDevice parent_obj;
MemoryRegion iomem;
@@ -46,6 +48,6 @@ typedef struct PL022State {
uint16_t rx_fifo[8];
qemu_irq irq;
SSIBus *ssi;
-} PL022State;
+};
#endif
diff --git a/include/hw/ssi/sifive_spi.h b/include/hw/ssi/sifive_spi.h
new file mode 100644
index 0000000000..d0c40cdb11
--- /dev/null
+++ b/include/hw/ssi/sifive_spi.h
@@ -0,0 +1,50 @@
+/*
+ * QEMU model of the SiFive SPI Controller
+ *
+ * Copyright (c) 2021 Wind River Systems, Inc.
+ *
+ * Author:
+ * Bin Meng <bin.meng@windriver.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_SIFIVE_SPI_H
+#define HW_SIFIVE_SPI_H
+
+#include "qemu/fifo8.h"
+#include "hw/sysbus.h"
+
+#define SIFIVE_SPI_REG_NUM (0x78 / 4)
+
+#define TYPE_SIFIVE_SPI "sifive.spi"
+#define SIFIVE_SPI(obj) OBJECT_CHECK(SiFiveSPIState, (obj), TYPE_SIFIVE_SPI)
+
+typedef struct SiFiveSPIState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion mmio;
+ qemu_irq irq;
+
+ uint32_t num_cs;
+ qemu_irq *cs_lines;
+
+ SSIBus *spi;
+
+ Fifo8 tx_fifo;
+ Fifo8 rx_fifo;
+
+ uint32_t regs[SIFIVE_SPI_REG_NUM];
+} SiFiveSPIState;
+
+#endif /* HW_SIFIVE_SPI_H */
diff --git a/include/hw/ssi/ssi.h b/include/hw/ssi/ssi.h
index eac168aa1d..3cdcbd5390 100644
--- a/include/hw/ssi/ssi.h
+++ b/include/hw/ssi/ssi.h
@@ -1,29 +1,26 @@
/* 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
#include "hw/qdev-core.h"
+#include "qom/object.h"
-typedef struct SSISlave SSISlave;
-typedef struct SSISlaveClass SSISlaveClass;
typedef enum SSICSMode SSICSMode;
-#define TYPE_SSI_SLAVE "ssi-slave"
-#define SSI_SLAVE(obj) \
- OBJECT_CHECK(SSISlave, (obj), TYPE_SSI_SLAVE)
-#define SSI_SLAVE_CLASS(klass) \
- OBJECT_CLASS_CHECK(SSISlaveClass, (klass), TYPE_SSI_SLAVE)
-#define SSI_SLAVE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(SSISlaveClass, (obj), TYPE_SSI_SLAVE)
+#define TYPE_SSI_PERIPHERAL "ssi-peripheral"
+OBJECT_DECLARE_TYPE(SSIPeripheral, SSIPeripheralClass,
+ SSI_PERIPHERAL)
#define SSI_GPIO_CS "ssi-gpio-cs"
@@ -33,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;
@@ -56,30 +53,36 @@ 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;
+ /* cache the class */
+ SSIPeripheralClass *spc;
+
/* Chip select state */
bool cs;
+
+ /* Chip select index */
+ uint8_t cs_index;
};
-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
*
@@ -90,10 +93,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
@@ -109,4 +112,6 @@ SSIBus *ssi_create_bus(DeviceState *parent, const char *name);
uint32_t ssi_transfer(SSIBus *bus, uint32_t val);
+DeviceState *ssi_get_cs(SSIBus *bus, uint8_t cs_index);
+
#endif
diff --git a/include/hw/ssi/stm32f2xx_spi.h b/include/hw/ssi/stm32f2xx_spi.h
index e24b007abf..3683b4ad32 100644
--- a/include/hw/ssi/stm32f2xx_spi.h
+++ b/include/hw/ssi/stm32f2xx_spi.h
@@ -27,6 +27,7 @@
#include "hw/sysbus.h"
#include "hw/ssi/ssi.h"
+#include "qom/object.h"
#define STM_SPI_CR1 0x00
#define STM_SPI_CR2 0x04
@@ -44,10 +45,9 @@
#define STM_SPI_SR_RXNE 1
#define TYPE_STM32F2XX_SPI "stm32f2xx-spi"
-#define STM32F2XX_SPI(obj) \
- OBJECT_CHECK(STM32F2XXSPIState, (obj), TYPE_STM32F2XX_SPI)
+OBJECT_DECLARE_SIMPLE_TYPE(STM32F2XXSPIState, STM32F2XX_SPI)
-typedef struct {
+struct STM32F2XXSPIState {
/* <private> */
SysBusDevice parent_obj;
@@ -66,6 +66,6 @@ typedef struct {
qemu_irq irq;
SSIBus *ssi;
-} STM32F2XXSPIState;
+};
#endif /* HW_STM32F2XX_SPI_H */
diff --git a/include/hw/ssi/xilinx_spips.h b/include/hw/ssi/xilinx_spips.h
index 6a39b55a7b..7a754bf67a 100644
--- a/include/hw/ssi/xilinx_spips.h
+++ b/include/hw/ssi/xilinx_spips.h
@@ -29,11 +29,14 @@
#include "qemu/fifo32.h"
#include "hw/stream.h"
#include "hw/sysbus.h"
+#include "qom/object.h"
typedef struct XilinxSPIPS XilinxSPIPS;
+/* For SPIPS, QSPIPS. */
#define XLNX_SPIPS_R_MAX (0x100 / 4)
-#define XLNX_ZYNQMP_SPIPS_R_MAX (0x830 / 4)
+/* For ZYNQMP_QSPIPS. */
+#define XLNX_ZYNQMP_SPIPS_R_MAX (0x200 / 4)
/* Bite off 4k chunks at a time */
#define LQSPI_CACHE_SIZE 1024
@@ -85,24 +88,25 @@ struct XilinxSPIPS {
bool man_start_com;
};
-typedef struct {
+struct XilinxQSPIPS {
XilinxSPIPS parent_obj;
uint8_t lqspi_buf[LQSPI_CACHE_SIZE];
hwaddr lqspi_cached_addr;
Error *migration_blocker;
bool mmio_execution_enabled;
-} XilinxQSPIPS;
+};
+typedef struct XilinxQSPIPS XilinxQSPIPS;
-typedef struct {
+struct XlnxZynqMPQSPIPS {
XilinxQSPIPS parent_obj;
- StreamSlave *dma;
+ StreamSink *dma;
int gqspi_irqline;
uint32_t regs[XLNX_ZYNQMP_SPIPS_R_MAX];
- /* GQSPI has seperate tx/rx fifos */
+ /* GQSPI has separate tx/rx fifos */
Fifo8 rx_fifo_g;
Fifo8 tx_fifo_g;
Fifo32 fifo_g;
@@ -117,32 +121,26 @@ typedef struct {
bool man_start_com_g;
uint32_t dma_burst_size;
uint8_t dma_buf[QSPI_DMA_MAX_BURST_SIZE];
-} XlnxZynqMPQSPIPS;
+};
-typedef struct XilinxSPIPSClass {
+struct XilinxSPIPSClass {
SysBusDeviceClass parent_class;
const MemoryRegionOps *reg_ops;
+ uint64_t reg_size;
uint32_t rx_fifo_size;
uint32_t tx_fifo_size;
-} XilinxSPIPSClass;
+};
#define TYPE_XILINX_SPIPS "xlnx.ps7-spi"
#define TYPE_XILINX_QSPIPS "xlnx.ps7-qspi"
#define TYPE_XLNX_ZYNQMP_QSPIPS "xlnx.usmp-gqspi"
-#define XILINX_SPIPS(obj) \
- OBJECT_CHECK(XilinxSPIPS, (obj), TYPE_XILINX_SPIPS)
-#define XILINX_SPIPS_CLASS(klass) \
- OBJECT_CLASS_CHECK(XilinxSPIPSClass, (klass), TYPE_XILINX_SPIPS)
-#define XILINX_SPIPS_GET_CLASS(obj) \
- OBJECT_GET_CLASS(XilinxSPIPSClass, (obj), TYPE_XILINX_SPIPS)
+OBJECT_DECLARE_TYPE(XilinxSPIPS, XilinxSPIPSClass, XILINX_SPIPS)
-#define XILINX_QSPIPS(obj) \
- OBJECT_CHECK(XilinxQSPIPS, (obj), TYPE_XILINX_QSPIPS)
+OBJECT_DECLARE_SIMPLE_TYPE(XilinxQSPIPS, XILINX_QSPIPS)
-#define XLNX_ZYNQMP_QSPIPS(obj) \
- OBJECT_CHECK(XlnxZynqMPQSPIPS, (obj), TYPE_XLNX_ZYNQMP_QSPIPS)
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPQSPIPS, XLNX_ZYNQMP_QSPIPS)
#endif /* XILINX_SPIPS_H */
diff --git a/include/hw/ssi/xlnx-versal-ospi.h b/include/hw/ssi/xlnx-versal-ospi.h
new file mode 100644
index 0000000000..4ac975aa2f
--- /dev/null
+++ b/include/hw/ssi/xlnx-versal-ospi.h
@@ -0,0 +1,111 @@
+/*
+ * Header file for the Xilinx Versal's OSPI controller
+ *
+ * Copyright (C) 2021 Xilinx Inc
+ * Written by Francisco Iglesias <francisco.iglesias@xilinx.com>
+ *
+ * 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.
+ */
+
+/*
+ * This is a model of Xilinx Versal's Octal SPI flash memory controller
+ * documented in Versal's Technical Reference manual [1] and the Versal ACAP
+ * Register reference [2].
+ *
+ * References:
+ *
+ * [1] Versal ACAP Technical Reference Manual,
+ * https://www.xilinx.com/support/documentation/architecture-manuals/am011-versal-acap-trm.pdf
+ *
+ * [2] Versal ACAP Register Reference,
+ * https://docs.xilinx.com/r/en-US/am012-versal-register-reference/OSPI-Module
+ *
+ *
+ * QEMU interface:
+ * + sysbus MMIO region 0: MemoryRegion for the device's registers
+ * + sysbus MMIO region 1: MemoryRegion for flash memory linear address space
+ * (data transfer).
+ * + sysbus IRQ 0: Device interrupt.
+ * + Named GPIO input "ospi-mux-sel": 0: enables indirect access mode
+ * and 1: enables direct access mode.
+ * + Property "dac-with-indac": Allow both direct accesses and indirect
+ * accesses simultaneously.
+ * + Property "indac-write-disabled": Disable indirect access writes.
+ */
+
+#ifndef XLNX_VERSAL_OSPI_H
+#define XLNX_VERSAL_OSPI_H
+
+#include "hw/register.h"
+#include "hw/ssi/ssi.h"
+#include "qemu/fifo8.h"
+#include "hw/dma/xlnx_csu_dma.h"
+
+#define TYPE_XILINX_VERSAL_OSPI "xlnx.versal-ospi"
+
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalOspi, XILINX_VERSAL_OSPI)
+
+#define XILINX_VERSAL_OSPI_R_MAX (0xfc / 4 + 1)
+
+/*
+ * Indirect operations
+ */
+typedef struct IndOp {
+ uint32_t flash_addr;
+ uint32_t num_bytes;
+ uint32_t done_bytes;
+ bool completed;
+} IndOp;
+
+struct XlnxVersalOspi {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ MemoryRegion iomem_dac;
+
+ uint8_t num_cs;
+ qemu_irq *cs_lines;
+
+ SSIBus *spi;
+
+ Fifo8 rx_fifo;
+ Fifo8 tx_fifo;
+
+ Fifo8 rx_sram;
+ Fifo8 tx_sram;
+
+ qemu_irq irq;
+
+ XlnxCSUDMA *dma_src;
+ bool ind_write_disabled;
+ bool dac_with_indac;
+ bool dac_enable;
+ bool src_dma_inprog;
+
+ IndOp rd_ind_op[2];
+ IndOp wr_ind_op[2];
+
+ uint32_t regs[XILINX_VERSAL_OSPI_R_MAX];
+ RegisterInfo regs_info[XILINX_VERSAL_OSPI_R_MAX];
+
+ /* Maximum inferred membank size is 512 bytes */
+ uint8_t stig_membank[512];
+};
+
+#endif /* XLNX_VERSAL_OSPI_H */
diff --git a/include/hw/stream.h b/include/hw/stream.h
index ed09e83683..f166facb09 100644
--- a/include/hw/stream.h
+++ b/include/hw/stream.h
@@ -3,52 +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"
-#define STREAM_SLAVE_CLASS(klass) \
- OBJECT_CLASS_CHECK(StreamSlaveClass, (klass), TYPE_STREAM_SLAVE)
-#define STREAM_SLAVE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(StreamSlaveClass, (obj), 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);
-typedef 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);
-} StreamSlaveClass;
+ 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/hw/sysbus.h b/include/hw/sysbus.h
index da9f85c58c..3cb29a480e 100644
--- a/include/hw/sysbus.h
+++ b/include/hw/sysbus.h
@@ -5,22 +5,19 @@
#include "hw/qdev-core.h"
#include "exec/memory.h"
+#include "qom/object.h"
#define QDEV_MAX_MMIO 32
#define QDEV_MAX_PIO 32
#define TYPE_SYSTEM_BUS "System"
-#define SYSTEM_BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_SYSTEM_BUS)
+DECLARE_INSTANCE_CHECKER(BusState, SYSTEM_BUS,
+ TYPE_SYSTEM_BUS)
-typedef struct SysBusDevice SysBusDevice;
#define TYPE_SYS_BUS_DEVICE "sys-bus-device"
-#define SYS_BUS_DEVICE(obj) \
- OBJECT_CHECK(SysBusDevice, (obj), TYPE_SYS_BUS_DEVICE)
-#define SYS_BUS_DEVICE_CLASS(klass) \
- OBJECT_CLASS_CHECK(SysBusDeviceClass, (klass), TYPE_SYS_BUS_DEVICE)
-#define SYS_BUS_DEVICE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(SysBusDeviceClass, (obj), TYPE_SYS_BUS_DEVICE)
+OBJECT_DECLARE_TYPE(SysBusDevice, SysBusDeviceClass,
+ SYS_BUS_DEVICE)
/**
* SysBusDeviceClass:
@@ -31,7 +28,7 @@ typedef struct SysBusDevice SysBusDevice;
#define SYSBUS_DEVICE_GPIO_IRQ "sysbus-irq"
-typedef struct SysBusDeviceClass {
+struct SysBusDeviceClass {
/*< private >*/
DeviceClass parent_class;
@@ -52,7 +49,7 @@ typedef struct SysBusDeviceClass {
*/
char *(*explicit_ofw_unit_address)(const SysBusDevice *dev);
void (*connect_irq_notifier)(SysBusDevice *dev, qemu_irq irq);
-} SysBusDeviceClass;
+};
struct SysBusDevice {
/*< private >*/
@@ -86,9 +83,6 @@ void sysbus_mmio_map(SysBusDevice *dev, int n, hwaddr addr);
void sysbus_mmio_map_overlap(SysBusDevice *dev, int n, hwaddr addr,
int priority);
void sysbus_mmio_unmap(SysBusDevice *dev, int n);
-void sysbus_add_io(SysBusDevice *dev, hwaddr addr,
- MemoryRegion *mem);
-MemoryRegion *sysbus_address_space(SysBusDevice *dev);
bool sysbus_realize(SysBusDevice *dev, Error **errp);
bool sysbus_realize_and_unref(SysBusDevice *dev, Error **errp);
diff --git a/include/hw/timer/a9gtimer.h b/include/hw/timer/a9gtimer.h
index 81c4388784..6ae9122e4b 100644
--- a/include/hw/timer/a9gtimer.h
+++ b/include/hw/timer/a9gtimer.h
@@ -24,11 +24,12 @@
#define A9GTIMER_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define A9_GTIMER_MAX_CPUS 4
#define TYPE_A9_GTIMER "arm.cortex-a9-global-timer"
-#define A9_GTIMER(obj) OBJECT_CHECK(A9GTimerState, (obj), TYPE_A9_GTIMER)
+OBJECT_DECLARE_SIMPLE_TYPE(A9GTimerState, A9_GTIMER)
#define R_COUNTER_LO 0x00
#define R_COUNTER_HI 0x04
@@ -55,7 +56,6 @@
#define R_AUTO_INCREMENT 0x18
typedef struct A9GTimerPerCPU A9GTimerPerCPU;
-typedef struct A9GTimerState A9GTimerState;
struct A9GTimerPerCPU {
A9GTimerState *parent;
diff --git a/include/hw/timer/allwinner-a10-pit.h b/include/hw/timer/allwinner-a10-pit.h
index 871c95b512..8435758ad6 100644
--- a/include/hw/timer/allwinner-a10-pit.h
+++ b/include/hw/timer/allwinner-a10-pit.h
@@ -3,9 +3,10 @@
#include "hw/ptimer.h"
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_AW_A10_PIT "allwinner-A10-timer"
-#define AW_A10_PIT(obj) OBJECT_CHECK(AwA10PITState, (obj), TYPE_AW_A10_PIT)
+OBJECT_DECLARE_SIMPLE_TYPE(AwA10PITState, AW_A10_PIT)
#define AW_A10_PIT_TIMER_NR 6
#define AW_A10_PIT_TIMER_IRQ 0x1
@@ -36,7 +37,6 @@
#define AW_A10_PIT_DEFAULT_CLOCK 0x4
-typedef struct AwA10PITState AwA10PITState;
typedef struct AwA10TimerContext {
AwA10PITState *container;
diff --git a/include/hw/timer/arm_mptimer.h b/include/hw/timer/arm_mptimer.h
index c46d8d2309..65a96e2a0d 100644
--- a/include/hw/timer/arm_mptimer.h
+++ b/include/hw/timer/arm_mptimer.h
@@ -22,6 +22,7 @@
#define HW_TIMER_ARM_MPTIMER_H
#include "hw/sysbus.h"
+#include "qom/object.h"
#define ARM_MPTIMER_MAX_CPUS 4
@@ -35,10 +36,9 @@ typedef struct {
} TimerBlock;
#define TYPE_ARM_MPTIMER "arm_mptimer"
-#define ARM_MPTIMER(obj) \
- OBJECT_CHECK(ARMMPTimerState, (obj), TYPE_ARM_MPTIMER)
+OBJECT_DECLARE_SIMPLE_TYPE(ARMMPTimerState, ARM_MPTIMER)
-typedef struct {
+struct ARMMPTimerState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -46,6 +46,6 @@ typedef struct {
uint32_t num_cpu;
TimerBlock timerblock[ARM_MPTIMER_MAX_CPUS];
MemoryRegion iomem;
-} ARMMPTimerState;
+};
#endif
diff --git a/include/hw/timer/armv7m_systick.h b/include/hw/timer/armv7m_systick.h
index 25e5ceacc8..ee09b13881 100644
--- a/include/hw/timer/armv7m_systick.h
+++ b/include/hw/timer/armv7m_systick.h
@@ -13,12 +13,26 @@
#define HW_TIMER_ARMV7M_SYSTICK_H
#include "hw/sysbus.h"
+#include "qom/object.h"
+#include "hw/ptimer.h"
+#include "hw/clock.h"
#define TYPE_SYSTICK "armv7m_systick"
-#define SYSTICK(obj) OBJECT_CHECK(SysTickState, (obj), TYPE_SYSTICK)
+OBJECT_DECLARE_SIMPLE_TYPE(SysTickState, SYSTICK)
-typedef struct SysTickState {
+/*
+ * QEMU interface:
+ * + sysbus MMIO region 0 is the register interface (covering
+ * the registers which are mapped at address 0xE000E010)
+ * + sysbus IRQ 0 is the interrupt line to the NVIC
+ * + Clock input "refclk" is the external reference clock
+ * (used when SYST_CSR.CLKSOURCE == 0)
+ * + Clock input "cpuclk" is the main CPU clock
+ * (used when SYST_CSR.CLKSOURCE == 1)
+ */
+
+struct SysTickState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -26,31 +40,11 @@ typedef struct SysTickState {
uint32_t control;
uint32_t reload;
int64_t tick;
- QEMUTimer *timer;
+ ptimer_state *ptimer;
MemoryRegion iomem;
qemu_irq irq;
-} SysTickState;
-
-/*
- * Multiplication factor to convert from system clock ticks to qemu timer
- * ticks. This should be set (by board code, usually) to a value
- * equal to NANOSECONDS_PER_SECOND / frq, where frq is the clock frequency
- * in Hz of the CPU.
- *
- * This value is used by the systick device when it is running in
- * its "use the CPU clock" mode (ie when SYST_CSR.CLKSOURCE == 1) to
- * set how fast the timer should tick.
- *
- * TODO: we should refactor this so that rather than using a global
- * we use a device property or something similar. This is complicated
- * because (a) the property would need to be plumbed through from the
- * board code down through various layers to the systick device
- * and (b) the property needs to be modifiable after realize, because
- * the stellaris board uses this to implement the behaviour where the
- * guest can reprogram the PLL registers to downclock the CPU, and the
- * systick device needs to react accordingly. Possibly this should
- * be deferred until we have a good API for modelling clock trees.
- */
-extern int system_clock_scale;
+ Clock *refclk;
+ Clock *cpuclk;
+};
#endif
diff --git a/include/hw/timer/aspeed_timer.h b/include/hw/timer/aspeed_timer.h
index 948329893c..07dc6b6f2c 100644
--- a/include/hw/timer/aspeed_timer.h
+++ b/include/hw/timer/aspeed_timer.h
@@ -24,13 +24,14 @@
#include "qemu/timer.h"
#include "hw/misc/aspeed_scu.h"
+#include "qom/object.h"
-#define ASPEED_TIMER(obj) \
- OBJECT_CHECK(AspeedTimerCtrlState, (obj), TYPE_ASPEED_TIMER);
#define TYPE_ASPEED_TIMER "aspeed.timer"
+OBJECT_DECLARE_TYPE(AspeedTimerCtrlState, AspeedTimerClass, ASPEED_TIMER)
#define TYPE_ASPEED_2400_TIMER TYPE_ASPEED_TIMER "-ast2400"
#define TYPE_ASPEED_2500_TIMER TYPE_ASPEED_TIMER "-ast2500"
#define TYPE_ASPEED_2600_TIMER TYPE_ASPEED_TIMER "-ast2600"
+#define TYPE_ASPEED_1030_TIMER TYPE_ASPEED_TIMER "-ast1030"
#define ASPEED_TIMER_NR_TIMERS 8
@@ -50,7 +51,7 @@ typedef struct AspeedTimer {
uint64_t start;
} AspeedTimer;
-typedef struct AspeedTimerCtrlState {
+struct AspeedTimerCtrlState {
/*< private >*/
SysBusDevice parent;
@@ -64,18 +65,14 @@ typedef struct AspeedTimerCtrlState {
AspeedTimer timers[ASPEED_TIMER_NR_TIMERS];
AspeedSCUState *scu;
-} AspeedTimerCtrlState;
+};
-#define ASPEED_TIMER_CLASS(klass) \
- OBJECT_CLASS_CHECK(AspeedTimerClass, (klass), TYPE_ASPEED_TIMER)
-#define ASPEED_TIMER_GET_CLASS(obj) \
- OBJECT_GET_CLASS(AspeedTimerClass, (obj), TYPE_ASPEED_TIMER)
-typedef struct AspeedTimerClass {
+struct AspeedTimerClass {
SysBusDeviceClass parent_class;
uint64_t (*read)(AspeedTimerCtrlState *s, hwaddr offset);
void (*write)(AspeedTimerCtrlState *s, hwaddr offset, uint64_t value);
-} AspeedTimerClass;
+};
#endif /* ASPEED_TIMER_H */
diff --git a/include/hw/timer/avr_timer16.h b/include/hw/timer/avr_timer16.h
index 982019d242..a1a032a24d 100644
--- a/include/hw/timer/avr_timer16.h
+++ b/include/hw/timer/avr_timer16.h
@@ -30,7 +30,7 @@
#include "hw/sysbus.h"
#include "qemu/timer.h"
-#include "hw/hw.h"
+#include "qom/object.h"
enum NextInterrupt {
OVERFLOW,
@@ -41,10 +41,9 @@ enum NextInterrupt {
};
#define TYPE_AVR_TIMER16 "avr-timer16"
-#define AVR_TIMER16(obj) \
- OBJECT_CHECK(AVRTimer16State, (obj), TYPE_AVR_TIMER16)
+OBJECT_DECLARE_SIMPLE_TYPE(AVRTimer16State, AVR_TIMER16)
-typedef struct AVRTimer16State {
+struct AVRTimer16State {
/* <private> */
SysBusDevice parent_obj;
@@ -89,6 +88,6 @@ typedef struct AVRTimer16State {
uint64_t period_ns;
uint64_t reset_time_ns;
enum NextInterrupt next_interrupt;
-} AVRTimer16State;
+};
#endif /* HW_TIMER_AVR_TIMER16_H */
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
index c0bc5c8127..a8f605beeb 100644
--- a/include/hw/timer/bcm2835_systmr.h
+++ b/include/hw/timer/bcm2835_systmr.h
@@ -6,28 +6,37 @@
* SPDX-License-Identifier: GPL-2.0-or-later
*/
-#ifndef BCM2835_SYSTIMER_H
-#define BCM2835_SYSTIMER_H
+#ifndef BCM2835_SYSTMR_H
+#define BCM2835_SYSTMR_H
#include "hw/sysbus.h"
#include "hw/irq.h"
+#include "qemu/timer.h"
+#include "qom/object.h"
#define TYPE_BCM2835_SYSTIMER "bcm2835-sys-timer"
-#define BCM2835_SYSTIMER(obj) \
- OBJECT_CHECK(BCM2835SystemTimerState, (obj), TYPE_BCM2835_SYSTIMER)
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835SystemTimerState, BCM2835_SYSTIMER)
+
+#define BCM2835_SYSTIMER_COUNT 4
typedef struct {
+ unsigned id;
+ QEMUTimer timer;
+ qemu_irq irq;
+ BCM2835SystemTimerState *state;
+} BCM2835SystemTimerCompare;
+
+struct BCM2835SystemTimerState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
MemoryRegion iomem;
- qemu_irq irq;
-
struct {
- uint32_t status;
- uint32_t compare[4];
+ uint32_t ctrl_status;
+ uint32_t compare[BCM2835_SYSTIMER_COUNT];
} reg;
-} BCM2835SystemTimerState;
+ BCM2835SystemTimerCompare tmr[BCM2835_SYSTIMER_COUNT];
+};
#endif
diff --git a/include/hw/timer/cadence_ttc.h b/include/hw/timer/cadence_ttc.h
new file mode 100644
index 0000000000..e1251383f2
--- /dev/null
+++ b/include/hw/timer/cadence_ttc.h
@@ -0,0 +1,54 @@
+/*
+ * Xilinx Zynq cadence TTC model
+ *
+ * Copyright (c) 2011 Xilinx Inc.
+ * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwaite@petalogix.com)
+ * Copyright (c) 2012 PetaLogix Pty Ltd.
+ * Written By Haibing Ma
+ * M. Habib
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef HW_TIMER_CADENCE_TTC_H
+#define HW_TIMER_CADENCE_TTC_H
+
+#include "hw/sysbus.h"
+#include "qemu/timer.h"
+
+typedef struct {
+ QEMUTimer *timer;
+ int freq;
+
+ uint32_t reg_clock;
+ uint32_t reg_count;
+ uint32_t reg_value;
+ uint16_t reg_interval;
+ uint16_t reg_match[3];
+ uint32_t reg_intr;
+ uint32_t reg_intr_en;
+ uint32_t reg_event_ctrl;
+ uint32_t reg_event;
+
+ uint64_t cpu_time;
+ unsigned int cpu_time_valid;
+
+ qemu_irq irq;
+} CadenceTimerState;
+
+#define TYPE_CADENCE_TTC "cadence_ttc"
+OBJECT_DECLARE_SIMPLE_TYPE(CadenceTTCState, CADENCE_TTC)
+
+struct CadenceTTCState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ CadenceTimerState timer[3];
+};
+
+#endif
diff --git a/include/hw/timer/cmsdk-apb-dualtimer.h b/include/hw/timer/cmsdk-apb-dualtimer.h
index 9843a9dbb1..f3ec86c00b 100644
--- a/include/hw/timer/cmsdk-apb-dualtimer.h
+++ b/include/hw/timer/cmsdk-apb-dualtimer.h
@@ -16,7 +16,7 @@
* https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
*
* QEMU interface:
- * + QOM property "pclk-frq": frequency at which the timer is clocked
+ * + Clock input "TIMCLK": clock (for both timers)
* + sysbus MMIO region 0: the register bank
* + sysbus IRQ 0: combined timer interrupt TIMINTC
* + sysbus IRO 1: timer block 1 interrupt TIMINT1
@@ -28,12 +28,12 @@
#include "hw/sysbus.h"
#include "hw/ptimer.h"
+#include "hw/clock.h"
+#include "qom/object.h"
#define TYPE_CMSDK_APB_DUALTIMER "cmsdk-apb-dualtimer"
-#define CMSDK_APB_DUALTIMER(obj) OBJECT_CHECK(CMSDKAPBDualTimer, (obj), \
- TYPE_CMSDK_APB_DUALTIMER)
+OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBDualTimer, CMSDK_APB_DUALTIMER)
-typedef struct CMSDKAPBDualTimer CMSDKAPBDualTimer;
/* One of the two identical timer modules in the dual-timer module */
typedef struct CMSDKAPBDualTimerModule {
@@ -62,7 +62,7 @@ struct CMSDKAPBDualTimer {
/*< public >*/
MemoryRegion iomem;
qemu_irq timerintc;
- uint32_t pclk_frq;
+ Clock *timclk;
CMSDKAPBDualTimerModule timermod[CMSDK_APB_DUALTIMER_NUM_MODULES];
uint32_t timeritcr;
diff --git a/include/hw/timer/cmsdk-apb-timer.h b/include/hw/timer/cmsdk-apb-timer.h
index f24bda6a46..2dd615d1be 100644
--- a/include/hw/timer/cmsdk-apb-timer.h
+++ b/include/hw/timer/cmsdk-apb-timer.h
@@ -12,49 +12,34 @@
#ifndef CMSDK_APB_TIMER_H
#define CMSDK_APB_TIMER_H
-#include "hw/qdev-properties.h"
#include "hw/sysbus.h"
#include "hw/ptimer.h"
+#include "hw/clock.h"
+#include "qom/object.h"
#define TYPE_CMSDK_APB_TIMER "cmsdk-apb-timer"
-#define CMSDK_APB_TIMER(obj) OBJECT_CHECK(CMSDKAPBTIMER, (obj), \
- TYPE_CMSDK_APB_TIMER)
+OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBTimer, CMSDK_APB_TIMER)
-typedef struct {
+/*
+ * QEMU interface:
+ * + Clock input "pclk": clock for the timer
+ * + sysbus MMIO region 0: the register bank
+ * + sysbus IRQ 0: timer interrupt TIMERINT
+ */
+struct CMSDKAPBTimer {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
MemoryRegion iomem;
qemu_irq timerint;
- uint32_t pclk_frq;
struct ptimer_state *timer;
+ Clock *pclk;
uint32_t ctrl;
uint32_t value;
uint32_t reload;
uint32_t intstatus;
-} CMSDKAPBTIMER;
-
-/**
- * cmsdk_apb_timer_create - convenience function to create TYPE_CMSDK_APB_TIMER
- * @addr: location in system memory to map registers
- * @pclk_frq: frequency in Hz of the PCLK clock (used for calculating baud rate)
- */
-static inline DeviceState *cmsdk_apb_timer_create(hwaddr addr,
- qemu_irq timerint,
- uint32_t pclk_frq)
-{
- DeviceState *dev;
- SysBusDevice *s;
-
- dev = qdev_new(TYPE_CMSDK_APB_TIMER);
- s = SYS_BUS_DEVICE(dev);
- qdev_prop_set_uint32(dev, "pclk-frq", pclk_frq);
- sysbus_realize_and_unref(s, &error_fatal);
- sysbus_mmio_map(s, 0, addr);
- sysbus_connect_irq(s, 0, timerint);
- return dev;
-}
+};
#endif
diff --git a/include/hw/timer/digic-timer.h b/include/hw/timer/digic-timer.h
index d9e67fe291..da82fb4663 100644
--- a/include/hw/timer/digic-timer.h
+++ b/include/hw/timer/digic-timer.h
@@ -20,9 +20,10 @@
#include "hw/sysbus.h"
#include "hw/ptimer.h"
+#include "qom/object.h"
#define TYPE_DIGIC_TIMER "digic-timer"
-#define DIGIC_TIMER(obj) OBJECT_CHECK(DigicTimerState, (obj), TYPE_DIGIC_TIMER)
+OBJECT_DECLARE_SIMPLE_TYPE(DigicTimerState, DIGIC_TIMER)
#define DIGIC_TIMER_CONTROL 0x00
#define DIGIC_TIMER_CONTROL_RST 0x80000000
@@ -30,7 +31,7 @@
#define DIGIC_TIMER_RELVALUE 0x08
#define DIGIC_TIMER_VALUE 0x0c
-typedef struct DigicTimerState {
+struct DigicTimerState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -40,6 +41,6 @@ typedef struct DigicTimerState {
uint32_t control;
uint32_t relvalue;
-} DigicTimerState;
+};
#endif /* HW_TIMER_DIGIC_TIMER_H */
diff --git a/include/hw/timer/grlib_gptimer.h b/include/hw/timer/grlib_gptimer.h
new file mode 100644
index 0000000000..e56f1b8bf3
--- /dev/null
+++ b/include/hw/timer/grlib_gptimer.h
@@ -0,0 +1,32 @@
+/*
+ * QEMU GRLIB GPTimer
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright (c) 2024 AdaCore
+ *
+ * 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.
+ */
+
+#ifndef GRLIB_GPTIMER_H
+#define GRLIB_GPTIMER_H
+
+#define TYPE_GRLIB_GPTIMER "grlib-gptimer"
+
+#endif
diff --git a/include/hw/timer/hpet.h b/include/hw/timer/hpet.h
index f04c4d3238..d17a8d4319 100644
--- a/include/hw/timer/hpet.h
+++ b/include/hw/timer/hpet.h
@@ -78,6 +78,8 @@ extern struct hpet_fw_config hpet_cfg;
#define TYPE_HPET "hpet"
+#define HPET_INTCAP "hpet-intcap"
+
static inline bool hpet_find(void)
{
return object_resolve_path_type("", TYPE_HPET, NULL);
diff --git a/include/hw/timer/i8254.h b/include/hw/timer/i8254.h
index e75b4a5a08..8402caad30 100644
--- a/include/hw/timer/i8254.h
+++ b/include/hw/timer/i8254.h
@@ -28,6 +28,7 @@
#include "hw/qdev-properties.h"
#include "hw/isa/isa.h"
#include "qapi/error.h"
+#include "qom/object.h"
#define PIT_FREQ 1193182
@@ -39,12 +40,7 @@ typedef struct PITChannelInfo {
} PITChannelInfo;
#define TYPE_PIT_COMMON "pit-common"
-#define PIT_COMMON(obj) \
- OBJECT_CHECK(PITCommonState, (obj), TYPE_PIT_COMMON)
-#define PIT_COMMON_CLASS(klass) \
- OBJECT_CLASS_CHECK(PITCommonClass, (klass), TYPE_PIT_COMMON)
-#define PIT_COMMON_GET_CLASS(obj) \
- OBJECT_GET_CLASS(PITCommonClass, (obj), TYPE_PIT_COMMON)
+OBJECT_DECLARE_TYPE(PITCommonState, PITCommonClass, PIT_COMMON)
#define TYPE_I8254 "isa-pit"
#define TYPE_KVM_I8254 "kvm-pit"
@@ -60,7 +56,8 @@ static inline ISADevice *i8254_pit_init(ISABus *bus, int base, int isa_irq,
qdev_prop_set_uint32(dev, "iobase", base);
isa_realize_and_unref(d, bus, &error_fatal);
qdev_connect_gpio_out(dev, 0,
- isa_irq >= 0 ? isa_get_irq(d, isa_irq) : alt_irq);
+ isa_irq >= 0 ? isa_bus_get_irq(bus, isa_irq)
+ : alt_irq);
return d;
}
diff --git a/include/hw/timer/i8254_internal.h b/include/hw/timer/i8254_internal.h
index 3db462aecd..1761deb4cf 100644
--- a/include/hw/timer/i8254_internal.h
+++ b/include/hw/timer/i8254_internal.h
@@ -50,22 +50,22 @@ typedef struct PITChannelState {
uint32_t irq_disabled;
} PITChannelState;
-typedef struct PITCommonState {
+struct PITCommonState {
ISADevice dev;
MemoryRegion ioports;
uint32_t iobase;
PITChannelState channels[3];
-} PITCommonState;
+};
-typedef struct PITCommonClass {
- ISADeviceClass parent_class;
+struct PITCommonClass {
+ DeviceClass parent_class;
void (*set_channel_gate)(PITCommonState *s, PITChannelState *sc, int val);
void (*get_channel_info)(PITCommonState *s, PITChannelState *sc,
PITChannelInfo *info);
void (*pre_save)(PITCommonState *s);
void (*post_load)(PITCommonState *s);
-} PITCommonClass;
+};
int pit_get_out(PITChannelState *s, int64_t current_time);
int64_t pit_get_next_transition_time(PITChannelState *s, int64_t current_time);
diff --git a/include/hw/timer/ibex_timer.h b/include/hw/timer/ibex_timer.h
new file mode 100644
index 0000000000..41f5c82a92
--- /dev/null
+++ b/include/hw/timer/ibex_timer.h
@@ -0,0 +1,55 @@
+/*
+ * QEMU lowRISC Ibex Timer device
+ *
+ * Copyright (c) 2021 Western Digital
+ *
+ * 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.
+ */
+
+#ifndef HW_IBEX_TIMER_H
+#define HW_IBEX_TIMER_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_IBEX_TIMER "ibex-timer"
+OBJECT_DECLARE_SIMPLE_TYPE(IbexTimerState, IBEX_TIMER)
+
+struct IbexTimerState {
+ /* <private> */
+ SysBusDevice parent_obj;
+ uint64_t mtimecmp;
+ QEMUTimer *mtimer; /* Internal timer for M-mode interrupt */
+
+ /* <public> */
+ MemoryRegion mmio;
+
+ uint32_t timer_ctrl;
+ uint32_t timer_cfg0;
+ uint32_t timer_compare_lower0;
+ uint32_t timer_compare_upper0;
+ uint32_t timer_intr_enable;
+ uint32_t timer_intr_state;
+
+ uint32_t timebase_freq;
+
+ qemu_irq irq;
+
+ qemu_irq m_timer_irq;
+};
+#endif /* HW_IBEX_TIMER_H */
diff --git a/include/hw/timer/imx_epit.h b/include/hw/timer/imx_epit.h
index 0730ac35e6..79aff0cec2 100644
--- a/include/hw/timer/imx_epit.h
+++ b/include/hw/timer/imx_epit.h
@@ -32,6 +32,7 @@
#include "hw/sysbus.h"
#include "hw/ptimer.h"
#include "hw/misc/imx_ccm.h"
+#include "qom/object.h"
/*
* EPIT: Enhanced periodic interrupt timer
@@ -42,7 +43,7 @@
#define CR_OCIEN (1 << 2)
#define CR_RLD (1 << 3)
#define CR_PRESCALE_SHIFT (4)
-#define CR_PRESCALE_MASK (0xfff)
+#define CR_PRESCALE_BITS (12)
#define CR_SWR (1 << 16)
#define CR_IOVW (1 << 17)
#define CR_DBGEN (1 << 18)
@@ -50,14 +51,16 @@
#define CR_DOZEN (1 << 20)
#define CR_STOPEN (1 << 21)
#define CR_CLKSRC_SHIFT (24)
-#define CR_CLKSRC_MASK (0x3 << CR_CLKSRC_SHIFT)
+#define CR_CLKSRC_BITS (2)
+
+#define SR_OCIF (1 << 0)
#define EPIT_TIMER_MAX 0XFFFFFFFFUL
#define TYPE_IMX_EPIT "imx.epit"
-#define IMX_EPIT(obj) OBJECT_CHECK(IMXEPITState, (obj), TYPE_IMX_EPIT)
+OBJECT_DECLARE_SIMPLE_TYPE(IMXEPITState, IMX_EPIT)
-typedef struct IMXEPITState{
+struct IMXEPITState {
/*< private >*/
SysBusDevice parent_obj;
@@ -71,10 +74,8 @@ typedef struct IMXEPITState{
uint32_t sr;
uint32_t lr;
uint32_t cmp;
- uint32_t cnt;
- uint32_t freq;
qemu_irq irq;
-} IMXEPITState;
+};
#endif /* IMX_EPIT_H */
diff --git a/include/hw/timer/imx_gpt.h b/include/hw/timer/imx_gpt.h
index 20ccb327c4..5a1230da35 100644
--- a/include/hw/timer/imx_gpt.h
+++ b/include/hw/timer/imx_gpt.h
@@ -32,6 +32,7 @@
#include "hw/sysbus.h"
#include "hw/ptimer.h"
#include "hw/misc/imx_ccm.h"
+#include "qom/object.h"
/*
* GPT : General purpose timer
@@ -77,13 +78,16 @@
#define TYPE_IMX25_GPT "imx25.gpt"
#define TYPE_IMX31_GPT "imx31.gpt"
#define TYPE_IMX6_GPT "imx6.gpt"
+#define TYPE_IMX6UL_GPT "imx6ul.gpt"
#define TYPE_IMX7_GPT "imx7.gpt"
#define TYPE_IMX_GPT TYPE_IMX25_GPT
-#define IMX_GPT(obj) OBJECT_CHECK(IMXGPTState, (obj), TYPE_IMX_GPT)
+typedef struct IMXGPTState IMXGPTState;
+DECLARE_INSTANCE_CHECKER(IMXGPTState, IMX_GPT,
+ TYPE_IMX_GPT)
-typedef struct IMXGPTState{
+struct IMXGPTState {
/*< private >*/
SysBusDevice parent_obj;
@@ -111,6 +115,6 @@ typedef struct IMXGPTState{
qemu_irq irq;
const IMXClk *clocks;
-} IMXGPTState;
+};
#endif /* IMX_GPT_H */
diff --git a/include/hw/timer/mss-timer.h b/include/hw/timer/mss-timer.h
index e5a784b27e..da38512904 100644
--- a/include/hw/timer/mss-timer.h
+++ b/include/hw/timer/mss-timer.h
@@ -27,10 +27,10 @@
#include "hw/sysbus.h"
#include "hw/ptimer.h"
+#include "qom/object.h"
#define TYPE_MSS_TIMER "mss-timer"
-#define MSS_TIMER(obj) OBJECT_CHECK(MSSTimerState, \
- (obj), TYPE_MSS_TIMER)
+OBJECT_DECLARE_SIMPLE_TYPE(MSSTimerState, MSS_TIMER)
/*
* There are two 32-bit down counting timers.
@@ -52,12 +52,12 @@ struct Msf2Timer {
qemu_irq irq;
};
-typedef struct MSSTimerState {
+struct MSSTimerState {
SysBusDevice parent_obj;
MemoryRegion mmio;
uint32_t freq_hz;
struct Msf2Timer timers[NUM_TIMERS];
-} MSSTimerState;
+};
#endif /* HW_MSS_TIMER_H */
diff --git a/include/hw/timer/npcm7xx_timer.h b/include/hw/timer/npcm7xx_timer.h
new file mode 100644
index 0000000000..d45c051b56
--- /dev/null
+++ b/include/hw/timer/npcm7xx_timer.h
@@ -0,0 +1,113 @@
+/*
+ * Nuvoton NPCM7xx Timer Controller
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_TIMER_H
+#define NPCM7XX_TIMER_H
+
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+#include "qemu/timer.h"
+
+/* Each Timer Module (TIM) instance holds five 25 MHz timers. */
+#define NPCM7XX_TIMERS_PER_CTRL (5)
+
+/*
+ * Number of registers in our device state structure. Don't change this without
+ * incrementing the version_id in the vmstate.
+ */
+#define NPCM7XX_TIMER_NR_REGS (0x54 / sizeof(uint32_t))
+
+/* The basic watchdog timer period is 2^14 clock cycles. */
+#define NPCM7XX_WATCHDOG_BASETIME_SHIFT 14
+
+#define NPCM7XX_WATCHDOG_RESET_GPIO_OUT "npcm7xx-clk-watchdog-reset-gpio-out"
+
+typedef struct NPCM7xxTimerCtrlState NPCM7xxTimerCtrlState;
+
+/**
+ * struct NPCM7xxBaseTimer - Basic functionality that both regular timer and
+ * watchdog timer use.
+ * @qtimer: QEMU timer that notifies us on expiration.
+ * @expires_ns: Absolute virtual expiration time.
+ * @remaining_ns: Remaining time until expiration if timer is paused.
+ */
+typedef struct NPCM7xxBaseTimer {
+ QEMUTimer qtimer;
+ int64_t expires_ns;
+ int64_t remaining_ns;
+} NPCM7xxBaseTimer;
+
+/**
+ * struct NPCM7xxTimer - Individual timer state.
+ * @ctrl: The timer module that owns this timer.
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
+ * @base_timer: The basic timer functionality for this timer.
+ * @tcsr: The Timer Control and Status Register.
+ * @ticr: The Timer Initial Count Register.
+ */
+typedef struct NPCM7xxTimer {
+ NPCM7xxTimerCtrlState *ctrl;
+
+ qemu_irq irq;
+ NPCM7xxBaseTimer base_timer;
+
+ uint32_t tcsr;
+ uint32_t ticr;
+} NPCM7xxTimer;
+
+/**
+ * struct NPCM7xxWatchdogTimer - The watchdog timer state.
+ * @ctrl: The timer module that owns this timer.
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
+ * @reset_signal: The GPIO used to send a reset signal.
+ * @base_timer: The basic timer functionality for this timer.
+ * @wtcr: The Watchdog Timer Control Register.
+ */
+typedef struct NPCM7xxWatchdogTimer {
+ NPCM7xxTimerCtrlState *ctrl;
+
+ qemu_irq irq;
+ qemu_irq reset_signal;
+ NPCM7xxBaseTimer base_timer;
+
+ uint32_t wtcr;
+} NPCM7xxWatchdogTimer;
+
+/**
+ * struct NPCM7xxTimerCtrlState - Timer Module device state.
+ * @parent: System bus device.
+ * @iomem: Memory region through which registers are accessed.
+ * @index: The index of this timer module.
+ * @tisr: The Timer Interrupt Status Register.
+ * @timer: The five individual timers managed by this module.
+ * @watchdog_timer: The watchdog timer managed by this module.
+ */
+struct NPCM7xxTimerCtrlState {
+ SysBusDevice parent;
+
+ MemoryRegion iomem;
+
+ uint32_t tisr;
+
+ Clock *clock;
+ NPCM7xxTimer timer[NPCM7XX_TIMERS_PER_CTRL];
+ NPCM7xxWatchdogTimer watchdog_timer;
+};
+
+#define TYPE_NPCM7XX_TIMER "npcm7xx-timer"
+#define NPCM7XX_TIMER(obj) \
+ OBJECT_CHECK(NPCM7xxTimerCtrlState, (obj), TYPE_NPCM7XX_TIMER)
+
+#endif /* NPCM7XX_TIMER_H */
diff --git a/include/hw/timer/nrf51_timer.h b/include/hw/timer/nrf51_timer.h
index eb6815f21d..76827c11dc 100644
--- a/include/hw/timer/nrf51_timer.h
+++ b/include/hw/timer/nrf51_timer.h
@@ -15,8 +15,9 @@
#include "hw/sysbus.h"
#include "qemu/timer.h"
+#include "qom/object.h"
#define TYPE_NRF51_TIMER "nrf51_soc.timer"
-#define NRF51_TIMER(obj) OBJECT_CHECK(NRF51TimerState, (obj), TYPE_NRF51_TIMER)
+OBJECT_DECLARE_SIMPLE_TYPE(NRF51TimerState, NRF51_TIMER)
#define NRF51_TIMER_REG_COUNT 4
@@ -53,7 +54,7 @@
#define NRF51_TIMER_REG_CC0 0x540
#define NRF51_TIMER_REG_CC3 0x54C
-typedef struct NRF51TimerState {
+struct NRF51TimerState {
SysBusDevice parent_obj;
MemoryRegion iomem;
@@ -75,7 +76,7 @@ typedef struct NRF51TimerState {
uint32_t bitmode;
uint32_t prescaler;
-} NRF51TimerState;
+};
#endif
diff --git a/include/hw/timer/renesas_cmt.h b/include/hw/timer/renesas_cmt.h
index e28a15cb38..1c0b65c1d5 100644
--- a/include/hw/timer/renesas_cmt.h
+++ b/include/hw/timer/renesas_cmt.h
@@ -11,16 +11,19 @@
#include "qemu/timer.h"
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_RENESAS_CMT "renesas-cmt"
-#define RCMT(obj) OBJECT_CHECK(RCMTState, (obj), TYPE_RENESAS_CMT)
+typedef struct RCMTState RCMTState;
+DECLARE_INSTANCE_CHECKER(RCMTState, RCMT,
+ TYPE_RENESAS_CMT)
enum {
CMT_CH = 2,
CMT_NR_IRQ = 1 * CMT_CH
};
-typedef struct RCMTState {
+struct RCMTState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -35,6 +38,6 @@ typedef struct RCMTState {
int64_t tick[CMT_CH];
qemu_irq cmi[CMT_CH];
QEMUTimer timer[CMT_CH];
-} RCMTState;
+};
#endif
diff --git a/include/hw/timer/renesas_tmr.h b/include/hw/timer/renesas_tmr.h
index cf3baa7a28..caf7eec0dc 100644
--- a/include/hw/timer/renesas_tmr.h
+++ b/include/hw/timer/renesas_tmr.h
@@ -11,9 +11,12 @@
#include "qemu/timer.h"
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_RENESAS_TMR "renesas-tmr"
-#define RTMR(obj) OBJECT_CHECK(RTMRState, (obj), TYPE_RENESAS_TMR)
+typedef struct RTMRState RTMRState;
+DECLARE_INSTANCE_CHECKER(RTMRState, RTMR,
+ TYPE_RENESAS_TMR)
enum timer_event {
cmia = 0,
@@ -28,7 +31,7 @@ enum {
TMR_NR_IRQ = 3 * TMR_CH
};
-typedef struct RTMRState {
+struct RTMRState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
@@ -50,6 +53,6 @@ typedef struct RTMRState {
qemu_irq cmib[TMR_CH];
qemu_irq ovi[TMR_CH];
QEMUTimer timer[TMR_CH];
-} RTMRState;
+};
#endif
diff --git a/include/hw/timer/sifive_pwm.h b/include/hw/timer/sifive_pwm.h
new file mode 100644
index 0000000000..6a8cf7b29e
--- /dev/null
+++ b/include/hw/timer/sifive_pwm.h
@@ -0,0 +1,62 @@
+/*
+ * SiFive PWM
+ *
+ * Copyright (c) 2020 Western Digital
+ *
+ * Author: Alistair Francis <alistair.francis@wdc.com>
+ *
+ * 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.
+ */
+
+#ifndef HW_SIFIVE_PWM_H
+#define HW_SIFIVE_PWM_H
+
+#include "hw/sysbus.h"
+#include "qemu/timer.h"
+#include "qom/object.h"
+
+#define TYPE_SIFIVE_PWM "sifive-pwm"
+
+#define SIFIVE_PWM(obj) \
+ OBJECT_CHECK(SiFivePwmState, (obj), TYPE_SIFIVE_PWM)
+
+#define SIFIVE_PWM_CHANS 4
+#define SIFIVE_PWM_IRQS SIFIVE_PWM_CHANS
+
+typedef struct SiFivePwmState {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /* <public> */
+ MemoryRegion mmio;
+ QEMUTimer timer[SIFIVE_PWM_CHANS];
+ /*
+ * if en bit(s) set, is the number of ticks when pwmcount was 0
+ * if en bit(s) not set, is the number of ticks in pwmcount
+ */
+ uint64_t tick_offset;
+ uint64_t freq_hz;
+
+ uint32_t pwmcfg;
+ uint32_t pwmcmp[SIFIVE_PWM_CHANS];
+
+ qemu_irq irqs[SIFIVE_PWM_IRQS];
+} SiFivePwmState;
+
+#endif /* HW_SIFIVE_PWM_H */
diff --git a/include/hw/timer/sse-counter.h b/include/hw/timer/sse-counter.h
new file mode 100644
index 0000000000..b433e58d37
--- /dev/null
+++ b/include/hw/timer/sse-counter.h
@@ -0,0 +1,105 @@
+/*
+ * Arm SSE Subsystem System Counter
+ *
+ * Copyright (c) 2020 Linaro Limited
+ * Written by Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or
+ * (at your option) any later version.
+ */
+
+/*
+ * This is a model of the "System counter" which is documented in
+ * the Arm SSE-123 Example Subsystem Technical Reference Manual:
+ * https://developer.arm.com/documentation/101370/latest/
+ *
+ * QEMU interface:
+ * + Clock input "CLK": clock
+ * + sysbus MMIO region 0: the control register frame
+ * + sysbus MMIO region 1: the status register frame
+ *
+ * Consumers of the system counter's timestamp, such as the SSE
+ * System Timer device, can also use the APIs sse_counter_for_timestamp(),
+ * sse_counter_tick_to_time() and sse_counter_register_consumer() to
+ * interact with an instance of the System Counter. Generally the
+ * consumer device should have a QOM link property which the board
+ * code can set to the appropriate instance of the system counter.
+ */
+
+#ifndef SSE_COUNTER_H
+#define SSE_COUNTER_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+#include "qemu/notify.h"
+
+#define TYPE_SSE_COUNTER "sse-counter"
+OBJECT_DECLARE_SIMPLE_TYPE(SSECounter, SSE_COUNTER)
+
+struct SSECounter {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion control_mr;
+ MemoryRegion status_mr;
+ Clock *clk;
+ NotifierList notifier_list;
+
+ uint32_t cntcr;
+ uint32_t cntscr0;
+
+ /*
+ * These are used for handling clock frequency changes: they are a
+ * tuple of (QEMU_CLOCK_VIRTUAL timestamp, CNTCV at that time),
+ * taken when the clock frequency changes. sse_cntcv() needs them
+ * to calculate the current CNTCV.
+ */
+ uint64_t ns_then;
+ uint64_t ticks_then;
+};
+
+/*
+ * These functions are the interface by which a consumer of
+ * the system timestamp (such as the SSE system timer device)
+ * can communicate with the SSECounter.
+ */
+
+/**
+ * sse_counter_for_timestamp:
+ * @counter: SSECounter
+ * @ns: timestamp of QEMU_CLOCK_VIRTUAL in nanoseconds
+ *
+ * Returns the value of the timestamp counter at the specified
+ * point in time (assuming that no changes to scale factor, enable, etc
+ * happen in the meantime).
+ */
+uint64_t sse_counter_for_timestamp(SSECounter *counter, uint64_t ns);
+
+/**
+ * sse_counter_tick_to_time:
+ * @counter: SSECounter
+ * @tick: tick value
+ *
+ * Returns the time (a QEMU_CLOCK_VIRTUAL timestamp in nanoseconds)
+ * when the timestamp counter will reach the specified tick count.
+ * If the counter is not currently running, returns UINT64_MAX.
+ */
+uint64_t sse_counter_tick_to_time(SSECounter *counter, uint64_t tick);
+
+/**
+ * sse_counter_register_consumer:
+ * @counter: SSECounter
+ * @notifier: Notifier which is notified on counter changes
+ *
+ * Registers @notifier with the SSECounter. When the counter's
+ * configuration changes in a way that might invalidate information
+ * previously returned via sse_counter_for_timestamp() or
+ * sse_counter_tick_to_time(), the notifier will be called.
+ * Devices which consume the timestamp counter can use this as
+ * a cue to recalculate timer events.
+ */
+void sse_counter_register_consumer(SSECounter *counter, Notifier *notifier);
+
+#endif
diff --git a/include/hw/timer/sse-timer.h b/include/hw/timer/sse-timer.h
new file mode 100644
index 0000000000..265ad32400
--- /dev/null
+++ b/include/hw/timer/sse-timer.h
@@ -0,0 +1,54 @@
+/*
+ * Arm SSE Subsystem System Timer
+ *
+ * Copyright (c) 2020 Linaro Limited
+ * Written by Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or
+ * (at your option) any later version.
+ */
+
+/*
+ * This is a model of the "System timer" which is documented in
+ * the Arm SSE-123 Example Subsystem Technical Reference Manual:
+ * https://developer.arm.com/documentation/101370/latest/
+ *
+ * QEMU interface:
+ * + QOM property "counter": link property to be set to the
+ * TYPE_SSE_COUNTER timestamp counter device this timer runs off
+ * + sysbus MMIO region 0: the register bank
+ * + sysbus IRQ 0: timer interrupt
+ */
+
+#ifndef SSE_TIMER_H
+#define SSE_TIMER_H
+
+#include "hw/sysbus.h"
+#include "qemu/timer.h"
+#include "qom/object.h"
+#include "hw/timer/sse-counter.h"
+
+#define TYPE_SSE_TIMER "sse-timer"
+OBJECT_DECLARE_SIMPLE_TYPE(SSETimer, SSE_TIMER)
+
+struct SSETimer {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+ qemu_irq irq;
+ SSECounter *counter;
+ QEMUTimer timer;
+ Notifier counter_notifier;
+
+ uint32_t cntfrq;
+ uint32_t cntp_ctl;
+ uint64_t cntp_cval;
+ uint64_t cntp_aival;
+ uint32_t cntp_aival_ctl;
+ uint32_t cntp_aival_reload;
+};
+
+#endif
diff --git a/include/hw/timer/stellaris-gptm.h b/include/hw/timer/stellaris-gptm.h
new file mode 100644
index 0000000000..fde1fc6f0c
--- /dev/null
+++ b/include/hw/timer/stellaris-gptm.h
@@ -0,0 +1,51 @@
+/*
+ * Luminary Micro Stellaris General Purpose Timer Module
+ *
+ * Copyright (c) 2006 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the GPL.
+ */
+
+#ifndef HW_TIMER_STELLARIS_GPTM_H
+#define HW_TIMER_STELLARIS_GPTM_H
+
+#include "qom/object.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "hw/clock.h"
+
+#define TYPE_STELLARIS_GPTM "stellaris-gptm"
+OBJECT_DECLARE_SIMPLE_TYPE(gptm_state, STELLARIS_GPTM)
+
+/*
+ * QEMU interface:
+ * + sysbus MMIO region 0: register bank
+ * + sysbus IRQ 0: timer interrupt
+ * + unnamed GPIO output 0: trigger output for the ADC
+ * + Clock input "clk": the 32-bit countdown timer runs at this speed
+ */
+struct gptm_state {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ uint32_t config;
+ uint32_t mode[2];
+ uint32_t control;
+ uint32_t state;
+ uint32_t mask;
+ uint32_t load[2];
+ uint32_t match[2];
+ uint32_t prescale[2];
+ uint32_t match_prescale[2];
+ uint32_t rtc;
+ int64_t tick[2];
+ struct gptm_state *opaque[2];
+ QEMUTimer *timer[2];
+ /* The timers have an alternate output used to trigger the ADC. */
+ qemu_irq trigger;
+ qemu_irq irq;
+ Clock *clk;
+};
+
+#endif
diff --git a/include/hw/timer/stm32f2xx_timer.h b/include/hw/timer/stm32f2xx_timer.h
index a96bc08b1b..90f40f1746 100644
--- a/include/hw/timer/stm32f2xx_timer.h
+++ b/include/hw/timer/stm32f2xx_timer.h
@@ -27,6 +27,7 @@
#include "hw/sysbus.h"
#include "qemu/timer.h"
+#include "qom/object.h"
#define TIM_CR1 0x00
#define TIM_CR2 0x04
@@ -61,10 +62,11 @@
#define TIM_DIER_UIE 1
#define TYPE_STM32F2XX_TIMER "stm32f2xx-timer"
-#define STM32F2XXTIMER(obj) OBJECT_CHECK(STM32F2XXTimerState, \
- (obj), TYPE_STM32F2XX_TIMER)
+typedef struct STM32F2XXTimerState STM32F2XXTimerState;
+DECLARE_INSTANCE_CHECKER(STM32F2XXTimerState, STM32F2XXTIMER,
+ TYPE_STM32F2XX_TIMER)
-typedef struct STM32F2XXTimerState {
+struct STM32F2XXTimerState {
/* <private> */
SysBusDevice parent_obj;
@@ -95,6 +97,6 @@ typedef struct STM32F2XXTimerState {
uint32_t tim_dcr;
uint32_t tim_dmar;
uint32_t tim_or;
-} STM32F2XXTimerState;
+};
#endif /* HW_STM32F2XX_TIMER_H */
diff --git a/include/hw/tricore/tc27x_soc.h b/include/hw/tricore/tc27x_soc.h
new file mode 100644
index 0000000000..dd3a7485c8
--- /dev/null
+++ b/include/hw/tricore/tc27x_soc.h
@@ -0,0 +1,129 @@
+/*
+ * Infineon tc27x SoC System emulation.
+ *
+ * Copyright (c) 2020 Andreas Konopik <andreas.konopik@efs-auto.de>
+ * Copyright (c) 2020 David Brenken <david.brenken@efs-auto.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TC27X_SOC_H
+#define TC27X_SOC_H
+
+#include "hw/sysbus.h"
+#include "target/tricore/cpu.h"
+#include "qom/object.h"
+
+#define TYPE_TC27X_SOC ("tc27x-soc")
+OBJECT_DECLARE_TYPE(TC27XSoCState, TC27XSoCClass, TC27X_SOC)
+
+typedef struct TC27XSoCCPUMemState {
+
+ MemoryRegion dspr;
+ MemoryRegion pspr;
+
+ MemoryRegion dcache;
+ MemoryRegion dtag;
+ MemoryRegion pcache;
+ MemoryRegion ptag;
+
+} TC27XSoCCPUMemState;
+
+typedef struct TC27XSoCFlashMemState {
+
+ MemoryRegion pflash0_c;
+ MemoryRegion pflash1_c;
+ MemoryRegion pflash0_u;
+ MemoryRegion pflash1_u;
+ MemoryRegion dflash0;
+ MemoryRegion dflash1;
+ MemoryRegion olda_c;
+ MemoryRegion olda_u;
+ MemoryRegion brom_c;
+ MemoryRegion brom_u;
+ MemoryRegion lmuram_c;
+ MemoryRegion lmuram_u;
+ MemoryRegion emem_c;
+ MemoryRegion emem_u;
+
+} TC27XSoCFlashMemState;
+
+typedef struct TC27XSoCState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ TriCoreCPU cpu;
+
+ MemoryRegion dsprX;
+ MemoryRegion psprX;
+
+ TC27XSoCCPUMemState cpu0mem;
+ TC27XSoCCPUMemState cpu1mem;
+ TC27XSoCCPUMemState cpu2mem;
+
+ TC27XSoCFlashMemState flashmem;
+
+} TC27XSoCState;
+
+typedef struct MemmapEntry {
+ hwaddr base;
+ hwaddr size;
+} MemmapEntry;
+
+typedef struct TC27XSoCClass {
+ DeviceClass parent_class;
+
+ const char *name;
+ const char *cpu_type;
+ const MemmapEntry *memmap;
+ uint32_t num_cpus;
+} TC27XSoCClass;
+
+enum {
+ TC27XD_DSPR2,
+ TC27XD_DCACHE2,
+ TC27XD_DTAG2,
+ TC27XD_PSPR2,
+ TC27XD_PCACHE2,
+ TC27XD_PTAG2,
+ TC27XD_DSPR1,
+ TC27XD_DCACHE1,
+ TC27XD_DTAG1,
+ TC27XD_PSPR1,
+ TC27XD_PCACHE1,
+ TC27XD_PTAG1,
+ TC27XD_DSPR0,
+ TC27XD_PSPR0,
+ TC27XD_PCACHE0,
+ TC27XD_PTAG0,
+ TC27XD_PFLASH0_C,
+ TC27XD_PFLASH1_C,
+ TC27XD_OLDA_C,
+ TC27XD_BROM_C,
+ TC27XD_LMURAM_C,
+ TC27XD_EMEM_C,
+ TC27XD_PFLASH0_U,
+ TC27XD_PFLASH1_U,
+ TC27XD_DFLASH0,
+ TC27XD_DFLASH1,
+ TC27XD_OLDA_U,
+ TC27XD_BROM_U,
+ TC27XD_LMURAM_U,
+ TC27XD_EMEM_U,
+ TC27XD_PSPRX,
+ TC27XD_DSPRX,
+};
+
+#endif
diff --git a/include/hw/tricore/triboard.h b/include/hw/tricore/triboard.h
new file mode 100644
index 0000000000..4fdd2d7d97
--- /dev/null
+++ b/include/hw/tricore/triboard.h
@@ -0,0 +1,48 @@
+/*
+ * Infineon TriBoard System emulation.
+ *
+ * Copyright (c) 2020 Andreas Konopik <andreas.konopik@efs-auto.de>
+ * Copyright (c) 2020 David Brenken <david.brenken@efs-auto.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qapi/error.h"
+#include "hw/boards.h"
+#include "sysemu/sysemu.h"
+#include "exec/address-spaces.h"
+#include "qom/object.h"
+
+#include "hw/tricore/tc27x_soc.h"
+
+#define TYPE_TRIBOARD_MACHINE MACHINE_TYPE_NAME("triboard")
+typedef struct TriBoardMachineState TriBoardMachineState;
+typedef struct TriBoardMachineClass TriBoardMachineClass;
+DECLARE_OBJ_CHECKERS(TriBoardMachineState, TriBoardMachineClass,
+ TRIBOARD_MACHINE, TYPE_TRIBOARD_MACHINE)
+
+
+struct TriBoardMachineState {
+ MachineState parent;
+
+ TC27XSoCState tc27x_soc;
+};
+
+struct TriBoardMachineClass {
+ MachineClass parent_obj;
+
+ const char *name;
+ const char *desc;
+ const char *soc_name;
+};
diff --git a/include/hw/tricore/tricore_testdevice.h b/include/hw/tricore/tricore_testdevice.h
new file mode 100644
index 0000000000..2c57b62f22
--- /dev/null
+++ b/include/hw/tricore/tricore_testdevice.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2018-2021 Bastian Koppelmann Paderborn University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_TRICORE_TESTDEVICE_H
+#define HW_TRICORE_TESTDEVICE_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_TRICORE_TESTDEVICE "tricore_testdevice"
+#define TRICORE_TESTDEVICE(obj) \
+ OBJECT_CHECK(TriCoreTestDeviceState, (obj), TYPE_TRICORE_TESTDEVICE)
+
+typedef struct {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+} TriCoreTestDeviceState;
+
+#endif
diff --git a/include/hw/unicore32/puv3.h b/include/hw/unicore32/puv3.h
deleted file mode 100644
index f587a1f622..0000000000
--- a/include/hw/unicore32/puv3.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Misc PKUnity SoC declarations
- *
- * Copyright (C) 2010-2012 Guan Xuetao
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation, or any later version.
- * See the COPYING file in the top-level directory.
- */
-
-#ifndef QEMU_HW_PUV3_H
-#define QEMU_HW_PUV3_H
-
-#define PUV3_REGS_OFFSET (0x1000) /* 4K is reasonable */
-
-/* Hardware interrupts */
-#define PUV3_IRQS_NR (32)
-
-#define PUV3_IRQS_GPIOLOW0 (0)
-#define PUV3_IRQS_GPIOLOW1 (1)
-#define PUV3_IRQS_GPIOLOW2 (2)
-#define PUV3_IRQS_GPIOLOW3 (3)
-#define PUV3_IRQS_GPIOLOW4 (4)
-#define PUV3_IRQS_GPIOLOW5 (5)
-#define PUV3_IRQS_GPIOLOW6 (6)
-#define PUV3_IRQS_GPIOLOW7 (7)
-#define PUV3_IRQS_GPIOHIGH (8)
-#define PUV3_IRQS_PS2_KBD (22)
-#define PUV3_IRQS_PS2_AUX (23)
-#define PUV3_IRQS_OST0 (26)
-
-/* All puv3_*.c use DPRINTF for debug. */
-#ifdef DEBUG_PUV3
-#define DPRINTF(fmt, ...) printf("%s: " fmt , __func__, ## __VA_ARGS__)
-#else
-#define DPRINTF(fmt, ...) do {} while (0)
-#endif
-
-#endif /* QEMU_HW_PUV3_H */
diff --git a/include/hw/usb.h b/include/hw/usb.h
index e29a37635b..d46d96779a 100644
--- a/include/hw/usb.h
+++ b/include/hw/usb.h
@@ -29,6 +29,8 @@
#include "hw/qdev-core.h"
#include "qemu/iov.h"
#include "qemu/queue.h"
+#include "qom/object.h"
+#include "qapi/error.h"
/* Constants related to the USB / PCI interaction */
#define USB_SBRN 0x60 /* Serial Bus Release Number Register */
@@ -65,42 +67,42 @@
//#define USB_STATE_POWERED 2
#define USB_STATE_DEFAULT 3
//#define USB_STATE_ADDRESS 4
-//#define USB_STATE_CONFIGURED 5
+//#define USB_STATE_CONFIGURED 5
#define USB_STATE_SUSPENDED 6
-#define USB_CLASS_AUDIO 1
-#define USB_CLASS_COMM 2
-#define USB_CLASS_HID 3
-#define USB_CLASS_PHYSICAL 5
-#define USB_CLASS_STILL_IMAGE 6
-#define USB_CLASS_PRINTER 7
-#define USB_CLASS_MASS_STORAGE 8
-#define USB_CLASS_HUB 9
-#define USB_CLASS_CDC_DATA 0x0a
-#define USB_CLASS_CSCID 0x0b
-#define USB_CLASS_CONTENT_SEC 0x0d
-#define USB_CLASS_APP_SPEC 0xfe
-#define USB_CLASS_VENDOR_SPEC 0xff
+#define USB_CLASS_AUDIO 1
+#define USB_CLASS_COMM 2
+#define USB_CLASS_HID 3
+#define USB_CLASS_PHYSICAL 5
+#define USB_CLASS_STILL_IMAGE 6
+#define USB_CLASS_PRINTER 7
+#define USB_CLASS_MASS_STORAGE 8
+#define USB_CLASS_HUB 9
+#define USB_CLASS_CDC_DATA 0x0a
+#define USB_CLASS_CSCID 0x0b
+#define USB_CLASS_CONTENT_SEC 0x0d
+#define USB_CLASS_APP_SPEC 0xfe
+#define USB_CLASS_VENDOR_SPEC 0xff
#define USB_SUBCLASS_UNDEFINED 0
#define USB_SUBCLASS_AUDIO_CONTROL 1
#define USB_SUBCLASS_AUDIO_STREAMING 2
#define USB_SUBCLASS_AUDIO_MIDISTREAMING 3
-#define USB_DIR_OUT 0
-#define USB_DIR_IN 0x80
+#define USB_DIR_OUT 0
+#define USB_DIR_IN 0x80
-#define USB_TYPE_MASK (0x03 << 5)
-#define USB_TYPE_STANDARD (0x00 << 5)
-#define USB_TYPE_CLASS (0x01 << 5)
-#define USB_TYPE_VENDOR (0x02 << 5)
-#define USB_TYPE_RESERVED (0x03 << 5)
+#define USB_TYPE_MASK (0x03 << 5)
+#define USB_TYPE_STANDARD (0x00 << 5)
+#define USB_TYPE_CLASS (0x01 << 5)
+#define USB_TYPE_VENDOR (0x02 << 5)
+#define USB_TYPE_RESERVED (0x03 << 5)
-#define USB_RECIP_MASK 0x1f
-#define USB_RECIP_DEVICE 0x00
-#define USB_RECIP_INTERFACE 0x01
-#define USB_RECIP_ENDPOINT 0x02
-#define USB_RECIP_OTHER 0x03
+#define USB_RECIP_MASK 0x1f
+#define USB_RECIP_DEVICE 0x00
+#define USB_RECIP_INTERFACE 0x01
+#define USB_RECIP_ENDPOINT 0x02
+#define USB_RECIP_OTHER 0x03
#define DeviceRequest ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8)
#define DeviceOutRequest ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8)
@@ -125,28 +127,28 @@
#define EndpointOutRequest \
((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8)
-#define USB_REQ_GET_STATUS 0x00
-#define USB_REQ_CLEAR_FEATURE 0x01
-#define USB_REQ_SET_FEATURE 0x03
-#define USB_REQ_SET_ADDRESS 0x05
-#define USB_REQ_GET_DESCRIPTOR 0x06
-#define USB_REQ_SET_DESCRIPTOR 0x07
-#define USB_REQ_GET_CONFIGURATION 0x08
-#define USB_REQ_SET_CONFIGURATION 0x09
-#define USB_REQ_GET_INTERFACE 0x0A
-#define USB_REQ_SET_INTERFACE 0x0B
-#define USB_REQ_SYNCH_FRAME 0x0C
+#define USB_REQ_GET_STATUS 0x00
+#define USB_REQ_CLEAR_FEATURE 0x01
+#define USB_REQ_SET_FEATURE 0x03
+#define USB_REQ_SET_ADDRESS 0x05
+#define USB_REQ_GET_DESCRIPTOR 0x06
+#define USB_REQ_SET_DESCRIPTOR 0x07
+#define USB_REQ_GET_CONFIGURATION 0x08
+#define USB_REQ_SET_CONFIGURATION 0x09
+#define USB_REQ_GET_INTERFACE 0x0A
+#define USB_REQ_SET_INTERFACE 0x0B
+#define USB_REQ_SYNCH_FRAME 0x0C
#define USB_REQ_SET_SEL 0x30
#define USB_REQ_SET_ISOCH_DELAY 0x31
-#define USB_DEVICE_SELF_POWERED 0
-#define USB_DEVICE_REMOTE_WAKEUP 1
+#define USB_DEVICE_SELF_POWERED 0
+#define USB_DEVICE_REMOTE_WAKEUP 1
-#define USB_DT_DEVICE 0x01
-#define USB_DT_CONFIG 0x02
-#define USB_DT_STRING 0x03
-#define USB_DT_INTERFACE 0x04
-#define USB_DT_ENDPOINT 0x05
+#define USB_DT_DEVICE 0x01
+#define USB_DT_CONFIG 0x02
+#define USB_DT_STRING 0x03
+#define USB_DT_INTERFACE 0x04
+#define USB_DT_ENDPOINT 0x05
#define USB_DT_DEVICE_QUALIFIER 0x06
#define USB_DT_OTHER_SPEED_CONFIG 0x07
#define USB_DT_DEBUG 0x0A
@@ -166,15 +168,14 @@
#define USB_CFG_ATT_WAKEUP (1 << 5)
#define USB_CFG_ATT_BATTERY (1 << 4)
-#define USB_ENDPOINT_XFER_CONTROL 0
-#define USB_ENDPOINT_XFER_ISOC 1
-#define USB_ENDPOINT_XFER_BULK 2
-#define USB_ENDPOINT_XFER_INT 3
+#define USB_ENDPOINT_XFER_CONTROL 0
+#define USB_ENDPOINT_XFER_ISOC 1
+#define USB_ENDPOINT_XFER_BULK 2
+#define USB_ENDPOINT_XFER_INT 3
#define USB_ENDPOINT_XFER_INVALID 255
#define USB_INTERFACE_INVALID 255
-typedef struct USBBus USBBus;
typedef struct USBBusOps USBBusOps;
typedef struct USBPort USBPort;
typedef struct USBDevice USBDevice;
@@ -216,10 +217,10 @@ struct USBEndpoint {
};
enum USBDeviceFlags {
- USB_DEV_FLAG_FULL_PATH,
USB_DEV_FLAG_IS_HOST,
USB_DEV_FLAG_MSOS_DESC_ENABLE,
USB_DEV_FLAG_MSOS_DESC_IN_USE,
+ USB_DEV_FLAG_IS_SCSI_STORAGE,
};
/* definition of a USB device */
@@ -231,6 +232,9 @@ struct USBDevice {
void *opaque;
uint32_t flags;
+ char *pcap_filename;
+ FILE *pcap;
+
/* Actual connected speed */
int speed;
/* Supported speeds, not in info because it may be variable (hostdevs) */
@@ -264,17 +268,12 @@ struct USBDevice {
};
#define TYPE_USB_DEVICE "usb-device"
-#define USB_DEVICE(obj) \
- OBJECT_CHECK(USBDevice, (obj), TYPE_USB_DEVICE)
-#define USB_DEVICE_CLASS(klass) \
- OBJECT_CLASS_CHECK(USBDeviceClass, (klass), TYPE_USB_DEVICE)
-#define USB_DEVICE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(USBDeviceClass, (obj), TYPE_USB_DEVICE)
+OBJECT_DECLARE_TYPE(USBDevice, USBDeviceClass, USB_DEVICE)
typedef void (*USBDeviceRealize)(USBDevice *dev, Error **errp);
typedef void (*USBDeviceUnrealize)(USBDevice *dev);
-typedef struct USBDeviceClass {
+struct USBDeviceClass {
DeviceClass parent_class;
USBDeviceRealize realize;
@@ -346,7 +345,7 @@ typedef struct USBDeviceClass {
const char *product_desc;
const USBDesc *usb_desc;
bool attached_settable;
-} USBDeviceClass;
+};
typedef struct USBPortOps {
void (*attach)(USBPort *port);
@@ -468,7 +467,6 @@ void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p);
/* usb-linux.c */
void hmp_info_usbhost(Monitor *mon, const QDict *qdict);
-bool usb_host_dev_is_scsi_storage(USBDevice *usbdev);
/* usb ports of the VM */
@@ -477,7 +475,7 @@ bool usb_host_dev_is_scsi_storage(USBDevice *usbdev);
/* usb-bus.c */
#define TYPE_USB_BUS "usb-bus"
-#define USB_BUS(obj) OBJECT_CHECK(USBBus, (obj), TYPE_USB_BUS)
+OBJECT_DECLARE_SIMPLE_TYPE(USBBus, USB_BUS)
struct USBBus {
BusState qbus;
@@ -500,12 +498,8 @@ struct USBBusOps {
void usb_bus_new(USBBus *bus, size_t bus_size,
USBBusOps *ops, DeviceState *host);
void usb_bus_release(USBBus *bus);
-USBBus *usb_bus_find(int busnr);
void usb_legacy_register(const char *typename, const char *usbdevice_name,
- USBDevice *(*usbdevice_init)(const char *params));
-USBDevice *usb_new(const char *name);
-bool usb_realize_and_unref(USBDevice *dev, USBBus *bus, Error **errp);
-USBDevice *usb_create_simple(USBBus *bus, const char *name);
+ USBDevice *(*usbdevice_init)(void));
USBDevice *usbdevice_create(const char *cmdline);
void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
USBPortOps *ops, int speedmask);
@@ -564,15 +558,48 @@ const char *usb_device_get_product_desc(USBDevice *dev);
const USBDesc *usb_device_get_usb_desc(USBDevice *dev);
+static inline bool usb_device_is_scsi_storage(USBDevice *dev)
+{
+ return dev->flags & (1 << USB_DEV_FLAG_IS_SCSI_STORAGE);
+}
+
/* quirks.c */
/* In bulk endpoints are streaming data sources (iow behave like isoc eps) */
-#define USB_QUIRK_BUFFER_BULK_IN 0x01
+#define USB_QUIRK_BUFFER_BULK_IN 0x01
/* Bulk pkts in FTDI format, need special handling when combining packets */
-#define USB_QUIRK_IS_FTDI 0x02
+#define USB_QUIRK_IS_FTDI 0x02
int usb_get_quirks(uint16_t vendor_id, uint16_t product_id,
uint8_t interface_class, uint8_t interface_subclass,
uint8_t interface_protocol);
+/* pcap.c */
+void usb_pcap_init(FILE *fp);
+void usb_pcap_ctrl(USBPacket *p, bool setup);
+void usb_pcap_data(USBPacket *p, bool setup);
+
+static inline USBDevice *usb_new(const char *name)
+{
+ return USB_DEVICE(qdev_new(name));
+}
+
+static inline USBDevice *usb_try_new(const char *name)
+{
+ return USB_DEVICE(qdev_try_new(name));
+}
+
+static inline bool usb_realize_and_unref(USBDevice *dev, USBBus *bus, Error **errp)
+{
+ return qdev_realize_and_unref(&dev->qdev, &bus->qbus, errp);
+}
+
+static inline USBDevice *usb_create_simple(USBBus *bus, const char *name)
+{
+ USBDevice *dev = usb_new(name);
+
+ usb_realize_and_unref(dev, bus, &error_abort);
+ return dev;
+}
+
#endif
diff --git a/include/hw/usb/chipidea.h b/include/hw/usb/chipidea.h
index 1ec2e9dbda..fe4113ee01 100644
--- a/include/hw/usb/chipidea.h
+++ b/include/hw/usb/chipidea.h
@@ -2,15 +2,16 @@
#define CHIPIDEA_H
#include "hw/usb/hcd-ehci.h"
+#include "qom/object.h"
-typedef struct ChipideaState {
+struct ChipideaState {
/*< private >*/
EHCISysBusState parent_obj;
MemoryRegion iomem[3];
-} ChipideaState;
+};
#define TYPE_CHIPIDEA "usb-chipidea"
-#define CHIPIDEA(obj) OBJECT_CHECK(ChipideaState, (obj), TYPE_CHIPIDEA)
+OBJECT_DECLARE_SIMPLE_TYPE(ChipideaState, CHIPIDEA)
#endif /* CHIPIDEA_H */
diff --git a/include/hw/usb/dwc2-regs.h b/include/hw/usb/dwc2-regs.h
index 40af23a0ba..0bf3f2aa17 100644
--- a/include/hw/usb/dwc2-regs.h
+++ b/include/hw/usb/dwc2-regs.h
@@ -39,791 +39,791 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __DWC2_HW_H__
-#define __DWC2_HW_H__
-
-#define HSOTG_REG(x) (x)
-
-#define GOTGCTL HSOTG_REG(0x000)
-#define GOTGCTL_CHIRPEN BIT(27)
-#define GOTGCTL_MULT_VALID_BC_MASK (0x1f << 22)
-#define GOTGCTL_MULT_VALID_BC_SHIFT 22
-#define GOTGCTL_OTGVER BIT(20)
-#define GOTGCTL_BSESVLD BIT(19)
-#define GOTGCTL_ASESVLD BIT(18)
-#define GOTGCTL_DBNC_SHORT BIT(17)
-#define GOTGCTL_CONID_B BIT(16)
-#define GOTGCTL_DBNCE_FLTR_BYPASS BIT(15)
-#define GOTGCTL_DEVHNPEN BIT(11)
-#define GOTGCTL_HSTSETHNPEN BIT(10)
-#define GOTGCTL_HNPREQ BIT(9)
-#define GOTGCTL_HSTNEGSCS BIT(8)
-#define GOTGCTL_SESREQ BIT(1)
-#define GOTGCTL_SESREQSCS BIT(0)
-
-#define GOTGINT HSOTG_REG(0x004)
-#define GOTGINT_DBNCE_DONE BIT(19)
-#define GOTGINT_A_DEV_TOUT_CHG BIT(18)
-#define GOTGINT_HST_NEG_DET BIT(17)
-#define GOTGINT_HST_NEG_SUC_STS_CHNG BIT(9)
-#define GOTGINT_SES_REQ_SUC_STS_CHNG BIT(8)
-#define GOTGINT_SES_END_DET BIT(2)
-
-#define GAHBCFG HSOTG_REG(0x008)
-#define GAHBCFG_AHB_SINGLE BIT(23)
-#define GAHBCFG_NOTI_ALL_DMA_WRIT BIT(22)
-#define GAHBCFG_REM_MEM_SUPP BIT(21)
-#define GAHBCFG_P_TXF_EMP_LVL BIT(8)
-#define GAHBCFG_NP_TXF_EMP_LVL BIT(7)
-#define GAHBCFG_DMA_EN BIT(5)
-#define GAHBCFG_HBSTLEN_MASK (0xf << 1)
-#define GAHBCFG_HBSTLEN_SHIFT 1
-#define GAHBCFG_HBSTLEN_SINGLE 0
-#define GAHBCFG_HBSTLEN_INCR 1
-#define GAHBCFG_HBSTLEN_INCR4 3
-#define GAHBCFG_HBSTLEN_INCR8 5
-#define GAHBCFG_HBSTLEN_INCR16 7
-#define GAHBCFG_GLBL_INTR_EN BIT(0)
-#define GAHBCFG_CTRL_MASK (GAHBCFG_P_TXF_EMP_LVL | \
- GAHBCFG_NP_TXF_EMP_LVL | \
- GAHBCFG_DMA_EN | \
- GAHBCFG_GLBL_INTR_EN)
-
-#define GUSBCFG HSOTG_REG(0x00C)
-#define GUSBCFG_FORCEDEVMODE BIT(30)
-#define GUSBCFG_FORCEHOSTMODE BIT(29)
-#define GUSBCFG_TXENDDELAY BIT(28)
-#define GUSBCFG_ICTRAFFICPULLREMOVE BIT(27)
-#define GUSBCFG_ICUSBCAP BIT(26)
-#define GUSBCFG_ULPI_INT_PROT_DIS BIT(25)
-#define GUSBCFG_INDICATORPASSTHROUGH BIT(24)
-#define GUSBCFG_INDICATORCOMPLEMENT BIT(23)
-#define GUSBCFG_TERMSELDLPULSE BIT(22)
-#define GUSBCFG_ULPI_INT_VBUS_IND BIT(21)
-#define GUSBCFG_ULPI_EXT_VBUS_DRV BIT(20)
-#define GUSBCFG_ULPI_CLK_SUSP_M BIT(19)
-#define GUSBCFG_ULPI_AUTO_RES BIT(18)
-#define GUSBCFG_ULPI_FS_LS BIT(17)
-#define GUSBCFG_OTG_UTMI_FS_SEL BIT(16)
-#define GUSBCFG_PHY_LP_CLK_SEL BIT(15)
-#define GUSBCFG_USBTRDTIM_MASK (0xf << 10)
-#define GUSBCFG_USBTRDTIM_SHIFT 10
-#define GUSBCFG_HNPCAP BIT(9)
-#define GUSBCFG_SRPCAP BIT(8)
-#define GUSBCFG_DDRSEL BIT(7)
-#define GUSBCFG_PHYSEL BIT(6)
-#define GUSBCFG_FSINTF BIT(5)
-#define GUSBCFG_ULPI_UTMI_SEL BIT(4)
-#define GUSBCFG_PHYIF16 BIT(3)
-#define GUSBCFG_PHYIF8 (0 << 3)
-#define GUSBCFG_TOUTCAL_MASK (0x7 << 0)
-#define GUSBCFG_TOUTCAL_SHIFT 0
-#define GUSBCFG_TOUTCAL_LIMIT 0x7
-#define GUSBCFG_TOUTCAL(_x) ((_x) << 0)
-
-#define GRSTCTL HSOTG_REG(0x010)
-#define GRSTCTL_AHBIDLE BIT(31)
-#define GRSTCTL_DMAREQ BIT(30)
-#define GRSTCTL_TXFNUM_MASK (0x1f << 6)
-#define GRSTCTL_TXFNUM_SHIFT 6
-#define GRSTCTL_TXFNUM_LIMIT 0x1f
-#define GRSTCTL_TXFNUM(_x) ((_x) << 6)
-#define GRSTCTL_TXFFLSH BIT(5)
-#define GRSTCTL_RXFFLSH BIT(4)
-#define GRSTCTL_IN_TKNQ_FLSH BIT(3)
-#define GRSTCTL_FRMCNTRRST BIT(2)
-#define GRSTCTL_HSFTRST BIT(1)
-#define GRSTCTL_CSFTRST BIT(0)
-
-#define GINTSTS HSOTG_REG(0x014)
-#define GINTMSK HSOTG_REG(0x018)
-#define GINTSTS_WKUPINT BIT(31)
-#define GINTSTS_SESSREQINT BIT(30)
-#define GINTSTS_DISCONNINT BIT(29)
-#define GINTSTS_CONIDSTSCHNG BIT(28)
-#define GINTSTS_LPMTRANRCVD BIT(27)
-#define GINTSTS_PTXFEMP BIT(26)
-#define GINTSTS_HCHINT BIT(25)
-#define GINTSTS_PRTINT BIT(24)
-#define GINTSTS_RESETDET BIT(23)
-#define GINTSTS_FET_SUSP BIT(22)
-#define GINTSTS_INCOMPL_IP BIT(21)
-#define GINTSTS_INCOMPL_SOOUT BIT(21)
-#define GINTSTS_INCOMPL_SOIN BIT(20)
-#define GINTSTS_OEPINT BIT(19)
-#define GINTSTS_IEPINT BIT(18)
-#define GINTSTS_EPMIS BIT(17)
-#define GINTSTS_RESTOREDONE BIT(16)
-#define GINTSTS_EOPF BIT(15)
-#define GINTSTS_ISOUTDROP BIT(14)
-#define GINTSTS_ENUMDONE BIT(13)
-#define GINTSTS_USBRST BIT(12)
-#define GINTSTS_USBSUSP BIT(11)
-#define GINTSTS_ERLYSUSP BIT(10)
-#define GINTSTS_I2CINT BIT(9)
-#define GINTSTS_ULPI_CK_INT BIT(8)
-#define GINTSTS_GOUTNAKEFF BIT(7)
-#define GINTSTS_GINNAKEFF BIT(6)
-#define GINTSTS_NPTXFEMP BIT(5)
-#define GINTSTS_RXFLVL BIT(4)
-#define GINTSTS_SOF BIT(3)
-#define GINTSTS_OTGINT BIT(2)
-#define GINTSTS_MODEMIS BIT(1)
-#define GINTSTS_CURMODE_HOST BIT(0)
-
-#define GRXSTSR HSOTG_REG(0x01C)
-#define GRXSTSP HSOTG_REG(0x020)
-#define GRXSTS_FN_MASK (0x7f << 25)
-#define GRXSTS_FN_SHIFT 25
-#define GRXSTS_PKTSTS_MASK (0xf << 17)
-#define GRXSTS_PKTSTS_SHIFT 17
-#define GRXSTS_PKTSTS_GLOBALOUTNAK 1
-#define GRXSTS_PKTSTS_OUTRX 2
-#define GRXSTS_PKTSTS_HCHIN 2
-#define GRXSTS_PKTSTS_OUTDONE 3
-#define GRXSTS_PKTSTS_HCHIN_XFER_COMP 3
-#define GRXSTS_PKTSTS_SETUPDONE 4
-#define GRXSTS_PKTSTS_DATATOGGLEERR 5
-#define GRXSTS_PKTSTS_SETUPRX 6
-#define GRXSTS_PKTSTS_HCHHALTED 7
-#define GRXSTS_HCHNUM_MASK (0xf << 0)
-#define GRXSTS_HCHNUM_SHIFT 0
-#define GRXSTS_DPID_MASK (0x3 << 15)
-#define GRXSTS_DPID_SHIFT 15
-#define GRXSTS_BYTECNT_MASK (0x7ff << 4)
-#define GRXSTS_BYTECNT_SHIFT 4
-#define GRXSTS_EPNUM_MASK (0xf << 0)
-#define GRXSTS_EPNUM_SHIFT 0
-
-#define GRXFSIZ HSOTG_REG(0x024)
-#define GRXFSIZ_DEPTH_MASK (0xffff << 0)
-#define GRXFSIZ_DEPTH_SHIFT 0
-
-#define GNPTXFSIZ HSOTG_REG(0x028)
+#ifndef DWC2_REGS_H
+#define DWC2_REGS_H
+
+#define HSOTG_REG(x) (x)
+
+#define GOTGCTL HSOTG_REG(0x000)
+#define GOTGCTL_CHIRPEN BIT(27)
+#define GOTGCTL_MULT_VALID_BC_MASK (0x1f << 22)
+#define GOTGCTL_MULT_VALID_BC_SHIFT 22
+#define GOTGCTL_OTGVER BIT(20)
+#define GOTGCTL_BSESVLD BIT(19)
+#define GOTGCTL_ASESVLD BIT(18)
+#define GOTGCTL_DBNC_SHORT BIT(17)
+#define GOTGCTL_CONID_B BIT(16)
+#define GOTGCTL_DBNCE_FLTR_BYPASS BIT(15)
+#define GOTGCTL_DEVHNPEN BIT(11)
+#define GOTGCTL_HSTSETHNPEN BIT(10)
+#define GOTGCTL_HNPREQ BIT(9)
+#define GOTGCTL_HSTNEGSCS BIT(8)
+#define GOTGCTL_SESREQ BIT(1)
+#define GOTGCTL_SESREQSCS BIT(0)
+
+#define GOTGINT HSOTG_REG(0x004)
+#define GOTGINT_DBNCE_DONE BIT(19)
+#define GOTGINT_A_DEV_TOUT_CHG BIT(18)
+#define GOTGINT_HST_NEG_DET BIT(17)
+#define GOTGINT_HST_NEG_SUC_STS_CHNG BIT(9)
+#define GOTGINT_SES_REQ_SUC_STS_CHNG BIT(8)
+#define GOTGINT_SES_END_DET BIT(2)
+
+#define GAHBCFG HSOTG_REG(0x008)
+#define GAHBCFG_AHB_SINGLE BIT(23)
+#define GAHBCFG_NOTI_ALL_DMA_WRIT BIT(22)
+#define GAHBCFG_REM_MEM_SUPP BIT(21)
+#define GAHBCFG_P_TXF_EMP_LVL BIT(8)
+#define GAHBCFG_NP_TXF_EMP_LVL BIT(7)
+#define GAHBCFG_DMA_EN BIT(5)
+#define GAHBCFG_HBSTLEN_MASK (0xf << 1)
+#define GAHBCFG_HBSTLEN_SHIFT 1
+#define GAHBCFG_HBSTLEN_SINGLE 0
+#define GAHBCFG_HBSTLEN_INCR 1
+#define GAHBCFG_HBSTLEN_INCR4 3
+#define GAHBCFG_HBSTLEN_INCR8 5
+#define GAHBCFG_HBSTLEN_INCR16 7
+#define GAHBCFG_GLBL_INTR_EN BIT(0)
+#define GAHBCFG_CTRL_MASK (GAHBCFG_P_TXF_EMP_LVL | \
+ GAHBCFG_NP_TXF_EMP_LVL | \
+ GAHBCFG_DMA_EN | \
+ GAHBCFG_GLBL_INTR_EN)
+
+#define GUSBCFG HSOTG_REG(0x00C)
+#define GUSBCFG_FORCEDEVMODE BIT(30)
+#define GUSBCFG_FORCEHOSTMODE BIT(29)
+#define GUSBCFG_TXENDDELAY BIT(28)
+#define GUSBCFG_ICTRAFFICPULLREMOVE BIT(27)
+#define GUSBCFG_ICUSBCAP BIT(26)
+#define GUSBCFG_ULPI_INT_PROT_DIS BIT(25)
+#define GUSBCFG_INDICATORPASSTHROUGH BIT(24)
+#define GUSBCFG_INDICATORCOMPLEMENT BIT(23)
+#define GUSBCFG_TERMSELDLPULSE BIT(22)
+#define GUSBCFG_ULPI_INT_VBUS_IND BIT(21)
+#define GUSBCFG_ULPI_EXT_VBUS_DRV BIT(20)
+#define GUSBCFG_ULPI_CLK_SUSP_M BIT(19)
+#define GUSBCFG_ULPI_AUTO_RES BIT(18)
+#define GUSBCFG_ULPI_FS_LS BIT(17)
+#define GUSBCFG_OTG_UTMI_FS_SEL BIT(16)
+#define GUSBCFG_PHY_LP_CLK_SEL BIT(15)
+#define GUSBCFG_USBTRDTIM_MASK (0xf << 10)
+#define GUSBCFG_USBTRDTIM_SHIFT 10
+#define GUSBCFG_HNPCAP BIT(9)
+#define GUSBCFG_SRPCAP BIT(8)
+#define GUSBCFG_DDRSEL BIT(7)
+#define GUSBCFG_PHYSEL BIT(6)
+#define GUSBCFG_FSINTF BIT(5)
+#define GUSBCFG_ULPI_UTMI_SEL BIT(4)
+#define GUSBCFG_PHYIF16 BIT(3)
+#define GUSBCFG_PHYIF8 (0 << 3)
+#define GUSBCFG_TOUTCAL_MASK (0x7 << 0)
+#define GUSBCFG_TOUTCAL_SHIFT 0
+#define GUSBCFG_TOUTCAL_LIMIT 0x7
+#define GUSBCFG_TOUTCAL(_x) ((_x) << 0)
+
+#define GRSTCTL HSOTG_REG(0x010)
+#define GRSTCTL_AHBIDLE BIT(31)
+#define GRSTCTL_DMAREQ BIT(30)
+#define GRSTCTL_TXFNUM_MASK (0x1f << 6)
+#define GRSTCTL_TXFNUM_SHIFT 6
+#define GRSTCTL_TXFNUM_LIMIT 0x1f
+#define GRSTCTL_TXFNUM(_x) ((_x) << 6)
+#define GRSTCTL_TXFFLSH BIT(5)
+#define GRSTCTL_RXFFLSH BIT(4)
+#define GRSTCTL_IN_TKNQ_FLSH BIT(3)
+#define GRSTCTL_FRMCNTRRST BIT(2)
+#define GRSTCTL_HSFTRST BIT(1)
+#define GRSTCTL_CSFTRST BIT(0)
+
+#define GINTSTS HSOTG_REG(0x014)
+#define GINTMSK HSOTG_REG(0x018)
+#define GINTSTS_WKUPINT BIT(31)
+#define GINTSTS_SESSREQINT BIT(30)
+#define GINTSTS_DISCONNINT BIT(29)
+#define GINTSTS_CONIDSTSCHNG BIT(28)
+#define GINTSTS_LPMTRANRCVD BIT(27)
+#define GINTSTS_PTXFEMP BIT(26)
+#define GINTSTS_HCHINT BIT(25)
+#define GINTSTS_PRTINT BIT(24)
+#define GINTSTS_RESETDET BIT(23)
+#define GINTSTS_FET_SUSP BIT(22)
+#define GINTSTS_INCOMPL_IP BIT(21)
+#define GINTSTS_INCOMPL_SOOUT BIT(21)
+#define GINTSTS_INCOMPL_SOIN BIT(20)
+#define GINTSTS_OEPINT BIT(19)
+#define GINTSTS_IEPINT BIT(18)
+#define GINTSTS_EPMIS BIT(17)
+#define GINTSTS_RESTOREDONE BIT(16)
+#define GINTSTS_EOPF BIT(15)
+#define GINTSTS_ISOUTDROP BIT(14)
+#define GINTSTS_ENUMDONE BIT(13)
+#define GINTSTS_USBRST BIT(12)
+#define GINTSTS_USBSUSP BIT(11)
+#define GINTSTS_ERLYSUSP BIT(10)
+#define GINTSTS_I2CINT BIT(9)
+#define GINTSTS_ULPI_CK_INT BIT(8)
+#define GINTSTS_GOUTNAKEFF BIT(7)
+#define GINTSTS_GINNAKEFF BIT(6)
+#define GINTSTS_NPTXFEMP BIT(5)
+#define GINTSTS_RXFLVL BIT(4)
+#define GINTSTS_SOF BIT(3)
+#define GINTSTS_OTGINT BIT(2)
+#define GINTSTS_MODEMIS BIT(1)
+#define GINTSTS_CURMODE_HOST BIT(0)
+
+#define GRXSTSR HSOTG_REG(0x01C)
+#define GRXSTSP HSOTG_REG(0x020)
+#define GRXSTS_FN_MASK (0x7f << 25)
+#define GRXSTS_FN_SHIFT 25
+#define GRXSTS_PKTSTS_MASK (0xf << 17)
+#define GRXSTS_PKTSTS_SHIFT 17
+#define GRXSTS_PKTSTS_GLOBALOUTNAK 1
+#define GRXSTS_PKTSTS_OUTRX 2
+#define GRXSTS_PKTSTS_HCHIN 2
+#define GRXSTS_PKTSTS_OUTDONE 3
+#define GRXSTS_PKTSTS_HCHIN_XFER_COMP 3
+#define GRXSTS_PKTSTS_SETUPDONE 4
+#define GRXSTS_PKTSTS_DATATOGGLEERR 5
+#define GRXSTS_PKTSTS_SETUPRX 6
+#define GRXSTS_PKTSTS_HCHHALTED 7
+#define GRXSTS_HCHNUM_MASK (0xf << 0)
+#define GRXSTS_HCHNUM_SHIFT 0
+#define GRXSTS_DPID_MASK (0x3 << 15)
+#define GRXSTS_DPID_SHIFT 15
+#define GRXSTS_BYTECNT_MASK (0x7ff << 4)
+#define GRXSTS_BYTECNT_SHIFT 4
+#define GRXSTS_EPNUM_MASK (0xf << 0)
+#define GRXSTS_EPNUM_SHIFT 0
+
+#define GRXFSIZ HSOTG_REG(0x024)
+#define GRXFSIZ_DEPTH_MASK (0xffff << 0)
+#define GRXFSIZ_DEPTH_SHIFT 0
+
+#define GNPTXFSIZ HSOTG_REG(0x028)
/* Use FIFOSIZE_* constants to access this register */
-#define GNPTXSTS HSOTG_REG(0x02C)
-#define GNPTXSTS_NP_TXQ_TOP_MASK (0x7f << 24)
-#define GNPTXSTS_NP_TXQ_TOP_SHIFT 24
-#define GNPTXSTS_NP_TXQ_SPC_AVAIL_MASK (0xff << 16)
-#define GNPTXSTS_NP_TXQ_SPC_AVAIL_SHIFT 16
-#define GNPTXSTS_NP_TXQ_SPC_AVAIL_GET(_v) (((_v) >> 16) & 0xff)
-#define GNPTXSTS_NP_TXF_SPC_AVAIL_MASK (0xffff << 0)
-#define GNPTXSTS_NP_TXF_SPC_AVAIL_SHIFT 0
-#define GNPTXSTS_NP_TXF_SPC_AVAIL_GET(_v) (((_v) >> 0) & 0xffff)
-
-#define GI2CCTL HSOTG_REG(0x0030)
-#define GI2CCTL_BSYDNE BIT(31)
-#define GI2CCTL_RW BIT(30)
-#define GI2CCTL_I2CDATSE0 BIT(28)
-#define GI2CCTL_I2CDEVADDR_MASK (0x3 << 26)
-#define GI2CCTL_I2CDEVADDR_SHIFT 26
-#define GI2CCTL_I2CSUSPCTL BIT(25)
-#define GI2CCTL_ACK BIT(24)
-#define GI2CCTL_I2CEN BIT(23)
-#define GI2CCTL_ADDR_MASK (0x7f << 16)
-#define GI2CCTL_ADDR_SHIFT 16
-#define GI2CCTL_REGADDR_MASK (0xff << 8)
-#define GI2CCTL_REGADDR_SHIFT 8
-#define GI2CCTL_RWDATA_MASK (0xff << 0)
-#define GI2CCTL_RWDATA_SHIFT 0
-
-#define GPVNDCTL HSOTG_REG(0x0034)
-#define GGPIO HSOTG_REG(0x0038)
-#define GGPIO_STM32_OTG_GCCFG_PWRDWN BIT(16)
-
-#define GUID HSOTG_REG(0x003c)
-#define GSNPSID HSOTG_REG(0x0040)
-#define GHWCFG1 HSOTG_REG(0x0044)
-#define GSNPSID_ID_MASK GENMASK(31, 16)
-
-#define GHWCFG2 HSOTG_REG(0x0048)
-#define GHWCFG2_OTG_ENABLE_IC_USB BIT(31)
-#define GHWCFG2_DEV_TOKEN_Q_DEPTH_MASK (0x1f << 26)
-#define GHWCFG2_DEV_TOKEN_Q_DEPTH_SHIFT 26
-#define GHWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK (0x3 << 24)
-#define GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT 24
-#define GHWCFG2_NONPERIO_TX_Q_DEPTH_MASK (0x3 << 22)
-#define GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT 22
-#define GHWCFG2_MULTI_PROC_INT BIT(20)
-#define GHWCFG2_DYNAMIC_FIFO BIT(19)
-#define GHWCFG2_PERIO_EP_SUPPORTED BIT(18)
-#define GHWCFG2_NUM_HOST_CHAN_MASK (0xf << 14)
-#define GHWCFG2_NUM_HOST_CHAN_SHIFT 14
-#define GHWCFG2_NUM_DEV_EP_MASK (0xf << 10)
-#define GHWCFG2_NUM_DEV_EP_SHIFT 10
-#define GHWCFG2_FS_PHY_TYPE_MASK (0x3 << 8)
-#define GHWCFG2_FS_PHY_TYPE_SHIFT 8
-#define GHWCFG2_FS_PHY_TYPE_NOT_SUPPORTED 0
-#define GHWCFG2_FS_PHY_TYPE_DEDICATED 1
-#define GHWCFG2_FS_PHY_TYPE_SHARED_UTMI 2
-#define GHWCFG2_FS_PHY_TYPE_SHARED_ULPI 3
-#define GHWCFG2_HS_PHY_TYPE_MASK (0x3 << 6)
-#define GHWCFG2_HS_PHY_TYPE_SHIFT 6
-#define GHWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0
-#define GHWCFG2_HS_PHY_TYPE_UTMI 1
-#define GHWCFG2_HS_PHY_TYPE_ULPI 2
-#define GHWCFG2_HS_PHY_TYPE_UTMI_ULPI 3
-#define GHWCFG2_POINT2POINT BIT(5)
-#define GHWCFG2_ARCHITECTURE_MASK (0x3 << 3)
-#define GHWCFG2_ARCHITECTURE_SHIFT 3
-#define GHWCFG2_SLAVE_ONLY_ARCH 0
-#define GHWCFG2_EXT_DMA_ARCH 1
-#define GHWCFG2_INT_DMA_ARCH 2
-#define GHWCFG2_OP_MODE_MASK (0x7 << 0)
-#define GHWCFG2_OP_MODE_SHIFT 0
-#define GHWCFG2_OP_MODE_HNP_SRP_CAPABLE 0
-#define GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE 1
-#define GHWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE 2
-#define GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3
-#define GHWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4
-#define GHWCFG2_OP_MODE_SRP_CAPABLE_HOST 5
-#define GHWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6
-#define GHWCFG2_OP_MODE_UNDEFINED 7
-
-#define GHWCFG3 HSOTG_REG(0x004c)
-#define GHWCFG3_DFIFO_DEPTH_MASK (0xffff << 16)
-#define GHWCFG3_DFIFO_DEPTH_SHIFT 16
-#define GHWCFG3_OTG_LPM_EN BIT(15)
-#define GHWCFG3_BC_SUPPORT BIT(14)
-#define GHWCFG3_OTG_ENABLE_HSIC BIT(13)
-#define GHWCFG3_ADP_SUPP BIT(12)
-#define GHWCFG3_SYNCH_RESET_TYPE BIT(11)
-#define GHWCFG3_OPTIONAL_FEATURES BIT(10)
-#define GHWCFG3_VENDOR_CTRL_IF BIT(9)
-#define GHWCFG3_I2C BIT(8)
-#define GHWCFG3_OTG_FUNC BIT(7)
-#define GHWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK (0x7 << 4)
-#define GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT 4
-#define GHWCFG3_XFER_SIZE_CNTR_WIDTH_MASK (0xf << 0)
-#define GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT 0
-
-#define GHWCFG4 HSOTG_REG(0x0050)
-#define GHWCFG4_DESC_DMA_DYN BIT(31)
-#define GHWCFG4_DESC_DMA BIT(30)
-#define GHWCFG4_NUM_IN_EPS_MASK (0xf << 26)
-#define GHWCFG4_NUM_IN_EPS_SHIFT 26
-#define GHWCFG4_DED_FIFO_EN BIT(25)
-#define GHWCFG4_DED_FIFO_SHIFT 25
-#define GHWCFG4_SESSION_END_FILT_EN BIT(24)
-#define GHWCFG4_B_VALID_FILT_EN BIT(23)
-#define GHWCFG4_A_VALID_FILT_EN BIT(22)
-#define GHWCFG4_VBUS_VALID_FILT_EN BIT(21)
-#define GHWCFG4_IDDIG_FILT_EN BIT(20)
-#define GHWCFG4_NUM_DEV_MODE_CTRL_EP_MASK (0xf << 16)
-#define GHWCFG4_NUM_DEV_MODE_CTRL_EP_SHIFT 16
-#define GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK (0x3 << 14)
-#define GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT 14
-#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8 0
-#define GHWCFG4_UTMI_PHY_DATA_WIDTH_16 1
-#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8_OR_16 2
-#define GHWCFG4_ACG_SUPPORTED BIT(12)
-#define GHWCFG4_IPG_ISOC_SUPPORTED BIT(11)
+#define GNPTXSTS HSOTG_REG(0x02C)
+#define GNPTXSTS_NP_TXQ_TOP_MASK (0x7f << 24)
+#define GNPTXSTS_NP_TXQ_TOP_SHIFT 24
+#define GNPTXSTS_NP_TXQ_SPC_AVAIL_MASK (0xff << 16)
+#define GNPTXSTS_NP_TXQ_SPC_AVAIL_SHIFT 16
+#define GNPTXSTS_NP_TXQ_SPC_AVAIL_GET(_v) (((_v) >> 16) & 0xff)
+#define GNPTXSTS_NP_TXF_SPC_AVAIL_MASK (0xffff << 0)
+#define GNPTXSTS_NP_TXF_SPC_AVAIL_SHIFT 0
+#define GNPTXSTS_NP_TXF_SPC_AVAIL_GET(_v) (((_v) >> 0) & 0xffff)
+
+#define GI2CCTL HSOTG_REG(0x0030)
+#define GI2CCTL_BSYDNE BIT(31)
+#define GI2CCTL_RW BIT(30)
+#define GI2CCTL_I2CDATSE0 BIT(28)
+#define GI2CCTL_I2CDEVADDR_MASK (0x3 << 26)
+#define GI2CCTL_I2CDEVADDR_SHIFT 26
+#define GI2CCTL_I2CSUSPCTL BIT(25)
+#define GI2CCTL_ACK BIT(24)
+#define GI2CCTL_I2CEN BIT(23)
+#define GI2CCTL_ADDR_MASK (0x7f << 16)
+#define GI2CCTL_ADDR_SHIFT 16
+#define GI2CCTL_REGADDR_MASK (0xff << 8)
+#define GI2CCTL_REGADDR_SHIFT 8
+#define GI2CCTL_RWDATA_MASK (0xff << 0)
+#define GI2CCTL_RWDATA_SHIFT 0
+
+#define GPVNDCTL HSOTG_REG(0x0034)
+#define GGPIO HSOTG_REG(0x0038)
+#define GGPIO_STM32_OTG_GCCFG_PWRDWN BIT(16)
+
+#define GUID HSOTG_REG(0x003c)
+#define GSNPSID HSOTG_REG(0x0040)
+#define GHWCFG1 HSOTG_REG(0x0044)
+#define GSNPSID_ID_MASK GENMASK(31, 16)
+
+#define GHWCFG2 HSOTG_REG(0x0048)
+#define GHWCFG2_OTG_ENABLE_IC_USB BIT(31)
+#define GHWCFG2_DEV_TOKEN_Q_DEPTH_MASK (0x1f << 26)
+#define GHWCFG2_DEV_TOKEN_Q_DEPTH_SHIFT 26
+#define GHWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK (0x3 << 24)
+#define GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT 24
+#define GHWCFG2_NONPERIO_TX_Q_DEPTH_MASK (0x3 << 22)
+#define GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT 22
+#define GHWCFG2_MULTI_PROC_INT BIT(20)
+#define GHWCFG2_DYNAMIC_FIFO BIT(19)
+#define GHWCFG2_PERIO_EP_SUPPORTED BIT(18)
+#define GHWCFG2_NUM_HOST_CHAN_MASK (0xf << 14)
+#define GHWCFG2_NUM_HOST_CHAN_SHIFT 14
+#define GHWCFG2_NUM_DEV_EP_MASK (0xf << 10)
+#define GHWCFG2_NUM_DEV_EP_SHIFT 10
+#define GHWCFG2_FS_PHY_TYPE_MASK (0x3 << 8)
+#define GHWCFG2_FS_PHY_TYPE_SHIFT 8
+#define GHWCFG2_FS_PHY_TYPE_NOT_SUPPORTED 0
+#define GHWCFG2_FS_PHY_TYPE_DEDICATED 1
+#define GHWCFG2_FS_PHY_TYPE_SHARED_UTMI 2
+#define GHWCFG2_FS_PHY_TYPE_SHARED_ULPI 3
+#define GHWCFG2_HS_PHY_TYPE_MASK (0x3 << 6)
+#define GHWCFG2_HS_PHY_TYPE_SHIFT 6
+#define GHWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0
+#define GHWCFG2_HS_PHY_TYPE_UTMI 1
+#define GHWCFG2_HS_PHY_TYPE_ULPI 2
+#define GHWCFG2_HS_PHY_TYPE_UTMI_ULPI 3
+#define GHWCFG2_POINT2POINT BIT(5)
+#define GHWCFG2_ARCHITECTURE_MASK (0x3 << 3)
+#define GHWCFG2_ARCHITECTURE_SHIFT 3
+#define GHWCFG2_SLAVE_ONLY_ARCH 0
+#define GHWCFG2_EXT_DMA_ARCH 1
+#define GHWCFG2_INT_DMA_ARCH 2
+#define GHWCFG2_OP_MODE_MASK (0x7 << 0)
+#define GHWCFG2_OP_MODE_SHIFT 0
+#define GHWCFG2_OP_MODE_HNP_SRP_CAPABLE 0
+#define GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE 1
+#define GHWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE 2
+#define GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3
+#define GHWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4
+#define GHWCFG2_OP_MODE_SRP_CAPABLE_HOST 5
+#define GHWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6
+#define GHWCFG2_OP_MODE_UNDEFINED 7
+
+#define GHWCFG3 HSOTG_REG(0x004c)
+#define GHWCFG3_DFIFO_DEPTH_MASK (0xffff << 16)
+#define GHWCFG3_DFIFO_DEPTH_SHIFT 16
+#define GHWCFG3_OTG_LPM_EN BIT(15)
+#define GHWCFG3_BC_SUPPORT BIT(14)
+#define GHWCFG3_OTG_ENABLE_HSIC BIT(13)
+#define GHWCFG3_ADP_SUPP BIT(12)
+#define GHWCFG3_SYNCH_RESET_TYPE BIT(11)
+#define GHWCFG3_OPTIONAL_FEATURES BIT(10)
+#define GHWCFG3_VENDOR_CTRL_IF BIT(9)
+#define GHWCFG3_I2C BIT(8)
+#define GHWCFG3_OTG_FUNC BIT(7)
+#define GHWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK (0x7 << 4)
+#define GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT 4
+#define GHWCFG3_XFER_SIZE_CNTR_WIDTH_MASK (0xf << 0)
+#define GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT 0
+
+#define GHWCFG4 HSOTG_REG(0x0050)
+#define GHWCFG4_DESC_DMA_DYN BIT(31)
+#define GHWCFG4_DESC_DMA BIT(30)
+#define GHWCFG4_NUM_IN_EPS_MASK (0xf << 26)
+#define GHWCFG4_NUM_IN_EPS_SHIFT 26
+#define GHWCFG4_DED_FIFO_EN BIT(25)
+#define GHWCFG4_DED_FIFO_SHIFT 25
+#define GHWCFG4_SESSION_END_FILT_EN BIT(24)
+#define GHWCFG4_B_VALID_FILT_EN BIT(23)
+#define GHWCFG4_A_VALID_FILT_EN BIT(22)
+#define GHWCFG4_VBUS_VALID_FILT_EN BIT(21)
+#define GHWCFG4_IDDIG_FILT_EN BIT(20)
+#define GHWCFG4_NUM_DEV_MODE_CTRL_EP_MASK (0xf << 16)
+#define GHWCFG4_NUM_DEV_MODE_CTRL_EP_SHIFT 16
+#define GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK (0x3 << 14)
+#define GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT 14
+#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8 0
+#define GHWCFG4_UTMI_PHY_DATA_WIDTH_16 1
+#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8_OR_16 2
+#define GHWCFG4_ACG_SUPPORTED BIT(12)
+#define GHWCFG4_IPG_ISOC_SUPPORTED BIT(11)
#define GHWCFG4_SERVICE_INTERVAL_SUPPORTED BIT(10)
-#define GHWCFG4_XHIBER BIT(7)
-#define GHWCFG4_HIBER BIT(6)
-#define GHWCFG4_MIN_AHB_FREQ BIT(5)
-#define GHWCFG4_POWER_OPTIMIZ BIT(4)
-#define GHWCFG4_NUM_DEV_PERIO_IN_EP_MASK (0xf << 0)
-#define GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT 0
-
-#define GLPMCFG HSOTG_REG(0x0054)
-#define GLPMCFG_INVSELHSIC BIT(31)
-#define GLPMCFG_HSICCON BIT(30)
-#define GLPMCFG_RSTRSLPSTS BIT(29)
-#define GLPMCFG_ENBESL BIT(28)
-#define GLPMCFG_LPM_RETRYCNT_STS_MASK (0x7 << 25)
-#define GLPMCFG_LPM_RETRYCNT_STS_SHIFT 25
-#define GLPMCFG_SNDLPM BIT(24)
-#define GLPMCFG_RETRY_CNT_MASK (0x7 << 21)
-#define GLPMCFG_RETRY_CNT_SHIFT 21
-#define GLPMCFG_LPM_REJECT_CTRL_CONTROL BIT(21)
-#define GLPMCFG_LPM_ACCEPT_CTRL_ISOC BIT(22)
-#define GLPMCFG_LPM_CHNL_INDX_MASK (0xf << 17)
-#define GLPMCFG_LPM_CHNL_INDX_SHIFT 17
-#define GLPMCFG_L1RESUMEOK BIT(16)
-#define GLPMCFG_SLPSTS BIT(15)
-#define GLPMCFG_COREL1RES_MASK (0x3 << 13)
-#define GLPMCFG_COREL1RES_SHIFT 13
-#define GLPMCFG_HIRD_THRES_MASK (0x1f << 8)
-#define GLPMCFG_HIRD_THRES_SHIFT 8
-#define GLPMCFG_HIRD_THRES_EN (0x10 << 8)
-#define GLPMCFG_ENBLSLPM BIT(7)
-#define GLPMCFG_BREMOTEWAKE BIT(6)
-#define GLPMCFG_HIRD_MASK (0xf << 2)
-#define GLPMCFG_HIRD_SHIFT 2
-#define GLPMCFG_APPL1RES BIT(1)
-#define GLPMCFG_LPMCAP BIT(0)
-
-#define GPWRDN HSOTG_REG(0x0058)
-#define GPWRDN_MULT_VAL_ID_BC_MASK (0x1f << 24)
-#define GPWRDN_MULT_VAL_ID_BC_SHIFT 24
-#define GPWRDN_ADP_INT BIT(23)
-#define GPWRDN_BSESSVLD BIT(22)
-#define GPWRDN_IDSTS BIT(21)
-#define GPWRDN_LINESTATE_MASK (0x3 << 19)
-#define GPWRDN_LINESTATE_SHIFT 19
-#define GPWRDN_STS_CHGINT_MSK BIT(18)
-#define GPWRDN_STS_CHGINT BIT(17)
-#define GPWRDN_SRP_DET_MSK BIT(16)
-#define GPWRDN_SRP_DET BIT(15)
-#define GPWRDN_CONNECT_DET_MSK BIT(14)
-#define GPWRDN_CONNECT_DET BIT(13)
-#define GPWRDN_DISCONN_DET_MSK BIT(12)
-#define GPWRDN_DISCONN_DET BIT(11)
-#define GPWRDN_RST_DET_MSK BIT(10)
-#define GPWRDN_RST_DET BIT(9)
-#define GPWRDN_LNSTSCHG_MSK BIT(8)
-#define GPWRDN_LNSTSCHG BIT(7)
-#define GPWRDN_DIS_VBUS BIT(6)
-#define GPWRDN_PWRDNSWTCH BIT(5)
-#define GPWRDN_PWRDNRSTN BIT(4)
-#define GPWRDN_PWRDNCLMP BIT(3)
-#define GPWRDN_RESTORE BIT(2)
-#define GPWRDN_PMUACTV BIT(1)
-#define GPWRDN_PMUINTSEL BIT(0)
-
-#define GDFIFOCFG HSOTG_REG(0x005c)
-#define GDFIFOCFG_EPINFOBASE_MASK (0xffff << 16)
-#define GDFIFOCFG_EPINFOBASE_SHIFT 16
-#define GDFIFOCFG_GDFIFOCFG_MASK (0xffff << 0)
-#define GDFIFOCFG_GDFIFOCFG_SHIFT 0
-
-#define ADPCTL HSOTG_REG(0x0060)
-#define ADPCTL_AR_MASK (0x3 << 27)
-#define ADPCTL_AR_SHIFT 27
-#define ADPCTL_ADP_TMOUT_INT_MSK BIT(26)
-#define ADPCTL_ADP_SNS_INT_MSK BIT(25)
-#define ADPCTL_ADP_PRB_INT_MSK BIT(24)
-#define ADPCTL_ADP_TMOUT_INT BIT(23)
-#define ADPCTL_ADP_SNS_INT BIT(22)
-#define ADPCTL_ADP_PRB_INT BIT(21)
-#define ADPCTL_ADPENA BIT(20)
-#define ADPCTL_ADPRES BIT(19)
-#define ADPCTL_ENASNS BIT(18)
-#define ADPCTL_ENAPRB BIT(17)
-#define ADPCTL_RTIM_MASK (0x7ff << 6)
-#define ADPCTL_RTIM_SHIFT 6
-#define ADPCTL_PRB_PER_MASK (0x3 << 4)
-#define ADPCTL_PRB_PER_SHIFT 4
-#define ADPCTL_PRB_DELTA_MASK (0x3 << 2)
-#define ADPCTL_PRB_DELTA_SHIFT 2
-#define ADPCTL_PRB_DSCHRG_MASK (0x3 << 0)
-#define ADPCTL_PRB_DSCHRG_SHIFT 0
-
-#define GREFCLK HSOTG_REG(0x0064)
-#define GREFCLK_REFCLKPER_MASK (0x1ffff << 15)
-#define GREFCLK_REFCLKPER_SHIFT 15
-#define GREFCLK_REF_CLK_MODE BIT(14)
-#define GREFCLK_SOF_CNT_WKUP_ALERT_MASK (0x3ff)
+#define GHWCFG4_XHIBER BIT(7)
+#define GHWCFG4_HIBER BIT(6)
+#define GHWCFG4_MIN_AHB_FREQ BIT(5)
+#define GHWCFG4_POWER_OPTIMIZ BIT(4)
+#define GHWCFG4_NUM_DEV_PERIO_IN_EP_MASK (0xf << 0)
+#define GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT 0
+
+#define GLPMCFG HSOTG_REG(0x0054)
+#define GLPMCFG_INVSELHSIC BIT(31)
+#define GLPMCFG_HSICCON BIT(30)
+#define GLPMCFG_RSTRSLPSTS BIT(29)
+#define GLPMCFG_ENBESL BIT(28)
+#define GLPMCFG_LPM_RETRYCNT_STS_MASK (0x7 << 25)
+#define GLPMCFG_LPM_RETRYCNT_STS_SHIFT 25
+#define GLPMCFG_SNDLPM BIT(24)
+#define GLPMCFG_RETRY_CNT_MASK (0x7 << 21)
+#define GLPMCFG_RETRY_CNT_SHIFT 21
+#define GLPMCFG_LPM_REJECT_CTRL_CONTROL BIT(21)
+#define GLPMCFG_LPM_ACCEPT_CTRL_ISOC BIT(22)
+#define GLPMCFG_LPM_CHNL_INDX_MASK (0xf << 17)
+#define GLPMCFG_LPM_CHNL_INDX_SHIFT 17
+#define GLPMCFG_L1RESUMEOK BIT(16)
+#define GLPMCFG_SLPSTS BIT(15)
+#define GLPMCFG_COREL1RES_MASK (0x3 << 13)
+#define GLPMCFG_COREL1RES_SHIFT 13
+#define GLPMCFG_HIRD_THRES_MASK (0x1f << 8)
+#define GLPMCFG_HIRD_THRES_SHIFT 8
+#define GLPMCFG_HIRD_THRES_EN (0x10 << 8)
+#define GLPMCFG_ENBLSLPM BIT(7)
+#define GLPMCFG_BREMOTEWAKE BIT(6)
+#define GLPMCFG_HIRD_MASK (0xf << 2)
+#define GLPMCFG_HIRD_SHIFT 2
+#define GLPMCFG_APPL1RES BIT(1)
+#define GLPMCFG_LPMCAP BIT(0)
+
+#define GPWRDN HSOTG_REG(0x0058)
+#define GPWRDN_MULT_VAL_ID_BC_MASK (0x1f << 24)
+#define GPWRDN_MULT_VAL_ID_BC_SHIFT 24
+#define GPWRDN_ADP_INT BIT(23)
+#define GPWRDN_BSESSVLD BIT(22)
+#define GPWRDN_IDSTS BIT(21)
+#define GPWRDN_LINESTATE_MASK (0x3 << 19)
+#define GPWRDN_LINESTATE_SHIFT 19
+#define GPWRDN_STS_CHGINT_MSK BIT(18)
+#define GPWRDN_STS_CHGINT BIT(17)
+#define GPWRDN_SRP_DET_MSK BIT(16)
+#define GPWRDN_SRP_DET BIT(15)
+#define GPWRDN_CONNECT_DET_MSK BIT(14)
+#define GPWRDN_CONNECT_DET BIT(13)
+#define GPWRDN_DISCONN_DET_MSK BIT(12)
+#define GPWRDN_DISCONN_DET BIT(11)
+#define GPWRDN_RST_DET_MSK BIT(10)
+#define GPWRDN_RST_DET BIT(9)
+#define GPWRDN_LNSTSCHG_MSK BIT(8)
+#define GPWRDN_LNSTSCHG BIT(7)
+#define GPWRDN_DIS_VBUS BIT(6)
+#define GPWRDN_PWRDNSWTCH BIT(5)
+#define GPWRDN_PWRDNRSTN BIT(4)
+#define GPWRDN_PWRDNCLMP BIT(3)
+#define GPWRDN_RESTORE BIT(2)
+#define GPWRDN_PMUACTV BIT(1)
+#define GPWRDN_PMUINTSEL BIT(0)
+
+#define GDFIFOCFG HSOTG_REG(0x005c)
+#define GDFIFOCFG_EPINFOBASE_MASK (0xffff << 16)
+#define GDFIFOCFG_EPINFOBASE_SHIFT 16
+#define GDFIFOCFG_GDFIFOCFG_MASK (0xffff << 0)
+#define GDFIFOCFG_GDFIFOCFG_SHIFT 0
+
+#define ADPCTL HSOTG_REG(0x0060)
+#define ADPCTL_AR_MASK (0x3 << 27)
+#define ADPCTL_AR_SHIFT 27
+#define ADPCTL_ADP_TMOUT_INT_MSK BIT(26)
+#define ADPCTL_ADP_SNS_INT_MSK BIT(25)
+#define ADPCTL_ADP_PRB_INT_MSK BIT(24)
+#define ADPCTL_ADP_TMOUT_INT BIT(23)
+#define ADPCTL_ADP_SNS_INT BIT(22)
+#define ADPCTL_ADP_PRB_INT BIT(21)
+#define ADPCTL_ADPENA BIT(20)
+#define ADPCTL_ADPRES BIT(19)
+#define ADPCTL_ENASNS BIT(18)
+#define ADPCTL_ENAPRB BIT(17)
+#define ADPCTL_RTIM_MASK (0x7ff << 6)
+#define ADPCTL_RTIM_SHIFT 6
+#define ADPCTL_PRB_PER_MASK (0x3 << 4)
+#define ADPCTL_PRB_PER_SHIFT 4
+#define ADPCTL_PRB_DELTA_MASK (0x3 << 2)
+#define ADPCTL_PRB_DELTA_SHIFT 2
+#define ADPCTL_PRB_DSCHRG_MASK (0x3 << 0)
+#define ADPCTL_PRB_DSCHRG_SHIFT 0
+
+#define GREFCLK HSOTG_REG(0x0064)
+#define GREFCLK_REFCLKPER_MASK (0x1ffff << 15)
+#define GREFCLK_REFCLKPER_SHIFT 15
+#define GREFCLK_REF_CLK_MODE BIT(14)
+#define GREFCLK_SOF_CNT_WKUP_ALERT_MASK (0x3ff)
#define GREFCLK_SOF_CNT_WKUP_ALERT_SHIFT 0
-#define GINTMSK2 HSOTG_REG(0x0068)
-#define GINTMSK2_WKUP_ALERT_INT_MSK BIT(0)
+#define GINTMSK2 HSOTG_REG(0x0068)
+#define GINTMSK2_WKUP_ALERT_INT_MSK BIT(0)
-#define GINTSTS2 HSOTG_REG(0x006c)
-#define GINTSTS2_WKUP_ALERT_INT BIT(0)
+#define GINTSTS2 HSOTG_REG(0x006c)
+#define GINTSTS2_WKUP_ALERT_INT BIT(0)
-#define HPTXFSIZ HSOTG_REG(0x100)
+#define HPTXFSIZ HSOTG_REG(0x100)
/* Use FIFOSIZE_* constants to access this register */
-#define DPTXFSIZN(_a) HSOTG_REG(0x104 + (((_a) - 1) * 4))
+#define DPTXFSIZN(_a) HSOTG_REG(0x104 + (((_a) - 1) * 4))
/* Use FIFOSIZE_* constants to access this register */
/* These apply to the GNPTXFSIZ, HPTXFSIZ and DPTXFSIZN registers */
-#define FIFOSIZE_DEPTH_MASK (0xffff << 16)
-#define FIFOSIZE_DEPTH_SHIFT 16
-#define FIFOSIZE_STARTADDR_MASK (0xffff << 0)
-#define FIFOSIZE_STARTADDR_SHIFT 0
-#define FIFOSIZE_DEPTH_GET(_x) (((_x) >> 16) & 0xffff)
+#define FIFOSIZE_DEPTH_MASK (0xffff << 16)
+#define FIFOSIZE_DEPTH_SHIFT 16
+#define FIFOSIZE_STARTADDR_MASK (0xffff << 0)
+#define FIFOSIZE_STARTADDR_SHIFT 0
+#define FIFOSIZE_DEPTH_GET(_x) (((_x) >> 16) & 0xffff)
/* Device mode registers */
-#define DCFG HSOTG_REG(0x800)
-#define DCFG_DESCDMA_EN BIT(23)
-#define DCFG_EPMISCNT_MASK (0x1f << 18)
-#define DCFG_EPMISCNT_SHIFT 18
-#define DCFG_EPMISCNT_LIMIT 0x1f
-#define DCFG_EPMISCNT(_x) ((_x) << 18)
-#define DCFG_IPG_ISOC_SUPPORDED BIT(17)
-#define DCFG_PERFRINT_MASK (0x3 << 11)
-#define DCFG_PERFRINT_SHIFT 11
-#define DCFG_PERFRINT_LIMIT 0x3
-#define DCFG_PERFRINT(_x) ((_x) << 11)
-#define DCFG_DEVADDR_MASK (0x7f << 4)
-#define DCFG_DEVADDR_SHIFT 4
-#define DCFG_DEVADDR_LIMIT 0x7f
-#define DCFG_DEVADDR(_x) ((_x) << 4)
-#define DCFG_NZ_STS_OUT_HSHK BIT(2)
-#define DCFG_DEVSPD_MASK (0x3 << 0)
-#define DCFG_DEVSPD_SHIFT 0
-#define DCFG_DEVSPD_HS 0
-#define DCFG_DEVSPD_FS 1
-#define DCFG_DEVSPD_LS 2
-#define DCFG_DEVSPD_FS48 3
-
-#define DCTL HSOTG_REG(0x804)
+#define DCFG HSOTG_REG(0x800)
+#define DCFG_DESCDMA_EN BIT(23)
+#define DCFG_EPMISCNT_MASK (0x1f << 18)
+#define DCFG_EPMISCNT_SHIFT 18
+#define DCFG_EPMISCNT_LIMIT 0x1f
+#define DCFG_EPMISCNT(_x) ((_x) << 18)
+#define DCFG_IPG_ISOC_SUPPORDED BIT(17)
+#define DCFG_PERFRINT_MASK (0x3 << 11)
+#define DCFG_PERFRINT_SHIFT 11
+#define DCFG_PERFRINT_LIMIT 0x3
+#define DCFG_PERFRINT(_x) ((_x) << 11)
+#define DCFG_DEVADDR_MASK (0x7f << 4)
+#define DCFG_DEVADDR_SHIFT 4
+#define DCFG_DEVADDR_LIMIT 0x7f
+#define DCFG_DEVADDR(_x) ((_x) << 4)
+#define DCFG_NZ_STS_OUT_HSHK BIT(2)
+#define DCFG_DEVSPD_MASK (0x3 << 0)
+#define DCFG_DEVSPD_SHIFT 0
+#define DCFG_DEVSPD_HS 0
+#define DCFG_DEVSPD_FS 1
+#define DCFG_DEVSPD_LS 2
+#define DCFG_DEVSPD_FS48 3
+
+#define DCTL HSOTG_REG(0x804)
#define DCTL_SERVICE_INTERVAL_SUPPORTED BIT(19)
-#define DCTL_PWRONPRGDONE BIT(11)
-#define DCTL_CGOUTNAK BIT(10)
-#define DCTL_SGOUTNAK BIT(9)
-#define DCTL_CGNPINNAK BIT(8)
-#define DCTL_SGNPINNAK BIT(7)
-#define DCTL_TSTCTL_MASK (0x7 << 4)
-#define DCTL_TSTCTL_SHIFT 4
-#define DCTL_GOUTNAKSTS BIT(3)
-#define DCTL_GNPINNAKSTS BIT(2)
-#define DCTL_SFTDISCON BIT(1)
-#define DCTL_RMTWKUPSIG BIT(0)
-
-#define DSTS HSOTG_REG(0x808)
-#define DSTS_SOFFN_MASK (0x3fff << 8)
-#define DSTS_SOFFN_SHIFT 8
-#define DSTS_SOFFN_LIMIT 0x3fff
-#define DSTS_SOFFN(_x) ((_x) << 8)
-#define DSTS_ERRATICERR BIT(3)
-#define DSTS_ENUMSPD_MASK (0x3 << 1)
-#define DSTS_ENUMSPD_SHIFT 1
-#define DSTS_ENUMSPD_HS 0
-#define DSTS_ENUMSPD_FS 1
-#define DSTS_ENUMSPD_LS 2
-#define DSTS_ENUMSPD_FS48 3
-#define DSTS_SUSPSTS BIT(0)
-
-#define DIEPMSK HSOTG_REG(0x810)
-#define DIEPMSK_NAKMSK BIT(13)
-#define DIEPMSK_BNAININTRMSK BIT(9)
-#define DIEPMSK_TXFIFOUNDRNMSK BIT(8)
-#define DIEPMSK_TXFIFOEMPTY BIT(7)
-#define DIEPMSK_INEPNAKEFFMSK BIT(6)
-#define DIEPMSK_INTKNEPMISMSK BIT(5)
-#define DIEPMSK_INTKNTXFEMPMSK BIT(4)
-#define DIEPMSK_TIMEOUTMSK BIT(3)
-#define DIEPMSK_AHBERRMSK BIT(2)
-#define DIEPMSK_EPDISBLDMSK BIT(1)
-#define DIEPMSK_XFERCOMPLMSK BIT(0)
-
-#define DOEPMSK HSOTG_REG(0x814)
-#define DOEPMSK_BNAMSK BIT(9)
-#define DOEPMSK_BACK2BACKSETUP BIT(6)
-#define DOEPMSK_STSPHSERCVDMSK BIT(5)
-#define DOEPMSK_OUTTKNEPDISMSK BIT(4)
-#define DOEPMSK_SETUPMSK BIT(3)
-#define DOEPMSK_AHBERRMSK BIT(2)
-#define DOEPMSK_EPDISBLDMSK BIT(1)
-#define DOEPMSK_XFERCOMPLMSK BIT(0)
-
-#define DAINT HSOTG_REG(0x818)
-#define DAINTMSK HSOTG_REG(0x81C)
-#define DAINT_OUTEP_SHIFT 16
-#define DAINT_OUTEP(_x) (1 << ((_x) + 16))
-#define DAINT_INEP(_x) (1 << (_x))
-
-#define DTKNQR1 HSOTG_REG(0x820)
-#define DTKNQR2 HSOTG_REG(0x824)
-#define DTKNQR3 HSOTG_REG(0x830)
-#define DTKNQR4 HSOTG_REG(0x834)
-#define DIEPEMPMSK HSOTG_REG(0x834)
-
-#define DVBUSDIS HSOTG_REG(0x828)
-#define DVBUSPULSE HSOTG_REG(0x82C)
-
-#define DIEPCTL0 HSOTG_REG(0x900)
-#define DIEPCTL(_a) HSOTG_REG(0x900 + ((_a) * 0x20))
-
-#define DOEPCTL0 HSOTG_REG(0xB00)
-#define DOEPCTL(_a) HSOTG_REG(0xB00 + ((_a) * 0x20))
+#define DCTL_PWRONPRGDONE BIT(11)
+#define DCTL_CGOUTNAK BIT(10)
+#define DCTL_SGOUTNAK BIT(9)
+#define DCTL_CGNPINNAK BIT(8)
+#define DCTL_SGNPINNAK BIT(7)
+#define DCTL_TSTCTL_MASK (0x7 << 4)
+#define DCTL_TSTCTL_SHIFT 4
+#define DCTL_GOUTNAKSTS BIT(3)
+#define DCTL_GNPINNAKSTS BIT(2)
+#define DCTL_SFTDISCON BIT(1)
+#define DCTL_RMTWKUPSIG BIT(0)
+
+#define DSTS HSOTG_REG(0x808)
+#define DSTS_SOFFN_MASK (0x3fff << 8)
+#define DSTS_SOFFN_SHIFT 8
+#define DSTS_SOFFN_LIMIT 0x3fff
+#define DSTS_SOFFN(_x) ((_x) << 8)
+#define DSTS_ERRATICERR BIT(3)
+#define DSTS_ENUMSPD_MASK (0x3 << 1)
+#define DSTS_ENUMSPD_SHIFT 1
+#define DSTS_ENUMSPD_HS 0
+#define DSTS_ENUMSPD_FS 1
+#define DSTS_ENUMSPD_LS 2
+#define DSTS_ENUMSPD_FS48 3
+#define DSTS_SUSPSTS BIT(0)
+
+#define DIEPMSK HSOTG_REG(0x810)
+#define DIEPMSK_NAKMSK BIT(13)
+#define DIEPMSK_BNAININTRMSK BIT(9)
+#define DIEPMSK_TXFIFOUNDRNMSK BIT(8)
+#define DIEPMSK_TXFIFOEMPTY BIT(7)
+#define DIEPMSK_INEPNAKEFFMSK BIT(6)
+#define DIEPMSK_INTKNEPMISMSK BIT(5)
+#define DIEPMSK_INTKNTXFEMPMSK BIT(4)
+#define DIEPMSK_TIMEOUTMSK BIT(3)
+#define DIEPMSK_AHBERRMSK BIT(2)
+#define DIEPMSK_EPDISBLDMSK BIT(1)
+#define DIEPMSK_XFERCOMPLMSK BIT(0)
+
+#define DOEPMSK HSOTG_REG(0x814)
+#define DOEPMSK_BNAMSK BIT(9)
+#define DOEPMSK_BACK2BACKSETUP BIT(6)
+#define DOEPMSK_STSPHSERCVDMSK BIT(5)
+#define DOEPMSK_OUTTKNEPDISMSK BIT(4)
+#define DOEPMSK_SETUPMSK BIT(3)
+#define DOEPMSK_AHBERRMSK BIT(2)
+#define DOEPMSK_EPDISBLDMSK BIT(1)
+#define DOEPMSK_XFERCOMPLMSK BIT(0)
+
+#define DAINT HSOTG_REG(0x818)
+#define DAINTMSK HSOTG_REG(0x81C)
+#define DAINT_OUTEP_SHIFT 16
+#define DAINT_OUTEP(_x) (1 << ((_x) + 16))
+#define DAINT_INEP(_x) (1 << (_x))
+
+#define DTKNQR1 HSOTG_REG(0x820)
+#define DTKNQR2 HSOTG_REG(0x824)
+#define DTKNQR3 HSOTG_REG(0x830)
+#define DTKNQR4 HSOTG_REG(0x834)
+#define DIEPEMPMSK HSOTG_REG(0x834)
+
+#define DVBUSDIS HSOTG_REG(0x828)
+#define DVBUSPULSE HSOTG_REG(0x82C)
+
+#define DIEPCTL0 HSOTG_REG(0x900)
+#define DIEPCTL(_a) HSOTG_REG(0x900 + ((_a) * 0x20))
+
+#define DOEPCTL0 HSOTG_REG(0xB00)
+#define DOEPCTL(_a) HSOTG_REG(0xB00 + ((_a) * 0x20))
/* EP0 specialness:
* bits[29..28] - reserved (no SetD0PID, SetD1PID)
* bits[25..22] - should always be zero, this isn't a periodic endpoint
* bits[10..0] - MPS setting different for EP0
*/
-#define D0EPCTL_MPS_MASK (0x3 << 0)
-#define D0EPCTL_MPS_SHIFT 0
-#define D0EPCTL_MPS_64 0
-#define D0EPCTL_MPS_32 1
-#define D0EPCTL_MPS_16 2
-#define D0EPCTL_MPS_8 3
-
-#define DXEPCTL_EPENA BIT(31)
-#define DXEPCTL_EPDIS BIT(30)
-#define DXEPCTL_SETD1PID BIT(29)
-#define DXEPCTL_SETODDFR BIT(29)
-#define DXEPCTL_SETD0PID BIT(28)
-#define DXEPCTL_SETEVENFR BIT(28)
-#define DXEPCTL_SNAK BIT(27)
-#define DXEPCTL_CNAK BIT(26)
-#define DXEPCTL_TXFNUM_MASK (0xf << 22)
-#define DXEPCTL_TXFNUM_SHIFT 22
-#define DXEPCTL_TXFNUM_LIMIT 0xf
-#define DXEPCTL_TXFNUM(_x) ((_x) << 22)
-#define DXEPCTL_STALL BIT(21)
-#define DXEPCTL_SNP BIT(20)
-#define DXEPCTL_EPTYPE_MASK (0x3 << 18)
-#define DXEPCTL_EPTYPE_CONTROL (0x0 << 18)
-#define DXEPCTL_EPTYPE_ISO (0x1 << 18)
-#define DXEPCTL_EPTYPE_BULK (0x2 << 18)
-#define DXEPCTL_EPTYPE_INTERRUPT (0x3 << 18)
-
-#define DXEPCTL_NAKSTS BIT(17)
-#define DXEPCTL_DPID BIT(16)
-#define DXEPCTL_EOFRNUM BIT(16)
-#define DXEPCTL_USBACTEP BIT(15)
-#define DXEPCTL_NEXTEP_MASK (0xf << 11)
-#define DXEPCTL_NEXTEP_SHIFT 11
-#define DXEPCTL_NEXTEP_LIMIT 0xf
-#define DXEPCTL_NEXTEP(_x) ((_x) << 11)
-#define DXEPCTL_MPS_MASK (0x7ff << 0)
-#define DXEPCTL_MPS_SHIFT 0
-#define DXEPCTL_MPS_LIMIT 0x7ff
-#define DXEPCTL_MPS(_x) ((_x) << 0)
-
-#define DIEPINT(_a) HSOTG_REG(0x908 + ((_a) * 0x20))
-#define DOEPINT(_a) HSOTG_REG(0xB08 + ((_a) * 0x20))
-#define DXEPINT_SETUP_RCVD BIT(15)
-#define DXEPINT_NYETINTRPT BIT(14)
-#define DXEPINT_NAKINTRPT BIT(13)
-#define DXEPINT_BBLEERRINTRPT BIT(12)
-#define DXEPINT_PKTDRPSTS BIT(11)
-#define DXEPINT_BNAINTR BIT(9)
-#define DXEPINT_TXFIFOUNDRN BIT(8)
-#define DXEPINT_OUTPKTERR BIT(8)
-#define DXEPINT_TXFEMP BIT(7)
-#define DXEPINT_INEPNAKEFF BIT(6)
-#define DXEPINT_BACK2BACKSETUP BIT(6)
-#define DXEPINT_INTKNEPMIS BIT(5)
-#define DXEPINT_STSPHSERCVD BIT(5)
-#define DXEPINT_INTKNTXFEMP BIT(4)
-#define DXEPINT_OUTTKNEPDIS BIT(4)
-#define DXEPINT_TIMEOUT BIT(3)
-#define DXEPINT_SETUP BIT(3)
-#define DXEPINT_AHBERR BIT(2)
-#define DXEPINT_EPDISBLD BIT(1)
-#define DXEPINT_XFERCOMPL BIT(0)
-
-#define DIEPTSIZ0 HSOTG_REG(0x910)
-#define DIEPTSIZ0_PKTCNT_MASK (0x3 << 19)
-#define DIEPTSIZ0_PKTCNT_SHIFT 19
-#define DIEPTSIZ0_PKTCNT_LIMIT 0x3
-#define DIEPTSIZ0_PKTCNT(_x) ((_x) << 19)
-#define DIEPTSIZ0_XFERSIZE_MASK (0x7f << 0)
-#define DIEPTSIZ0_XFERSIZE_SHIFT 0
-#define DIEPTSIZ0_XFERSIZE_LIMIT 0x7f
-#define DIEPTSIZ0_XFERSIZE(_x) ((_x) << 0)
-
-#define DOEPTSIZ0 HSOTG_REG(0xB10)
-#define DOEPTSIZ0_SUPCNT_MASK (0x3 << 29)
-#define DOEPTSIZ0_SUPCNT_SHIFT 29
-#define DOEPTSIZ0_SUPCNT_LIMIT 0x3
-#define DOEPTSIZ0_SUPCNT(_x) ((_x) << 29)
-#define DOEPTSIZ0_PKTCNT BIT(19)
-#define DOEPTSIZ0_XFERSIZE_MASK (0x7f << 0)
-#define DOEPTSIZ0_XFERSIZE_SHIFT 0
-
-#define DIEPTSIZ(_a) HSOTG_REG(0x910 + ((_a) * 0x20))
-#define DOEPTSIZ(_a) HSOTG_REG(0xB10 + ((_a) * 0x20))
-#define DXEPTSIZ_MC_MASK (0x3 << 29)
-#define DXEPTSIZ_MC_SHIFT 29
-#define DXEPTSIZ_MC_LIMIT 0x3
-#define DXEPTSIZ_MC(_x) ((_x) << 29)
-#define DXEPTSIZ_PKTCNT_MASK (0x3ff << 19)
-#define DXEPTSIZ_PKTCNT_SHIFT 19
-#define DXEPTSIZ_PKTCNT_LIMIT 0x3ff
-#define DXEPTSIZ_PKTCNT_GET(_v) (((_v) >> 19) & 0x3ff)
-#define DXEPTSIZ_PKTCNT(_x) ((_x) << 19)
-#define DXEPTSIZ_XFERSIZE_MASK (0x7ffff << 0)
-#define DXEPTSIZ_XFERSIZE_SHIFT 0
-#define DXEPTSIZ_XFERSIZE_LIMIT 0x7ffff
-#define DXEPTSIZ_XFERSIZE_GET(_v) (((_v) >> 0) & 0x7ffff)
-#define DXEPTSIZ_XFERSIZE(_x) ((_x) << 0)
-
-#define DIEPDMA(_a) HSOTG_REG(0x914 + ((_a) * 0x20))
-#define DOEPDMA(_a) HSOTG_REG(0xB14 + ((_a) * 0x20))
-
-#define DTXFSTS(_a) HSOTG_REG(0x918 + ((_a) * 0x20))
-
-#define PCGCTL HSOTG_REG(0x0e00)
-#define PCGCTL_IF_DEV_MODE BIT(31)
-#define PCGCTL_P2HD_PRT_SPD_MASK (0x3 << 29)
-#define PCGCTL_P2HD_PRT_SPD_SHIFT 29
-#define PCGCTL_P2HD_DEV_ENUM_SPD_MASK (0x3 << 27)
-#define PCGCTL_P2HD_DEV_ENUM_SPD_SHIFT 27
-#define PCGCTL_MAC_DEV_ADDR_MASK (0x7f << 20)
-#define PCGCTL_MAC_DEV_ADDR_SHIFT 20
-#define PCGCTL_MAX_TERMSEL BIT(19)
-#define PCGCTL_MAX_XCVRSELECT_MASK (0x3 << 17)
-#define PCGCTL_MAX_XCVRSELECT_SHIFT 17
-#define PCGCTL_PORT_POWER BIT(16)
-#define PCGCTL_PRT_CLK_SEL_MASK (0x3 << 14)
-#define PCGCTL_PRT_CLK_SEL_SHIFT 14
-#define PCGCTL_ESS_REG_RESTORED BIT(13)
-#define PCGCTL_EXTND_HIBER_SWITCH BIT(12)
-#define PCGCTL_EXTND_HIBER_PWRCLMP BIT(11)
-#define PCGCTL_ENBL_EXTND_HIBER BIT(10)
-#define PCGCTL_RESTOREMODE BIT(9)
-#define PCGCTL_RESETAFTSUSP BIT(8)
-#define PCGCTL_DEEP_SLEEP BIT(7)
-#define PCGCTL_PHY_IN_SLEEP BIT(6)
-#define PCGCTL_ENBL_SLEEP_GATING BIT(5)
-#define PCGCTL_RSTPDWNMODULE BIT(3)
-#define PCGCTL_PWRCLMP BIT(2)
-#define PCGCTL_GATEHCLK BIT(1)
-#define PCGCTL_STOPPCLK BIT(0)
+#define D0EPCTL_MPS_MASK (0x3 << 0)
+#define D0EPCTL_MPS_SHIFT 0
+#define D0EPCTL_MPS_64 0
+#define D0EPCTL_MPS_32 1
+#define D0EPCTL_MPS_16 2
+#define D0EPCTL_MPS_8 3
+
+#define DXEPCTL_EPENA BIT(31)
+#define DXEPCTL_EPDIS BIT(30)
+#define DXEPCTL_SETD1PID BIT(29)
+#define DXEPCTL_SETODDFR BIT(29)
+#define DXEPCTL_SETD0PID BIT(28)
+#define DXEPCTL_SETEVENFR BIT(28)
+#define DXEPCTL_SNAK BIT(27)
+#define DXEPCTL_CNAK BIT(26)
+#define DXEPCTL_TXFNUM_MASK (0xf << 22)
+#define DXEPCTL_TXFNUM_SHIFT 22
+#define DXEPCTL_TXFNUM_LIMIT 0xf
+#define DXEPCTL_TXFNUM(_x) ((_x) << 22)
+#define DXEPCTL_STALL BIT(21)
+#define DXEPCTL_SNP BIT(20)
+#define DXEPCTL_EPTYPE_MASK (0x3 << 18)
+#define DXEPCTL_EPTYPE_CONTROL (0x0 << 18)
+#define DXEPCTL_EPTYPE_ISO (0x1 << 18)
+#define DXEPCTL_EPTYPE_BULK (0x2 << 18)
+#define DXEPCTL_EPTYPE_INTERRUPT (0x3 << 18)
+
+#define DXEPCTL_NAKSTS BIT(17)
+#define DXEPCTL_DPID BIT(16)
+#define DXEPCTL_EOFRNUM BIT(16)
+#define DXEPCTL_USBACTEP BIT(15)
+#define DXEPCTL_NEXTEP_MASK (0xf << 11)
+#define DXEPCTL_NEXTEP_SHIFT 11
+#define DXEPCTL_NEXTEP_LIMIT 0xf
+#define DXEPCTL_NEXTEP(_x) ((_x) << 11)
+#define DXEPCTL_MPS_MASK (0x7ff << 0)
+#define DXEPCTL_MPS_SHIFT 0
+#define DXEPCTL_MPS_LIMIT 0x7ff
+#define DXEPCTL_MPS(_x) ((_x) << 0)
+
+#define DIEPINT(_a) HSOTG_REG(0x908 + ((_a) * 0x20))
+#define DOEPINT(_a) HSOTG_REG(0xB08 + ((_a) * 0x20))
+#define DXEPINT_SETUP_RCVD BIT(15)
+#define DXEPINT_NYETINTRPT BIT(14)
+#define DXEPINT_NAKINTRPT BIT(13)
+#define DXEPINT_BBLEERRINTRPT BIT(12)
+#define DXEPINT_PKTDRPSTS BIT(11)
+#define DXEPINT_BNAINTR BIT(9)
+#define DXEPINT_TXFIFOUNDRN BIT(8)
+#define DXEPINT_OUTPKTERR BIT(8)
+#define DXEPINT_TXFEMP BIT(7)
+#define DXEPINT_INEPNAKEFF BIT(6)
+#define DXEPINT_BACK2BACKSETUP BIT(6)
+#define DXEPINT_INTKNEPMIS BIT(5)
+#define DXEPINT_STSPHSERCVD BIT(5)
+#define DXEPINT_INTKNTXFEMP BIT(4)
+#define DXEPINT_OUTTKNEPDIS BIT(4)
+#define DXEPINT_TIMEOUT BIT(3)
+#define DXEPINT_SETUP BIT(3)
+#define DXEPINT_AHBERR BIT(2)
+#define DXEPINT_EPDISBLD BIT(1)
+#define DXEPINT_XFERCOMPL BIT(0)
+
+#define DIEPTSIZ0 HSOTG_REG(0x910)
+#define DIEPTSIZ0_PKTCNT_MASK (0x3 << 19)
+#define DIEPTSIZ0_PKTCNT_SHIFT 19
+#define DIEPTSIZ0_PKTCNT_LIMIT 0x3
+#define DIEPTSIZ0_PKTCNT(_x) ((_x) << 19)
+#define DIEPTSIZ0_XFERSIZE_MASK (0x7f << 0)
+#define DIEPTSIZ0_XFERSIZE_SHIFT 0
+#define DIEPTSIZ0_XFERSIZE_LIMIT 0x7f
+#define DIEPTSIZ0_XFERSIZE(_x) ((_x) << 0)
+
+#define DOEPTSIZ0 HSOTG_REG(0xB10)
+#define DOEPTSIZ0_SUPCNT_MASK (0x3 << 29)
+#define DOEPTSIZ0_SUPCNT_SHIFT 29
+#define DOEPTSIZ0_SUPCNT_LIMIT 0x3
+#define DOEPTSIZ0_SUPCNT(_x) ((_x) << 29)
+#define DOEPTSIZ0_PKTCNT BIT(19)
+#define DOEPTSIZ0_XFERSIZE_MASK (0x7f << 0)
+#define DOEPTSIZ0_XFERSIZE_SHIFT 0
+
+#define DIEPTSIZ(_a) HSOTG_REG(0x910 + ((_a) * 0x20))
+#define DOEPTSIZ(_a) HSOTG_REG(0xB10 + ((_a) * 0x20))
+#define DXEPTSIZ_MC_MASK (0x3 << 29)
+#define DXEPTSIZ_MC_SHIFT 29
+#define DXEPTSIZ_MC_LIMIT 0x3
+#define DXEPTSIZ_MC(_x) ((_x) << 29)
+#define DXEPTSIZ_PKTCNT_MASK (0x3ff << 19)
+#define DXEPTSIZ_PKTCNT_SHIFT 19
+#define DXEPTSIZ_PKTCNT_LIMIT 0x3ff
+#define DXEPTSIZ_PKTCNT_GET(_v) (((_v) >> 19) & 0x3ff)
+#define DXEPTSIZ_PKTCNT(_x) ((_x) << 19)
+#define DXEPTSIZ_XFERSIZE_MASK (0x7ffff << 0)
+#define DXEPTSIZ_XFERSIZE_SHIFT 0
+#define DXEPTSIZ_XFERSIZE_LIMIT 0x7ffff
+#define DXEPTSIZ_XFERSIZE_GET(_v) (((_v) >> 0) & 0x7ffff)
+#define DXEPTSIZ_XFERSIZE(_x) ((_x) << 0)
+
+#define DIEPDMA(_a) HSOTG_REG(0x914 + ((_a) * 0x20))
+#define DOEPDMA(_a) HSOTG_REG(0xB14 + ((_a) * 0x20))
+
+#define DTXFSTS(_a) HSOTG_REG(0x918 + ((_a) * 0x20))
+
+#define PCGCTL HSOTG_REG(0x0e00)
+#define PCGCTL_IF_DEV_MODE BIT(31)
+#define PCGCTL_P2HD_PRT_SPD_MASK (0x3 << 29)
+#define PCGCTL_P2HD_PRT_SPD_SHIFT 29
+#define PCGCTL_P2HD_DEV_ENUM_SPD_MASK (0x3 << 27)
+#define PCGCTL_P2HD_DEV_ENUM_SPD_SHIFT 27
+#define PCGCTL_MAC_DEV_ADDR_MASK (0x7f << 20)
+#define PCGCTL_MAC_DEV_ADDR_SHIFT 20
+#define PCGCTL_MAX_TERMSEL BIT(19)
+#define PCGCTL_MAX_XCVRSELECT_MASK (0x3 << 17)
+#define PCGCTL_MAX_XCVRSELECT_SHIFT 17
+#define PCGCTL_PORT_POWER BIT(16)
+#define PCGCTL_PRT_CLK_SEL_MASK (0x3 << 14)
+#define PCGCTL_PRT_CLK_SEL_SHIFT 14
+#define PCGCTL_ESS_REG_RESTORED BIT(13)
+#define PCGCTL_EXTND_HIBER_SWITCH BIT(12)
+#define PCGCTL_EXTND_HIBER_PWRCLMP BIT(11)
+#define PCGCTL_ENBL_EXTND_HIBER BIT(10)
+#define PCGCTL_RESTOREMODE BIT(9)
+#define PCGCTL_RESETAFTSUSP BIT(8)
+#define PCGCTL_DEEP_SLEEP BIT(7)
+#define PCGCTL_PHY_IN_SLEEP BIT(6)
+#define PCGCTL_ENBL_SLEEP_GATING BIT(5)
+#define PCGCTL_RSTPDWNMODULE BIT(3)
+#define PCGCTL_PWRCLMP BIT(2)
+#define PCGCTL_GATEHCLK BIT(1)
+#define PCGCTL_STOPPCLK BIT(0)
#define PCGCCTL1 HSOTG_REG(0xe04)
#define PCGCCTL1_TIMER (0x3 << 1)
#define PCGCCTL1_GATEEN BIT(0)
-#define EPFIFO(_a) HSOTG_REG(0x1000 + ((_a) * 0x1000))
+#define EPFIFO(_a) HSOTG_REG(0x1000 + ((_a) * 0x1000))
/* Host Mode Registers */
-#define HCFG HSOTG_REG(0x0400)
-#define HCFG_MODECHTIMEN BIT(31)
-#define HCFG_PERSCHEDENA BIT(26)
-#define HCFG_FRLISTEN_MASK (0x3 << 24)
-#define HCFG_FRLISTEN_SHIFT 24
-#define HCFG_FRLISTEN_8 (0 << 24)
-#define FRLISTEN_8_SIZE 8
-#define HCFG_FRLISTEN_16 BIT(24)
-#define FRLISTEN_16_SIZE 16
-#define HCFG_FRLISTEN_32 (2 << 24)
-#define FRLISTEN_32_SIZE 32
-#define HCFG_FRLISTEN_64 (3 << 24)
-#define FRLISTEN_64_SIZE 64
-#define HCFG_DESCDMA BIT(23)
-#define HCFG_RESVALID_MASK (0xff << 8)
-#define HCFG_RESVALID_SHIFT 8
-#define HCFG_ENA32KHZ BIT(7)
-#define HCFG_FSLSSUPP BIT(2)
-#define HCFG_FSLSPCLKSEL_MASK (0x3 << 0)
-#define HCFG_FSLSPCLKSEL_SHIFT 0
-#define HCFG_FSLSPCLKSEL_30_60_MHZ 0
-#define HCFG_FSLSPCLKSEL_48_MHZ 1
-#define HCFG_FSLSPCLKSEL_6_MHZ 2
-
-#define HFIR HSOTG_REG(0x0404)
-#define HFIR_FRINT_MASK (0xffff << 0)
-#define HFIR_FRINT_SHIFT 0
-#define HFIR_RLDCTRL BIT(16)
-
-#define HFNUM HSOTG_REG(0x0408)
-#define HFNUM_FRREM_MASK (0xffff << 16)
-#define HFNUM_FRREM_SHIFT 16
-#define HFNUM_FRNUM_MASK (0xffff << 0)
-#define HFNUM_FRNUM_SHIFT 0
-#define HFNUM_MAX_FRNUM 0x3fff
-
-#define HPTXSTS HSOTG_REG(0x0410)
-#define TXSTS_QTOP_ODD BIT(31)
-#define TXSTS_QTOP_CHNEP_MASK (0xf << 27)
-#define TXSTS_QTOP_CHNEP_SHIFT 27
-#define TXSTS_QTOP_TOKEN_MASK (0x3 << 25)
-#define TXSTS_QTOP_TOKEN_SHIFT 25
-#define TXSTS_QTOP_TERMINATE BIT(24)
-#define TXSTS_QSPCAVAIL_MASK (0xff << 16)
-#define TXSTS_QSPCAVAIL_SHIFT 16
-#define TXSTS_FSPCAVAIL_MASK (0xffff << 0)
-#define TXSTS_FSPCAVAIL_SHIFT 0
-
-#define HAINT HSOTG_REG(0x0414)
-#define HAINTMSK HSOTG_REG(0x0418)
-#define HFLBADDR HSOTG_REG(0x041c)
-
-#define HPRT0 HSOTG_REG(0x0440)
-#define HPRT0_SPD_MASK (0x3 << 17)
-#define HPRT0_SPD_SHIFT 17
-#define HPRT0_SPD_HIGH_SPEED 0
-#define HPRT0_SPD_FULL_SPEED 1
-#define HPRT0_SPD_LOW_SPEED 2
-#define HPRT0_TSTCTL_MASK (0xf << 13)
-#define HPRT0_TSTCTL_SHIFT 13
-#define HPRT0_PWR BIT(12)
-#define HPRT0_LNSTS_MASK (0x3 << 10)
-#define HPRT0_LNSTS_SHIFT 10
-#define HPRT0_RST BIT(8)
-#define HPRT0_SUSP BIT(7)
-#define HPRT0_RES BIT(6)
-#define HPRT0_OVRCURRCHG BIT(5)
-#define HPRT0_OVRCURRACT BIT(4)
-#define HPRT0_ENACHG BIT(3)
-#define HPRT0_ENA BIT(2)
-#define HPRT0_CONNDET BIT(1)
-#define HPRT0_CONNSTS BIT(0)
-
-#define HCCHAR(_ch) HSOTG_REG(0x0500 + 0x20 * (_ch))
-#define HCCHAR_CHENA BIT(31)
-#define HCCHAR_CHDIS BIT(30)
-#define HCCHAR_ODDFRM BIT(29)
-#define HCCHAR_DEVADDR_MASK (0x7f << 22)
-#define HCCHAR_DEVADDR_SHIFT 22
-#define HCCHAR_MULTICNT_MASK (0x3 << 20)
-#define HCCHAR_MULTICNT_SHIFT 20
-#define HCCHAR_EPTYPE_MASK (0x3 << 18)
-#define HCCHAR_EPTYPE_SHIFT 18
-#define HCCHAR_LSPDDEV BIT(17)
-#define HCCHAR_EPDIR BIT(15)
-#define HCCHAR_EPNUM_MASK (0xf << 11)
-#define HCCHAR_EPNUM_SHIFT 11
-#define HCCHAR_MPS_MASK (0x7ff << 0)
-#define HCCHAR_MPS_SHIFT 0
-
-#define HCSPLT(_ch) HSOTG_REG(0x0504 + 0x20 * (_ch))
-#define HCSPLT_SPLTENA BIT(31)
-#define HCSPLT_COMPSPLT BIT(16)
-#define HCSPLT_XACTPOS_MASK (0x3 << 14)
-#define HCSPLT_XACTPOS_SHIFT 14
-#define HCSPLT_XACTPOS_MID 0
-#define HCSPLT_XACTPOS_END 1
-#define HCSPLT_XACTPOS_BEGIN 2
-#define HCSPLT_XACTPOS_ALL 3
-#define HCSPLT_HUBADDR_MASK (0x7f << 7)
-#define HCSPLT_HUBADDR_SHIFT 7
-#define HCSPLT_PRTADDR_MASK (0x7f << 0)
-#define HCSPLT_PRTADDR_SHIFT 0
-
-#define HCINT(_ch) HSOTG_REG(0x0508 + 0x20 * (_ch))
-#define HCINTMSK(_ch) HSOTG_REG(0x050c + 0x20 * (_ch))
-#define HCINTMSK_RESERVED14_31 (0x3ffff << 14)
-#define HCINTMSK_FRM_LIST_ROLL BIT(13)
-#define HCINTMSK_XCS_XACT BIT(12)
-#define HCINTMSK_BNA BIT(11)
-#define HCINTMSK_DATATGLERR BIT(10)
-#define HCINTMSK_FRMOVRUN BIT(9)
-#define HCINTMSK_BBLERR BIT(8)
-#define HCINTMSK_XACTERR BIT(7)
-#define HCINTMSK_NYET BIT(6)
-#define HCINTMSK_ACK BIT(5)
-#define HCINTMSK_NAK BIT(4)
-#define HCINTMSK_STALL BIT(3)
-#define HCINTMSK_AHBERR BIT(2)
-#define HCINTMSK_CHHLTD BIT(1)
-#define HCINTMSK_XFERCOMPL BIT(0)
-
-#define HCTSIZ(_ch) HSOTG_REG(0x0510 + 0x20 * (_ch))
-#define TSIZ_DOPNG BIT(31)
-#define TSIZ_SC_MC_PID_MASK (0x3 << 29)
-#define TSIZ_SC_MC_PID_SHIFT 29
-#define TSIZ_SC_MC_PID_DATA0 0
-#define TSIZ_SC_MC_PID_DATA2 1
-#define TSIZ_SC_MC_PID_DATA1 2
-#define TSIZ_SC_MC_PID_MDATA 3
-#define TSIZ_SC_MC_PID_SETUP 3
-#define TSIZ_PKTCNT_MASK (0x3ff << 19)
-#define TSIZ_PKTCNT_SHIFT 19
-#define TSIZ_NTD_MASK (0xff << 8)
-#define TSIZ_NTD_SHIFT 8
-#define TSIZ_SCHINFO_MASK (0xff << 0)
-#define TSIZ_SCHINFO_SHIFT 0
-#define TSIZ_XFERSIZE_MASK (0x7ffff << 0)
-#define TSIZ_XFERSIZE_SHIFT 0
-
-#define HCDMA(_ch) HSOTG_REG(0x0514 + 0x20 * (_ch))
-
-#define HCDMAB(_ch) HSOTG_REG(0x051c + 0x20 * (_ch))
-
-#define HCFIFO(_ch) HSOTG_REG(0x1000 + 0x1000 * (_ch))
+#define HCFG HSOTG_REG(0x0400)
+#define HCFG_MODECHTIMEN BIT(31)
+#define HCFG_PERSCHEDENA BIT(26)
+#define HCFG_FRLISTEN_MASK (0x3 << 24)
+#define HCFG_FRLISTEN_SHIFT 24
+#define HCFG_FRLISTEN_8 (0 << 24)
+#define FRLISTEN_8_SIZE 8
+#define HCFG_FRLISTEN_16 BIT(24)
+#define FRLISTEN_16_SIZE 16
+#define HCFG_FRLISTEN_32 (2 << 24)
+#define FRLISTEN_32_SIZE 32
+#define HCFG_FRLISTEN_64 (3 << 24)
+#define FRLISTEN_64_SIZE 64
+#define HCFG_DESCDMA BIT(23)
+#define HCFG_RESVALID_MASK (0xff << 8)
+#define HCFG_RESVALID_SHIFT 8
+#define HCFG_ENA32KHZ BIT(7)
+#define HCFG_FSLSSUPP BIT(2)
+#define HCFG_FSLSPCLKSEL_MASK (0x3 << 0)
+#define HCFG_FSLSPCLKSEL_SHIFT 0
+#define HCFG_FSLSPCLKSEL_30_60_MHZ 0
+#define HCFG_FSLSPCLKSEL_48_MHZ 1
+#define HCFG_FSLSPCLKSEL_6_MHZ 2
+
+#define HFIR HSOTG_REG(0x0404)
+#define HFIR_FRINT_MASK (0xffff << 0)
+#define HFIR_FRINT_SHIFT 0
+#define HFIR_RLDCTRL BIT(16)
+
+#define HFNUM HSOTG_REG(0x0408)
+#define HFNUM_FRREM_MASK (0xffff << 16)
+#define HFNUM_FRREM_SHIFT 16
+#define HFNUM_FRNUM_MASK (0xffff << 0)
+#define HFNUM_FRNUM_SHIFT 0
+#define HFNUM_MAX_FRNUM 0x3fff
+
+#define HPTXSTS HSOTG_REG(0x0410)
+#define TXSTS_QTOP_ODD BIT(31)
+#define TXSTS_QTOP_CHNEP_MASK (0xf << 27)
+#define TXSTS_QTOP_CHNEP_SHIFT 27
+#define TXSTS_QTOP_TOKEN_MASK (0x3 << 25)
+#define TXSTS_QTOP_TOKEN_SHIFT 25
+#define TXSTS_QTOP_TERMINATE BIT(24)
+#define TXSTS_QSPCAVAIL_MASK (0xff << 16)
+#define TXSTS_QSPCAVAIL_SHIFT 16
+#define TXSTS_FSPCAVAIL_MASK (0xffff << 0)
+#define TXSTS_FSPCAVAIL_SHIFT 0
+
+#define HAINT HSOTG_REG(0x0414)
+#define HAINTMSK HSOTG_REG(0x0418)
+#define HFLBADDR HSOTG_REG(0x041c)
+
+#define HPRT0 HSOTG_REG(0x0440)
+#define HPRT0_SPD_MASK (0x3 << 17)
+#define HPRT0_SPD_SHIFT 17
+#define HPRT0_SPD_HIGH_SPEED 0
+#define HPRT0_SPD_FULL_SPEED 1
+#define HPRT0_SPD_LOW_SPEED 2
+#define HPRT0_TSTCTL_MASK (0xf << 13)
+#define HPRT0_TSTCTL_SHIFT 13
+#define HPRT0_PWR BIT(12)
+#define HPRT0_LNSTS_MASK (0x3 << 10)
+#define HPRT0_LNSTS_SHIFT 10
+#define HPRT0_RST BIT(8)
+#define HPRT0_SUSP BIT(7)
+#define HPRT0_RES BIT(6)
+#define HPRT0_OVRCURRCHG BIT(5)
+#define HPRT0_OVRCURRACT BIT(4)
+#define HPRT0_ENACHG BIT(3)
+#define HPRT0_ENA BIT(2)
+#define HPRT0_CONNDET BIT(1)
+#define HPRT0_CONNSTS BIT(0)
+
+#define HCCHAR(_ch) HSOTG_REG(0x0500 + 0x20 * (_ch))
+#define HCCHAR_CHENA BIT(31)
+#define HCCHAR_CHDIS BIT(30)
+#define HCCHAR_ODDFRM BIT(29)
+#define HCCHAR_DEVADDR_MASK (0x7f << 22)
+#define HCCHAR_DEVADDR_SHIFT 22
+#define HCCHAR_MULTICNT_MASK (0x3 << 20)
+#define HCCHAR_MULTICNT_SHIFT 20
+#define HCCHAR_EPTYPE_MASK (0x3 << 18)
+#define HCCHAR_EPTYPE_SHIFT 18
+#define HCCHAR_LSPDDEV BIT(17)
+#define HCCHAR_EPDIR BIT(15)
+#define HCCHAR_EPNUM_MASK (0xf << 11)
+#define HCCHAR_EPNUM_SHIFT 11
+#define HCCHAR_MPS_MASK (0x7ff << 0)
+#define HCCHAR_MPS_SHIFT 0
+
+#define HCSPLT(_ch) HSOTG_REG(0x0504 + 0x20 * (_ch))
+#define HCSPLT_SPLTENA BIT(31)
+#define HCSPLT_COMPSPLT BIT(16)
+#define HCSPLT_XACTPOS_MASK (0x3 << 14)
+#define HCSPLT_XACTPOS_SHIFT 14
+#define HCSPLT_XACTPOS_MID 0
+#define HCSPLT_XACTPOS_END 1
+#define HCSPLT_XACTPOS_BEGIN 2
+#define HCSPLT_XACTPOS_ALL 3
+#define HCSPLT_HUBADDR_MASK (0x7f << 7)
+#define HCSPLT_HUBADDR_SHIFT 7
+#define HCSPLT_PRTADDR_MASK (0x7f << 0)
+#define HCSPLT_PRTADDR_SHIFT 0
+
+#define HCINT(_ch) HSOTG_REG(0x0508 + 0x20 * (_ch))
+#define HCINTMSK(_ch) HSOTG_REG(0x050c + 0x20 * (_ch))
+#define HCINTMSK_RESERVED14_31 (0x3ffff << 14)
+#define HCINTMSK_FRM_LIST_ROLL BIT(13)
+#define HCINTMSK_XCS_XACT BIT(12)
+#define HCINTMSK_BNA BIT(11)
+#define HCINTMSK_DATATGLERR BIT(10)
+#define HCINTMSK_FRMOVRUN BIT(9)
+#define HCINTMSK_BBLERR BIT(8)
+#define HCINTMSK_XACTERR BIT(7)
+#define HCINTMSK_NYET BIT(6)
+#define HCINTMSK_ACK BIT(5)
+#define HCINTMSK_NAK BIT(4)
+#define HCINTMSK_STALL BIT(3)
+#define HCINTMSK_AHBERR BIT(2)
+#define HCINTMSK_CHHLTD BIT(1)
+#define HCINTMSK_XFERCOMPL BIT(0)
+
+#define HCTSIZ(_ch) HSOTG_REG(0x0510 + 0x20 * (_ch))
+#define TSIZ_DOPNG BIT(31)
+#define TSIZ_SC_MC_PID_MASK (0x3 << 29)
+#define TSIZ_SC_MC_PID_SHIFT 29
+#define TSIZ_SC_MC_PID_DATA0 0
+#define TSIZ_SC_MC_PID_DATA2 1
+#define TSIZ_SC_MC_PID_DATA1 2
+#define TSIZ_SC_MC_PID_MDATA 3
+#define TSIZ_SC_MC_PID_SETUP 3
+#define TSIZ_PKTCNT_MASK (0x3ff << 19)
+#define TSIZ_PKTCNT_SHIFT 19
+#define TSIZ_NTD_MASK (0xff << 8)
+#define TSIZ_NTD_SHIFT 8
+#define TSIZ_SCHINFO_MASK (0xff << 0)
+#define TSIZ_SCHINFO_SHIFT 0
+#define TSIZ_XFERSIZE_MASK (0x7ffff << 0)
+#define TSIZ_XFERSIZE_SHIFT 0
+
+#define HCDMA(_ch) HSOTG_REG(0x0514 + 0x20 * (_ch))
+
+#define HCDMAB(_ch) HSOTG_REG(0x051c + 0x20 * (_ch))
+
+#define HCFIFO(_ch) HSOTG_REG(0x1000 + 0x1000 * (_ch))
/**
* struct dwc2_dma_desc - DMA descriptor structure,
@@ -836,64 +836,64 @@
* Status quadlet and Data buffer pointer.
*/
struct dwc2_dma_desc {
- uint32_t status;
- uint32_t buf;
+ uint32_t status;
+ uint32_t buf;
} __packed;
/* Host Mode DMA descriptor status quadlet */
-#define HOST_DMA_A BIT(31)
-#define HOST_DMA_STS_MASK (0x3 << 28)
-#define HOST_DMA_STS_SHIFT 28
-#define HOST_DMA_STS_PKTERR BIT(28)
-#define HOST_DMA_EOL BIT(26)
-#define HOST_DMA_IOC BIT(25)
-#define HOST_DMA_SUP BIT(24)
-#define HOST_DMA_ALT_QTD BIT(23)
-#define HOST_DMA_QTD_OFFSET_MASK (0x3f << 17)
-#define HOST_DMA_QTD_OFFSET_SHIFT 17
-#define HOST_DMA_ISOC_NBYTES_MASK (0xfff << 0)
-#define HOST_DMA_ISOC_NBYTES_SHIFT 0
-#define HOST_DMA_NBYTES_MASK (0x1ffff << 0)
-#define HOST_DMA_NBYTES_SHIFT 0
-#define HOST_DMA_NBYTES_LIMIT 131071
+#define HOST_DMA_A BIT(31)
+#define HOST_DMA_STS_MASK (0x3 << 28)
+#define HOST_DMA_STS_SHIFT 28
+#define HOST_DMA_STS_PKTERR BIT(28)
+#define HOST_DMA_EOL BIT(26)
+#define HOST_DMA_IOC BIT(25)
+#define HOST_DMA_SUP BIT(24)
+#define HOST_DMA_ALT_QTD BIT(23)
+#define HOST_DMA_QTD_OFFSET_MASK (0x3f << 17)
+#define HOST_DMA_QTD_OFFSET_SHIFT 17
+#define HOST_DMA_ISOC_NBYTES_MASK (0xfff << 0)
+#define HOST_DMA_ISOC_NBYTES_SHIFT 0
+#define HOST_DMA_NBYTES_MASK (0x1ffff << 0)
+#define HOST_DMA_NBYTES_SHIFT 0
+#define HOST_DMA_NBYTES_LIMIT 131071
/* Device Mode DMA descriptor status quadlet */
-#define DEV_DMA_BUFF_STS_MASK (0x3 << 30)
-#define DEV_DMA_BUFF_STS_SHIFT 30
-#define DEV_DMA_BUFF_STS_HREADY 0
-#define DEV_DMA_BUFF_STS_DMABUSY 1
-#define DEV_DMA_BUFF_STS_DMADONE 2
-#define DEV_DMA_BUFF_STS_HBUSY 3
-#define DEV_DMA_STS_MASK (0x3 << 28)
-#define DEV_DMA_STS_SHIFT 28
-#define DEV_DMA_STS_SUCC 0
-#define DEV_DMA_STS_BUFF_FLUSH 1
-#define DEV_DMA_STS_BUFF_ERR 3
-#define DEV_DMA_L BIT(27)
-#define DEV_DMA_SHORT BIT(26)
-#define DEV_DMA_IOC BIT(25)
-#define DEV_DMA_SR BIT(24)
-#define DEV_DMA_MTRF BIT(23)
-#define DEV_DMA_ISOC_PID_MASK (0x3 << 23)
-#define DEV_DMA_ISOC_PID_SHIFT 23
-#define DEV_DMA_ISOC_PID_DATA0 0
-#define DEV_DMA_ISOC_PID_DATA2 1
-#define DEV_DMA_ISOC_PID_DATA1 2
-#define DEV_DMA_ISOC_PID_MDATA 3
-#define DEV_DMA_ISOC_FRNUM_MASK (0x7ff << 12)
-#define DEV_DMA_ISOC_FRNUM_SHIFT 12
-#define DEV_DMA_ISOC_TX_NBYTES_MASK (0xfff << 0)
-#define DEV_DMA_ISOC_TX_NBYTES_LIMIT 0xfff
-#define DEV_DMA_ISOC_RX_NBYTES_MASK (0x7ff << 0)
-#define DEV_DMA_ISOC_RX_NBYTES_LIMIT 0x7ff
-#define DEV_DMA_ISOC_NBYTES_SHIFT 0
-#define DEV_DMA_NBYTES_MASK (0xffff << 0)
-#define DEV_DMA_NBYTES_SHIFT 0
-#define DEV_DMA_NBYTES_LIMIT 0xffff
-
-#define MAX_DMA_DESC_NUM_GENERIC 64
-#define MAX_DMA_DESC_NUM_HS_ISOC 256
-
-#endif /* __DWC2_HW_H__ */
+#define DEV_DMA_BUFF_STS_MASK (0x3 << 30)
+#define DEV_DMA_BUFF_STS_SHIFT 30
+#define DEV_DMA_BUFF_STS_HREADY 0
+#define DEV_DMA_BUFF_STS_DMABUSY 1
+#define DEV_DMA_BUFF_STS_DMADONE 2
+#define DEV_DMA_BUFF_STS_HBUSY 3
+#define DEV_DMA_STS_MASK (0x3 << 28)
+#define DEV_DMA_STS_SHIFT 28
+#define DEV_DMA_STS_SUCC 0
+#define DEV_DMA_STS_BUFF_FLUSH 1
+#define DEV_DMA_STS_BUFF_ERR 3
+#define DEV_DMA_L BIT(27)
+#define DEV_DMA_SHORT BIT(26)
+#define DEV_DMA_IOC BIT(25)
+#define DEV_DMA_SR BIT(24)
+#define DEV_DMA_MTRF BIT(23)
+#define DEV_DMA_ISOC_PID_MASK (0x3 << 23)
+#define DEV_DMA_ISOC_PID_SHIFT 23
+#define DEV_DMA_ISOC_PID_DATA0 0
+#define DEV_DMA_ISOC_PID_DATA2 1
+#define DEV_DMA_ISOC_PID_DATA1 2
+#define DEV_DMA_ISOC_PID_MDATA 3
+#define DEV_DMA_ISOC_FRNUM_MASK (0x7ff << 12)
+#define DEV_DMA_ISOC_FRNUM_SHIFT 12
+#define DEV_DMA_ISOC_TX_NBYTES_MASK (0xfff << 0)
+#define DEV_DMA_ISOC_TX_NBYTES_LIMIT 0xfff
+#define DEV_DMA_ISOC_RX_NBYTES_MASK (0x7ff << 0)
+#define DEV_DMA_ISOC_RX_NBYTES_LIMIT 0x7ff
+#define DEV_DMA_ISOC_NBYTES_SHIFT 0
+#define DEV_DMA_NBYTES_MASK (0xffff << 0)
+#define DEV_DMA_NBYTES_SHIFT 0
+#define DEV_DMA_NBYTES_LIMIT 0xffff
+
+#define MAX_DMA_DESC_NUM_GENERIC 64
+#define MAX_DMA_DESC_NUM_HS_ISOC 256
+
+#endif /* DWC2_REGS_H */
diff --git a/include/hw/usb/hcd-dwc3.h b/include/hw/usb/hcd-dwc3.h
new file mode 100644
index 0000000000..f752a27e94
--- /dev/null
+++ b/include/hw/usb/hcd-dwc3.h
@@ -0,0 +1,56 @@
+/*
+ * QEMU model of the USB DWC3 host controller emulation.
+ *
+ * Copyright (c) 2020 Xilinx Inc.
+ *
+ * Written by Vikram Garhwal<fnu.vikram@xilinx.com>
+ *
+ * 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.
+ */
+#ifndef HCD_DWC3_H
+#define HCD_DWC3_H
+
+#include "hw/register.h"
+#include "hw/usb/hcd-xhci.h"
+#include "hw/usb/hcd-xhci-sysbus.h"
+
+#define TYPE_USB_DWC3 "usb_dwc3"
+
+#define USB_DWC3(obj) \
+ OBJECT_CHECK(USBDWC3, (obj), TYPE_USB_DWC3)
+
+#define USB_DWC3_R_MAX ((0x530 / 4) + 1)
+#define DWC3_SIZE 0x10000
+
+typedef struct USBDWC3 {
+ SysBusDevice parent_obj;
+ MemoryRegion iomem;
+ XHCISysbusState sysbus_xhci;
+
+ uint32_t regs[USB_DWC3_R_MAX];
+ RegisterInfo regs_info[USB_DWC3_R_MAX];
+
+ struct {
+ uint8_t mode;
+ uint32_t dwc_usb3_user;
+ } cfg;
+
+} USBDWC3;
+
+#endif
diff --git a/include/hw/usb/hcd-musb.h b/include/hw/usb/hcd-musb.h
index c874b9f292..4d4b1ec0fc 100644
--- a/include/hw/usb/hcd-musb.h
+++ b/include/hw/usb/hcd-musb.h
@@ -10,8 +10,10 @@
* SPDX-License-Identifier: GPL-2.0-or-later
*/
-#ifndef HW_USB_MUSB_H
-#define HW_USB_MUSB_H
+#ifndef HW_USB_HCD_MUSB_H
+#define HW_USB_HCD_MUSB_H
+
+#include "exec/hwaddr.h"
enum musb_irq_source_e {
musb_irq_suspend = 0,
diff --git a/include/hw/usb/hid.h b/include/hw/usb/hid.h
new file mode 100644
index 0000000000..1c142584ff
--- /dev/null
+++ b/include/hw/usb/hid.h
@@ -0,0 +1,17 @@
+#ifndef HW_USB_HID_H
+#define HW_USB_HID_H
+
+/* HID interface requests */
+#define HID_GET_REPORT 0xa101
+#define HID_GET_IDLE 0xa102
+#define HID_GET_PROTOCOL 0xa103
+#define HID_SET_REPORT 0x2109
+#define HID_SET_IDLE 0x210a
+#define HID_SET_PROTOCOL 0x210b
+
+/* HID descriptor types */
+#define USB_DT_HID 0x21
+#define USB_DT_REPORT 0x22
+#define USB_DT_PHY 0x23
+
+#endif
diff --git a/include/hw/usb/imx-usb-phy.h b/include/hw/usb/imx-usb-phy.h
index 07f0235d10..d1e867b77a 100644
--- a/include/hw/usb/imx-usb-phy.h
+++ b/include/hw/usb/imx-usb-phy.h
@@ -3,6 +3,7 @@
#include "hw/sysbus.h"
#include "qemu/bitops.h"
+#include "qom/object.h"
enum IMXUsbPhyRegisters {
USBPHY_PWD,
@@ -38,9 +39,9 @@ enum IMXUsbPhyRegisters {
#define USBPHY_CTRL_SFTRST BIT(31)
#define TYPE_IMX_USBPHY "imx.usbphy"
-#define IMX_USBPHY(obj) OBJECT_CHECK(IMXUSBPHYState, (obj), TYPE_IMX_USBPHY)
+OBJECT_DECLARE_SIMPLE_TYPE(IMXUSBPHYState, IMX_USBPHY)
-typedef struct IMXUSBPHYState {
+struct IMXUSBPHYState {
/* <private> */
SysBusDevice parent_obj;
@@ -48,6 +49,6 @@ typedef struct IMXUSBPHYState {
MemoryRegion iomem;
uint32_t usbphy[USBPHY_MAX];
-} IMXUSBPHYState;
+};
#endif /* IMX_USB_PHY_H */
diff --git a/include/hw/usb/msd.h b/include/hw/usb/msd.h
new file mode 100644
index 0000000000..f9fd862b52
--- /dev/null
+++ b/include/hw/usb/msd.h
@@ -0,0 +1,55 @@
+/*
+ * USB Mass Storage Device emulation
+ *
+ * Copyright (c) 2006 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the LGPL.
+ */
+
+#include "hw/usb.h"
+#include "hw/scsi/scsi.h"
+
+enum USBMSDMode {
+ USB_MSDM_CBW, /* Command Block. */
+ USB_MSDM_DATAOUT, /* Transfer data to device. */
+ USB_MSDM_DATAIN, /* Transfer data from device. */
+ USB_MSDM_CSW /* Command Status. */
+};
+
+struct QEMU_PACKED usb_msd_csw {
+ uint32_t sig;
+ uint32_t tag;
+ uint32_t residue;
+ uint8_t status;
+};
+
+struct MSDState {
+ USBDevice dev;
+ enum USBMSDMode mode;
+ uint32_t scsi_off;
+ uint32_t scsi_len;
+ uint32_t data_len;
+ struct usb_msd_csw csw;
+ SCSIRequest *req;
+ SCSIBus bus;
+ /* For async completion. */
+ USBPacket *packet;
+ /* usb-storage only */
+ BlockConf conf;
+ bool removable;
+ bool commandlog;
+ SCSIDevice *scsi_dev;
+ bool needs_reset;
+};
+
+typedef struct MSDState MSDState;
+#define TYPE_USB_STORAGE "usb-storage-dev"
+DECLARE_INSTANCE_CHECKER(MSDState, USB_STORAGE_DEV,
+ TYPE_USB_STORAGE)
+
+void usb_msd_transfer_data(SCSIRequest *req, uint32_t len);
+void usb_msd_command_complete(SCSIRequest *req, size_t resid);
+void usb_msd_request_cancelled(SCSIRequest *req);
+void *usb_msd_load_request(QEMUFile *f, SCSIRequest *req);
+void usb_msd_handle_reset(USBDevice *dev);
diff --git a/include/hw/usb/xhci.h b/include/hw/usb/xhci.h
new file mode 100644
index 0000000000..5c90e1373e
--- /dev/null
+++ b/include/hw/usb/xhci.h
@@ -0,0 +1,21 @@
+#ifndef HW_USB_XHCI_H
+#define HW_USB_XHCI_H
+
+#define TYPE_XHCI "base-xhci"
+#define TYPE_NEC_XHCI "nec-usb-xhci"
+#define TYPE_QEMU_XHCI "qemu-xhci"
+#define TYPE_XHCI_SYSBUS "sysbus-xhci"
+
+#define XHCI_MAXPORTS_2 15
+#define XHCI_MAXPORTS_3 15
+
+#define XHCI_MAXPORTS (XHCI_MAXPORTS_2 + XHCI_MAXPORTS_3)
+#define XHCI_MAXSLOTS 64
+#define XHCI_MAXINTRS 16
+
+/* must be power of 2 */
+#define XHCI_LEN_REGS 0x4000
+
+void xhci_sysbus_build_aml(Aml *scope, uint32_t mmio, unsigned int irq);
+
+#endif
diff --git a/include/hw/usb/xlnx-usb-subsystem.h b/include/hw/usb/xlnx-usb-subsystem.h
new file mode 100644
index 0000000000..40f9e97e09
--- /dev/null
+++ b/include/hw/usb/xlnx-usb-subsystem.h
@@ -0,0 +1,47 @@
+/*
+ * QEMU model of the Xilinx usb subsystem
+ *
+ * Copyright (c) 2020 Xilinx Inc. Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
+ *
+ * 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.
+ */
+
+#ifndef XLNX_USB_SUBSYSTEM_H
+#define XLNX_USB_SUBSYSTEM_H
+
+#include "hw/register.h"
+#include "hw/sysbus.h"
+#include "hw/usb/xlnx-versal-usb2-ctrl-regs.h"
+#include "hw/usb/hcd-dwc3.h"
+
+#define TYPE_XILINX_VERSAL_USB2 "xlnx.versal-usb2"
+
+#define VERSAL_USB2(obj) \
+ OBJECT_CHECK(VersalUsb2, (obj), TYPE_XILINX_VERSAL_USB2)
+
+typedef struct VersalUsb2 {
+ SysBusDevice parent_obj;
+ MemoryRegion dwc3_mr;
+ MemoryRegion usb2Ctrl_mr;
+
+ VersalUsb2CtrlRegs usb2Ctrl;
+ USBDWC3 dwc3;
+} VersalUsb2;
+
+#endif
diff --git a/include/hw/usb/xlnx-versal-usb2-ctrl-regs.h b/include/hw/usb/xlnx-versal-usb2-ctrl-regs.h
new file mode 100644
index 0000000000..6a502006b0
--- /dev/null
+++ b/include/hw/usb/xlnx-versal-usb2-ctrl-regs.h
@@ -0,0 +1,48 @@
+/*
+ * QEMU model of the VersalUsb2CtrlRegs Register control/Status block for
+ * USB2.0 controller
+ *
+ * Copyright (c) 2020 Xilinx Inc. Vikram Garhwal <fnu.vikram@xilinx.com>
+ *
+ * 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.
+ */
+
+#ifndef XLNX_VERSAL_USB2_CTRL_REGS_H
+#define XLNX_VERSAL_USB2_CTRL_REGS_H
+
+#include "hw/register.h"
+#include "hw/sysbus.h"
+
+#define TYPE_XILINX_VERSAL_USB2_CTRL_REGS "xlnx.versal-usb2-ctrl-regs"
+
+#define XILINX_VERSAL_USB2_CTRL_REGS(obj) \
+ OBJECT_CHECK(VersalUsb2CtrlRegs, (obj), TYPE_XILINX_VERSAL_USB2_CTRL_REGS)
+
+#define USB2_REGS_R_MAX ((0x78 / 4) + 1)
+
+typedef struct VersalUsb2CtrlRegs {
+ SysBusDevice parent_obj;
+ MemoryRegion iomem;
+ qemu_irq irq_ir;
+
+ uint32_t regs[USB2_REGS_R_MAX];
+ RegisterInfo regs_info[USB2_REGS_R_MAX];
+} VersalUsb2CtrlRegs;
+
+#endif
diff --git a/include/hw/vfio/vfio-amd-xgbe.h b/include/hw/vfio/vfio-amd-xgbe.h
index 9fff65e99d..a894546c02 100644
--- a/include/hw/vfio/vfio-amd-xgbe.h
+++ b/include/hw/vfio/vfio-amd-xgbe.h
@@ -15,6 +15,7 @@
#define HW_VFIO_VFIO_AMD_XGBE_H
#include "hw/vfio/vfio-platform.h"
+#include "qom/object.h"
#define TYPE_VFIO_AMD_XGBE "vfio-amd-xgbe"
@@ -39,13 +40,7 @@ struct VFIOAmdXgbeDeviceClass {
typedef struct VFIOAmdXgbeDeviceClass VFIOAmdXgbeDeviceClass;
-#define VFIO_AMD_XGBE_DEVICE(obj) \
- OBJECT_CHECK(VFIOAmdXgbeDevice, (obj), TYPE_VFIO_AMD_XGBE)
-#define VFIO_AMD_XGBE_DEVICE_CLASS(klass) \
- OBJECT_CLASS_CHECK(VFIOAmdXgbeDeviceClass, (klass), \
- TYPE_VFIO_AMD_XGBE)
-#define VFIO_AMD_XGBE_DEVICE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(VFIOAmdXgbeDeviceClass, (obj), \
- TYPE_VFIO_AMD_XGBE)
+DECLARE_OBJ_CHECKERS(VFIOAmdXgbeDevice, VFIOAmdXgbeDeviceClass,
+ VFIO_AMD_XGBE_DEVICE, TYPE_VFIO_AMD_XGBE)
#endif
diff --git a/include/hw/vfio/vfio-calxeda-xgmac.h b/include/hw/vfio/vfio-calxeda-xgmac.h
index f994775c09..8482f151dd 100644
--- a/include/hw/vfio/vfio-calxeda-xgmac.h
+++ b/include/hw/vfio/vfio-calxeda-xgmac.h
@@ -15,6 +15,7 @@
#define HW_VFIO_VFIO_CALXEDA_XGMAC_H
#include "hw/vfio/vfio-platform.h"
+#include "qom/object.h"
#define TYPE_VFIO_CALXEDA_XGMAC "vfio-calxeda-xgmac"
@@ -23,24 +24,20 @@
* - a single MMIO region corresponding to its register space
* - 3 IRQS (main and 2 power related IRQs)
*/
-typedef struct VFIOCalxedaXgmacDevice {
+struct VFIOCalxedaXgmacDevice {
VFIOPlatformDevice vdev;
-} VFIOCalxedaXgmacDevice;
+};
+typedef struct VFIOCalxedaXgmacDevice VFIOCalxedaXgmacDevice;
-typedef struct VFIOCalxedaXgmacDeviceClass {
+struct VFIOCalxedaXgmacDeviceClass {
/*< private >*/
VFIOPlatformDeviceClass parent_class;
/*< public >*/
DeviceRealize parent_realize;
-} VFIOCalxedaXgmacDeviceClass;
+};
+typedef struct VFIOCalxedaXgmacDeviceClass VFIOCalxedaXgmacDeviceClass;
-#define VFIO_CALXEDA_XGMAC_DEVICE(obj) \
- OBJECT_CHECK(VFIOCalxedaXgmacDevice, (obj), TYPE_VFIO_CALXEDA_XGMAC)
-#define VFIO_CALXEDA_XGMAC_DEVICE_CLASS(klass) \
- OBJECT_CLASS_CHECK(VFIOCalxedaXgmacDeviceClass, (klass), \
- TYPE_VFIO_CALXEDA_XGMAC)
-#define VFIO_CALXEDA_XGMAC_DEVICE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(VFIOCalxedaXgmacDeviceClass, (obj), \
- TYPE_VFIO_CALXEDA_XGMAC)
+DECLARE_OBJ_CHECKERS(VFIOCalxedaXgmacDevice, VFIOCalxedaXgmacDeviceClass,
+ VFIO_CALXEDA_XGMAC_DEVICE, TYPE_VFIO_CALXEDA_XGMAC)
#endif
diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
index c78f3ff559..b9da6c08ef 100644
--- a/include/hw/vfio/vfio-common.h
+++ b/include/hw/vfio/vfio-common.h
@@ -29,6 +29,8 @@
#ifdef CONFIG_LINUX
#include <linux/vfio.h>
#endif
+#include "sysemu/sysemu.h"
+#include "hw/vfio/vfio-container-base.h"
#define VFIO_MSG_PREFIX "vfio %s: "
@@ -57,37 +59,29 @@ typedef struct VFIORegion {
uint8_t nr; /* cache the region number for debug */
} VFIORegion;
-typedef struct VFIOAddressSpace {
- AddressSpace *as;
- QLIST_HEAD(, VFIOContainer) containers;
- QLIST_ENTRY(VFIOAddressSpace) list;
-} VFIOAddressSpace;
+typedef struct VFIOMigration {
+ struct VFIODevice *vbasedev;
+ VMChangeStateEntry *vm_state;
+ NotifierWithReturn migration_state;
+ uint32_t device_state;
+ int data_fd;
+ void *data_buffer;
+ size_t data_buffer_size;
+ uint64_t mig_flags;
+ uint64_t precopy_init_size;
+ uint64_t precopy_dirty_size;
+ bool initial_data_sent;
+} VFIOMigration;
struct VFIOGroup;
typedef struct VFIOContainer {
- VFIOAddressSpace *space;
+ VFIOContainerBase bcontainer;
int fd; /* /dev/vfio/vfio, empowered by the attached groups */
- MemoryListener listener;
- MemoryListener prereg_listener;
unsigned iommu_type;
- Error *error;
- bool initialized;
- unsigned long pgsizes;
- QLIST_HEAD(, VFIOGuestIOMMU) giommu_list;
- QLIST_HEAD(, VFIOHostDMAWindow) hostwin_list;
QLIST_HEAD(, VFIOGroup) group_list;
- QLIST_ENTRY(VFIOContainer) next;
} VFIOContainer;
-typedef struct VFIOGuestIOMMU {
- VFIOContainer *container;
- IOMMUMemoryRegion *iommu;
- hwaddr iommu_offset;
- IOMMUNotifier n;
- QLIST_ENTRY(VFIOGuestIOMMU) giommu_next;
-} VFIOGuestIOMMU;
-
typedef struct VFIOHostDMAWindow {
hwaddr min_iova;
hwaddr max_iova;
@@ -95,11 +89,22 @@ typedef struct VFIOHostDMAWindow {
QLIST_ENTRY(VFIOHostDMAWindow) hostwin_next;
} VFIOHostDMAWindow;
+typedef struct IOMMUFDBackend IOMMUFDBackend;
+
+typedef struct VFIOIOMMUFDContainer {
+ VFIOContainerBase bcontainer;
+ IOMMUFDBackend *be;
+ uint32_t ioas_id;
+} VFIOIOMMUFDContainer;
+
typedef struct VFIODeviceOps VFIODeviceOps;
typedef struct VFIODevice {
QLIST_ENTRY(VFIODevice) next;
+ QLIST_ENTRY(VFIODevice) container_next;
+ QLIST_ENTRY(VFIODevice) global_next;
struct VFIOGroup *group;
+ VFIOContainerBase *bcontainer;
char *sysfsdev;
char *name;
DeviceState *dev;
@@ -109,16 +114,27 @@ typedef struct VFIODevice {
bool needs_reset;
bool no_mmap;
bool ram_block_discard_allowed;
+ OnOffAuto enable_migration;
VFIODeviceOps *ops;
unsigned int num_irqs;
unsigned int num_regions;
unsigned int flags;
+ VFIOMigration *migration;
+ Error *migration_blocker;
+ OnOffAuto pre_copy_dirty_page_tracking;
+ bool dirty_pages_supported;
+ bool dirty_tracking;
+ int devid;
+ IOMMUFDBackend *iommufd;
} VFIODevice;
struct VFIODeviceOps {
void (*vfio_compute_needs_reset)(VFIODevice *vdev);
int (*vfio_hot_reset_multi)(VFIODevice *vdev);
void (*vfio_eoi)(VFIODevice *vdev);
+ Object *(*vfio_get_object)(VFIODevice *vdev);
+ void (*vfio_save_config)(VFIODevice *vdev, QEMUFile *f);
+ int (*vfio_load_config)(VFIODevice *vdev, QEMUFile *f);
};
typedef struct VFIOGroup {
@@ -157,7 +173,13 @@ typedef struct VFIODisplay {
} dmabuf;
} VFIODisplay;
-void vfio_put_base_device(VFIODevice *vbasedev);
+VFIOAddressSpace *vfio_get_address_space(AddressSpace *as);
+void vfio_put_address_space(VFIOAddressSpace *space);
+
+/* SPAPR specific */
+int vfio_spapr_container_init(VFIOContainer *container, Error **errp);
+void vfio_spapr_container_deinit(VFIOContainer *container);
+
void vfio_disable_irqindex(VFIODevice *vbasedev, int index);
void vfio_unmask_single_irqindex(VFIODevice *vbasedev, int index);
void vfio_mask_single_irqindex(VFIODevice *vbasedev, int index);
@@ -171,17 +193,37 @@ int vfio_region_setup(Object *obj, VFIODevice *vbasedev, VFIORegion *region,
int index, const char *name);
int vfio_region_mmap(VFIORegion *region);
void vfio_region_mmaps_set_enabled(VFIORegion *region, bool enabled);
+void vfio_region_unmap(VFIORegion *region);
void vfio_region_exit(VFIORegion *region);
void vfio_region_finalize(VFIORegion *region);
void vfio_reset_handler(void *opaque);
-VFIOGroup *vfio_get_group(int groupid, AddressSpace *as, Error **errp);
-void vfio_put_group(VFIOGroup *group);
-int vfio_get_device(VFIOGroup *group, const char *name,
- VFIODevice *vbasedev, Error **errp);
+struct vfio_device_info *vfio_get_device_info(int fd);
+int vfio_attach_device(char *name, VFIODevice *vbasedev,
+ AddressSpace *as, Error **errp);
+void vfio_detach_device(VFIODevice *vbasedev);
+
+int vfio_kvm_device_add_fd(int fd, Error **errp);
+int vfio_kvm_device_del_fd(int fd, Error **errp);
+
+int vfio_cpr_register_container(VFIOContainerBase *bcontainer, Error **errp);
+void vfio_cpr_unregister_container(VFIOContainerBase *bcontainer);
extern const MemoryRegionOps vfio_region_ops;
typedef QLIST_HEAD(VFIOGroupList, VFIOGroup) VFIOGroupList;
+typedef QLIST_HEAD(VFIODeviceList, VFIODevice) VFIODeviceList;
extern VFIOGroupList vfio_group_list;
+extern VFIODeviceList vfio_device_list;
+extern const MemoryListener vfio_memory_listener;
+extern int vfio_kvm_device_fd;
+
+bool vfio_mig_active(void);
+int vfio_block_multiple_devices_migration(VFIODevice *vbasedev, Error **errp);
+void vfio_unblock_multiple_devices_migration(void);
+bool vfio_viommu_preset(VFIODevice *vbasedev);
+int64_t vfio_mig_bytes_transferred(void);
+void vfio_reset_bytes_transferred(void);
+bool vfio_device_state_is_running(VFIODevice *vbasedev);
+bool vfio_device_state_is_precopy(VFIODevice *vbasedev);
#ifdef CONFIG_LINUX
int vfio_get_region_info(VFIODevice *vbasedev, int index,
@@ -191,13 +233,31 @@ int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type,
bool vfio_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_type);
struct vfio_info_cap_header *
vfio_get_region_info_cap(struct vfio_region_info *info, uint16_t id);
+bool vfio_get_info_dma_avail(struct vfio_iommu_type1_info *info,
+ unsigned int *avail);
+struct vfio_info_cap_header *
+vfio_get_device_info_cap(struct vfio_device_info *info, uint16_t id);
+struct vfio_info_cap_header *
+vfio_get_cap(void *ptr, uint32_t cap_offset, uint16_t id);
#endif
-extern const MemoryListener vfio_prereg_listener;
-int vfio_spapr_create_window(VFIOContainer *container,
- MemoryRegionSection *section,
- hwaddr *pgsize);
-int vfio_spapr_remove_window(VFIOContainer *container,
- hwaddr offset_within_address_space);
+bool vfio_migration_realize(VFIODevice *vbasedev, Error **errp);
+void vfio_migration_exit(VFIODevice *vbasedev);
+
+int vfio_bitmap_alloc(VFIOBitmap *vbmap, hwaddr size);
+bool
+vfio_devices_all_running_and_mig_active(const VFIOContainerBase *bcontainer);
+bool
+vfio_devices_all_device_dirty_tracking(const VFIOContainerBase *bcontainer);
+int vfio_devices_query_dirty_bitmap(const VFIOContainerBase *bcontainer,
+ VFIOBitmap *vbmap, hwaddr iova,
+ hwaddr size);
+int vfio_get_dirty_bitmap(const VFIOContainerBase *bcontainer, uint64_t iova,
+ uint64_t size, ram_addr_t ram_addr);
+/* Returns 0 on success, or a negative errno. */
+int vfio_device_get_name(VFIODevice *vbasedev, Error **errp);
+void vfio_device_set_fd(VFIODevice *vbasedev, const char *str, Error **errp);
+void vfio_device_init(VFIODevice *vbasedev, int type, VFIODeviceOps *ops,
+ DeviceState *dev, bool ram_discard);
#endif /* HW_VFIO_VFIO_COMMON_H */
diff --git a/include/hw/vfio/vfio-container-base.h b/include/hw/vfio/vfio-container-base.h
new file mode 100644
index 0000000000..3582d5f97a
--- /dev/null
+++ b/include/hw/vfio/vfio-container-base.h
@@ -0,0 +1,141 @@
+/*
+ * VFIO BASE CONTAINER
+ *
+ * Copyright (C) 2023 Intel Corporation.
+ * Copyright Red Hat, Inc. 2023
+ *
+ * Authors: Yi Liu <yi.l.liu@intel.com>
+ * Eric Auger <eric.auger@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_VFIO_VFIO_CONTAINER_BASE_H
+#define HW_VFIO_VFIO_CONTAINER_BASE_H
+
+#include "exec/memory.h"
+
+typedef struct VFIODevice VFIODevice;
+typedef struct VFIOIOMMUClass VFIOIOMMUClass;
+
+typedef struct {
+ unsigned long *bitmap;
+ hwaddr size;
+ hwaddr pages;
+} VFIOBitmap;
+
+typedef struct VFIOAddressSpace {
+ AddressSpace *as;
+ QLIST_HEAD(, VFIOContainerBase) containers;
+ QLIST_ENTRY(VFIOAddressSpace) list;
+} VFIOAddressSpace;
+
+/*
+ * This is the base object for vfio container backends
+ */
+typedef struct VFIOContainerBase {
+ const VFIOIOMMUClass *ops;
+ VFIOAddressSpace *space;
+ MemoryListener listener;
+ Error *error;
+ bool initialized;
+ uint64_t dirty_pgsizes;
+ uint64_t max_dirty_bitmap_size;
+ unsigned long pgsizes;
+ unsigned int dma_max_mappings;
+ bool dirty_pages_supported;
+ QLIST_HEAD(, VFIOGuestIOMMU) giommu_list;
+ QLIST_HEAD(, VFIORamDiscardListener) vrdl_list;
+ QLIST_ENTRY(VFIOContainerBase) next;
+ QLIST_HEAD(, VFIODevice) device_list;
+ GList *iova_ranges;
+ NotifierWithReturn cpr_reboot_notifier;
+} VFIOContainerBase;
+
+typedef struct VFIOGuestIOMMU {
+ VFIOContainerBase *bcontainer;
+ IOMMUMemoryRegion *iommu_mr;
+ hwaddr iommu_offset;
+ IOMMUNotifier n;
+ QLIST_ENTRY(VFIOGuestIOMMU) giommu_next;
+} VFIOGuestIOMMU;
+
+typedef struct VFIORamDiscardListener {
+ VFIOContainerBase *bcontainer;
+ MemoryRegion *mr;
+ hwaddr offset_within_address_space;
+ hwaddr size;
+ uint64_t granularity;
+ RamDiscardListener listener;
+ QLIST_ENTRY(VFIORamDiscardListener) next;
+} VFIORamDiscardListener;
+
+int vfio_container_dma_map(VFIOContainerBase *bcontainer,
+ hwaddr iova, ram_addr_t size,
+ void *vaddr, bool readonly);
+int vfio_container_dma_unmap(VFIOContainerBase *bcontainer,
+ hwaddr iova, ram_addr_t size,
+ IOMMUTLBEntry *iotlb);
+int vfio_container_add_section_window(VFIOContainerBase *bcontainer,
+ MemoryRegionSection *section,
+ Error **errp);
+void vfio_container_del_section_window(VFIOContainerBase *bcontainer,
+ MemoryRegionSection *section);
+int vfio_container_set_dirty_page_tracking(VFIOContainerBase *bcontainer,
+ bool start);
+int vfio_container_query_dirty_bitmap(const VFIOContainerBase *bcontainer,
+ VFIOBitmap *vbmap,
+ hwaddr iova, hwaddr size);
+
+void vfio_container_init(VFIOContainerBase *bcontainer,
+ VFIOAddressSpace *space,
+ const VFIOIOMMUClass *ops);
+void vfio_container_destroy(VFIOContainerBase *bcontainer);
+
+
+#define TYPE_VFIO_IOMMU "vfio-iommu"
+#define TYPE_VFIO_IOMMU_LEGACY TYPE_VFIO_IOMMU "-legacy"
+#define TYPE_VFIO_IOMMU_SPAPR TYPE_VFIO_IOMMU "-spapr"
+#define TYPE_VFIO_IOMMU_IOMMUFD TYPE_VFIO_IOMMU "-iommufd"
+
+/*
+ * VFIOContainerBase is not an abstract QOM object because it felt
+ * unnecessary to expose all the IOMMU backends to the QEMU machine
+ * and human interface. However, we can still abstract the IOMMU
+ * backend handlers using a QOM interface class. This provides more
+ * flexibility when referencing the various implementations.
+ */
+DECLARE_CLASS_CHECKERS(VFIOIOMMUClass, VFIO_IOMMU, TYPE_VFIO_IOMMU)
+
+struct VFIOIOMMUClass {
+ InterfaceClass parent_class;
+
+ /* basic feature */
+ int (*setup)(VFIOContainerBase *bcontainer, Error **errp);
+ int (*dma_map)(const VFIOContainerBase *bcontainer,
+ hwaddr iova, ram_addr_t size,
+ void *vaddr, bool readonly);
+ int (*dma_unmap)(const VFIOContainerBase *bcontainer,
+ hwaddr iova, ram_addr_t size,
+ IOMMUTLBEntry *iotlb);
+ int (*attach_device)(const char *name, VFIODevice *vbasedev,
+ AddressSpace *as, Error **errp);
+ void (*detach_device)(VFIODevice *vbasedev);
+ /* migration feature */
+ int (*set_dirty_page_tracking)(const VFIOContainerBase *bcontainer,
+ bool start);
+ int (*query_dirty_bitmap)(const VFIOContainerBase *bcontainer,
+ VFIOBitmap *vbmap,
+ hwaddr iova, hwaddr size);
+ /* PCI specific */
+ int (*pci_hot_reset)(VFIODevice *vbasedev, bool single);
+
+ /* SPAPR specific */
+ int (*add_window)(VFIOContainerBase *bcontainer,
+ MemoryRegionSection *section,
+ Error **errp);
+ void (*del_window)(VFIOContainerBase *bcontainer,
+ MemoryRegionSection *section);
+ void (*release)(VFIOContainerBase *bcontainer);
+};
+#endif /* HW_VFIO_VFIO_CONTAINER_BASE_H */
diff --git a/include/hw/vfio/vfio-platform.h b/include/hw/vfio/vfio-platform.h
index 4ec70c813a..c414c3dffc 100644
--- a/include/hw/vfio/vfio-platform.h
+++ b/include/hw/vfio/vfio-platform.h
@@ -20,6 +20,7 @@
#include "hw/vfio/vfio-common.h"
#include "qemu/event_notifier.h"
#include "qemu/queue.h"
+#include "qom/object.h"
#define TYPE_VFIO_PLATFORM "vfio-platform"
@@ -46,7 +47,7 @@ typedef struct VFIOINTp {
/* function type for user side eventfd handler */
typedef void (*eventfd_user_side_handler_t)(VFIOINTp *intp);
-typedef struct VFIOPlatformDevice {
+struct VFIOPlatformDevice {
SysBusDevice sbdev;
VFIODevice vbasedev; /* not a QOM object */
VFIORegion **regions;
@@ -59,19 +60,17 @@ typedef struct VFIOPlatformDevice {
QEMUTimer *mmap_timer; /* allows fast-path resume after IRQ hit */
QemuMutex intp_mutex; /* protect the intp_list IRQ state */
bool irqfd_allowed; /* debug option to force irqfd on/off */
-} VFIOPlatformDevice;
+};
+typedef struct VFIOPlatformDevice VFIOPlatformDevice;
-typedef struct VFIOPlatformDeviceClass {
+struct VFIOPlatformDeviceClass {
/*< private >*/
SysBusDeviceClass parent_class;
/*< public >*/
-} VFIOPlatformDeviceClass;
+};
+typedef struct VFIOPlatformDeviceClass VFIOPlatformDeviceClass;
-#define VFIO_PLATFORM_DEVICE(obj) \
- OBJECT_CHECK(VFIOPlatformDevice, (obj), TYPE_VFIO_PLATFORM)
-#define VFIO_PLATFORM_DEVICE_CLASS(klass) \
- OBJECT_CLASS_CHECK(VFIOPlatformDeviceClass, (klass), TYPE_VFIO_PLATFORM)
-#define VFIO_PLATFORM_DEVICE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(VFIOPlatformDeviceClass, (obj), TYPE_VFIO_PLATFORM)
+DECLARE_OBJ_CHECKERS(VFIOPlatformDevice, VFIOPlatformDeviceClass,
+ VFIO_PLATFORM_DEVICE, TYPE_VFIO_PLATFORM)
#endif /* HW_VFIO_VFIO_PLATFORM_H */
diff --git a/include/hw/vfio/vfio.h b/include/hw/vfio/vfio.h
deleted file mode 100644
index 86248f5436..0000000000
--- a/include/hw/vfio/vfio.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef HW_VFIO_H
-#define HW_VFIO_H
-
-bool vfio_eeh_as_ok(AddressSpace *as);
-int vfio_eeh_as_op(AddressSpace *as, uint32_t op);
-
-#endif
diff --git a/include/hw/virtio/vdpa-dev.h b/include/hw/virtio/vdpa-dev.h
new file mode 100644
index 0000000000..4dbf98195c
--- /dev/null
+++ b/include/hw/virtio/vdpa-dev.h
@@ -0,0 +1,43 @@
+/*
+ * Vhost Vdpa Device
+ *
+ * Copyright (c) Huawei Technologies Co., Ltd. 2022. All Rights Reserved.
+ *
+ * Authors:
+ * Longpeng <longpeng2@huawei.com>
+ *
+ * Largely based on the "vhost-user-blk.h" implemented by:
+ * Changpeng Liu <changpeng.liu@intel.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+#ifndef _VHOST_VDPA_DEVICE_H
+#define _VHOST_VDPA_DEVICE_H
+
+#include "hw/virtio/vhost.h"
+#include "hw/virtio/vhost-vdpa.h"
+#include "qom/object.h"
+
+
+#define TYPE_VHOST_VDPA_DEVICE "vhost-vdpa-device"
+OBJECT_DECLARE_SIMPLE_TYPE(VhostVdpaDevice, VHOST_VDPA_DEVICE)
+
+struct VhostVdpaDevice {
+ VirtIODevice parent_obj;
+ char *vhostdev;
+ int vhostfd;
+ int32_t bootindex;
+ uint32_t vdev_id;
+ uint32_t num_queues;
+ struct vhost_dev dev;
+ struct vhost_vdpa vdpa;
+ VirtQueue **virtqs;
+ uint8_t *config;
+ int config_size;
+ uint16_t queue_size;
+ bool started;
+ int (*post_init)(VhostVdpaDevice *v, Error **errp);
+};
+
+#endif
diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h
index 8825bd278f..70c2e8ffee 100644
--- a/include/hw/virtio/vhost-backend.h
+++ b/include/hw/virtio/vhost-backend.h
@@ -22,10 +22,22 @@ typedef enum VhostBackendType {
} VhostBackendType;
typedef enum VhostSetConfigType {
- VHOST_SET_CONFIG_TYPE_MASTER = 0,
+ VHOST_SET_CONFIG_TYPE_FRONTEND = 0,
VHOST_SET_CONFIG_TYPE_MIGRATION = 1,
} VhostSetConfigType;
+typedef enum VhostDeviceStateDirection {
+ /* Transfer state from back-end (device) to front-end */
+ VHOST_TRANSFER_STATE_DIRECTION_SAVE = 0,
+ /* Transfer state from front-end to back-end (device) */
+ VHOST_TRANSFER_STATE_DIRECTION_LOAD = 1,
+} VhostDeviceStateDirection;
+
+typedef enum VhostDeviceStatePhase {
+ /* The device (and all its vrings) is stopped */
+ VHOST_TRANSFER_STATE_PHASE_STOPPED = 0,
+} VhostDeviceStatePhase;
+
struct vhost_inflight;
struct vhost_dev;
struct vhost_log;
@@ -33,11 +45,14 @@ struct vhost_memory;
struct vhost_vring_file;
struct vhost_vring_state;
struct vhost_vring_addr;
+struct vhost_vring_worker;
+struct vhost_worker_state;
struct vhost_scsi_target;
struct vhost_iotlb_msg;
struct vhost_virtqueue;
-typedef int (*vhost_backend_init)(struct vhost_dev *dev, void *opaque);
+typedef int (*vhost_backend_init)(struct vhost_dev *dev, void *opaque,
+ Error **errp);
typedef int (*vhost_backend_cleanup)(struct vhost_dev *dev);
typedef int (*vhost_backend_memslots_limit)(struct vhost_dev *dev);
@@ -68,12 +83,23 @@ typedef int (*vhost_set_vring_kick_op)(struct vhost_dev *dev,
struct vhost_vring_file *file);
typedef int (*vhost_set_vring_call_op)(struct vhost_dev *dev,
struct vhost_vring_file *file);
+typedef int (*vhost_set_vring_err_op)(struct vhost_dev *dev,
+ struct vhost_vring_file *file);
typedef int (*vhost_set_vring_busyloop_timeout_op)(struct vhost_dev *dev,
struct vhost_vring_state *r);
+typedef int (*vhost_attach_vring_worker_op)(struct vhost_dev *dev,
+ struct vhost_vring_worker *worker);
+typedef int (*vhost_get_vring_worker_op)(struct vhost_dev *dev,
+ struct vhost_vring_worker *worker);
+typedef int (*vhost_new_worker_op)(struct vhost_dev *dev,
+ struct vhost_worker_state *worker);
+typedef int (*vhost_free_worker_op)(struct vhost_dev *dev,
+ struct vhost_worker_state *worker);
typedef int (*vhost_set_features_op)(struct vhost_dev *dev,
uint64_t features);
typedef int (*vhost_get_features_op)(struct vhost_dev *dev,
uint64_t *features);
+typedef int (*vhost_set_backend_cap_op)(struct vhost_dev *dev);
typedef int (*vhost_set_owner_op)(struct vhost_dev *dev);
typedef int (*vhost_reset_device_op)(struct vhost_dev *dev);
typedef int (*vhost_get_vq_index_op)(struct vhost_dev *dev, int idx);
@@ -82,9 +108,6 @@ typedef int (*vhost_set_vring_enable_op)(struct vhost_dev *dev,
typedef bool (*vhost_requires_shm_log_op)(struct vhost_dev *dev);
typedef int (*vhost_migration_done_op)(struct vhost_dev *dev,
char *mac_addr);
-typedef bool (*vhost_backend_can_merge_op)(struct vhost_dev *dev,
- uint64_t start1, uint64_t size1,
- uint64_t start2, uint64_t size2);
typedef int (*vhost_vsock_set_guest_cid_op)(struct vhost_dev *dev,
uint64_t guest_cid);
typedef int (*vhost_vsock_set_running_op)(struct vhost_dev *dev, int start);
@@ -96,7 +119,7 @@ typedef int (*vhost_set_config_op)(struct vhost_dev *dev, const uint8_t *data,
uint32_t offset, uint32_t size,
uint32_t flags);
typedef int (*vhost_get_config_op)(struct vhost_dev *dev, uint8_t *config,
- uint32_t config_len);
+ uint32_t config_len, Error **errp);
typedef int (*vhost_crypto_create_session_op)(struct vhost_dev *dev,
void *session_info,
@@ -104,8 +127,7 @@ typedef int (*vhost_crypto_create_session_op)(struct vhost_dev *dev,
typedef int (*vhost_crypto_close_session_op)(struct vhost_dev *dev,
uint64_t session_id);
-typedef bool (*vhost_backend_mem_section_filter_op)(struct vhost_dev *dev,
- MemoryRegionSection *section);
+typedef bool (*vhost_backend_no_private_memslots_op)(struct vhost_dev *dev);
typedef int (*vhost_get_inflight_fd_op)(struct vhost_dev *dev,
uint16_t queue_size,
@@ -124,11 +146,26 @@ typedef int (*vhost_get_device_id_op)(struct vhost_dev *dev, uint32_t *dev_id);
typedef bool (*vhost_force_iommu_op)(struct vhost_dev *dev);
+typedef int (*vhost_set_config_call_op)(struct vhost_dev *dev,
+ int fd);
+
+typedef void (*vhost_reset_status_op)(struct vhost_dev *dev);
+
+typedef bool (*vhost_supports_device_state_op)(struct vhost_dev *dev);
+typedef int (*vhost_set_device_state_fd_op)(struct vhost_dev *dev,
+ VhostDeviceStateDirection direction,
+ VhostDeviceStatePhase phase,
+ int fd,
+ int *reply_fd,
+ Error **errp);
+typedef int (*vhost_check_device_state_op)(struct vhost_dev *dev, Error **errp);
+
typedef struct VhostOps {
VhostBackendType backend_type;
vhost_backend_init vhost_backend_init;
vhost_backend_cleanup vhost_backend_cleanup;
vhost_backend_memslots_limit vhost_backend_memslots_limit;
+ vhost_backend_no_private_memslots_op vhost_backend_no_private_memslots;
vhost_net_set_backend_op vhost_net_set_backend;
vhost_net_set_mtu_op vhost_net_set_mtu;
vhost_scsi_set_endpoint_op vhost_scsi_set_endpoint;
@@ -143,16 +180,21 @@ typedef struct VhostOps {
vhost_get_vring_base_op vhost_get_vring_base;
vhost_set_vring_kick_op vhost_set_vring_kick;
vhost_set_vring_call_op vhost_set_vring_call;
+ vhost_set_vring_err_op vhost_set_vring_err;
vhost_set_vring_busyloop_timeout_op vhost_set_vring_busyloop_timeout;
+ vhost_new_worker_op vhost_new_worker;
+ vhost_free_worker_op vhost_free_worker;
+ vhost_get_vring_worker_op vhost_get_vring_worker;
+ vhost_attach_vring_worker_op vhost_attach_vring_worker;
vhost_set_features_op vhost_set_features;
vhost_get_features_op vhost_get_features;
+ vhost_set_backend_cap_op vhost_set_backend_cap;
vhost_set_owner_op vhost_set_owner;
vhost_reset_device_op vhost_reset_device;
vhost_get_vq_index_op vhost_get_vq_index;
vhost_set_vring_enable_op vhost_set_vring_enable;
vhost_requires_shm_log_op vhost_requires_shm_log;
vhost_migration_done_op vhost_migration_done;
- vhost_backend_can_merge_op vhost_backend_can_merge;
vhost_vsock_set_guest_cid_op vhost_vsock_set_guest_cid;
vhost_vsock_set_running_op vhost_vsock_set_running;
vhost_set_iotlb_callback_op vhost_set_iotlb_callback;
@@ -161,21 +203,19 @@ typedef struct VhostOps {
vhost_set_config_op vhost_set_config;
vhost_crypto_create_session_op vhost_crypto_create_session;
vhost_crypto_close_session_op vhost_crypto_close_session;
- vhost_backend_mem_section_filter_op vhost_backend_mem_section_filter;
vhost_get_inflight_fd_op vhost_get_inflight_fd;
vhost_set_inflight_fd_op vhost_set_inflight_fd;
vhost_dev_start_op vhost_dev_start;
vhost_vq_get_addr_op vhost_vq_get_addr;
vhost_get_device_id_op vhost_get_device_id;
vhost_force_iommu_op vhost_force_iommu;
+ vhost_set_config_call_op vhost_set_config_call;
+ vhost_reset_status_op vhost_reset_status;
+ vhost_supports_device_state_op vhost_supports_device_state;
+ vhost_set_device_state_fd_op vhost_set_device_state_fd;
+ vhost_check_device_state_op vhost_check_device_state;
} VhostOps;
-extern const VhostOps user_ops;
-extern const VhostOps vdpa_ops;
-
-int vhost_set_backend_type(struct vhost_dev *dev,
- VhostBackendType backend_type);
-
int vhost_backend_update_device_iotlb(struct vhost_dev *dev,
uint64_t iova, uint64_t uaddr,
uint64_t len,
@@ -189,4 +229,7 @@ int vhost_backend_handle_iotlb_msg(struct vhost_dev *dev,
int vhost_user_gpu_set_socket(struct vhost_dev *dev, int fd);
+int vhost_user_get_shared_object(struct vhost_dev *dev, unsigned char *uuid,
+ int *dmabuf_fd);
+
#endif /* VHOST_BACKEND_H */
diff --git a/include/hw/virtio/vhost-scsi-common.h b/include/hw/virtio/vhost-scsi-common.h
index 16bf1a73c1..c5d2c09455 100644
--- a/include/hw/virtio/vhost-scsi-common.h
+++ b/include/hw/virtio/vhost-scsi-common.h
@@ -17,12 +17,12 @@
#include "hw/virtio/virtio-scsi.h"
#include "hw/virtio/vhost.h"
#include "hw/fw-path-provider.h"
+#include "qom/object.h"
#define TYPE_VHOST_SCSI_COMMON "vhost-scsi-common"
-#define VHOST_SCSI_COMMON(obj) \
- OBJECT_CHECK(VHostSCSICommon, (obj), TYPE_VHOST_SCSI_COMMON)
+OBJECT_DECLARE_SIMPLE_TYPE(VHostSCSICommon, VHOST_SCSI_COMMON)
-typedef struct VHostSCSICommon {
+struct VHostSCSICommon {
VirtIOSCSICommon parent_obj;
Error *migration_blocker;
@@ -35,9 +35,11 @@ typedef struct VHostSCSICommon {
int lun;
uint64_t host_features;
bool migratable;
-} VHostSCSICommon;
-int vhost_scsi_common_start(VHostSCSICommon *vsc);
+ struct vhost_inflight *inflight;
+};
+
+int vhost_scsi_common_start(VHostSCSICommon *vsc, Error **errp);
void vhost_scsi_common_stop(VHostSCSICommon *vsc);
char *vhost_scsi_common_get_fw_dev_path(FWPathProvider *p, BusState *bus,
DeviceState *dev);
diff --git a/include/hw/virtio/vhost-scsi.h b/include/hw/virtio/vhost-scsi.h
index 23252153ff..7dc2bdd69d 100644
--- a/include/hw/virtio/vhost-scsi.h
+++ b/include/hw/virtio/vhost-scsi.h
@@ -17,6 +17,7 @@
#include "hw/virtio/virtio-scsi.h"
#include "hw/virtio/vhost.h"
#include "hw/virtio/vhost-scsi-common.h"
+#include "qom/object.h"
enum vhost_scsi_vq_list {
VHOST_SCSI_VQ_CONTROL = 0,
@@ -25,11 +26,10 @@ enum vhost_scsi_vq_list {
};
#define TYPE_VHOST_SCSI "vhost-scsi"
-#define VHOST_SCSI(obj) \
- OBJECT_CHECK(VHostSCSI, (obj), TYPE_VHOST_SCSI)
+OBJECT_DECLARE_SIMPLE_TYPE(VHostSCSI, VHOST_SCSI)
-typedef struct VHostSCSI {
+struct VHostSCSI {
VHostSCSICommon parent_obj;
-} VHostSCSI;
+};
#endif
diff --git a/include/hw/virtio/vhost-user-base.h b/include/hw/virtio/vhost-user-base.h
new file mode 100644
index 0000000000..51d0968b89
--- /dev/null
+++ b/include/hw/virtio/vhost-user-base.h
@@ -0,0 +1,49 @@
+/*
+ * Vhost-user generic virtio device
+ *
+ * Copyright (c) 2023 Linaro Ltd
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef QEMU_VHOST_USER_BASE_H
+#define QEMU_VHOST_USER_BASE_H
+
+#include "hw/virtio/vhost.h"
+#include "hw/virtio/vhost-user.h"
+
+#define TYPE_VHOST_USER_BASE "vhost-user-base"
+
+OBJECT_DECLARE_TYPE(VHostUserBase, VHostUserBaseClass, VHOST_USER_BASE)
+
+struct VHostUserBase {
+ VirtIODevice parent_obj;
+
+ /* Properties */
+ CharBackend chardev;
+ uint16_t virtio_id;
+ uint32_t num_vqs;
+ uint32_t vq_size; /* can't exceed VIRTIO_QUEUE_MAX */
+ uint32_t config_size;
+ /* State tracking */
+ VhostUserState vhost_user;
+ struct vhost_virtqueue *vhost_vq;
+ struct vhost_dev vhost_dev;
+ GPtrArray *vqs;
+ bool connected;
+};
+
+/*
+ * Needed so we can use the base realize after specialisation
+ * tweaks
+ */
+struct VHostUserBaseClass {
+ VirtioDeviceClass parent_class;
+
+ DeviceRealize parent_realize;
+};
+
+
+#define TYPE_VHOST_USER_DEVICE "vhost-user-device"
+
+#endif /* QEMU_VHOST_USER_BASE_H */
diff --git a/include/hw/virtio/vhost-user-blk.h b/include/hw/virtio/vhost-user-blk.h
index 34ad6f0c0e..ea085ee1ed 100644
--- a/include/hw/virtio/vhost-user-blk.h
+++ b/include/hw/virtio/vhost-user-blk.h
@@ -20,25 +20,36 @@
#include "chardev/char-fe.h"
#include "hw/virtio/vhost.h"
#include "hw/virtio/vhost-user.h"
+#include "qom/object.h"
#define TYPE_VHOST_USER_BLK "vhost-user-blk"
-#define VHOST_USER_BLK(obj) \
- OBJECT_CHECK(VHostUserBlk, (obj), TYPE_VHOST_USER_BLK)
+OBJECT_DECLARE_SIMPLE_TYPE(VHostUserBlk, VHOST_USER_BLK)
-typedef struct VHostUserBlk {
+#define VHOST_USER_BLK_AUTO_NUM_QUEUES UINT16_MAX
+
+struct VHostUserBlk {
VirtIODevice parent_obj;
CharBackend chardev;
int32_t bootindex;
struct virtio_blk_config blkcfg;
uint16_t num_queues;
uint32_t queue_size;
- uint32_t config_wce;
struct vhost_dev dev;
struct vhost_inflight *inflight;
VhostUserState vhost_user;
struct vhost_virtqueue *vhost_vqs;
VirtQueue **virtqs;
+
+ /*
+ * There are at least two steps of initialization of the
+ * vhost-user device. The first is a "connect" step and
+ * second is a "start" step. Make a separation between
+ * those initialization phases by using two fields.
+ */
+ /* vhost_user_blk_connect/vhost_user_blk_disconnect */
bool connected;
-} VHostUserBlk;
+ /* vhost_user_blk_start/vhost_user_blk_stop */
+ bool started_vu;
+};
#endif
diff --git a/include/hw/virtio/vhost-user-fs.h b/include/hw/virtio/vhost-user-fs.h
index 6f3030d288..94c3aaa84e 100644
--- a/include/hw/virtio/vhost-user-fs.h
+++ b/include/hw/virtio/vhost-user-fs.h
@@ -11,17 +11,17 @@
* top-level directory.
*/
-#ifndef _QEMU_VHOST_USER_FS_H
-#define _QEMU_VHOST_USER_FS_H
+#ifndef QEMU_VHOST_USER_FS_H
+#define QEMU_VHOST_USER_FS_H
#include "hw/virtio/virtio.h"
#include "hw/virtio/vhost.h"
#include "hw/virtio/vhost-user.h"
#include "chardev/char-fe.h"
+#include "qom/object.h"
#define TYPE_VHOST_USER_FS "vhost-user-fs-device"
-#define VHOST_USER_FS(obj) \
- OBJECT_CHECK(VHostUserFS, (obj), TYPE_VHOST_USER_FS)
+OBJECT_DECLARE_SIMPLE_TYPE(VHostUserFS, VHOST_USER_FS)
typedef struct {
CharBackend chardev;
@@ -30,7 +30,7 @@ typedef struct {
uint16_t queue_size;
} VHostUserFSConf;
-typedef struct {
+struct VHostUserFS {
/*< private >*/
VirtIODevice parent;
VHostUserFSConf conf;
@@ -39,8 +39,9 @@ typedef struct {
VhostUserState vhost_user;
VirtQueue **req_vqs;
VirtQueue *hiprio_vq;
+ int32_t bootindex;
/*< public >*/
-} VHostUserFS;
+};
-#endif /* _QEMU_VHOST_USER_FS_H */
+#endif /* QEMU_VHOST_USER_FS_H */
diff --git a/include/hw/virtio/vhost-user-gpio.h b/include/hw/virtio/vhost-user-gpio.h
new file mode 100644
index 0000000000..5814a8400a
--- /dev/null
+++ b/include/hw/virtio/vhost-user-gpio.h
@@ -0,0 +1,24 @@
+/*
+ * Vhost-user GPIO virtio device
+ *
+ * Copyright (c) 2021 Viresh Kumar <viresh.kumar@linaro.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef _QEMU_VHOST_USER_GPIO_H
+#define _QEMU_VHOST_USER_GPIO_H
+
+#include "hw/virtio/virtio.h"
+#include "hw/virtio/vhost.h"
+#include "hw/virtio/vhost-user.h"
+#include "hw/virtio/vhost-user-base.h"
+
+#define TYPE_VHOST_USER_GPIO "vhost-user-gpio-device"
+OBJECT_DECLARE_SIMPLE_TYPE(VHostUserGPIO, VHOST_USER_GPIO);
+
+struct VHostUserGPIO {
+ VHostUserBase parent_obj;
+};
+
+#endif /* _QEMU_VHOST_USER_GPIO_H */
diff --git a/include/hw/virtio/vhost-user-i2c.h b/include/hw/virtio/vhost-user-i2c.h
new file mode 100644
index 0000000000..a9b5612ad0
--- /dev/null
+++ b/include/hw/virtio/vhost-user-i2c.h
@@ -0,0 +1,25 @@
+/*
+ * Vhost-user i2c virtio device
+ *
+ * Copyright (c) 2021 Viresh Kumar <viresh.kumar@linaro.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef QEMU_VHOST_USER_I2C_H
+#define QEMU_VHOST_USER_I2C_H
+
+#include "hw/virtio/virtio.h"
+#include "hw/virtio/vhost.h"
+#include "hw/virtio/vhost-user.h"
+#include "hw/virtio/vhost-user-base.h"
+
+#define TYPE_VHOST_USER_I2C "vhost-user-i2c-device"
+
+OBJECT_DECLARE_SIMPLE_TYPE(VHostUserI2C, VHOST_USER_I2C)
+
+struct VHostUserI2C {
+ VHostUserBase parent_obj;
+};
+
+#endif /* QEMU_VHOST_USER_I2C_H */
diff --git a/include/hw/virtio/vhost-user-rng.h b/include/hw/virtio/vhost-user-rng.h
new file mode 100644
index 0000000000..10868c7de4
--- /dev/null
+++ b/include/hw/virtio/vhost-user-rng.h
@@ -0,0 +1,24 @@
+/*
+ * Vhost-user RNG virtio device
+ *
+ * Copyright (c) 2021 Mathieu Poirier <mathieu.poirier@linaro.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef QEMU_VHOST_USER_RNG_H
+#define QEMU_VHOST_USER_RNG_H
+
+#include "hw/virtio/virtio.h"
+#include "hw/virtio/vhost.h"
+#include "hw/virtio/vhost-user.h"
+#include "hw/virtio/vhost-user-base.h"
+
+#define TYPE_VHOST_USER_RNG "vhost-user-rng"
+OBJECT_DECLARE_SIMPLE_TYPE(VHostUserRNG, VHOST_USER_RNG)
+
+struct VHostUserRNG {
+ VHostUserBase parent_obj;
+};
+
+#endif /* QEMU_VHOST_USER_RNG_H */
diff --git a/include/hw/virtio/vhost-user-scmi.h b/include/hw/virtio/vhost-user-scmi.h
new file mode 100644
index 0000000000..c90db77dd5
--- /dev/null
+++ b/include/hw/virtio/vhost-user-scmi.h
@@ -0,0 +1,31 @@
+/*
+ * Vhost-user SCMI virtio device
+ *
+ * Copyright (c) 2023 Red Hat, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef _QEMU_VHOST_USER_SCMI_H
+#define _QEMU_VHOST_USER_SCMI_H
+
+#include "hw/virtio/virtio.h"
+#include "hw/virtio/vhost.h"
+#include "hw/virtio/vhost-user.h"
+
+#define TYPE_VHOST_USER_SCMI "vhost-user-scmi"
+OBJECT_DECLARE_SIMPLE_TYPE(VHostUserSCMI, VHOST_USER_SCMI);
+
+struct VHostUserSCMI {
+ VirtIODevice parent;
+ CharBackend chardev;
+ struct vhost_virtqueue *vhost_vqs;
+ struct vhost_dev vhost_dev;
+ VhostUserState vhost_user;
+ VirtQueue *cmd_vq;
+ VirtQueue *event_vq;
+ bool connected;
+ bool started_vu;
+};
+
+#endif /* _QEMU_VHOST_USER_SCMI_H */
diff --git a/include/hw/virtio/vhost-user-scsi.h b/include/hw/virtio/vhost-user-scsi.h
index 99ab2f2cc4..78fe616ccb 100644
--- a/include/hw/virtio/vhost-user-scsi.h
+++ b/include/hw/virtio/vhost-user-scsi.h
@@ -21,14 +21,20 @@
#include "hw/virtio/vhost.h"
#include "hw/virtio/vhost-user.h"
#include "hw/virtio/vhost-scsi-common.h"
+#include "qom/object.h"
#define TYPE_VHOST_USER_SCSI "vhost-user-scsi"
-#define VHOST_USER_SCSI(obj) \
- OBJECT_CHECK(VHostUserSCSI, (obj), TYPE_VHOST_USER_SCSI)
+OBJECT_DECLARE_SIMPLE_TYPE(VHostUserSCSI, VHOST_USER_SCSI)
-typedef struct VHostUserSCSI {
+struct VHostUserSCSI {
VHostSCSICommon parent_obj;
+
+ /* Properties */
+ bool connected;
+ bool started_vu;
+
VhostUserState vhost_user;
-} VHostUserSCSI;
+ struct vhost_virtqueue *vhost_vqs;
+};
#endif /* VHOST_USER_SCSI_H */
diff --git a/include/hw/virtio/vhost-user-snd.h b/include/hw/virtio/vhost-user-snd.h
new file mode 100644
index 0000000000..f9260116a7
--- /dev/null
+++ b/include/hw/virtio/vhost-user-snd.h
@@ -0,0 +1,24 @@
+/*
+ * Vhost-user Sound virtio device
+ *
+ * Copyright (c) 2021 Mathieu Poirier <mathieu.poirier@linaro.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef QEMU_VHOST_USER_SND_H
+#define QEMU_VHOST_USER_SND_H
+
+#include "hw/virtio/virtio.h"
+#include "hw/virtio/vhost.h"
+#include "hw/virtio/vhost-user.h"
+#include "hw/virtio/vhost-user-base.h"
+
+#define TYPE_VHOST_USER_SND "vhost-user-snd"
+OBJECT_DECLARE_SIMPLE_TYPE(VHostUserSound, VHOST_USER_SND)
+
+struct VHostUserSound {
+ VHostUserBase parent_obj;
+};
+
+#endif /* QEMU_VHOST_USER_SND_H */
diff --git a/include/hw/virtio/vhost-user-vsock.h b/include/hw/virtio/vhost-user-vsock.h
index 4e128a4b9f..67aa46c952 100644
--- a/include/hw/virtio/vhost-user-vsock.h
+++ b/include/hw/virtio/vhost-user-vsock.h
@@ -8,22 +8,22 @@
* top-level directory.
*/
-#ifndef _QEMU_VHOST_USER_VSOCK_H
-#define _QEMU_VHOST_USER_VSOCK_H
+#ifndef QEMU_VHOST_USER_VSOCK_H
+#define QEMU_VHOST_USER_VSOCK_H
#include "hw/virtio/vhost-vsock-common.h"
#include "hw/virtio/vhost-user.h"
#include "standard-headers/linux/virtio_vsock.h"
+#include "qom/object.h"
#define TYPE_VHOST_USER_VSOCK "vhost-user-vsock-device"
-#define VHOST_USER_VSOCK(obj) \
- OBJECT_CHECK(VHostUserVSock, (obj), TYPE_VHOST_USER_VSOCK)
+OBJECT_DECLARE_SIMPLE_TYPE(VHostUserVSock, VHOST_USER_VSOCK)
typedef struct {
CharBackend chardev;
} VHostUserVSockConf;
-typedef struct {
+struct VHostUserVSock {
/*< private >*/
VHostVSockCommon parent;
VhostUserState vhost_user;
@@ -31,6 +31,6 @@ typedef struct {
struct virtio_vsock_config vsockcfg;
/*< public >*/
-} VHostUserVSock;
+};
-#endif /* _QEMU_VHOST_USER_VSOCK_H */
+#endif /* QEMU_VHOST_USER_VSOCK_H */
diff --git a/include/hw/virtio/vhost-user.h b/include/hw/virtio/vhost-user.h
index a9abca3288..d7c09ffd34 100644
--- a/include/hw/virtio/vhost-user.h
+++ b/include/hw/virtio/vhost-user.h
@@ -11,19 +11,104 @@
#include "chardev/char-fe.h"
#include "hw/virtio/virtio.h"
+enum VhostUserProtocolFeature {
+ VHOST_USER_PROTOCOL_F_MQ = 0,
+ VHOST_USER_PROTOCOL_F_LOG_SHMFD = 1,
+ VHOST_USER_PROTOCOL_F_RARP = 2,
+ VHOST_USER_PROTOCOL_F_REPLY_ACK = 3,
+ VHOST_USER_PROTOCOL_F_NET_MTU = 4,
+ VHOST_USER_PROTOCOL_F_BACKEND_REQ = 5,
+ VHOST_USER_PROTOCOL_F_CROSS_ENDIAN = 6,
+ VHOST_USER_PROTOCOL_F_CRYPTO_SESSION = 7,
+ VHOST_USER_PROTOCOL_F_PAGEFAULT = 8,
+ VHOST_USER_PROTOCOL_F_CONFIG = 9,
+ VHOST_USER_PROTOCOL_F_BACKEND_SEND_FD = 10,
+ VHOST_USER_PROTOCOL_F_HOST_NOTIFIER = 11,
+ VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD = 12,
+ VHOST_USER_PROTOCOL_F_RESET_DEVICE = 13,
+ VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS = 14,
+ VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS = 15,
+ VHOST_USER_PROTOCOL_F_STATUS = 16,
+ /* Feature 17 reserved for VHOST_USER_PROTOCOL_F_XEN_MMAP. */
+ VHOST_USER_PROTOCOL_F_SHARED_OBJECT = 18,
+ VHOST_USER_PROTOCOL_F_DEVICE_STATE = 19,
+ VHOST_USER_PROTOCOL_F_MAX
+};
+
+/**
+ * VhostUserHostNotifier - notifier information for one queue
+ * @rcu: rcu_head for cleanup
+ * @mr: memory region of notifier
+ * @addr: current mapped address
+ * @unmap_addr: address to be un-mapped
+ * @idx: virtioqueue index
+ *
+ * The VhostUserHostNotifier entries are re-used. When an old mapping
+ * is to be released it is moved to @unmap_addr and @addr is replaced.
+ * Once the RCU process has completed the unmap @unmap_addr is
+ * cleared.
+ */
typedef struct VhostUserHostNotifier {
+ struct rcu_head rcu;
MemoryRegion mr;
void *addr;
- bool set;
+ void *unmap_addr;
+ int idx;
} VhostUserHostNotifier;
+/**
+ * VhostUserState - shared state for all vhost-user devices
+ * @chr: the character backend for the socket
+ * @notifiers: GPtrArray of @VhostUserHostnotifier
+ * @memory_slots:
+ */
typedef struct VhostUserState {
CharBackend *chr;
- VhostUserHostNotifier notifier[VIRTIO_QUEUE_MAX];
+ GPtrArray *notifiers;
int memory_slots;
+ bool supports_config;
} VhostUserState;
+/**
+ * vhost_user_init() - initialise shared vhost_user state
+ * @user: allocated area for storing shared state
+ * @chr: the chardev for the vhost socket
+ * @errp: error handle
+ *
+ * User can either directly g_new() space for the state or embed
+ * VhostUserState in their larger device structure and just point to
+ * it.
+ *
+ * Return: true on success, false on error while setting errp.
+ */
bool vhost_user_init(VhostUserState *user, CharBackend *chr, Error **errp);
+
+/**
+ * vhost_user_cleanup() - cleanup state
+ * @user: ptr to use state
+ *
+ * Cleans up shared state and notifiers, callee is responsible for
+ * freeing the @VhostUserState memory itself.
+ */
void vhost_user_cleanup(VhostUserState *user);
+/**
+ * vhost_user_async_close() - cleanup vhost-user post connection drop
+ * @d: DeviceState for the associated device (passed to callback)
+ * @chardev: the CharBackend associated with the connection
+ * @vhost: the common vhost device
+ * @cb: the user callback function to complete the clean-up
+ *
+ * This function is used to handle the shutdown of a vhost-user
+ * connection to a backend. We handle this centrally to make sure we
+ * do all the steps and handle potential races due to VM shutdowns.
+ * Once the connection is disabled we call a backhalf to ensure
+ */
+typedef void (*vu_async_close_fn)(DeviceState *cb);
+
+void vhost_user_async_close(DeviceState *d,
+ CharBackend *chardev, struct vhost_dev *vhost,
+ vu_async_close_fn cb,
+ IOEventHandler *event_cb);
+
#endif
diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h
index 6455663388..0a9575b469 100644
--- a/include/hw/virtio/vhost-vdpa.h
+++ b/include/hw/virtio/vhost-vdpa.h
@@ -12,15 +12,84 @@
#ifndef HW_VIRTIO_VHOST_VDPA_H
#define HW_VIRTIO_VHOST_VDPA_H
+#include <gmodule.h>
+
+#include "hw/virtio/vhost-iova-tree.h"
+#include "hw/virtio/vhost-shadow-virtqueue.h"
#include "hw/virtio/virtio.h"
+#include "standard-headers/linux/vhost_types.h"
-typedef struct vhost_vdpa {
+/*
+ * ASID dedicated to map guest's addresses. If SVQ is disabled it maps GPA to
+ * qemu's IOVA. If SVQ is enabled it maps also the SVQ vring here
+ */
+#define VHOST_VDPA_GUEST_PA_ASID 0
+
+typedef struct VhostVDPAHostNotifier {
+ MemoryRegion mr;
+ void *addr;
+} VhostVDPAHostNotifier;
+
+typedef enum SVQTransitionState {
+ SVQ_TSTATE_DISABLING = -1,
+ SVQ_TSTATE_DONE,
+ SVQ_TSTATE_ENABLING
+} SVQTransitionState;
+
+/* Info shared by all vhost_vdpa device models */
+typedef struct vhost_vdpa_shared {
int device_fd;
- uint32_t msg_type;
MemoryListener listener;
+ struct vhost_vdpa_iova_range iova_range;
+ QLIST_HEAD(, vdpa_iommu) iommu_list;
+
+ /* IOVA mapping used by the Shadow Virtqueue */
+ VhostIOVATree *iova_tree;
+
+ /* Copy of backend features */
+ uint64_t backend_cap;
+
+ bool iotlb_batch_begin_sent;
+
+ /* Vdpa must send shadow addresses as IOTLB key for data queues, not GPA */
+ bool shadow_data;
+
+ /* SVQ switching is in progress, or already completed? */
+ SVQTransitionState svq_switching;
+} VhostVDPAShared;
+
+typedef struct vhost_vdpa {
+ int index;
+ uint32_t address_space_id;
+ uint64_t acked_features;
+ bool shadow_vqs_enabled;
+ /* Device suspended successfully */
+ bool suspended;
+ VhostVDPAShared *shared;
+ GPtrArray *shadow_vqs;
+ const VhostShadowVirtqueueOps *shadow_vq_ops;
+ void *shadow_vq_ops_opaque;
+ struct vhost_dev *dev;
+ Error *migration_blocker;
+ VhostVDPAHostNotifier notifier[VIRTIO_QUEUE_MAX];
+ IOMMUNotifier n;
} VhostVDPA;
-extern AddressSpace address_space_memory;
-extern int vhost_vdpa_get_device_id(struct vhost_dev *dev,
- uint32_t *device_id);
+int vhost_vdpa_get_iova_range(int fd, struct vhost_vdpa_iova_range *iova_range);
+int vhost_vdpa_set_vring_ready(struct vhost_vdpa *v, unsigned idx);
+
+int vhost_vdpa_dma_map(VhostVDPAShared *s, uint32_t asid, hwaddr iova,
+ hwaddr size, void *vaddr, bool readonly);
+int vhost_vdpa_dma_unmap(VhostVDPAShared *s, uint32_t asid, hwaddr iova,
+ hwaddr size);
+
+typedef struct vdpa_iommu {
+ VhostVDPAShared *dev_shared;
+ IOMMUMemoryRegion *iommu_mr;
+ hwaddr iommu_offset;
+ IOMMUNotifier n;
+ QLIST_ENTRY(vdpa_iommu) iommu_next;
+} VDPAIOMMUState;
+
+
#endif
diff --git a/include/hw/virtio/vhost-vsock-common.h b/include/hw/virtio/vhost-vsock-common.h
index f8b4aaae00..75a74e8a99 100644
--- a/include/hw/virtio/vhost-vsock-common.h
+++ b/include/hw/virtio/vhost-vsock-common.h
@@ -8,15 +8,16 @@
* top-level directory.
*/
-#ifndef _QEMU_VHOST_VSOCK_COMMON_H
-#define _QEMU_VHOST_VSOCK_COMMON_H
+#ifndef QEMU_VHOST_VSOCK_COMMON_H
+#define QEMU_VHOST_VSOCK_COMMON_H
+#include "qapi/qapi-types-common.h"
#include "hw/virtio/virtio.h"
#include "hw/virtio/vhost.h"
+#include "qom/object.h"
#define TYPE_VHOST_VSOCK_COMMON "vhost-vsock-common"
-#define VHOST_VSOCK_COMMON(obj) \
- OBJECT_CHECK(VHostVSockCommon, (obj), TYPE_VHOST_VSOCK_COMMON)
+OBJECT_DECLARE_SIMPLE_TYPE(VHostVSockCommon, VHOST_VSOCK_COMMON)
enum {
VHOST_VSOCK_SAVEVM_VERSION = 0,
@@ -24,7 +25,7 @@ enum {
VHOST_VSOCK_QUEUE_SIZE = 128,
};
-typedef struct {
+struct VHostVSockCommon {
VirtIODevice parent;
struct vhost_virtqueue vhost_vqs[2];
@@ -35,13 +36,18 @@ typedef struct {
VirtQueue *trans_vq;
QEMUTimer *post_load_timer;
-} VHostVSockCommon;
+
+ /* features */
+ OnOffAuto seqpacket;
+};
int vhost_vsock_common_start(VirtIODevice *vdev);
void vhost_vsock_common_stop(VirtIODevice *vdev);
int vhost_vsock_common_pre_save(void *opaque);
int vhost_vsock_common_post_load(void *opaque, int version_id);
-void vhost_vsock_common_realize(VirtIODevice *vdev, const char *name);
+void vhost_vsock_common_realize(VirtIODevice *vdev);
void vhost_vsock_common_unrealize(VirtIODevice *vdev);
+uint64_t vhost_vsock_common_get_features(VirtIODevice *vdev, uint64_t features,
+ Error **errp);
-#endif /* _QEMU_VHOST_VSOCK_COMMON_H */
+#endif /* QEMU_VHOST_VSOCK_COMMON_H */
diff --git a/include/hw/virtio/vhost-vsock.h b/include/hw/virtio/vhost-vsock.h
index 8cbb7b90f9..84f4e727c7 100644
--- a/include/hw/virtio/vhost-vsock.h
+++ b/include/hw/virtio/vhost-vsock.h
@@ -15,22 +15,22 @@
#define QEMU_VHOST_VSOCK_H
#include "hw/virtio/vhost-vsock-common.h"
+#include "qom/object.h"
#define TYPE_VHOST_VSOCK "vhost-vsock-device"
-#define VHOST_VSOCK(obj) \
- OBJECT_CHECK(VHostVSock, (obj), TYPE_VHOST_VSOCK)
+OBJECT_DECLARE_SIMPLE_TYPE(VHostVSock, VHOST_VSOCK)
typedef struct {
uint64_t guest_cid;
char *vhostfd;
} VHostVSockConf;
-typedef struct {
+struct VHostVSock {
/*< private >*/
VHostVSockCommon parent;
VHostVSockConf conf;
/*< public >*/
-} VHostVSock;
+};
#endif /* QEMU_VHOST_VSOCK_H */
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index 767a95ec0b..02477788df 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -5,6 +5,11 @@
#include "hw/virtio/virtio.h"
#include "exec/memory.h"
+#define VHOST_F_DEVICE_IOTLB 63
+#define VHOST_USER_F_PROTOCOL_FEATURES 30
+
+#define VU_REALIZE_CONN_RETRIES 3
+
/* Generic structures common for any vhost based device. */
struct vhost_inflight {
@@ -29,6 +34,8 @@ struct vhost_virtqueue {
unsigned long long used_phys;
unsigned used_size;
EventNotifier masked_notifier;
+ EventNotifier error_notifier;
+ EventNotifier masked_config_notifier;
struct vhost_dev *dev;
};
@@ -37,6 +44,7 @@ typedef unsigned long vhost_log_chunk_t;
#define VHOST_LOG_BITS (8 * sizeof(vhost_log_chunk_t))
#define VHOST_LOG_CHUNK (VHOST_LOG_PAGE * VHOST_LOG_BITS)
#define VHOST_INVALID_FEATURE_BIT (0xff)
+#define VHOST_QUEUE_NUM_CONFIG_INR 0
struct vhost_log {
unsigned long long size;
@@ -61,6 +69,12 @@ typedef struct VhostDevConfigOps {
} VhostDevConfigOps;
struct vhost_memory;
+
+/**
+ * struct vhost_dev - common vhost_dev structure
+ * @vhost_ops: backend specific ops
+ * @config_ops: ops for config changes (see @vhost_dev_set_config_notifier)
+ */
struct vhost_dev {
VirtIODevice *vdev;
MemoryListener memory_listener;
@@ -71,14 +85,42 @@ struct vhost_dev {
int n_tmp_sections;
MemoryRegionSection *tmp_sections;
struct vhost_virtqueue *vqs;
- int nvqs;
+ unsigned int nvqs;
/* the first virtqueue which would be used by this vhost dev */
int vq_index;
+ /* one past the last vq index for the virtio device (not vhost) */
+ int vq_index_end;
+ /* if non-zero, minimum required value for max_queues */
+ int num_queues;
+ /**
+ * vhost feature handling requires matching the feature set
+ * offered by a backend which may be a subset of the total
+ * features eventually offered to the guest.
+ *
+ * @features: available features provided by the backend
+ * @acked_features: final negotiated features with front-end driver
+ *
+ * @backend_features: this is used in a couple of places to either
+ * store VHOST_USER_F_PROTOCOL_FEATURES to apply to
+ * VHOST_USER_SET_FEATURES or VHOST_NET_F_VIRTIO_NET_HDR. Its
+ * future use should be discouraged and the variable retired as
+ * its easy to confuse with the VirtIO backend_features.
+ */
uint64_t features;
uint64_t acked_features;
uint64_t backend_features;
+
+ /**
+ * @protocol_features: is the vhost-user only feature set by
+ * VHOST_USER_SET_PROTOCOL_FEATURES. Protocol features are only
+ * negotiated if VHOST_USER_F_PROTOCOL_FEATURES has been offered
+ * by the backend (see @features).
+ */
uint64_t protocol_features;
+
uint64_t max_queues;
+ uint64_t backend_cap;
+ /* @started: is the vhost device started? */
bool started;
bool log_enabled;
uint64_t log_size;
@@ -92,6 +134,10 @@ struct vhost_dev {
const VhostDevConfigOps *config_ops;
};
+extern const VhostOps kernel_ops;
+extern const VhostOps user_ops;
+extern const VhostOps vdpa_ops;
+
struct vhost_net {
struct vhost_dev dev;
struct vhost_virtqueue vqs[2];
@@ -99,14 +145,143 @@ struct vhost_net {
NetClientState *nc;
};
+/**
+ * vhost_dev_init() - initialise the vhost interface
+ * @hdev: the common vhost_dev structure
+ * @opaque: opaque ptr passed to backend (vhost/vhost-user/vdpa)
+ * @backend_type: type of backend
+ * @busyloop_timeout: timeout for polling virtqueue
+ * @errp: error handle
+ *
+ * The initialisation of the vhost device will trigger the
+ * initialisation of the backend and potentially capability
+ * negotiation of backend interface. Configuration of the VirtIO
+ * itself won't happen until the interface is started.
+ *
+ * Return: 0 on success, non-zero on error while setting errp.
+ */
int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
VhostBackendType backend_type,
- uint32_t busyloop_timeout);
+ uint32_t busyloop_timeout, Error **errp);
+
+/**
+ * vhost_dev_cleanup() - tear down and cleanup vhost interface
+ * @hdev: the common vhost_dev structure
+ */
void vhost_dev_cleanup(struct vhost_dev *hdev);
-int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev);
-void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev);
+
+/**
+ * vhost_dev_enable_notifiers() - enable event notifiers
+ * @hdev: common vhost_dev structure
+ * @vdev: the VirtIODevice structure
+ *
+ * Enable notifications directly to the vhost device rather than being
+ * triggered by QEMU itself. Notifications should be enabled before
+ * the vhost device is started via @vhost_dev_start.
+ *
+ * Return: 0 on success, < 0 on error.
+ */
int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev);
+
+/**
+ * vhost_dev_disable_notifiers - disable event notifications
+ * @hdev: common vhost_dev structure
+ * @vdev: the VirtIODevice structure
+ *
+ * Disable direct notifications to vhost device.
+ */
void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev);
+bool vhost_config_pending(struct vhost_dev *hdev);
+void vhost_config_mask(struct vhost_dev *hdev, VirtIODevice *vdev, bool mask);
+
+/**
+ * vhost_dev_is_started() - report status of vhost device
+ * @hdev: common vhost_dev structure
+ *
+ * Return the started status of the vhost device
+ */
+static inline bool vhost_dev_is_started(struct vhost_dev *hdev)
+{
+ return hdev->started;
+}
+
+/**
+ * vhost_dev_start() - start the vhost device
+ * @hdev: common vhost_dev structure
+ * @vdev: the VirtIODevice structure
+ * @vrings: true to have vrings enabled in this call
+ *
+ * Starts the vhost device. From this point VirtIO feature negotiation
+ * can start and the device can start processing VirtIO transactions.
+ *
+ * Return: 0 on success, < 0 on error.
+ */
+int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings);
+
+/**
+ * vhost_dev_stop() - stop the vhost device
+ * @hdev: common vhost_dev structure
+ * @vdev: the VirtIODevice structure
+ * @vrings: true to have vrings disabled in this call
+ *
+ * Stop the vhost device. After the device is stopped the notifiers
+ * can be disabled (@vhost_dev_disable_notifiers) and the device can
+ * be torn down (@vhost_dev_cleanup).
+ */
+void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings);
+
+/**
+ * DOC: vhost device configuration handling
+ *
+ * The VirtIO device configuration space is used for rarely changing
+ * or initialisation time parameters. The configuration can be updated
+ * by either the guest driver or the device itself. If the device can
+ * change the configuration over time the vhost handler should
+ * register a @VhostDevConfigOps structure with
+ * @vhost_dev_set_config_notifier so the guest can be notified. Some
+ * devices register a handler anyway and will signal an error if an
+ * unexpected config change happens.
+ */
+
+/**
+ * vhost_dev_get_config() - fetch device configuration
+ * @hdev: common vhost_dev_structure
+ * @config: pointer to device appropriate config structure
+ * @config_len: size of device appropriate config structure
+ *
+ * Return: 0 on success, < 0 on error while setting errp
+ */
+int vhost_dev_get_config(struct vhost_dev *hdev, uint8_t *config,
+ uint32_t config_len, Error **errp);
+
+/**
+ * vhost_dev_set_config() - set device configuration
+ * @hdev: common vhost_dev_structure
+ * @data: pointer to data to set
+ * @offset: offset into configuration space
+ * @size: length of set
+ * @flags: @VhostSetConfigType flags
+ *
+ * By use of @offset/@size a subset of the configuration space can be
+ * written to. The @flags are used to indicate if it is a normal
+ * transaction or related to migration.
+ *
+ * Return: 0 on success, non-zero on error
+ */
+int vhost_dev_set_config(struct vhost_dev *dev, const uint8_t *data,
+ uint32_t offset, uint32_t size, uint32_t flags);
+
+/**
+ * vhost_dev_set_config_notifier() - register VhostDevConfigOps
+ * @hdev: common vhost_dev_structure
+ * @ops: notifier ops
+ *
+ * If the device is expected to change configuration a notifier can be
+ * setup to handle the case.
+ */
+void vhost_dev_set_config_notifier(struct vhost_dev *dev,
+ const VhostDevConfigOps *ops);
+
/* Test and clear masked event pending status.
* Should be called after unmask to avoid losing events.
@@ -117,31 +292,176 @@ bool vhost_virtqueue_pending(struct vhost_dev *hdev, int n);
*/
void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n,
bool mask);
+
+/**
+ * vhost_get_features() - return a sanitised set of feature bits
+ * @hdev: common vhost_dev structure
+ * @feature_bits: pointer to terminated table of feature bits
+ * @features: original feature set
+ *
+ * This returns a set of features bits that is an intersection of what
+ * is supported by the vhost backend (hdev->features), the supported
+ * feature_bits and the requested feature set.
+ */
uint64_t vhost_get_features(struct vhost_dev *hdev, const int *feature_bits,
uint64_t features);
+
+/**
+ * vhost_ack_features() - set vhost acked_features
+ * @hdev: common vhost_dev structure
+ * @feature_bits: pointer to terminated table of feature bits
+ * @features: requested feature set
+ *
+ * This sets the internal hdev->acked_features to the intersection of
+ * the backends advertised features and the supported feature_bits.
+ */
void vhost_ack_features(struct vhost_dev *hdev, const int *feature_bits,
uint64_t features);
-bool vhost_has_free_slot(void);
+unsigned int vhost_get_max_memslots(void);
+unsigned int vhost_get_free_memslots(void);
int vhost_net_set_backend(struct vhost_dev *hdev,
struct vhost_vring_file *file);
+void vhost_toggle_device_iotlb(VirtIODevice *vdev);
int vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t iova, int write);
-int vhost_dev_get_config(struct vhost_dev *dev, uint8_t *config,
- uint32_t config_len);
-int vhost_dev_set_config(struct vhost_dev *dev, const uint8_t *data,
- uint32_t offset, uint32_t size, uint32_t flags);
-/* notifier callback in case vhost device config space changed
- */
-void vhost_dev_set_config_notifier(struct vhost_dev *dev,
- const VhostDevConfigOps *ops);
+
+int vhost_virtqueue_start(struct vhost_dev *dev, struct VirtIODevice *vdev,
+ struct vhost_virtqueue *vq, unsigned idx);
+void vhost_virtqueue_stop(struct vhost_dev *dev, struct VirtIODevice *vdev,
+ struct vhost_virtqueue *vq, unsigned idx);
void vhost_dev_reset_inflight(struct vhost_inflight *inflight);
void vhost_dev_free_inflight(struct vhost_inflight *inflight);
void vhost_dev_save_inflight(struct vhost_inflight *inflight, QEMUFile *f);
int vhost_dev_load_inflight(struct vhost_inflight *inflight, QEMUFile *f);
+int vhost_dev_prepare_inflight(struct vhost_dev *hdev, VirtIODevice *vdev);
int vhost_dev_set_inflight(struct vhost_dev *dev,
struct vhost_inflight *inflight);
int vhost_dev_get_inflight(struct vhost_dev *dev, uint16_t queue_size,
struct vhost_inflight *inflight);
+bool vhost_dev_has_iommu(struct vhost_dev *dev);
+
+#ifdef CONFIG_VHOST
+int vhost_reset_device(struct vhost_dev *hdev);
+#else
+static inline int vhost_reset_device(struct vhost_dev *hdev)
+{
+ return -ENOSYS;
+}
+#endif /* CONFIG_VHOST */
+
+/**
+ * vhost_supports_device_state(): Checks whether the back-end supports
+ * transferring internal device state for the purpose of migration.
+ * Support for this feature is required for vhost_set_device_state_fd()
+ * and vhost_check_device_state().
+ *
+ * @dev: The vhost device
+ *
+ * Returns true if the device supports these commands, and false if it
+ * does not.
+ */
+bool vhost_supports_device_state(struct vhost_dev *dev);
+
+/**
+ * vhost_set_device_state_fd(): Begin transfer of internal state from/to
+ * the back-end for the purpose of migration. Data is to be transferred
+ * over a pipe according to @direction and @phase. The sending end must
+ * only write to the pipe, and the receiving end must only read from it.
+ * Once the sending end is done, it closes its FD. The receiving end
+ * must take this as the end-of-transfer signal and close its FD, too.
+ *
+ * @fd is the back-end's end of the pipe: The write FD for SAVE, and the
+ * read FD for LOAD. This function transfers ownership of @fd to the
+ * back-end, i.e. closes it in the front-end.
+ *
+ * The back-end may optionally reply with an FD of its own, if this
+ * improves efficiency on its end. In this case, the returned FD is
+ * stored in *reply_fd. The back-end will discard the FD sent to it,
+ * and the front-end must use *reply_fd for transferring state to/from
+ * the back-end.
+ *
+ * @dev: The vhost device
+ * @direction: The direction in which the state is to be transferred.
+ * For outgoing migrations, this is SAVE, and data is read
+ * from the back-end and stored by the front-end in the
+ * migration stream.
+ * For incoming migrations, this is LOAD, and data is read
+ * by the front-end from the migration stream and sent to
+ * the back-end to restore the saved state.
+ * @phase: Which migration phase we are in. Currently, there is only
+ * STOPPED (device and all vrings are stopped), in the future,
+ * more phases such as PRE_COPY or POST_COPY may be added.
+ * @fd: Back-end's end of the pipe through which to transfer state; note
+ * that ownership is transferred to the back-end, so this function
+ * closes @fd in the front-end.
+ * @reply_fd: If the back-end wishes to use a different pipe for state
+ * transfer, this will contain an FD for the front-end to
+ * use. Otherwise, -1 is stored here.
+ * @errp: Potential error description
+ *
+ * Returns 0 on success, and -errno on failure.
+ */
+int vhost_set_device_state_fd(struct vhost_dev *dev,
+ VhostDeviceStateDirection direction,
+ VhostDeviceStatePhase phase,
+ int fd,
+ int *reply_fd,
+ Error **errp);
+
+/**
+ * vhost_set_device_state_fd(): After transferring state from/to the
+ * back-end via vhost_set_device_state_fd(), i.e. once the sending end
+ * has closed the pipe, inquire the back-end to report any potential
+ * errors that have occurred on its side. This allows to sense errors
+ * like:
+ * - During outgoing migration, when the source side had already started
+ * to produce its state, something went wrong and it failed to finish
+ * - During incoming migration, when the received state is somehow
+ * invalid and cannot be processed by the back-end
+ *
+ * @dev: The vhost device
+ * @errp: Potential error description
+ *
+ * Returns 0 when the back-end reports successful state transfer and
+ * processing, and -errno when an error occurred somewhere.
+ */
+int vhost_check_device_state(struct vhost_dev *dev, Error **errp);
+
+/**
+ * vhost_save_backend_state(): High-level function to receive a vhost
+ * back-end's state, and save it in @f. Uses
+ * `vhost_set_device_state_fd()` to get the data from the back-end, and
+ * stores it in consecutive chunks that are each prefixed by their
+ * respective length (be32). The end is marked by a 0-length chunk.
+ *
+ * Must only be called while the device and all its vrings are stopped
+ * (`VHOST_TRANSFER_STATE_PHASE_STOPPED`).
+ *
+ * @dev: The vhost device from which to save the state
+ * @f: Migration stream in which to save the state
+ * @errp: Potential error message
+ *
+ * Returns 0 on success, and -errno otherwise.
+ */
+int vhost_save_backend_state(struct vhost_dev *dev, QEMUFile *f, Error **errp);
+
+/**
+ * vhost_load_backend_state(): High-level function to load a vhost
+ * back-end's state from @f, and send it over to the back-end. Reads
+ * the data from @f in the format used by `vhost_save_state()`, and uses
+ * `vhost_set_device_state_fd()` to transfer it to the back-end.
+ *
+ * Must only be called while the device and all its vrings are stopped
+ * (`VHOST_TRANSFER_STATE_PHASE_STOPPED`).
+ *
+ * @dev: The vhost device to which to send the state
+ * @f: Migration stream from which to load the state
+ * @errp: Potential error message
+ *
+ * Returns 0 on success, and -errno otherwise.
+ */
+int vhost_load_backend_state(struct vhost_dev *dev, QEMUFile *f, Error **errp);
+
#endif
diff --git a/include/hw/virtio/virtio-access.h b/include/hw/virtio/virtio-access.h
index 6818a23a2d..07aae69042 100644
--- a/include/hw/virtio/virtio-access.h
+++ b/include/hw/virtio/virtio-access.h
@@ -28,7 +28,7 @@ static inline bool virtio_access_is_big_endian(VirtIODevice *vdev)
{
#if defined(LEGACY_VIRTIO_IS_BIENDIAN)
return virtio_is_big_endian(vdev);
-#elif defined(TARGET_WORDS_BIGENDIAN)
+#elif TARGET_BIG_ENDIAN
if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
/* Devices conforming to VIRTIO 1.0 or later are always LE. */
return false;
@@ -149,7 +149,7 @@ static inline uint64_t virtio_ldq_p(VirtIODevice *vdev, const void *ptr)
static inline uint16_t virtio_tswap16(VirtIODevice *vdev, uint16_t s)
{
-#ifdef HOST_WORDS_BIGENDIAN
+#if HOST_BIG_ENDIAN
return virtio_access_is_big_endian(vdev) ? s : bswap16(s);
#else
return virtio_access_is_big_endian(vdev) ? bswap16(s) : s;
@@ -215,7 +215,7 @@ static inline void virtio_tswap16s(VirtIODevice *vdev, uint16_t *s)
static inline uint32_t virtio_tswap32(VirtIODevice *vdev, uint32_t s)
{
-#ifdef HOST_WORDS_BIGENDIAN
+#if HOST_BIG_ENDIAN
return virtio_access_is_big_endian(vdev) ? s : bswap32(s);
#else
return virtio_access_is_big_endian(vdev) ? bswap32(s) : s;
@@ -229,7 +229,7 @@ static inline void virtio_tswap32s(VirtIODevice *vdev, uint32_t *s)
static inline uint64_t virtio_tswap64(VirtIODevice *vdev, uint64_t s)
{
-#ifdef HOST_WORDS_BIGENDIAN
+#if HOST_BIG_ENDIAN
return virtio_access_is_big_endian(vdev) ? s : bswap64(s);
#else
return virtio_access_is_big_endian(vdev) ? bswap64(s) : s;
diff --git a/include/hw/virtio/virtio-acpi.h b/include/hw/virtio/virtio-acpi.h
new file mode 100644
index 0000000000..cace2a315f
--- /dev/null
+++ b/include/hw/virtio/virtio-acpi.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * ACPI support for virtio
+ */
+
+#ifndef VIRTIO_ACPI_H
+#define VIRTIO_ACPI_H
+
+#include "exec/hwaddr.h"
+
+void virtio_acpi_dsdt_add(Aml *scope, const hwaddr virtio_mmio_base,
+ const hwaddr virtio_mmio_size, uint32_t mmio_irq,
+ long int start_index, int num);
+
+#endif
diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h
index 28fd2b3960..5139cf8ab6 100644
--- a/include/hw/virtio/virtio-balloon.h
+++ b/include/hw/virtio/virtio-balloon.h
@@ -18,10 +18,10 @@
#include "standard-headers/linux/virtio_balloon.h"
#include "hw/virtio/virtio.h"
#include "sysemu/iothread.h"
+#include "qom/object.h"
#define TYPE_VIRTIO_BALLOON "virtio-balloon-device"
-#define VIRTIO_BALLOON(obj) \
- OBJECT_CHECK(VirtIOBalloon, (obj), TYPE_VIRTIO_BALLOON)
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIOBalloon, VIRTIO_BALLOON)
#define VIRTIO_BALLOON_FREE_PAGE_HINT_CMD_ID_MIN 0x80000000
@@ -40,7 +40,7 @@ enum virtio_balloon_free_page_hint_status {
FREE_PAGE_HINT_S_DONE = 3,
};
-typedef struct VirtIOBalloon {
+struct VirtIOBalloon {
VirtIODevice parent_obj;
VirtQueue *ivq, *dvq, *svq, *free_page_vq, *reporting_vq;
uint32_t free_page_hint_status;
@@ -71,6 +71,6 @@ typedef struct VirtIOBalloon {
bool qemu_4_0_config_size;
uint32_t poison_val;
-} VirtIOBalloon;
+};
#endif
diff --git a/include/hw/virtio/virtio-blk-common.h b/include/hw/virtio/virtio-blk-common.h
new file mode 100644
index 0000000000..31daada3e3
--- /dev/null
+++ b/include/hw/virtio/virtio-blk-common.h
@@ -0,0 +1,20 @@
+/*
+ * Virtio Block Device common helpers
+ *
+ * Copyright IBM, Corp. 2007
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef VIRTIO_BLK_COMMON_H
+#define VIRTIO_BLK_COMMON_H
+
+#include "hw/virtio/virtio.h"
+
+extern const VirtIOConfigSizeParams virtio_blk_cfg_size_params;
+
+#endif
diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
index b1334c3904..5c14110c4b 100644
--- a/include/hw/virtio/virtio-blk.h
+++ b/include/hw/virtio/virtio-blk.h
@@ -19,10 +19,12 @@
#include "hw/block/block.h"
#include "sysemu/iothread.h"
#include "sysemu/block-backend.h"
+#include "sysemu/block-ram-registrar.h"
+#include "qom/object.h"
+#include "qapi/qapi-types-virtio.h"
#define TYPE_VIRTIO_BLK "virtio-blk-device"
-#define VIRTIO_BLK(obj) \
- OBJECT_CHECK(VirtIOBlock, (obj), TYPE_VIRTIO_BLK)
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIOBlock, VIRTIO_BLK)
/* This is the last element of the write scatter-gather list */
struct virtio_blk_inhdr
@@ -30,44 +32,57 @@ struct virtio_blk_inhdr
unsigned char status;
};
+#define VIRTIO_BLK_AUTO_NUM_QUEUES UINT16_MAX
+
struct VirtIOBlkConf
{
BlockConf conf;
IOThread *iothread;
+ IOThreadVirtQueueMappingList *iothread_vq_mapping_list;
char *serial;
uint32_t request_merging;
uint16_t num_queues;
uint16_t queue_size;
bool seg_max_adjust;
+ bool report_discard_granularity;
uint32_t max_discard_sectors;
uint32_t max_write_zeroes_sectors;
bool x_enable_wce_if_config_wce;
};
-struct VirtIOBlockDataPlane;
-
struct VirtIOBlockReq;
-typedef struct VirtIOBlock {
+struct VirtIOBlock {
VirtIODevice parent_obj;
BlockBackend *blk;
- void *rq;
- QEMUBH *bh;
+ QemuMutex rq_lock;
+ struct VirtIOBlockReq *rq; /* protected by rq_lock */
VirtIOBlkConf conf;
unsigned short sector_mask;
bool original_wce;
VMChangeStateEntry *change;
- bool dataplane_disabled;
- bool dataplane_started;
- struct VirtIOBlockDataPlane *dataplane;
+ bool ioeventfd_disabled;
+ bool ioeventfd_started;
+ bool ioeventfd_starting;
+ bool ioeventfd_stopping;
+
+ /*
+ * The AioContext for each virtqueue. The BlockDriverState will use the
+ * first element as its AioContext.
+ */
+ AioContext **vq_aio_context;
+
uint64_t host_features;
size_t config_size;
-} VirtIOBlock;
+ BlockRAMRegistrar blk_ram_registrar;
+};
typedef struct VirtIOBlockReq {
VirtQueueElement elem;
int64_t sector_num;
VirtIOBlock *dev;
VirtQueue *vq;
+ IOVDiscardUndo inhdr_undo;
+ IOVDiscardUndo outhdr_undo;
struct virtio_blk_inhdr *in;
struct virtio_blk_outhdr out;
QEMUIOVector qiov;
@@ -85,7 +100,6 @@ typedef struct MultiReqBuffer {
bool is_write;
} MultiReqBuffer;
-bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq);
-void virtio_blk_process_queued_requests(VirtIOBlock *s, bool is_bh);
+void virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq);
#endif
diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h
index 0f6f215925..7ab8c9dab0 100644
--- a/include/hw/virtio/virtio-bus.h
+++ b/include/hw/virtio/virtio-bus.h
@@ -27,17 +27,16 @@
#include "hw/qdev-core.h"
#include "hw/virtio/virtio.h"
+#include "qom/object.h"
#define TYPE_VIRTIO_BUS "virtio-bus"
-#define VIRTIO_BUS_GET_CLASS(obj) \
- OBJECT_GET_CLASS(VirtioBusClass, obj, TYPE_VIRTIO_BUS)
-#define VIRTIO_BUS_CLASS(klass) \
- OBJECT_CLASS_CHECK(VirtioBusClass, klass, TYPE_VIRTIO_BUS)
-#define VIRTIO_BUS(obj) OBJECT_CHECK(VirtioBusState, (obj), TYPE_VIRTIO_BUS)
-
+typedef struct VirtioBusClass VirtioBusClass;
typedef struct VirtioBusState VirtioBusState;
+DECLARE_OBJ_CHECKERS(VirtioBusState, VirtioBusClass,
+ VIRTIO_BUS, TYPE_VIRTIO_BUS)
+
-typedef struct VirtioBusClass {
+struct VirtioBusClass {
/* This is what a VirtioBus must implement */
BusClass parent;
void (*notify)(DeviceState *d, uint16_t vector);
@@ -94,7 +93,8 @@ typedef struct VirtioBusClass {
*/
bool has_variable_vring_alignment;
AddressSpace *(*get_dma_as)(DeviceState *d);
-} VirtioBusClass;
+ bool (*iommu_enabled)(DeviceState *d);
+};
struct VirtioBusState {
BusState parent_obj;
@@ -155,5 +155,6 @@ void virtio_bus_release_ioeventfd(VirtioBusState *bus);
int virtio_bus_set_host_notifier(VirtioBusState *bus, int n, bool assign);
/* Tell the bus that the ioeventfd handler is no longer required. */
void virtio_bus_cleanup_host_notifier(VirtioBusState *bus, int n);
-
+/* Whether the IOMMU is enabled for this device */
+bool virtio_bus_device_iommu_enabled(VirtIODevice *vdev);
#endif /* VIRTIO_BUS_H */
diff --git a/include/hw/virtio/virtio-crypto.h b/include/hw/virtio/virtio-crypto.h
index ffe2391ece..348749f5d5 100644
--- a/include/hw/virtio/virtio-crypto.h
+++ b/include/hw/virtio/virtio-crypto.h
@@ -18,6 +18,7 @@
#include "hw/virtio/virtio.h"
#include "sysemu/iothread.h"
#include "sysemu/cryptodev.h"
+#include "qom/object.h"
#define DEBUG_VIRTIO_CRYPTO 0
@@ -31,8 +32,7 @@ do { \
#define TYPE_VIRTIO_CRYPTO "virtio-crypto-device"
-#define VIRTIO_CRYPTO(obj) \
- OBJECT_CHECK(VirtIOCrypto, (obj), TYPE_VIRTIO_CRYPTO)
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIOCrypto, VIRTIO_CRYPTO)
#define VIRTIO_CRYPTO_GET_PARENT_CLASS(obj) \
OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_CRYPTO)
@@ -50,6 +50,7 @@ typedef struct VirtIOCryptoConf {
uint32_t mac_algo_l;
uint32_t mac_algo_h;
uint32_t aead_algo;
+ uint32_t akcipher_algo;
/* Maximum length of cipher key */
uint32_t max_cipher_key_len;
@@ -71,9 +72,7 @@ typedef struct VirtIOCryptoReq {
size_t in_len;
VirtQueue *vq;
struct VirtIOCrypto *vcrypto;
- union {
- CryptoDevBackendSymOpInfo *sym_op_info;
- } u;
+ CryptoDevBackendOpInfo op_info;
} VirtIOCryptoReq;
typedef struct VirtIOCryptoQueue {
@@ -82,7 +81,7 @@ typedef struct VirtIOCryptoQueue {
struct VirtIOCrypto *vcrypto;
} VirtIOCryptoQueue;
-typedef struct VirtIOCrypto {
+struct VirtIOCrypto {
VirtIODevice parent_obj;
VirtQueue *ctrl_vq;
@@ -97,6 +96,6 @@ typedef struct VirtIOCrypto {
uint32_t curr_queues;
size_t config_size;
uint8_t vhost_started;
-} VirtIOCrypto;
+};
#endif /* QEMU_VIRTIO_CRYPTO_H */
diff --git a/include/hw/virtio/virtio-dmabuf.h b/include/hw/virtio/virtio-dmabuf.h
new file mode 100644
index 0000000000..627c3b6db7
--- /dev/null
+++ b/include/hw/virtio/virtio-dmabuf.h
@@ -0,0 +1,100 @@
+/*
+ * Virtio Shared dma-buf
+ *
+ * Copyright Red Hat, Inc. 2023
+ *
+ * Authors:
+ * Albert Esteve <aesteve@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef VIRTIO_DMABUF_H
+#define VIRTIO_DMABUF_H
+
+#include "qemu/uuid.h"
+#include "vhost.h"
+
+typedef enum SharedObjectType {
+ TYPE_INVALID = 0,
+ TYPE_DMABUF,
+ TYPE_VHOST_DEV,
+} SharedObjectType;
+
+typedef struct VirtioSharedObject {
+ SharedObjectType type;
+ gpointer value;
+} VirtioSharedObject;
+
+/**
+ * virtio_add_dmabuf() - Add a new dma-buf resource to the lookup table
+ * @uuid: new resource's UUID
+ * @dmabuf_fd: the dma-buf descriptor that will be stored and shared with
+ * other virtio devices. The caller retains ownership over the
+ * descriptor and its lifecycle.
+ *
+ * Note: @dmabuf_fd must be a valid (non-negative) file descriptor.
+ *
+ * Return: true if the UUID did not exist and the resource has been added,
+ * false if another resource with the same UUID already existed.
+ * Note that if it finds a repeated UUID, the resource is not inserted in
+ * the lookup table.
+ */
+bool virtio_add_dmabuf(QemuUUID *uuid, int dmabuf_fd);
+
+/**
+ * virtio_add_vhost_device() - Add a new exporter vhost device that holds the
+ * resource with the associated UUID
+ * @uuid: new resource's UUID
+ * @dev: the pointer to the vhost device that holds the resource. The caller
+ * retains ownership over the device struct and its lifecycle.
+ *
+ * Return: true if the UUID did not exist and the device has been tracked,
+ * false if another resource with the same UUID already existed.
+ * Note that if it finds a repeated UUID, the resource is not inserted in
+ * the lookup table.
+ */
+bool virtio_add_vhost_device(QemuUUID *uuid, struct vhost_dev *dev);
+
+/**
+ * virtio_remove_resource() - Removes a resource from the lookup table
+ * @uuid: resource's UUID
+ *
+ * Return: true if the UUID has been found and removed from the lookup table.
+ */
+bool virtio_remove_resource(const QemuUUID *uuid);
+
+/**
+ * virtio_lookup_dmabuf() - Looks for a dma-buf resource in the lookup table
+ * @uuid: resource's UUID
+ *
+ * Return: the dma-buf file descriptor integer, or -1 if the key is not found.
+ */
+int virtio_lookup_dmabuf(const QemuUUID *uuid);
+
+/**
+ * virtio_lookup_vhost_device() - Looks for an exporter vhost device in the
+ * lookup table
+ * @uuid: resource's UUID
+ *
+ * Return: pointer to the vhost_dev struct, or NULL if the key is not found.
+ */
+struct vhost_dev *virtio_lookup_vhost_device(const QemuUUID *uuid);
+
+/**
+ * virtio_object_type() - Looks for the type of resource in the lookup table
+ * @uuid: resource's UUID
+ *
+ * Return: the type of resource associated with the UUID, or TYPE_INVALID if
+ * the key is not found.
+ */
+SharedObjectType virtio_object_type(const QemuUUID *uuid);
+
+/**
+ * virtio_free_resources() - Destroys all keys and values of the shared
+ * resources lookup table, and frees them
+ */
+void virtio_free_resources(void);
+
+#endif /* VIRTIO_DMABUF_H */
diff --git a/include/hw/virtio/virtio-gpu-bswap.h b/include/hw/virtio/virtio-gpu-bswap.h
index 203f9e1718..dd1975e2d4 100644
--- a/include/hw/virtio/virtio-gpu-bswap.h
+++ b/include/hw/virtio/virtio-gpu-bswap.h
@@ -24,13 +24,12 @@ virtio_gpu_ctrl_hdr_bswap(struct virtio_gpu_ctrl_hdr *hdr)
le32_to_cpus(&hdr->flags);
le64_to_cpus(&hdr->fence_id);
le32_to_cpus(&hdr->ctx_id);
- le32_to_cpus(&hdr->padding);
}
static inline void
virtio_gpu_bswap_32(void *ptr, size_t size)
{
-#ifdef HOST_WORDS_BIGENDIAN
+#if HOST_BIG_ENDIAN
size_t i;
struct virtio_gpu_ctrl_hdr *hdr = (struct virtio_gpu_ctrl_hdr *) ptr;
@@ -59,4 +58,38 @@ virtio_gpu_t2d_bswap(struct virtio_gpu_transfer_to_host_2d *t2d)
le32_to_cpus(&t2d->padding);
}
+static inline void
+virtio_gpu_create_blob_bswap(struct virtio_gpu_resource_create_blob *cblob)
+{
+ virtio_gpu_ctrl_hdr_bswap(&cblob->hdr);
+ le32_to_cpus(&cblob->resource_id);
+ le32_to_cpus(&cblob->blob_mem);
+ le32_to_cpus(&cblob->blob_flags);
+ le32_to_cpus(&cblob->nr_entries);
+ le64_to_cpus(&cblob->blob_id);
+ le64_to_cpus(&cblob->size);
+}
+
+static inline void
+virtio_gpu_map_blob_bswap(struct virtio_gpu_resource_map_blob *mblob)
+{
+ virtio_gpu_ctrl_hdr_bswap(&mblob->hdr);
+ le32_to_cpus(&mblob->resource_id);
+ le64_to_cpus(&mblob->offset);
+}
+
+static inline void
+virtio_gpu_unmap_blob_bswap(struct virtio_gpu_resource_unmap_blob *ublob)
+{
+ virtio_gpu_ctrl_hdr_bswap(&ublob->hdr);
+ le32_to_cpus(&ublob->resource_id);
+}
+
+static inline void
+virtio_gpu_scanout_blob_bswap(struct virtio_gpu_set_scanout_blob *ssb)
+{
+ virtio_gpu_bswap_32(ssb, sizeof(*ssb) - sizeof(ssb->offsets[3]));
+ le32_to_cpus(&ssb->offsets[3]);
+}
+
#endif
diff --git a/include/hw/virtio/virtio-gpu-pci.h b/include/hw/virtio/virtio-gpu-pci.h
index 2f69b5a9cc..225cbbc2e4 100644
--- a/include/hw/virtio/virtio-gpu-pci.h
+++ b/include/hw/virtio/virtio-gpu-pci.h
@@ -16,15 +16,14 @@
#include "hw/virtio/virtio-pci.h"
#include "hw/virtio/virtio-gpu.h"
+#include "qom/object.h"
-typedef struct VirtIOGPUPCIBase VirtIOGPUPCIBase;
/*
* virtio-gpu-pci-base: This extends VirtioPCIProxy.
*/
#define TYPE_VIRTIO_GPU_PCI_BASE "virtio-gpu-pci-base"
-#define VIRTIO_GPU_PCI_BASE(obj) \
- OBJECT_CHECK(VirtIOGPUPCIBase, (obj), TYPE_VIRTIO_GPU_PCI_BASE)
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIOGPUPCIBase, VIRTIO_GPU_PCI_BASE)
struct VirtIOGPUPCIBase {
VirtIOPCIProxy parent_obj;
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 6dd57f2025..ed44cdad6b 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -22,22 +22,24 @@
#include "sysemu/vhost-user-backend.h"
#include "standard-headers/linux/virtio_gpu.h"
+#include "standard-headers/linux/virtio_ids.h"
+#include "qom/object.h"
#define TYPE_VIRTIO_GPU_BASE "virtio-gpu-base"
-#define VIRTIO_GPU_BASE(obj) \
- OBJECT_CHECK(VirtIOGPUBase, (obj), TYPE_VIRTIO_GPU_BASE)
-#define VIRTIO_GPU_BASE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(VirtIOGPUBaseClass, obj, TYPE_VIRTIO_GPU_BASE)
-#define VIRTIO_GPU_BASE_CLASS(klass) \
- OBJECT_CLASS_CHECK(VirtIOGPUBaseClass, klass, TYPE_VIRTIO_GPU_BASE)
+OBJECT_DECLARE_TYPE(VirtIOGPUBase, VirtIOGPUBaseClass,
+ VIRTIO_GPU_BASE)
#define TYPE_VIRTIO_GPU "virtio-gpu-device"
-#define VIRTIO_GPU(obj) \
- OBJECT_CHECK(VirtIOGPU, (obj), TYPE_VIRTIO_GPU)
+OBJECT_DECLARE_TYPE(VirtIOGPU, VirtIOGPUClass, VIRTIO_GPU)
+
+#define TYPE_VIRTIO_GPU_GL "virtio-gpu-gl-device"
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIOGPUGL, VIRTIO_GPU_GL)
#define TYPE_VHOST_USER_GPU "vhost-user-gpu"
+OBJECT_DECLARE_SIMPLE_TYPE(VhostUserGPU, VHOST_USER_GPU)
-#define VIRTIO_ID_GPU 16
+#define TYPE_VIRTIO_GPU_RUTABAGA "virtio-gpu-rutabaga-device"
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIOGPURutabaga, VIRTIO_GPU_RUTABAGA)
struct virtio_gpu_simple_resource {
uint32_t resource_id;
@@ -49,10 +51,27 @@ struct virtio_gpu_simple_resource {
unsigned int iov_cnt;
uint32_t scanout_bitmask;
pixman_image_t *image;
+#ifdef WIN32
+ HANDLE handle;
+#endif
uint64_t hostmem;
+
+ uint64_t blob_size;
+ void *blob;
+ int dmabuf_fd;
+ uint8_t *remapped;
+
QTAILQ_ENTRY(virtio_gpu_simple_resource) next;
};
+struct virtio_gpu_framebuffer {
+ pixman_format_code_t format;
+ uint32_t bytes_pp;
+ uint32_t width, height;
+ uint32_t stride;
+ uint32_t offset;
+};
+
struct virtio_gpu_scanout {
QemuConsole *con;
DisplaySurface *ds;
@@ -62,10 +81,13 @@ struct virtio_gpu_scanout {
uint32_t resource_id;
struct virtio_gpu_update_cursor cursor;
QEMUCursor *current_cursor;
+ struct virtio_gpu_framebuffer fb;
};
struct virtio_gpu_requested_state {
+ uint16_t width_mm, height_mm;
uint32_t width, height;
+ uint32_t refresh_rate;
int x, y;
};
@@ -73,6 +95,10 @@ enum virtio_gpu_base_conf_flags {
VIRTIO_GPU_FLAG_VIRGL_ENABLED = 1,
VIRTIO_GPU_FLAG_STATS_ENABLED,
VIRTIO_GPU_FLAG_EDID_ENABLED,
+ VIRTIO_GPU_FLAG_DMABUF_ENABLED,
+ VIRTIO_GPU_FLAG_BLOB_ENABLED,
+ VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED,
+ VIRTIO_GPU_FLAG_RUTABAGA_ENABLED,
};
#define virtio_gpu_virgl_enabled(_cfg) \
@@ -81,12 +107,23 @@ enum virtio_gpu_base_conf_flags {
(_cfg.flags & (1 << VIRTIO_GPU_FLAG_STATS_ENABLED))
#define virtio_gpu_edid_enabled(_cfg) \
(_cfg.flags & (1 << VIRTIO_GPU_FLAG_EDID_ENABLED))
+#define virtio_gpu_dmabuf_enabled(_cfg) \
+ (_cfg.flags & (1 << VIRTIO_GPU_FLAG_DMABUF_ENABLED))
+#define virtio_gpu_blob_enabled(_cfg) \
+ (_cfg.flags & (1 << VIRTIO_GPU_FLAG_BLOB_ENABLED))
+#define virtio_gpu_context_init_enabled(_cfg) \
+ (_cfg.flags & (1 << VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED))
+#define virtio_gpu_rutabaga_enabled(_cfg) \
+ (_cfg.flags & (1 << VIRTIO_GPU_FLAG_RUTABAGA_ENABLED))
+#define virtio_gpu_hostmem_enabled(_cfg) \
+ (_cfg.hostmem > 0)
struct virtio_gpu_base_conf {
uint32_t max_outputs;
uint32_t flags;
uint32_t xres;
uint32_t yres;
+ uint64_t hostmem;
};
struct virtio_gpu_ctrl_command {
@@ -98,38 +135,46 @@ struct virtio_gpu_ctrl_command {
QTAILQ_ENTRY(virtio_gpu_ctrl_command) next;
};
-typedef struct VirtIOGPUBase {
+struct VirtIOGPUBase {
VirtIODevice parent_obj;
Error *migration_blocker;
struct virtio_gpu_base_conf conf;
struct virtio_gpu_config virtio_config;
+ const GraphicHwOps *hw_ops;
- bool use_virgl_renderer;
int renderer_blocked;
int enable;
+ MemoryRegion hostmem;
+
struct virtio_gpu_scanout scanout[VIRTIO_GPU_MAX_SCANOUTS];
int enabled_output_bitmask;
struct virtio_gpu_requested_state req_state[VIRTIO_GPU_MAX_SCANOUTS];
-} VirtIOGPUBase;
+};
-typedef struct VirtIOGPUBaseClass {
+struct VirtIOGPUBaseClass {
VirtioDeviceClass parent;
- void (*gl_unblock)(VirtIOGPUBase *g);
-} VirtIOGPUBaseClass;
+ void (*gl_flushed)(VirtIOGPUBase *g);
+};
#define VIRTIO_GPU_BASE_PROPERTIES(_state, _conf) \
DEFINE_PROP_UINT32("max_outputs", _state, _conf.max_outputs, 1), \
DEFINE_PROP_BIT("edid", _state, _conf.flags, \
VIRTIO_GPU_FLAG_EDID_ENABLED, true), \
- DEFINE_PROP_UINT32("xres", _state, _conf.xres, 1024), \
- DEFINE_PROP_UINT32("yres", _state, _conf.yres, 768)
+ DEFINE_PROP_UINT32("xres", _state, _conf.xres, 1280), \
+ DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800)
+
+typedef struct VGPUDMABuf {
+ QemuDmaBuf buf;
+ uint32_t scanout_id;
+ QTAILQ_ENTRY(VGPUDMABuf) next;
+} VGPUDMABuf;
-typedef struct VirtIOGPU {
+struct VirtIOGPU {
VirtIOGPUBase parent_obj;
uint64_t conf_max_hostmem;
@@ -139,6 +184,9 @@ typedef struct VirtIOGPU {
QEMUBH *ctrl_bh;
QEMUBH *cursor_bh;
+ QEMUBH *reset_bh;
+ QemuCond reset_cond;
+ bool reset_finished;
QTAILQ_HEAD(, virtio_gpu_simple_resource) reslist;
QTAILQ_HEAD(, virtio_gpu_ctrl_command) cmdq;
@@ -146,8 +194,7 @@ typedef struct VirtIOGPU {
uint64_t hostmem;
- bool renderer_inited;
- bool renderer_reset;
+ bool processing_cmdq;
QEMUTimer *fence_poll;
QEMUTimer *print_stats;
@@ -158,9 +205,34 @@ typedef struct VirtIOGPU {
uint32_t req_3d;
uint32_t bytes_3d;
} stats;
-} VirtIOGPU;
-typedef struct VhostUserGPU {
+ struct {
+ QTAILQ_HEAD(, VGPUDMABuf) bufs;
+ VGPUDMABuf *primary[VIRTIO_GPU_MAX_SCANOUTS];
+ } dmabuf;
+};
+
+struct VirtIOGPUClass {
+ VirtIOGPUBaseClass parent;
+
+ void (*handle_ctrl)(VirtIODevice *vdev, VirtQueue *vq);
+ void (*process_cmd)(VirtIOGPU *g, struct virtio_gpu_ctrl_command *cmd);
+ void (*update_cursor_data)(VirtIOGPU *g,
+ struct virtio_gpu_scanout *s,
+ uint32_t resource_id);
+ void (*resource_destroy)(VirtIOGPU *g,
+ struct virtio_gpu_simple_resource *res,
+ Error **errp);
+};
+
+struct VirtIOGPUGL {
+ struct VirtIOGPU parent_obj;
+
+ bool renderer_inited;
+ bool renderer_reset;
+};
+
+struct VhostUserGPU {
VirtIOGPUBase parent_obj;
VhostUserBackend *vhost;
@@ -168,18 +240,37 @@ typedef struct VhostUserGPU {
CharBackend vhost_chr;
QemuDmaBuf dmabuf[VIRTIO_GPU_MAX_SCANOUTS];
bool backend_blocked;
-} VhostUserGPU;
+};
+
+#define MAX_SLOTS 4096
-extern const GraphicHwOps virtio_gpu_ops;
+struct MemoryRegionInfo {
+ int used;
+ MemoryRegion mr;
+ uint32_t resource_id;
+};
+
+struct rutabaga;
+
+struct VirtIOGPURutabaga {
+ VirtIOGPU parent_obj;
+ struct MemoryRegionInfo memory_regions[MAX_SLOTS];
+ uint64_t capset_mask;
+ char *wayland_socket_path;
+ char *wsi;
+ bool headless;
+ uint32_t num_capsets;
+ struct rutabaga *rutabaga;
+};
#define VIRTIO_GPU_FILL_CMD(out) do { \
- size_t s; \
- s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, 0, \
+ size_t virtiogpufillcmd_s_ = \
+ iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, 0, \
&out, sizeof(out)); \
- if (s != sizeof(out)) { \
+ if (virtiogpufillcmd_s_ != sizeof(out)) { \
qemu_log_mask(LOG_GUEST_ERROR, \
"%s: command size incorrect %zu vs %zu\n", \
- __func__, s, sizeof(out)); \
+ __func__, virtiogpufillcmd_s_, sizeof(out)); \
return; \
} \
} while (0)
@@ -189,11 +280,17 @@ bool virtio_gpu_base_device_realize(DeviceState *qdev,
VirtIOHandleOutput ctrl_cb,
VirtIOHandleOutput cursor_cb,
Error **errp);
+void virtio_gpu_base_device_unrealize(DeviceState *qdev);
void virtio_gpu_base_reset(VirtIOGPUBase *g);
void virtio_gpu_base_fill_display_info(VirtIOGPUBase *g,
struct virtio_gpu_resp_display_info *dpy_info);
+void virtio_gpu_base_generate_edid(VirtIOGPUBase *g, int scanout,
+ struct virtio_gpu_resp_edid *edid);
/* virtio-gpu.c */
+struct virtio_gpu_simple_resource *
+virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id);
+
void virtio_gpu_ctrl_response(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd,
struct virtio_gpu_ctrl_hdr *resp,
@@ -206,17 +303,37 @@ void virtio_gpu_get_display_info(VirtIOGPU *g,
void virtio_gpu_get_edid(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd);
int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
- struct virtio_gpu_resource_attach_backing *ab,
+ uint32_t nr_entries, uint32_t offset,
struct virtio_gpu_ctrl_command *cmd,
- uint64_t **addr, struct iovec **iov);
+ uint64_t **addr, struct iovec **iov,
+ uint32_t *niov);
void virtio_gpu_cleanup_mapping_iov(VirtIOGPU *g,
struct iovec *iov, uint32_t count);
+void virtio_gpu_cleanup_mapping(VirtIOGPU *g,
+ struct virtio_gpu_simple_resource *res);
void virtio_gpu_process_cmdq(VirtIOGPU *g);
+void virtio_gpu_device_realize(DeviceState *qdev, Error **errp);
+void virtio_gpu_reset(VirtIODevice *vdev);
+void virtio_gpu_simple_process_cmd(VirtIOGPU *g, struct virtio_gpu_ctrl_command *cmd);
+void virtio_gpu_update_cursor_data(VirtIOGPU *g,
+ struct virtio_gpu_scanout *s,
+ uint32_t resource_id);
+
+/* virtio-gpu-udmabuf.c */
+bool virtio_gpu_have_udmabuf(void);
+void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res);
+void virtio_gpu_fini_udmabuf(struct virtio_gpu_simple_resource *res);
+int virtio_gpu_update_dmabuf(VirtIOGPU *g,
+ uint32_t scanout_id,
+ struct virtio_gpu_simple_resource *res,
+ struct virtio_gpu_framebuffer *fb,
+ struct virtio_gpu_rect *r);
/* virtio-gpu-3d.c */
void virtio_gpu_virgl_process_cmd(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd);
void virtio_gpu_virgl_fence_poll(VirtIOGPU *g);
+void virtio_gpu_virgl_reset_scanout(VirtIOGPU *g);
void virtio_gpu_virgl_reset(VirtIOGPU *g);
int virtio_gpu_virgl_init(VirtIOGPU *g);
int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g);
diff --git a/include/hw/virtio/virtio-input.h b/include/hw/virtio/virtio-input.h
index 4fca03e796..e69c0aeca3 100644
--- a/include/hw/virtio/virtio-input.h
+++ b/include/hw/virtio/virtio-input.h
@@ -1,6 +1,8 @@
#ifndef QEMU_VIRTIO_INPUT_H
#define QEMU_VIRTIO_INPUT_H
+#include "hw/virtio/vhost-user.h"
+#include "hw/virtio/vhost-user-base.h"
#include "ui/input.h"
#include "sysemu/vhost-user-backend.h"
@@ -9,6 +11,7 @@
#include "standard-headers/linux/virtio_ids.h"
#include "standard-headers/linux/virtio_input.h"
+#include "qom/object.h"
typedef struct virtio_input_absinfo virtio_input_absinfo;
typedef struct virtio_input_config virtio_input_config;
@@ -18,43 +21,32 @@ typedef struct virtio_input_event virtio_input_event;
/* qemu internals */
#define TYPE_VIRTIO_INPUT "virtio-input-device"
-#define VIRTIO_INPUT(obj) \
- OBJECT_CHECK(VirtIOInput, (obj), TYPE_VIRTIO_INPUT)
+OBJECT_DECLARE_TYPE(VirtIOInput, VirtIOInputClass,
+ VIRTIO_INPUT)
#define VIRTIO_INPUT_GET_PARENT_CLASS(obj) \
OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_INPUT)
-#define VIRTIO_INPUT_GET_CLASS(obj) \
- OBJECT_GET_CLASS(VirtIOInputClass, obj, TYPE_VIRTIO_INPUT)
-#define VIRTIO_INPUT_CLASS(klass) \
- OBJECT_CLASS_CHECK(VirtIOInputClass, klass, TYPE_VIRTIO_INPUT)
-
-#define TYPE_VIRTIO_INPUT_HID "virtio-input-hid-device"
-#define TYPE_VIRTIO_KEYBOARD "virtio-keyboard-device"
-#define TYPE_VIRTIO_MOUSE "virtio-mouse-device"
-#define TYPE_VIRTIO_TABLET "virtio-tablet-device"
-
-#define VIRTIO_INPUT_HID(obj) \
- OBJECT_CHECK(VirtIOInputHID, (obj), TYPE_VIRTIO_INPUT_HID)
+
+#define TYPE_VIRTIO_INPUT_HID "virtio-input-hid-device"
+#define TYPE_VIRTIO_KEYBOARD "virtio-keyboard-device"
+#define TYPE_VIRTIO_MOUSE "virtio-mouse-device"
+#define TYPE_VIRTIO_TABLET "virtio-tablet-device"
+#define TYPE_VIRTIO_MULTITOUCH "virtio-multitouch-device"
+
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIOInputHID, VIRTIO_INPUT_HID)
#define VIRTIO_INPUT_HID_GET_PARENT_CLASS(obj) \
OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_INPUT_HID)
#define TYPE_VIRTIO_INPUT_HOST "virtio-input-host-device"
-#define VIRTIO_INPUT_HOST(obj) \
- OBJECT_CHECK(VirtIOInputHost, (obj), TYPE_VIRTIO_INPUT_HOST)
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIOInputHost, VIRTIO_INPUT_HOST)
#define VIRTIO_INPUT_HOST_GET_PARENT_CLASS(obj) \
OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_INPUT_HOST)
#define TYPE_VHOST_USER_INPUT "vhost-user-input"
-#define VHOST_USER_INPUT(obj) \
- OBJECT_CHECK(VHostUserInput, (obj), TYPE_VHOST_USER_INPUT)
+OBJECT_DECLARE_SIMPLE_TYPE(VHostUserInput, VHOST_USER_INPUT)
#define VHOST_USER_INPUT_GET_PARENT_CLASS(obj) \
OBJECT_GET_PARENT_CLASS(obj, TYPE_VHOST_USER_INPUT)
-typedef struct VirtIOInput VirtIOInput;
-typedef struct VirtIOInputClass VirtIOInputClass;
typedef struct VirtIOInputConfig VirtIOInputConfig;
-typedef struct VirtIOInputHID VirtIOInputHID;
-typedef struct VirtIOInputHost VirtIOInputHost;
-typedef struct VHostUserInput VHostUserInput;
struct VirtIOInputConfig {
virtio_input_config config;
@@ -94,7 +86,7 @@ struct VirtIOInputHID {
VirtIOInput parent_obj;
char *display;
uint32_t head;
- QemuInputHandler *handler;
+ const QemuInputHandler *handler;
QemuInputHandlerState *hs;
int ledstate;
bool wheel_axis;
@@ -107,9 +99,7 @@ struct VirtIOInputHost {
};
struct VHostUserInput {
- VirtIOInput parent_obj;
-
- VhostUserBackend *vhost;
+ VHostUserBase parent_obj;
};
void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event);
diff --git a/include/hw/virtio/virtio-iommu.h b/include/hw/virtio/virtio-iommu.h
index 49eb105cd8..83a52cc446 100644
--- a/include/hw/virtio/virtio-iommu.h
+++ b/include/hw/virtio/virtio-iommu.h
@@ -23,11 +23,12 @@
#include "standard-headers/linux/virtio_iommu.h"
#include "hw/virtio/virtio.h"
#include "hw/pci/pci.h"
+#include "qom/object.h"
+#include "qapi/qapi-types-virtio.h"
#define TYPE_VIRTIO_IOMMU "virtio-iommu-device"
-#define TYPE_VIRTIO_IOMMU_PCI "virtio-iommu-device-base"
-#define VIRTIO_IOMMU(obj) \
- OBJECT_CHECK(VirtIOIOMMU, (obj), TYPE_VIRTIO_IOMMU)
+#define TYPE_VIRTIO_IOMMU_PCI "virtio-iommu-pci"
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIOIOMMU, VIRTIO_IOMMU)
#define TYPE_VIRTIO_IOMMU_MEMORY_REGION "virtio-iommu-memory-region"
@@ -37,6 +38,11 @@ typedef struct IOMMUDevice {
int devfn;
IOMMUMemoryRegion iommu_mr;
AddressSpace as;
+ MemoryRegion root; /* The root container of the device */
+ MemoryRegion bypass_mr; /* The alias of shared memory MR */
+ GList *resv_regions;
+ GList *host_resv_ranges;
+ bool probe_done;
} IOMMUDevice;
typedef struct IOMMUPciBus {
@@ -44,7 +50,7 @@ typedef struct IOMMUPciBus {
IOMMUDevice *pbdev[]; /* Parent array is sparse, so dynamically alloc */
} IOMMUPciBus;
-typedef struct VirtIOIOMMU {
+struct VirtIOIOMMU {
VirtIODevice parent_obj;
VirtQueue *req_vq;
VirtQueue *event_vq;
@@ -53,11 +59,16 @@ typedef struct VirtIOIOMMU {
GHashTable *as_by_busptr;
IOMMUPciBus *iommu_pcibus_by_bus_num[PCI_BUS_MAX];
PCIBus *primary_bus;
- ReservedRegion *reserved_regions;
- uint32_t nb_reserved_regions;
+ ReservedRegion *prop_resv_regions;
+ uint32_t nr_prop_resv_regions;
GTree *domains;
- QemuMutex mutex;
+ QemuRecMutex mutex;
GTree *endpoints;
-} VirtIOIOMMU;
+ bool boot_bypass;
+ Notifier machine_done;
+ bool granule_frozen;
+ GranuleMode granule_mode;
+ uint8_t aw_bits;
+};
#endif
diff --git a/include/hw/virtio/virtio-md-pci.h b/include/hw/virtio/virtio-md-pci.h
new file mode 100644
index 0000000000..5912e16674
--- /dev/null
+++ b/include/hw/virtio/virtio-md-pci.h
@@ -0,0 +1,44 @@
+/*
+ * Abstract virtio based memory device
+ *
+ * Copyright (C) 2023 Red Hat, Inc.
+ *
+ * Authors:
+ * David Hildenbrand <david@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef HW_VIRTIO_MD_PCI_H
+#define HW_VIRTIO_MD_PCI_H
+
+#include "hw/virtio/virtio-pci.h"
+#include "qom/object.h"
+
+/*
+ * virtio-md-pci: This extends VirtioPCIProxy.
+ */
+#define TYPE_VIRTIO_MD_PCI "virtio-md-pci"
+
+OBJECT_DECLARE_TYPE(VirtIOMDPCI, VirtIOMDPCIClass, VIRTIO_MD_PCI)
+
+struct VirtIOMDPCIClass {
+ /* private */
+ VirtioPCIClass parent;
+
+ /* public */
+ void (*unplug_request_check)(VirtIOMDPCI *vmd, Error **errp);
+};
+
+struct VirtIOMDPCI {
+ VirtIOPCIProxy parent_obj;
+};
+
+void virtio_md_pci_pre_plug(VirtIOMDPCI *vmd, MachineState *ms, Error **errp);
+void virtio_md_pci_plug(VirtIOMDPCI *vmd, MachineState *ms, Error **errp);
+void virtio_md_pci_unplug_request(VirtIOMDPCI *vmd, MachineState *ms,
+ Error **errp);
+void virtio_md_pci_unplug(VirtIOMDPCI *vmd, MachineState *ms, Error **errp);
+
+#endif
diff --git a/include/hw/virtio/virtio-mem.h b/include/hw/virtio/virtio-mem.h
index 0778224964..5f5b02b8f9 100644
--- a/include/hw/virtio/virtio-mem.h
+++ b/include/hw/virtio/virtio-mem.h
@@ -17,15 +17,12 @@
#include "hw/virtio/virtio.h"
#include "qapi/qapi-types-misc.h"
#include "sysemu/hostmem.h"
+#include "qom/object.h"
#define TYPE_VIRTIO_MEM "virtio-mem"
-#define VIRTIO_MEM(obj) \
- OBJECT_CHECK(VirtIOMEM, (obj), TYPE_VIRTIO_MEM)
-#define VIRTIO_MEM_CLASS(oc) \
- OBJECT_CLASS_CHECK(VirtIOMEMClass, (oc), TYPE_VIRTIO_MEM)
-#define VIRTIO_MEM_GET_CLASS(obj) \
- OBJECT_GET_CLASS(VirtIOMEMClass, (obj), TYPE_VIRTIO_MEM)
+OBJECT_DECLARE_TYPE(VirtIOMEM, VirtIOMEMClass,
+ VIRTIO_MEM)
#define VIRTIO_MEM_MEMDEV_PROP "memdev"
#define VIRTIO_MEM_NODE_PROP "node"
@@ -33,8 +30,12 @@
#define VIRTIO_MEM_REQUESTED_SIZE_PROP "requested-size"
#define VIRTIO_MEM_BLOCK_SIZE_PROP "block-size"
#define VIRTIO_MEM_ADDR_PROP "memaddr"
+#define VIRTIO_MEM_UNPLUGGED_INACCESSIBLE_PROP "unplugged-inaccessible"
+#define VIRTIO_MEM_EARLY_MIGRATION_PROP "x-early-migration"
+#define VIRTIO_MEM_PREALLOC_PROP "prealloc"
+#define VIRTIO_MEM_DYNAMIC_MEMSLOTS_PROP "dynamic-memslots"
-typedef struct VirtIOMEM {
+struct VirtIOMEM {
VirtIODevice parent_obj;
/* guest -> host request queue */
@@ -44,7 +45,28 @@ typedef struct VirtIOMEM {
int32_t bitmap_size;
unsigned long *bitmap;
- /* assigned memory backend and memory region */
+ /*
+ * With "dynamic-memslots=on": Device memory region in which we dynamically
+ * map the memslots.
+ */
+ MemoryRegion *mr;
+
+ /*
+ * With "dynamic-memslots=on": The individual memslots (aliases into the
+ * memory backend).
+ */
+ MemoryRegion *memslots;
+
+ /* With "dynamic-memslots=on": The total number of memslots. */
+ uint16_t nb_memslots;
+
+ /*
+ * With "dynamic-memslots=on": Size of one memslot (the size of the
+ * last one can differ).
+ */
+ uint64_t memslot_size;
+
+ /* Assigned memory backend with the RAM memory region. */
HostMemoryBackend *memdev;
/* NUMA node */
@@ -65,22 +87,48 @@ typedef struct VirtIOMEM {
/* block size and alignment */
uint64_t block_size;
+ /*
+ * Whether we indicate VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE to the guest.
+ * For !x86 targets this will always be "on" and consequently indicate
+ * VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE.
+ */
+ OnOffAuto unplugged_inaccessible;
+
+ /* whether to prealloc memory when plugging new blocks */
+ bool prealloc;
+
+ /*
+ * Whether we migrate properties that are immutable while migration is
+ * active early, before state of other devices and especially, before
+ * migrating any RAM content.
+ */
+ bool early_migration;
+
+ /*
+ * Whether we dynamically map (multiple, if possible) memslots instead of
+ * statically mapping the whole RAM memory region.
+ */
+ bool dynamic_memslots;
+
/* notifiers to notify when "size" changes */
NotifierList size_change_notifiers;
- /* don't migrate unplugged memory */
- NotifierWithReturn precopy_notifier;
-} VirtIOMEM;
+ /* listeners to notify on plug/unplug activity. */
+ QLIST_HEAD(, RamDiscardListener) rdl_list;
+};
-typedef struct VirtIOMEMClass {
+struct VirtIOMEMClass {
/* private */
VirtIODevice parent;
/* public */
void (*fill_device_info)(const VirtIOMEM *vmen, VirtioMEMDeviceInfo *vi);
MemoryRegion *(*get_memory_region)(VirtIOMEM *vmem, Error **errp);
+ void (*decide_memslots)(VirtIOMEM *vmem, unsigned int limit);
+ unsigned int (*get_memslots)(VirtIOMEM *vmem);
void (*add_size_change_notifier)(VirtIOMEM *vmem, Notifier *notifier);
void (*remove_size_change_notifier)(VirtIOMEM *vmem, Notifier *notifier);
-} VirtIOMEMClass;
+ void (*unplug_request_check)(VirtIOMEM *vmem, Error **errp);
+};
#endif
diff --git a/include/hw/virtio/virtio-mmio.h b/include/hw/virtio/virtio-mmio.h
index 7dbfd03dcf..aa49262022 100644
--- a/include/hw/virtio/virtio-mmio.h
+++ b/include/hw/virtio/virtio-mmio.h
@@ -22,22 +22,19 @@
#ifndef HW_VIRTIO_MMIO_H
#define HW_VIRTIO_MMIO_H
+#include "hw/sysbus.h"
#include "hw/virtio/virtio-bus.h"
/* QOM macros */
/* virtio-mmio-bus */
#define TYPE_VIRTIO_MMIO_BUS "virtio-mmio-bus"
-#define VIRTIO_MMIO_BUS(obj) \
- OBJECT_CHECK(VirtioBusState, (obj), TYPE_VIRTIO_MMIO_BUS)
-#define VIRTIO_MMIO_BUS_GET_CLASS(obj) \
- OBJECT_GET_CLASS(VirtioBusClass, (obj), TYPE_VIRTIO_MMIO_BUS)
-#define VIRTIO_MMIO_BUS_CLASS(klass) \
- OBJECT_CLASS_CHECK(VirtioBusClass, (klass), TYPE_VIRTIO_MMIO_BUS)
+/* This is reusing the VirtioBusState typedef from TYPE_VIRTIO_BUS */
+DECLARE_OBJ_CHECKERS(VirtioBusState, VirtioBusClass,
+ VIRTIO_MMIO_BUS, TYPE_VIRTIO_MMIO_BUS)
/* virtio-mmio */
#define TYPE_VIRTIO_MMIO "virtio-mmio"
-#define VIRTIO_MMIO(obj) \
- OBJECT_CHECK(VirtIOMMIOProxy, (obj), TYPE_VIRTIO_MMIO)
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIOMMIOProxy, VIRTIO_MMIO)
#define VIRT_MAGIC 0x74726976 /* 'virt' */
#define VIRT_VERSION 2
@@ -52,12 +49,17 @@ typedef struct VirtIOMMIOQueue {
uint32_t used[2];
} VirtIOMMIOQueue;
-typedef struct {
+#define VIRTIO_IOMMIO_FLAG_USE_IOEVENTFD_BIT 1
+#define VIRTIO_IOMMIO_FLAG_USE_IOEVENTFD \
+ (1 << VIRTIO_IOMMIO_FLAG_USE_IOEVENTFD_BIT)
+
+struct VirtIOMMIOProxy {
/* Generic */
SysBusDevice parent_obj;
MemoryRegion iomem;
qemu_irq irq;
bool legacy;
+ uint32_t flags;
/* Guest accessible state needing migration and reset */
uint32_t host_features_sel;
uint32_t guest_features_sel;
@@ -68,6 +70,6 @@ typedef struct {
/* Fields only used for non-legacy (v2) devices */
uint32_t guest_features[2];
VirtIOMMIOQueue vqs[VIRTIO_QUEUE_MAX];
-} VirtIOMMIOProxy;
+};
#endif
diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
index a45ef8278e..060c23c04d 100644
--- a/include/hw/virtio/virtio-net.h
+++ b/include/hw/virtio/virtio-net.h
@@ -19,10 +19,12 @@
#include "hw/virtio/virtio.h"
#include "net/announce.h"
#include "qemu/option_int.h"
+#include "qom/object.h"
+
+#include "ebpf/ebpf_rss.h"
#define TYPE_VIRTIO_NET "virtio-net-device"
-#define VIRTIO_NET(obj) \
- OBJECT_CHECK(VirtIONet, (obj), TYPE_VIRTIO_NET)
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIONet, VIRTIO_NET)
#define TX_TIMER_INTERVAL 150000 /* 150 us */
@@ -33,6 +35,15 @@
* and latency. */
#define TX_BURST 256
+/* Maximum VIRTIO_NET_CTRL_MAC_TABLE_SET unicast + multicast entries. */
+#define MAC_TABLE_ENTRIES 64
+
+/*
+ * The maximum number of VLANs in the VLAN filter table
+ * added by VIRTIO_NET_CTRL_VLAN_ADD
+ */
+#define MAX_VLAN (1 << 12) /* Per 802.1Q definition */
+
typedef struct virtio_net_conf
{
uint32_t txtimer;
@@ -104,12 +115,11 @@ typedef struct VirtioNetRscSeg {
size_t size;
uint16_t packets;
uint16_t dup_ack;
- bool is_coalesced; /* need recal ipv4 header checksum, mark here */
+ bool is_coalesced; /* need recall ipv4 header checksum, mark here */
VirtioNetRscUnit unit;
NetClientState *nc;
} VirtioNetRscSeg;
-typedef struct VirtIONet VirtIONet;
/* Chain is divided by protocol(ipv4/v6) and NetClientInfo */
typedef struct VirtioNetRscChain {
@@ -131,6 +141,7 @@ typedef struct VirtioNetRscChain {
typedef struct VirtioNetRssData {
bool enabled;
+ bool enabled_software_rss;
bool redirect;
bool populate_hash;
uint32_t hash_types;
@@ -192,8 +203,9 @@ struct VirtIONet {
NICConf nic_conf;
DeviceState *qdev;
int multiqueue;
- uint16_t max_queues;
- uint16_t curr_queues;
+ uint16_t max_queue_pairs;
+ uint16_t curr_queue_pairs;
+ uint16_t max_ncs;
size_t config_size;
char *netclient_name;
char *netclient_type;
@@ -203,21 +215,26 @@ struct VirtIONet {
AnnounceTimer announce_timer;
bool needs_vnet_hdr_swap;
bool mtu_bypass_backend;
- QemuOpts *primary_device_opts;
- QDict *primary_device_dict;
- DeviceState *primary_dev;
- BusState *primary_bus;
- char *primary_device_id;
- char *standby_id;
- bool primary_should_be_hidden;
+ /* primary failover device is hidden*/
+ bool failover_primary_hidden;
bool failover;
DeviceListener primary_listener;
- Notifier migration_state;
+ QDict *primary_opts;
+ bool primary_opts_from_json;
+ NotifierWithReturn migration_state;
VirtioNetRssData rss_data;
struct NetRxPkt *rx_pkt;
+ struct EBPFRSSContext ebpf_rss;
+ uint32_t nr_ebpf_rss_fds;
+ char **ebpf_rss_fds;
};
+size_t virtio_net_handle_ctrl_iov(VirtIODevice *vdev,
+ const struct iovec *in_sg, unsigned in_num,
+ const struct iovec *out_sg,
+ unsigned out_num);
void virtio_net_set_netclient_name(VirtIONet *n, const char *name,
const char *type);
+uint64_t virtio_net_supported_guest_offloads(const VirtIONet *n);
#endif
diff --git a/include/hw/virtio/virtio-pci.h b/include/hw/virtio/virtio-pci.h
new file mode 100644
index 0000000000..59d88018c1
--- /dev/null
+++ b/include/hw/virtio/virtio-pci.h
@@ -0,0 +1,272 @@
+/*
+ * Virtio PCI Bindings
+ *
+ * Copyright IBM, Corp. 2007
+ * Copyright (c) 2009 CodeSourcery
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@us.ibm.com>
+ * Paul Brook <paul@codesourcery.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef QEMU_VIRTIO_PCI_H
+#define QEMU_VIRTIO_PCI_H
+
+#include "hw/pci/msi.h"
+#include "hw/virtio/virtio-bus.h"
+#include "qom/object.h"
+
+
+/* virtio-pci-bus */
+
+typedef struct VirtioBusState VirtioPCIBusState;
+typedef struct VirtioBusClass VirtioPCIBusClass;
+
+#define TYPE_VIRTIO_PCI_BUS "virtio-pci-bus"
+DECLARE_OBJ_CHECKERS(VirtioPCIBusState, VirtioPCIBusClass,
+ VIRTIO_PCI_BUS, TYPE_VIRTIO_PCI_BUS)
+
+enum {
+ VIRTIO_PCI_FLAG_BUS_MASTER_BUG_MIGRATION_BIT,
+ VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT,
+ VIRTIO_PCI_FLAG_MIGRATE_EXTRA_BIT,
+ VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY_BIT,
+ VIRTIO_PCI_FLAG_DISABLE_PCIE_BIT,
+ VIRTIO_PCI_FLAG_PAGE_PER_VQ_BIT,
+ VIRTIO_PCI_FLAG_ATS_BIT,
+ VIRTIO_PCI_FLAG_INIT_DEVERR_BIT,
+ VIRTIO_PCI_FLAG_INIT_LNKCTL_BIT,
+ VIRTIO_PCI_FLAG_INIT_PM_BIT,
+ VIRTIO_PCI_FLAG_INIT_FLR_BIT,
+ VIRTIO_PCI_FLAG_AER_BIT,
+ VIRTIO_PCI_FLAG_ATS_PAGE_ALIGNED_BIT,
+};
+
+/* Need to activate work-arounds for buggy guests at vmstate load. */
+#define VIRTIO_PCI_FLAG_BUS_MASTER_BUG_MIGRATION \
+ (1 << VIRTIO_PCI_FLAG_BUS_MASTER_BUG_MIGRATION_BIT)
+
+/* Performance improves when virtqueue kick processing is decoupled from the
+ * vcpu thread using ioeventfd for some devices. */
+#define VIRTIO_PCI_FLAG_USE_IOEVENTFD (1 << VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT)
+
+/* virtio version flags */
+#define VIRTIO_PCI_FLAG_DISABLE_PCIE (1 << VIRTIO_PCI_FLAG_DISABLE_PCIE_BIT)
+
+/* migrate extra state */
+#define VIRTIO_PCI_FLAG_MIGRATE_EXTRA (1 << VIRTIO_PCI_FLAG_MIGRATE_EXTRA_BIT)
+
+/* have pio notification for modern device ? */
+#define VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY \
+ (1 << VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY_BIT)
+
+/* page per vq flag to be used by split drivers within guests */
+#define VIRTIO_PCI_FLAG_PAGE_PER_VQ \
+ (1 << VIRTIO_PCI_FLAG_PAGE_PER_VQ_BIT)
+
+/* address space translation service */
+#define VIRTIO_PCI_FLAG_ATS (1 << VIRTIO_PCI_FLAG_ATS_BIT)
+
+/* Init error enabling flags */
+#define VIRTIO_PCI_FLAG_INIT_DEVERR (1 << VIRTIO_PCI_FLAG_INIT_DEVERR_BIT)
+
+/* Init Link Control register */
+#define VIRTIO_PCI_FLAG_INIT_LNKCTL (1 << VIRTIO_PCI_FLAG_INIT_LNKCTL_BIT)
+
+/* Init Power Management */
+#define VIRTIO_PCI_FLAG_INIT_PM (1 << VIRTIO_PCI_FLAG_INIT_PM_BIT)
+
+/* Init Function Level Reset capability */
+#define VIRTIO_PCI_FLAG_INIT_FLR (1 << VIRTIO_PCI_FLAG_INIT_FLR_BIT)
+
+/* Advanced Error Reporting capability */
+#define VIRTIO_PCI_FLAG_AER (1 << VIRTIO_PCI_FLAG_AER_BIT)
+
+/* Page Aligned Address space Translation Service */
+#define VIRTIO_PCI_FLAG_ATS_PAGE_ALIGNED \
+ (1 << VIRTIO_PCI_FLAG_ATS_PAGE_ALIGNED_BIT)
+
+typedef struct {
+ MSIMessage msg;
+ int virq;
+ unsigned int users;
+} VirtIOIRQFD;
+
+/*
+ * virtio-pci: This is the PCIDevice which has a virtio-pci-bus.
+ */
+#define TYPE_VIRTIO_PCI "virtio-pci"
+OBJECT_DECLARE_TYPE(VirtIOPCIProxy, VirtioPCIClass, VIRTIO_PCI)
+
+struct VirtioPCIClass {
+ PCIDeviceClass parent_class;
+ DeviceRealize parent_dc_realize;
+ void (*realize)(VirtIOPCIProxy *vpci_dev, Error **errp);
+};
+
+typedef struct VirtIOPCIRegion {
+ MemoryRegion mr;
+ uint32_t offset;
+ uint32_t size;
+ uint32_t type;
+} VirtIOPCIRegion;
+
+typedef struct VirtIOPCIQueue {
+ uint16_t num;
+ bool enabled;
+ /*
+ * No need to migrate the reset status, because it is always 0
+ * when the migration starts.
+ */
+ bool reset;
+ uint32_t desc[2];
+ uint32_t avail[2];
+ uint32_t used[2];
+} VirtIOPCIQueue;
+
+struct VirtIOPCIProxy {
+ PCIDevice pci_dev;
+ MemoryRegion bar;
+ union {
+ struct {
+ VirtIOPCIRegion common;
+ VirtIOPCIRegion isr;
+ VirtIOPCIRegion device;
+ VirtIOPCIRegion notify;
+ VirtIOPCIRegion notify_pio;
+ };
+ VirtIOPCIRegion regs[5];
+ };
+ MemoryRegion modern_bar;
+ MemoryRegion io_bar;
+ uint32_t legacy_io_bar_idx;
+ uint32_t msix_bar_idx;
+ uint32_t modern_io_bar_idx;
+ uint32_t modern_mem_bar_idx;
+ int config_cap;
+ uint32_t flags;
+ bool disable_modern;
+ bool ignore_backend_features;
+ OnOffAuto disable_legacy;
+ /* Transitional device id */
+ uint16_t trans_devid;
+ uint32_t class_code;
+ uint32_t nvectors;
+ uint32_t dfselect;
+ uint32_t gfselect;
+ uint32_t guest_features[2];
+ VirtIOPCIQueue vqs[VIRTIO_QUEUE_MAX];
+
+ VirtIOIRQFD *vector_irqfd;
+ int nvqs_with_notifiers;
+ VirtioBusState bus;
+};
+
+static inline bool virtio_pci_modern(VirtIOPCIProxy *proxy)
+{
+ return !proxy->disable_modern;
+}
+
+static inline bool virtio_pci_legacy(VirtIOPCIProxy *proxy)
+{
+ return proxy->disable_legacy == ON_OFF_AUTO_OFF;
+}
+
+static inline void virtio_pci_force_virtio_1(VirtIOPCIProxy *proxy)
+{
+ proxy->disable_modern = false;
+ proxy->disable_legacy = ON_OFF_AUTO_ON;
+}
+
+static inline void virtio_pci_disable_modern(VirtIOPCIProxy *proxy)
+{
+ proxy->disable_modern = true;
+}
+
+uint16_t virtio_pci_get_trans_devid(uint16_t device_id);
+uint16_t virtio_pci_get_class_id(uint16_t device_id);
+
+/*
+ * virtio-input-pci: This extends VirtioPCIProxy.
+ */
+#define TYPE_VIRTIO_INPUT_PCI "virtio-input-pci"
+
+/* Virtio ABI version, if we increment this, we break the guest driver. */
+#define VIRTIO_PCI_ABI_VERSION 0
+
+/* Input for virtio_pci_types_register() */
+typedef struct VirtioPCIDeviceTypeInfo {
+ /*
+ * Common base class for the subclasses below.
+ *
+ * Required only if transitional_name or non_transitional_name is set.
+ *
+ * We need a separate base type instead of making all types
+ * inherit from generic_name for two reasons:
+ * 1) generic_name implements INTERFACE_PCIE_DEVICE, but
+ * transitional_name does not.
+ * 2) generic_name has the "disable-legacy" and "disable-modern"
+ * properties, transitional_name and non_transitional name don't.
+ */
+ const char *base_name;
+ /*
+ * Generic device type. Optional.
+ *
+ * Supports both transitional and non-transitional modes,
+ * using the disable-legacy and disable-modern properties.
+ * If disable-legacy=auto, (non-)transitional mode is selected
+ * depending on the bus where the device is plugged.
+ *
+ * Implements both INTERFACE_PCIE_DEVICE and INTERFACE_CONVENTIONAL_PCI_DEVICE,
+ * but PCI Express is supported only in non-transitional mode.
+ *
+ * The only type implemented by QEMU 3.1 and older.
+ */
+ const char *generic_name;
+ /*
+ * The transitional device type. Optional.
+ *
+ * Implements both INTERFACE_PCIE_DEVICE and INTERFACE_CONVENTIONAL_PCI_DEVICE.
+ */
+ const char *transitional_name;
+ /*
+ * The non-transitional device type. Optional.
+ *
+ * Implements INTERFACE_CONVENTIONAL_PCI_DEVICE only.
+ */
+ const char *non_transitional_name;
+
+ /* Parent type. If NULL, TYPE_VIRTIO_PCI is used */
+ const char *parent;
+
+ /* Same as TypeInfo fields: */
+ size_t instance_size;
+ size_t class_size;
+ void (*instance_init)(Object *obj);
+ void (*instance_finalize)(Object *obj);
+ void (*class_init)(ObjectClass *klass, void *data);
+ InterfaceInfo *interfaces;
+} VirtioPCIDeviceTypeInfo;
+
+/* Register virtio-pci type(s). @t must be static. */
+void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t);
+
+/**
+ * virtio_pci_optimal_num_queues:
+ * @fixed_queues: number of queues that are always present
+ *
+ * Returns: The optimal number of queues for a multi-queue device, excluding
+ * @fixed_queues.
+ */
+unsigned virtio_pci_optimal_num_queues(unsigned fixed_queues);
+void virtio_pci_set_guest_notifier_fd_handler(VirtIODevice *vdev, VirtQueue *vq,
+ int n, bool assign,
+ bool with_irqfd);
+
+int virtio_pci_add_shm_cap(VirtIOPCIProxy *proxy, uint8_t bar, uint64_t offset,
+ uint64_t length, uint8_t id);
+
+#endif
diff --git a/include/hw/virtio/virtio-pmem.h b/include/hw/virtio/virtio-pmem.h
index 33f1999320..fc4fd1f7fe 100644
--- a/include/hw/virtio/virtio-pmem.h
+++ b/include/hw/virtio/virtio-pmem.h
@@ -15,35 +15,32 @@
#define HW_VIRTIO_PMEM_H
#include "hw/virtio/virtio.h"
-#include "qapi/qapi-types-misc.h"
+#include "qapi/qapi-types-machine.h"
+#include "qom/object.h"
#define TYPE_VIRTIO_PMEM "virtio-pmem"
-#define VIRTIO_PMEM(obj) \
- OBJECT_CHECK(VirtIOPMEM, (obj), TYPE_VIRTIO_PMEM)
-#define VIRTIO_PMEM_CLASS(oc) \
- OBJECT_CLASS_CHECK(VirtIOPMEMClass, (oc), TYPE_VIRTIO_PMEM)
-#define VIRTIO_PMEM_GET_CLASS(obj) \
- OBJECT_GET_CLASS(VirtIOPMEMClass, (obj), TYPE_VIRTIO_PMEM)
+OBJECT_DECLARE_TYPE(VirtIOPMEM, VirtIOPMEMClass,
+ VIRTIO_PMEM)
#define VIRTIO_PMEM_ADDR_PROP "memaddr"
#define VIRTIO_PMEM_MEMDEV_PROP "memdev"
-typedef struct VirtIOPMEM {
+struct VirtIOPMEM {
VirtIODevice parent_obj;
VirtQueue *rq_vq;
uint64_t start;
HostMemoryBackend *memdev;
-} VirtIOPMEM;
+};
-typedef struct VirtIOPMEMClass {
+struct VirtIOPMEMClass {
/* private */
VirtIODevice parent;
/* public */
void (*fill_device_info)(const VirtIOPMEM *pmem, VirtioPMEMDeviceInfo *vi);
MemoryRegion *(*get_memory_region)(VirtIOPMEM *pmem, Error **errp);
-} VirtIOPMEMClass;
+};
#endif
diff --git a/include/hw/virtio/virtio-rng.h b/include/hw/virtio/virtio-rng.h
index bd05d734b8..82734255d9 100644
--- a/include/hw/virtio/virtio-rng.h
+++ b/include/hw/virtio/virtio-rng.h
@@ -15,10 +15,10 @@
#include "hw/virtio/virtio.h"
#include "sysemu/rng.h"
#include "standard-headers/linux/virtio_rng.h"
+#include "qom/object.h"
#define TYPE_VIRTIO_RNG "virtio-rng-device"
-#define VIRTIO_RNG(obj) \
- OBJECT_CHECK(VirtIORNG, (obj), TYPE_VIRTIO_RNG)
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIORNG, VIRTIO_RNG)
#define VIRTIO_RNG_GET_PARENT_CLASS(obj) \
OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_RNG)
@@ -28,7 +28,7 @@ struct VirtIORNGConf {
uint32_t period_ms;
};
-typedef struct VirtIORNG {
+struct VirtIORNG {
VirtIODevice parent_obj;
/* Only one vq - guest puts buffer(s) on it when it needs entropy */
@@ -46,6 +46,6 @@ typedef struct VirtIORNG {
bool activate_timer;
VMChangeStateEntry *vmstate;
-} VirtIORNG;
+};
#endif
diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
index 24e768909d..7be0105918 100644
--- a/include/hw/virtio/virtio-scsi.h
+++ b/include/hw/virtio/virtio-scsi.h
@@ -13,29 +13,32 @@
#ifndef QEMU_VIRTIO_SCSI_H
#define QEMU_VIRTIO_SCSI_H
+#include "qom/object.h"
/* Override CDB/sense data size: they are dynamic (guest controlled) in QEMU */
#define VIRTIO_SCSI_CDB_SIZE 0
#define VIRTIO_SCSI_SENSE_SIZE 0
#include "standard-headers/linux/virtio_scsi.h"
#include "hw/virtio/virtio.h"
-#include "hw/pci/pci.h"
#include "hw/scsi/scsi.h"
#include "chardev/char-fe.h"
#include "sysemu/iothread.h"
#define TYPE_VIRTIO_SCSI_COMMON "virtio-scsi-common"
-#define VIRTIO_SCSI_COMMON(obj) \
- OBJECT_CHECK(VirtIOSCSICommon, (obj), TYPE_VIRTIO_SCSI_COMMON)
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIOSCSICommon, VIRTIO_SCSI_COMMON)
#define TYPE_VIRTIO_SCSI "virtio-scsi-device"
-#define VIRTIO_SCSI(obj) \
- OBJECT_CHECK(VirtIOSCSI, (obj), TYPE_VIRTIO_SCSI)
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIOSCSI, VIRTIO_SCSI)
#define VIRTIO_SCSI_MAX_CHANNEL 0
#define VIRTIO_SCSI_MAX_TARGET 255
#define VIRTIO_SCSI_MAX_LUN 16383
+/* Number of virtqueues that are always present */
+#define VIRTIO_SCSI_VQ_NUM_FIXED 2
+
+#define VIRTIO_SCSI_AUTO_NUM_QUEUES UINT32_MAX
+
typedef struct virtio_scsi_cmd_req VirtIOSCSICmdReq;
typedef struct virtio_scsi_cmd_resp VirtIOSCSICmdResp;
typedef struct virtio_scsi_ctrl_tmf_req VirtIOSCSICtrlTMFReq;
@@ -48,13 +51,12 @@ typedef struct virtio_scsi_config VirtIOSCSIConfig;
struct VirtIOSCSIConf {
uint32_t num_queues;
uint32_t virtqueue_size;
+ bool worker_per_virtqueue;
bool seg_max_adjust;
uint32_t max_sectors;
uint32_t cmd_per_lun;
-#ifdef CONFIG_VHOST_SCSI
char *vhostfd;
char *wwpn;
-#endif
CharBackend chardev;
uint32_t boot_tpgt;
IOThread *iothread;
@@ -62,7 +64,7 @@ struct VirtIOSCSIConf {
struct VirtIOSCSI;
-typedef struct VirtIOSCSICommon {
+struct VirtIOSCSICommon {
VirtIODevice parent_obj;
VirtIOSCSIConf conf;
@@ -71,15 +73,25 @@ typedef struct VirtIOSCSICommon {
VirtQueue *ctrl_vq;
VirtQueue *event_vq;
VirtQueue **cmd_vqs;
-} VirtIOSCSICommon;
+};
-typedef struct VirtIOSCSI {
+struct VirtIOSCSIReq;
+
+struct VirtIOSCSI {
VirtIOSCSICommon parent_obj;
SCSIBus bus;
- int resetting;
+ int resetting; /* written from main loop thread, read from any thread */
bool events_dropped;
+ /*
+ * TMFs deferred to main loop BH. These fields are protected by
+ * tmf_bh_lock.
+ */
+ QemuMutex tmf_bh_lock;
+ QEMUBH *tmf_bh;
+ QTAILQ_HEAD(, VirtIOSCSIReq) tmf_bh_list;
+
/* Fields for dataplane below */
AioContext *ctx; /* one iothread per virtio-scsi-pci for now */
@@ -88,57 +100,7 @@ typedef struct VirtIOSCSI {
bool dataplane_stopping;
bool dataplane_fenced;
uint32_t host_features;
-} VirtIOSCSI;
-
-typedef struct VirtIOSCSIReq {
- /* Note:
- * - fields up to resp_iov are initialized by virtio_scsi_init_req;
- * - fields starting at vring are zeroed by virtio_scsi_init_req.
- * */
- VirtQueueElement elem;
-
- VirtIOSCSI *dev;
- VirtQueue *vq;
- QEMUSGList qsgl;
- QEMUIOVector resp_iov;
-
- union {
- /* Used for two-stage request submission */
- QTAILQ_ENTRY(VirtIOSCSIReq) next;
-
- /* Used for cancellation of request during TMFs */
- int remaining;
- };
-
- SCSIRequest *sreq;
- size_t resp_size;
- enum SCSIXferMode mode;
- union {
- VirtIOSCSICmdResp cmd;
- VirtIOSCSICtrlTMFResp tmf;
- VirtIOSCSICtrlANResp an;
- VirtIOSCSIEvent event;
- } resp;
- union {
- VirtIOSCSICmdReq cmd;
- VirtIOSCSICtrlTMFReq tmf;
- VirtIOSCSICtrlANReq an;
- } req;
-} VirtIOSCSIReq;
-
-static inline void virtio_scsi_acquire(VirtIOSCSI *s)
-{
- if (s->ctx) {
- aio_context_acquire(s->ctx);
- }
-}
-
-static inline void virtio_scsi_release(VirtIOSCSI *s)
-{
- if (s->ctx) {
- aio_context_release(s->ctx);
- }
-}
+};
void virtio_scsi_common_realize(DeviceState *dev,
VirtIOHandleOutput ctrl,
@@ -147,13 +109,6 @@ void virtio_scsi_common_realize(DeviceState *dev,
Error **errp);
void virtio_scsi_common_unrealize(DeviceState *dev);
-bool virtio_scsi_handle_event_vq(VirtIOSCSI *s, VirtQueue *vq);
-bool virtio_scsi_handle_cmd_vq(VirtIOSCSI *s, VirtQueue *vq);
-bool virtio_scsi_handle_ctrl_vq(VirtIOSCSI *s, VirtQueue *vq);
-void virtio_scsi_init_req(VirtIOSCSI *s, VirtQueue *vq, VirtIOSCSIReq *req);
-void virtio_scsi_free_req(VirtIOSCSIReq *req);
-void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev,
- uint32_t event, uint32_t reason);
void virtio_scsi_dataplane_setup(VirtIOSCSI *s, Error **errp);
int virtio_scsi_dataplane_start(VirtIODevice *s);
diff --git a/include/hw/virtio/virtio-serial.h b/include/hw/virtio/virtio-serial.h
index ed3e916b68..d87c62eab7 100644
--- a/include/hw/virtio/virtio-serial.h
+++ b/include/hw/virtio/virtio-serial.h
@@ -18,6 +18,7 @@
#include "standard-headers/linux/virtio_console.h"
#include "hw/virtio/virtio.h"
+#include "qom/object.h"
struct virtio_serial_conf {
/* Max. number of ports we can have for a virtio-serial device */
@@ -25,18 +26,16 @@ struct virtio_serial_conf {
};
#define TYPE_VIRTIO_SERIAL_PORT "virtio-serial-port"
-#define VIRTIO_SERIAL_PORT(obj) \
- OBJECT_CHECK(VirtIOSerialPort, (obj), TYPE_VIRTIO_SERIAL_PORT)
-#define VIRTIO_SERIAL_PORT_CLASS(klass) \
- OBJECT_CLASS_CHECK(VirtIOSerialPortClass, (klass), TYPE_VIRTIO_SERIAL_PORT)
-#define VIRTIO_SERIAL_PORT_GET_CLASS(obj) \
- OBJECT_GET_CLASS(VirtIOSerialPortClass, (obj), TYPE_VIRTIO_SERIAL_PORT)
+OBJECT_DECLARE_TYPE(VirtIOSerialPort, VirtIOSerialPortClass,
+ VIRTIO_SERIAL_PORT)
typedef struct VirtIOSerial VirtIOSerial;
-typedef struct VirtIOSerialBus VirtIOSerialBus;
-typedef struct VirtIOSerialPort VirtIOSerialPort;
-typedef struct VirtIOSerialPortClass {
+#define TYPE_VIRTIO_SERIAL_BUS "virtio-serial-bus"
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIOSerialBus, VIRTIO_SERIAL_BUS)
+
+
+struct VirtIOSerialPortClass {
DeviceClass parent_class;
/* Is this a device that binds with hvc in the guest? */
@@ -81,7 +80,7 @@ typedef struct VirtIOSerialPortClass {
*/
ssize_t (*have_data)(VirtIOSerialPort *port, const uint8_t *buf,
ssize_t len);
-} VirtIOSerialPortClass;
+};
/*
* This is the state that's shared between all the ports. Some of the
@@ -223,7 +222,6 @@ size_t virtio_serial_guest_ready(VirtIOSerialPort *port);
void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle);
#define TYPE_VIRTIO_SERIAL "virtio-serial-device"
-#define VIRTIO_SERIAL(obj) \
- OBJECT_CHECK(VirtIOSerial, (obj), TYPE_VIRTIO_SERIAL)
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIOSerial, VIRTIO_SERIAL)
#endif
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index e424df12cf..7d5ffdc145 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -21,9 +21,16 @@
#include "qemu/event_notifier.h"
#include "standard-headers/linux/virtio_config.h"
#include "standard-headers/linux/virtio_ring.h"
+#include "qom/object.h"
+#include "block/aio.h"
-/* A guest should never accept this. It implies negotiation is broken. */
-#define VIRTIO_F_BAD_FEATURE 30
+/*
+ * A guest should never accept this. It implies negotiation is broken
+ * between the driver frontend and the device. This bit is re-used for
+ * vhost-user to advertise VHOST_USER_F_PROTOCOL_FEATURES between QEMU
+ * and a vhost-user backend.
+ */
+#define VIRTIO_F_BAD_FEATURE 30
#define VIRTIO_LEGACY_FEATURES ((0x1ULL << VIRTIO_F_BAD_FEATURE) | \
(0x1ULL << VIRTIO_F_NOTIFY_ON_EMPTY) | \
@@ -42,8 +49,14 @@ typedef struct VirtIOFeature {
size_t end;
} VirtIOFeature;
-size_t virtio_feature_get_config_size(VirtIOFeature *features,
- uint64_t host_features);
+typedef struct VirtIOConfigSizeParams {
+ size_t min_size;
+ size_t max_size;
+ const VirtIOFeature *feature_sizes;
+} VirtIOConfigSizeParams;
+
+size_t virtio_get_config_size(const VirtIOConfigSizeParams *params,
+ uint64_t host_features);
typedef struct VirtQueue VirtQueue;
@@ -66,13 +79,16 @@ typedef struct VirtQueueElement
#define VIRTIO_NO_VECTOR 0xffff
+/* special index value used internally for config irqs */
+#define VIRTIO_CONFIG_IRQ_IDX -1
+
#define TYPE_VIRTIO_DEVICE "virtio-device"
-#define VIRTIO_DEVICE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(VirtioDeviceClass, obj, TYPE_VIRTIO_DEVICE)
-#define VIRTIO_DEVICE_CLASS(klass) \
- OBJECT_CLASS_CHECK(VirtioDeviceClass, klass, TYPE_VIRTIO_DEVICE)
-#define VIRTIO_DEVICE(obj) \
- OBJECT_CHECK(VirtIODevice, (obj), TYPE_VIRTIO_DEVICE)
+OBJECT_DECLARE_TYPE(VirtIODevice, VirtioDeviceClass, VIRTIO_DEVICE)
+
+typedef struct {
+ int virtio_bit;
+ const char *feature_desc;
+} qmp_virtio_feature_map_t;
enum virtio_device_endian {
VIRTIO_DEVICE_ENDIAN_UNKNOWN,
@@ -80,6 +96,12 @@ enum virtio_device_endian {
VIRTIO_DEVICE_ENDIAN_BIG,
};
+/**
+ * struct VirtIODevice - common VirtIO structure
+ * @name: name of the device
+ * @status: VirtIO Device Status field
+ *
+ */
struct VirtIODevice
{
DeviceState parent_obj;
@@ -87,9 +109,20 @@ struct VirtIODevice
uint8_t status;
uint8_t isr;
uint16_t queue_sel;
- uint64_t guest_features;
+ /**
+ * These fields represent a set of VirtIO features at various
+ * levels of the stack. @host_features indicates the complete
+ * feature set the VirtIO device can offer to the driver.
+ * @guest_features indicates which features the VirtIO driver has
+ * selected by writing to the feature register. Finally
+ * @backend_features represents everything supported by the
+ * backend (e.g. vhost) and could potentially be a subset of the
+ * total feature set offered by QEMU.
+ */
uint64_t host_features;
+ uint64_t guest_features;
uint64_t backend_features;
+
size_t config_len;
void *config;
uint16_t config_vector;
@@ -98,22 +131,43 @@ struct VirtIODevice
VirtQueue *vq;
MemoryListener listener;
uint16_t device_id;
+ /* @vm_running: current VM running state via virtio_vmstate_change() */
bool vm_running;
bool broken; /* device in invalid state, needs reset */
bool use_disabled_flag; /* allow use of 'disable' flag when needed */
bool disabled; /* device in temporarily disabled state */
+ /**
+ * @use_started: true if the @started flag should be used to check the
+ * current state of the VirtIO device. Otherwise status bits
+ * should be checked for a current status of the device.
+ * @use_started is only set via QMP and defaults to true for all
+ * modern machines (since 4.1).
+ */
bool use_started;
bool started;
bool start_on_kick; /* when virtio 1.0 feature has not been negotiated */
+ bool disable_legacy_check;
+ bool vhost_started;
VMChangeStateEntry *vmstate;
char *bus_name;
uint8_t device_endian;
+ /**
+ * @user_guest_notifier_mask: gate usage of ->guest_notifier_mask() callback.
+ * This is used to suppress the masking of guest updates for
+ * vhost-user devices which are asynchronous by design.
+ */
bool use_guest_notifier_mask;
AddressSpace *dma_as;
QLIST_HEAD(, VirtQueue) *vector_queues;
+ QTAILQ_ENTRY(VirtIODevice) next;
+ /**
+ * @config_notifier: the event notifier that handles config events
+ */
+ EventNotifier config_notifier;
+ bool device_iotlb_enabled;
};
-typedef struct VirtioDeviceClass {
+struct VirtioDeviceClass {
/*< private >*/
DeviceClass parent;
/*< public >*/
@@ -131,6 +185,10 @@ typedef struct VirtioDeviceClass {
void (*set_config)(VirtIODevice *vdev, const uint8_t *config);
void (*reset)(VirtIODevice *vdev);
void (*set_status)(VirtIODevice *vdev, uint8_t val);
+ /* Device must validate queue_index. */
+ void (*queue_reset)(VirtIODevice *vdev, uint32_t queue_index);
+ /* Device must validate queue_index. */
+ void (*queue_enable)(VirtIODevice *vdev, uint32_t queue_index);
/* For transitional devices, this is a bitmap of features
* that are only exposed on the legacy interface but not
* the modern one.
@@ -163,22 +221,29 @@ typedef struct VirtioDeviceClass {
int (*post_load)(VirtIODevice *vdev);
const VMStateDescription *vmsd;
bool (*primary_unplug_pending)(void *opaque);
-} VirtioDeviceClass;
+ struct vhost_dev *(*get_vhost)(VirtIODevice *vdev);
+ void (*toggle_device_iotlb)(VirtIODevice *vdev);
+};
void virtio_instance_init_common(Object *proxy_obj, void *data,
size_t vdev_size, const char *vdev_name);
-void virtio_init(VirtIODevice *vdev, const char *name,
- uint16_t device_id, size_t config_size);
+/**
+ * virtio_init() - initialise the common VirtIODevice structure
+ * @vdev: pointer to VirtIODevice
+ * @device_id: the VirtIO device ID (see virtio_ids.h)
+ * @config_size: size of the config space
+ */
+void virtio_init(VirtIODevice *vdev, uint16_t device_id, size_t config_size);
+
void virtio_cleanup(VirtIODevice *vdev);
-void virtio_error(VirtIODevice *vdev, const char *fmt, ...) GCC_FMT_ATTR(2, 3);
+void virtio_error(VirtIODevice *vdev, const char *fmt, ...) G_GNUC_PRINTF(2, 3);
/* Set the child bus name. */
void virtio_device_set_child_bus_name(VirtIODevice *vdev, char *bus_name);
typedef void (*VirtIOHandleOutput)(VirtIODevice *, VirtQueue *);
-typedef bool (*VirtIOHandleAIOOutput)(VirtIODevice *, VirtQueue *);
VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
VirtIOHandleOutput handle_output);
@@ -226,6 +291,13 @@ extern const VMStateInfo virtio_vmstate_info;
int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id);
+/**
+ * virtio_notify_config() - signal a change to device config
+ * @vdev: the virtio device
+ *
+ * Assuming the virtio device is up (VIRTIO_CONFIG_S_DRIVER_OK) this
+ * will trigger a guest interrupt and update the config version.
+ */
void virtio_notify_config(VirtIODevice *vdev);
bool virtio_queue_get_notification(VirtQueue *vq);
@@ -261,6 +333,7 @@ int virtio_get_num_queues(VirtIODevice *vdev);
void virtio_queue_set_rings(VirtIODevice *vdev, int n, hwaddr desc,
hwaddr avail, hwaddr used);
void virtio_queue_update_rings(VirtIODevice *vdev, int n);
+void virtio_init_region_cache(VirtIODevice *vdev, int n);
void virtio_queue_set_align(VirtIODevice *vdev, int n, int align);
void virtio_queue_notify(VirtIODevice *vdev, int n);
uint16_t virtio_queue_vector(VirtIODevice *vdev, int n);
@@ -269,6 +342,8 @@ int virtio_queue_set_host_notifier_mr(VirtIODevice *vdev, int n,
MemoryRegion *mr, bool assign);
int virtio_set_status(VirtIODevice *vdev, uint8_t val);
void virtio_reset(void *opaque);
+void virtio_queue_reset(VirtIODevice *vdev, uint32_t queue_index);
+void virtio_queue_enable(VirtIODevice *vdev, uint32_t queue_index);
void virtio_update_irq(VirtIODevice *vdev);
int virtio_set_features(VirtIODevice *vdev, uint64_t val);
@@ -292,7 +367,9 @@ typedef struct VirtIORNGConf VirtIORNGConf;
DEFINE_PROP_BIT64("iommu_platform", _state, _field, \
VIRTIO_F_IOMMU_PLATFORM, false), \
DEFINE_PROP_BIT64("packed", _state, _field, \
- VIRTIO_F_RING_PACKED, false)
+ VIRTIO_F_RING_PACKED, false), \
+ DEFINE_PROP_BIT64("queue_reset", _state, _field, \
+ VIRTIO_F_RING_RESET, true)
hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, int n);
bool virtio_queue_enabled_legacy(VirtIODevice *vdev, int n);
@@ -320,10 +397,14 @@ bool virtio_device_ioeventfd_enabled(VirtIODevice *vdev);
EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq);
void virtio_queue_set_host_notifier_enabled(VirtQueue *vq, bool enabled);
void virtio_queue_host_notifier_read(EventNotifier *n);
-void virtio_queue_aio_set_host_notifier_handler(VirtQueue *vq, AioContext *ctx,
- VirtIOHandleAIOOutput handle_output);
+void virtio_queue_aio_attach_host_notifier(VirtQueue *vq, AioContext *ctx);
+void virtio_queue_aio_attach_host_notifier_no_poll(VirtQueue *vq, AioContext *ctx);
+void virtio_queue_aio_detach_host_notifier(VirtQueue *vq, AioContext *ctx);
VirtQueue *virtio_vector_first_queue(VirtIODevice *vdev, uint16_t vector);
VirtQueue *virtio_vector_next_queue(VirtQueue *vq);
+EventNotifier *virtio_config_get_guest_notifier(VirtIODevice *vdev);
+void virtio_config_set_guest_notifier_fd_handler(VirtIODevice *vdev,
+ bool assign, bool with_irqfd);
static inline void virtio_add_feature(uint64_t *features, unsigned int fbit)
{
@@ -343,7 +424,7 @@ static inline bool virtio_has_feature(uint64_t features, unsigned int fbit)
return !!(features & (1ULL << fbit));
}
-static inline bool virtio_vdev_has_feature(VirtIODevice *vdev,
+static inline bool virtio_vdev_has_feature(const VirtIODevice *vdev,
unsigned int fbit)
{
return virtio_has_feature(vdev->guest_features, fbit);
@@ -365,6 +446,16 @@ static inline bool virtio_is_big_endian(VirtIODevice *vdev)
return false;
}
+/**
+ * virtio_device_started() - check if device started
+ * @vdev - the VirtIO device
+ * @status - the devices status bits
+ *
+ * Check if the device is started. For most modern machines this is
+ * tracked via the @vdev->started field (to support migration),
+ * otherwise we check for the final negotiated status bit that
+ * indicates everything is ready.
+ */
static inline bool virtio_device_started(VirtIODevice *vdev, uint8_t status)
{
if (vdev->use_started) {
@@ -374,6 +465,24 @@ static inline bool virtio_device_started(VirtIODevice *vdev, uint8_t status)
return status & VIRTIO_CONFIG_S_DRIVER_OK;
}
+/**
+ * virtio_device_should_start() - check if device startable
+ * @vdev - the VirtIO device
+ * @status - the devices status bits
+ *
+ * This is similar to virtio_device_started() but also encapsulates a
+ * check on the VM status which would prevent a device starting
+ * anyway.
+ */
+static inline bool virtio_device_should_start(VirtIODevice *vdev, uint8_t status)
+{
+ if (!vdev->vm_running) {
+ return false;
+ }
+
+ return virtio_device_started(vdev, status);
+}
+
static inline void virtio_set_started(VirtIODevice *vdev, bool started)
{
if (started) {
@@ -398,5 +507,12 @@ static inline bool virtio_device_disabled(VirtIODevice *vdev)
}
bool virtio_legacy_allowed(VirtIODevice *vdev);
+bool virtio_legacy_check_disabled(VirtIODevice *vdev);
+
+QEMUBH *virtio_bh_new_guarded_full(DeviceState *dev,
+ QEMUBHFunc *cb, void *opaque,
+ const char *name);
+#define virtio_bh_new_guarded(dev, cb, opaque) \
+ virtio_bh_new_guarded_full((dev), (cb), (opaque), (stringify(cb)))
#endif
diff --git a/include/hw/vmstate-if.h b/include/hw/vmstate-if.h
index 8ff7f0f292..52df571d17 100644
--- a/include/hw/vmstate-if.h
+++ b/include/hw/vmstate-if.h
@@ -13,20 +13,19 @@
#define TYPE_VMSTATE_IF "vmstate-if"
-#define VMSTATE_IF_CLASS(klass) \
- OBJECT_CLASS_CHECK(VMStateIfClass, (klass), TYPE_VMSTATE_IF)
-#define VMSTATE_IF_GET_CLASS(obj) \
- OBJECT_GET_CLASS(VMStateIfClass, (obj), TYPE_VMSTATE_IF)
+typedef struct VMStateIfClass VMStateIfClass;
+DECLARE_CLASS_CHECKERS(VMStateIfClass, VMSTATE_IF,
+ TYPE_VMSTATE_IF)
#define VMSTATE_IF(obj) \
INTERFACE_CHECK(VMStateIf, (obj), TYPE_VMSTATE_IF)
typedef struct VMStateIf VMStateIf;
-typedef struct VMStateIfClass {
+struct VMStateIfClass {
InterfaceClass parent_class;
char * (*get_id)(VMStateIf *obj);
-} VMStateIfClass;
+};
static inline char *vmstate_if_get_id(VMStateIf *vmif)
{
diff --git a/include/hw/watchdog/allwinner-wdt.h b/include/hw/watchdog/allwinner-wdt.h
new file mode 100644
index 0000000000..7fe41e20f2
--- /dev/null
+++ b/include/hw/watchdog/allwinner-wdt.h
@@ -0,0 +1,123 @@
+/*
+ * Allwinner Watchdog emulation
+ *
+ * Copyright (C) 2023 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
+ *
+ * This file is derived from Allwinner RTC,
+ * by Niek Linnenbank.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_WATCHDOG_ALLWINNER_WDT_H
+#define HW_WATCHDOG_ALLWINNER_WDT_H
+
+#include "qom/object.h"
+#include "hw/ptimer.h"
+#include "hw/sysbus.h"
+
+/*
+ * This is a model of the Allwinner watchdog.
+ * Since watchdog registers belong to the timer module (and are shared with the
+ * RTC module), the interrupt line from watchdog is not handled right now.
+ * In QEMU, we just wire up the watchdog reset to watchdog_perform_action(),
+ * at least for the moment.
+ */
+
+#define TYPE_AW_WDT "allwinner-wdt"
+
+/** Allwinner WDT sun4i family (A10, A12), also sun7i (A20) */
+#define TYPE_AW_WDT_SUN4I TYPE_AW_WDT "-sun4i"
+
+/** Allwinner WDT sun6i family and newer (A31, H2+, H3, etc) */
+#define TYPE_AW_WDT_SUN6I TYPE_AW_WDT "-sun6i"
+
+/** Number of WDT registers */
+#define AW_WDT_REGS_NUM (5)
+
+OBJECT_DECLARE_TYPE(AwWdtState, AwWdtClass, AW_WDT)
+
+/**
+ * Allwinner WDT object instance state.
+ */
+struct AwWdtState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+ struct ptimer_state *timer;
+
+ uint32_t regs[AW_WDT_REGS_NUM];
+};
+
+/**
+ * Allwinner WDT class-level struct.
+ *
+ * This struct is filled by each sunxi device specific code
+ * such that the generic code can use this struct to support
+ * all devices.
+ */
+struct AwWdtClass {
+ /*< private >*/
+ SysBusDeviceClass parent_class;
+ /*< public >*/
+
+ /** Defines device specific register map */
+ const uint8_t *regmap;
+
+ /** Size of the regmap in bytes */
+ size_t regmap_size;
+
+ /**
+ * Read device specific register
+ *
+ * @offset: register offset to read
+ * @return true if register read successful, false otherwise
+ */
+ bool (*read)(AwWdtState *s, uint32_t offset);
+
+ /**
+ * Write device specific register
+ *
+ * @offset: register offset to write
+ * @data: value to set in register
+ * @return true if register write successful, false otherwise
+ */
+ bool (*write)(AwWdtState *s, uint32_t offset, uint32_t data);
+
+ /**
+ * Check if watchdog can generate system reset
+ *
+ * @return true if watchdog can generate system reset
+ */
+ bool (*can_reset_system)(AwWdtState *s);
+
+ /**
+ * Check if provided key is valid
+ *
+ * @value: value written to register
+ * @return true if key is valid, false otherwise
+ */
+ bool (*is_key_valid)(AwWdtState *s, uint32_t val);
+
+ /**
+ * Get current INTV_VALUE setting
+ *
+ * @return current INTV_VALUE (0-15)
+ */
+ uint8_t (*get_intv_value)(AwWdtState *s);
+};
+
+#endif /* HW_WATCHDOG_ALLWINNER_WDT_H */
diff --git a/include/hw/watchdog/cmsdk-apb-watchdog.h b/include/hw/watchdog/cmsdk-apb-watchdog.h
index 6ae9531370..c6b3e78731 100644
--- a/include/hw/watchdog/cmsdk-apb-watchdog.h
+++ b/include/hw/watchdog/cmsdk-apb-watchdog.h
@@ -16,7 +16,7 @@
* https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
*
* QEMU interface:
- * + QOM property "wdogclk-frq": frequency at which the watchdog is clocked
+ * + Clock input "WDOGCLK": clock for the watchdog's timer
* + sysbus MMIO region 0: the register bank
* + sysbus IRQ 0: watchdog interrupt
*
@@ -33,10 +33,11 @@
#include "hw/sysbus.h"
#include "hw/ptimer.h"
+#include "hw/clock.h"
+#include "qom/object.h"
#define TYPE_CMSDK_APB_WATCHDOG "cmsdk-apb-watchdog"
-#define CMSDK_APB_WATCHDOG(obj) OBJECT_CHECK(CMSDKAPBWatchdog, (obj), \
- TYPE_CMSDK_APB_WATCHDOG)
+OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBWatchdog, CMSDK_APB_WATCHDOG)
/*
* This shares the same struct (and cast macro) as the base
@@ -44,16 +45,16 @@
*/
#define TYPE_LUMINARY_WATCHDOG "luminary-watchdog"
-typedef struct CMSDKAPBWatchdog {
+struct CMSDKAPBWatchdog {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
MemoryRegion iomem;
qemu_irq wdogint;
- uint32_t wdogclk_frq;
bool is_luminary;
struct ptimer_state *timer;
+ Clock *wdogclk;
uint32_t control;
uint32_t intstatus;
@@ -62,6 +63,6 @@ typedef struct CMSDKAPBWatchdog {
uint32_t itop;
uint32_t resetstatus;
const uint32_t *id;
-} CMSDKAPBWatchdog;
+};
#endif
diff --git a/include/hw/watchdog/sbsa_gwdt.h b/include/hw/watchdog/sbsa_gwdt.h
new file mode 100644
index 0000000000..70b137de30
--- /dev/null
+++ b/include/hw/watchdog/sbsa_gwdt.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2020 Linaro Limited
+ *
+ * Authors:
+ * Shashi Mallela <shashi.mallela@linaro.org>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at your
+ * option) any later version. See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef WDT_SBSA_GWDT_H
+#define WDT_SBSA_GWDT_H
+
+#include "qemu/bitops.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+
+#define TYPE_WDT_SBSA "sbsa_gwdt"
+#define SBSA_GWDT(obj) \
+ OBJECT_CHECK(SBSA_GWDTState, (obj), TYPE_WDT_SBSA)
+#define SBSA_GWDT_CLASS(klass) \
+ OBJECT_CLASS_CHECK(SBSA_GWDTClass, (klass), TYPE_WDT_SBSA)
+#define SBSA_GWDT_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(SBSA_GWDTClass, (obj), TYPE_WDT_SBSA)
+
+/* SBSA Generic Watchdog register definitions */
+/* refresh frame */
+#define SBSA_GWDT_WRR 0x000
+
+/* control frame */
+#define SBSA_GWDT_WCS 0x000
+#define SBSA_GWDT_WOR 0x008
+#define SBSA_GWDT_WORU 0x00C
+#define SBSA_GWDT_WCV 0x010
+#define SBSA_GWDT_WCVU 0x014
+
+/* Watchdog Interface Identification Register */
+#define SBSA_GWDT_W_IIDR 0xFCC
+
+/* Watchdog Control and Status Register Bits */
+#define SBSA_GWDT_WCS_EN BIT(0)
+#define SBSA_GWDT_WCS_WS0 BIT(1)
+#define SBSA_GWDT_WCS_WS1 BIT(2)
+
+#define SBSA_GWDT_WOR_MASK 0x0000FFFF
+
+/*
+ * Watchdog Interface Identification Register definition
+ * considering JEP106 code for ARM in Bits [11:0]
+ */
+#define SBSA_GWDT_ID 0x1043B
+
+/* 2 Separate memory regions for each of refresh & control register frames */
+#define SBSA_GWDT_RMMIO_SIZE 0x1000
+#define SBSA_GWDT_CMMIO_SIZE 0x1000
+
+#define SBSA_TIMER_FREQ 62500000 /* Hz */
+
+typedef struct SBSA_GWDTState {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion rmmio;
+ MemoryRegion cmmio;
+ qemu_irq irq;
+
+ QEMUTimer *timer;
+
+ uint32_t id;
+ uint32_t wcs;
+ uint32_t worl;
+ uint32_t woru;
+ uint32_t wcvl;
+ uint32_t wcvu;
+} SBSA_GWDTState;
+
+#endif /* WDT_SBSA_GWDT_H */
diff --git a/include/hw/watchdog/wdt_aspeed.h b/include/hw/watchdog/wdt_aspeed.h
index 819c22993a..e90ef86651 100644
--- a/include/hw/watchdog/wdt_aspeed.h
+++ b/include/hw/watchdog/wdt_aspeed.h
@@ -12,17 +12,18 @@
#include "hw/misc/aspeed_scu.h"
#include "hw/sysbus.h"
+#include "qom/object.h"
#define TYPE_ASPEED_WDT "aspeed.wdt"
-#define ASPEED_WDT(obj) \
- OBJECT_CHECK(AspeedWDTState, (obj), TYPE_ASPEED_WDT)
+OBJECT_DECLARE_TYPE(AspeedWDTState, AspeedWDTClass, ASPEED_WDT)
#define TYPE_ASPEED_2400_WDT TYPE_ASPEED_WDT "-ast2400"
#define TYPE_ASPEED_2500_WDT TYPE_ASPEED_WDT "-ast2500"
#define TYPE_ASPEED_2600_WDT TYPE_ASPEED_WDT "-ast2600"
+#define TYPE_ASPEED_1030_WDT TYPE_ASPEED_WDT "-ast1030"
-#define ASPEED_WDT_REGS_MAX (0x20 / 4)
+#define ASPEED_WDT_REGS_MAX (0x30 / 4)
-typedef struct AspeedWDTState {
+struct AspeedWDTState {
/*< private >*/
SysBusDevice parent_obj;
QEMUTimer *timer;
@@ -33,21 +34,20 @@ typedef struct AspeedWDTState {
AspeedSCUState *scu;
uint32_t pclk_freq;
-} AspeedWDTState;
+};
-#define ASPEED_WDT_CLASS(klass) \
- OBJECT_CLASS_CHECK(AspeedWDTClass, (klass), TYPE_ASPEED_WDT)
-#define ASPEED_WDT_GET_CLASS(obj) \
- OBJECT_GET_CLASS(AspeedWDTClass, (obj), TYPE_ASPEED_WDT)
-typedef struct AspeedWDTClass {
+struct AspeedWDTClass {
SysBusDeviceClass parent_class;
- uint32_t offset;
+ uint32_t iosize;
uint32_t ext_pulse_width_mask;
uint32_t reset_ctrl_reg;
void (*reset_pulse)(AspeedWDTState *s, uint32_t property);
void (*wdt_reload)(AspeedWDTState *s);
-} AspeedWDTClass;
+ uint64_t (*sanitize_ctrl)(uint64_t data);
+ uint32_t default_status;
+ uint32_t default_reload_value;
+};
#endif /* WDT_ASPEED_H */
diff --git a/include/hw/watchdog/wdt_diag288.h b/include/hw/watchdog/wdt_diag288.h
index 19d83a0937..f72c1d3318 100644
--- a/include/hw/watchdog/wdt_diag288.h
+++ b/include/hw/watchdog/wdt_diag288.h
@@ -2,35 +2,34 @@
#define WDT_DIAG288_H
#include "hw/qdev-core.h"
+#include "qom/object.h"
#define TYPE_WDT_DIAG288 "diag288"
-#define DIAG288(obj) \
- OBJECT_CHECK(DIAG288State, (obj), TYPE_WDT_DIAG288)
-#define DIAG288_CLASS(klass) \
- OBJECT_CLASS_CHECK(DIAG288Class, (klass), TYPE_WDT_DIAG288)
-#define DIAG288_GET_CLASS(obj) \
- OBJECT_GET_CLASS(DIAG288Class, (obj), TYPE_WDT_DIAG288)
+typedef struct DIAG288Class DIAG288Class;
+typedef struct DIAG288State DIAG288State;
+DECLARE_OBJ_CHECKERS(DIAG288State, DIAG288Class,
+ DIAG288, TYPE_WDT_DIAG288)
#define WDT_DIAG288_INIT 0
#define WDT_DIAG288_CHANGE 1
#define WDT_DIAG288_CANCEL 2
-typedef struct DIAG288State {
+struct DIAG288State {
/*< private >*/
DeviceState parent_obj;
QEMUTimer *timer;
bool enabled;
/*< public >*/
-} DIAG288State;
+};
-typedef struct DIAG288Class {
+struct DIAG288Class {
/*< private >*/
DeviceClass parent_class;
/*< public >*/
int (*handle_timer)(DIAG288State *dev,
uint64_t func, uint64_t timeout);
-} DIAG288Class;
+};
#endif /* WDT_DIAG288_H */
diff --git a/include/hw/watchdog/wdt_imx2.h b/include/hw/watchdog/wdt_imx2.h
index f9af6be4b6..600a552d2e 100644
--- a/include/hw/watchdog/wdt_imx2.h
+++ b/include/hw/watchdog/wdt_imx2.h
@@ -9,16 +9,17 @@
* See the COPYING file in the top-level directory.
*/
-#ifndef IMX2_WDT_H
-#define IMX2_WDT_H
+#ifndef WDT_IMX2_H
+#define WDT_IMX2_H
#include "qemu/bitops.h"
#include "hw/sysbus.h"
#include "hw/irq.h"
#include "hw/ptimer.h"
+#include "qom/object.h"
#define TYPE_IMX2_WDT "imx2.wdt"
-#define IMX2_WDT(obj) OBJECT_CHECK(IMX2WdtState, (obj), TYPE_IMX2_WDT)
+OBJECT_DECLARE_SIMPLE_TYPE(IMX2WdtState, IMX2_WDT)
enum IMX2WdtRegisters {
IMX2_WDT_WCR = 0x0000, /* Control Register */
@@ -62,7 +63,7 @@ enum IMX2WdtRegisters {
/* Misc Control Register definitions */
#define IMX2_WDT_WMCR_PDE BIT(0) /* Power-Down Enable */
-typedef struct IMX2WdtState {
+struct IMX2WdtState {
/* <private> */
SysBusDevice parent_obj;
@@ -85,6 +86,6 @@ typedef struct IMX2WdtState {
bool wcr_locked; /* affects WDZST, WDBG, and WDW */
bool wcr_wde_locked; /* affects WDE */
bool wcr_wdt_locked; /* affects WDT (never cleared) */
-} IMX2WdtState;
+};
-#endif /* IMX2_WDT_H */
+#endif /* WDT_IMX2_H */
diff --git a/include/hw/xen/arch_hvm.h b/include/hw/xen/arch_hvm.h
new file mode 100644
index 0000000000..c7c515220d
--- /dev/null
+++ b/include/hw/xen/arch_hvm.h
@@ -0,0 +1,5 @@
+#if defined(TARGET_I386) || defined(TARGET_X86_64)
+#include "hw/i386/xen_arch_hvm.h"
+#elif defined(TARGET_ARM) || defined(TARGET_ARM_64)
+#include "hw/arm/xen_arch_hvm.h"
+#endif
diff --git a/include/hw/xen/interface/arch-arm.h b/include/hw/xen/interface/arch-arm.h
new file mode 100644
index 0000000000..1528ced509
--- /dev/null
+++ b/include/hw/xen/interface/arch-arm.h
@@ -0,0 +1,509 @@
+/* SPDX-License-Identifier: MIT */
+/******************************************************************************
+ * arch-arm.h
+ *
+ * Guest OS interface to ARM Xen.
+ *
+ * Copyright 2011 (C) Citrix Systems
+ */
+
+#ifndef __XEN_PUBLIC_ARCH_ARM_H__
+#define __XEN_PUBLIC_ARCH_ARM_H__
+
+/*
+ * `incontents 50 arm_abi Hypercall Calling Convention
+ *
+ * A hypercall is issued using the ARM HVC instruction.
+ *
+ * A hypercall can take up to 5 arguments. These are passed in
+ * registers, the first argument in x0/r0 (for arm64/arm32 guests
+ * respectively irrespective of whether the underlying hypervisor is
+ * 32- or 64-bit), the second argument in x1/r1, the third in x2/r2,
+ * the forth in x3/r3 and the fifth in x4/r4.
+ *
+ * The hypercall number is passed in r12 (arm) or x16 (arm64). In both
+ * cases the relevant ARM procedure calling convention specifies this
+ * is an inter-procedure-call scratch register (e.g. for use in linker
+ * stubs). This use does not conflict with use during a hypercall.
+ *
+ * The HVC ISS must contain a Xen specific TAG: XEN_HYPERCALL_TAG.
+ *
+ * The return value is in x0/r0.
+ *
+ * The hypercall will clobber x16/r12 and the argument registers used
+ * by that hypercall (except r0 which is the return value) i.e. in
+ * addition to x16/r12 a 2 argument hypercall will clobber x1/r1 and a
+ * 4 argument hypercall will clobber x1/r1, x2/r2 and x3/r3.
+ *
+ * Parameter structs passed to hypercalls are laid out according to
+ * the Procedure Call Standard for the ARM Architecture (AAPCS, AKA
+ * EABI) and Procedure Call Standard for the ARM 64-bit Architecture
+ * (AAPCS64). Where there is a conflict the 64-bit standard should be
+ * used regardless of guest type. Structures which are passed as
+ * hypercall arguments are always little endian.
+ *
+ * All memory which is shared with other entities in the system
+ * (including the hypervisor and other guests) must reside in memory
+ * which is mapped as Normal Inner Write-Back Outer Write-Back Inner-Shareable.
+ * This applies to:
+ * - hypercall arguments passed via a pointer to guest memory.
+ * - memory shared via the grant table mechanism (including PV I/O
+ * rings etc).
+ * - memory shared with the hypervisor (struct shared_info, struct
+ * vcpu_info, the grant table, etc).
+ *
+ * Any cache allocation hints are acceptable.
+ */
+
+/*
+ * `incontents 55 arm_hcall Supported Hypercalls
+ *
+ * Xen on ARM makes extensive use of hardware facilities and therefore
+ * only a subset of the potential hypercalls are required.
+ *
+ * Since ARM uses second stage paging any machine/physical addresses
+ * passed to hypercalls are Guest Physical Addresses (Intermediate
+ * Physical Addresses) unless otherwise noted.
+ *
+ * The following hypercalls (and sub operations) are supported on the
+ * ARM platform. Other hypercalls should be considered
+ * unavailable/unsupported.
+ *
+ * HYPERVISOR_memory_op
+ * All generic sub-operations
+ *
+ * HYPERVISOR_domctl
+ * All generic sub-operations, with the exception of:
+ * * XEN_DOMCTL_irq_permission (not yet implemented)
+ *
+ * HYPERVISOR_sched_op
+ * All generic sub-operations, with the exception of:
+ * * SCHEDOP_block -- prefer wfi hardware instruction
+ *
+ * HYPERVISOR_console_io
+ * All generic sub-operations
+ *
+ * HYPERVISOR_xen_version
+ * All generic sub-operations
+ *
+ * HYPERVISOR_event_channel_op
+ * All generic sub-operations
+ *
+ * HYPERVISOR_physdev_op
+ * Exactly these sub-operations are supported:
+ * PHYSDEVOP_pci_device_add
+ * PHYSDEVOP_pci_device_remove
+ *
+ * HYPERVISOR_sysctl
+ * All generic sub-operations, with the exception of:
+ * * XEN_SYSCTL_page_offline_op
+ * * XEN_SYSCTL_get_pmstat
+ * * XEN_SYSCTL_pm_op
+ *
+ * HYPERVISOR_hvm_op
+ * Exactly these sub-operations are supported:
+ * * HVMOP_set_param
+ * * HVMOP_get_param
+ *
+ * HYPERVISOR_grant_table_op
+ * All generic sub-operations
+ *
+ * HYPERVISOR_vcpu_op
+ * Exactly these sub-operations are supported:
+ * * VCPUOP_register_vcpu_info
+ * * VCPUOP_register_runstate_memory_area
+ *
+ * HYPERVISOR_argo_op
+ * All generic sub-operations
+ *
+ * Other notes on the ARM ABI:
+ *
+ * - struct start_info is not exported to ARM guests.
+ *
+ * - struct shared_info is mapped by ARM guests using the
+ * HYPERVISOR_memory_op sub-op XENMEM_add_to_physmap, passing
+ * XENMAPSPACE_shared_info as space parameter.
+ *
+ * - All the per-cpu struct vcpu_info are mapped by ARM guests using the
+ * HYPERVISOR_vcpu_op sub-op VCPUOP_register_vcpu_info, including cpu0
+ * struct vcpu_info.
+ *
+ * - The grant table is mapped using the HYPERVISOR_memory_op sub-op
+ * XENMEM_add_to_physmap, passing XENMAPSPACE_grant_table as space
+ * parameter. The memory range specified under the Xen compatible
+ * hypervisor node on device tree can be used as target gpfn for the
+ * mapping.
+ *
+ * - Xenstore is initialized by using the two hvm_params
+ * HVM_PARAM_STORE_PFN and HVM_PARAM_STORE_EVTCHN. They can be read
+ * with the HYPERVISOR_hvm_op sub-op HVMOP_get_param.
+ *
+ * - The paravirtualized console is initialized by using the two
+ * hvm_params HVM_PARAM_CONSOLE_PFN and HVM_PARAM_CONSOLE_EVTCHN. They
+ * can be read with the HYPERVISOR_hvm_op sub-op HVMOP_get_param.
+ *
+ * - Event channel notifications are delivered using the percpu GIC
+ * interrupt specified under the Xen compatible hypervisor node on
+ * device tree.
+ *
+ * - The device tree Xen compatible node is fully described under Linux
+ * at Documentation/devicetree/bindings/arm/xen.txt.
+ */
+
+#define XEN_HYPERCALL_TAG 0XEA1
+
+#define int64_aligned_t int64_t __attribute__((aligned(8)))
+#define uint64_aligned_t uint64_t __attribute__((aligned(8)))
+
+#ifndef __ASSEMBLY__
+#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
+ typedef union { type *p; unsigned long q; } \
+ __guest_handle_ ## name; \
+ typedef union { type *p; uint64_aligned_t q; } \
+ __guest_handle_64_ ## name
+
+/*
+ * XEN_GUEST_HANDLE represents a guest pointer, when passed as a field
+ * in a struct in memory. On ARM is always 8 bytes sizes and 8 bytes
+ * aligned.
+ * XEN_GUEST_HANDLE_PARAM represents a guest pointer, when passed as an
+ * hypercall argument. It is 4 bytes on aarch32 and 8 bytes on aarch64.
+ */
+#define __DEFINE_XEN_GUEST_HANDLE(name, type) \
+ ___DEFINE_XEN_GUEST_HANDLE(name, type); \
+ ___DEFINE_XEN_GUEST_HANDLE(const_##name, const type)
+#define DEFINE_XEN_GUEST_HANDLE(name) __DEFINE_XEN_GUEST_HANDLE(name, name)
+#define __XEN_GUEST_HANDLE(name) __guest_handle_64_ ## name
+#define XEN_GUEST_HANDLE(name) __XEN_GUEST_HANDLE(name)
+#define XEN_GUEST_HANDLE_PARAM(name) __guest_handle_ ## name
+#define set_xen_guest_handle_raw(hnd, val) \
+ do { \
+ __typeof__(&(hnd)) _sxghr_tmp = &(hnd); \
+ _sxghr_tmp->q = 0; \
+ _sxghr_tmp->p = val; \
+ } while ( 0 )
+#define set_xen_guest_handle(hnd, val) set_xen_guest_handle_raw(hnd, val)
+
+typedef uint64_t xen_pfn_t;
+#define PRI_xen_pfn PRIx64
+#define PRIu_xen_pfn PRIu64
+
+/*
+ * Maximum number of virtual CPUs in legacy multi-processor guests.
+ * Only one. All other VCPUS must use VCPUOP_register_vcpu_info.
+ */
+#define XEN_LEGACY_MAX_VCPUS 1
+
+typedef uint64_t xen_ulong_t;
+#define PRI_xen_ulong PRIx64
+
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+/* Anonymous union includes both 32- and 64-bit names (e.g., r0/x0). */
+# define __DECL_REG(n64, n32) union { \
+ uint64_t n64; \
+ uint32_t n32; \
+ }
+#else
+/* Non-gcc sources must always use the proper 64-bit name (e.g., x0). */
+#define __DECL_REG(n64, n32) uint64_t n64
+#endif
+
+struct vcpu_guest_core_regs
+{
+ /* Aarch64 Aarch32 */
+ __DECL_REG(x0, r0_usr);
+ __DECL_REG(x1, r1_usr);
+ __DECL_REG(x2, r2_usr);
+ __DECL_REG(x3, r3_usr);
+ __DECL_REG(x4, r4_usr);
+ __DECL_REG(x5, r5_usr);
+ __DECL_REG(x6, r6_usr);
+ __DECL_REG(x7, r7_usr);
+ __DECL_REG(x8, r8_usr);
+ __DECL_REG(x9, r9_usr);
+ __DECL_REG(x10, r10_usr);
+ __DECL_REG(x11, r11_usr);
+ __DECL_REG(x12, r12_usr);
+
+ __DECL_REG(x13, sp_usr);
+ __DECL_REG(x14, lr_usr);
+
+ __DECL_REG(x15, __unused_sp_hyp);
+
+ __DECL_REG(x16, lr_irq);
+ __DECL_REG(x17, sp_irq);
+
+ __DECL_REG(x18, lr_svc);
+ __DECL_REG(x19, sp_svc);
+
+ __DECL_REG(x20, lr_abt);
+ __DECL_REG(x21, sp_abt);
+
+ __DECL_REG(x22, lr_und);
+ __DECL_REG(x23, sp_und);
+
+ __DECL_REG(x24, r8_fiq);
+ __DECL_REG(x25, r9_fiq);
+ __DECL_REG(x26, r10_fiq);
+ __DECL_REG(x27, r11_fiq);
+ __DECL_REG(x28, r12_fiq);
+
+ __DECL_REG(x29, sp_fiq);
+ __DECL_REG(x30, lr_fiq);
+
+ /* Return address and mode */
+ __DECL_REG(pc64, pc32); /* ELR_EL2 */
+ uint64_t cpsr; /* SPSR_EL2 */
+
+ union {
+ uint64_t spsr_el1; /* AArch64 */
+ uint32_t spsr_svc; /* AArch32 */
+ };
+
+ /* AArch32 guests only */
+ uint32_t spsr_fiq, spsr_irq, spsr_und, spsr_abt;
+
+ /* AArch64 guests only */
+ uint64_t sp_el0;
+ uint64_t sp_el1, elr_el1;
+};
+typedef struct vcpu_guest_core_regs vcpu_guest_core_regs_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_guest_core_regs_t);
+
+#undef __DECL_REG
+
+struct vcpu_guest_context {
+#define _VGCF_online 0
+#define VGCF_online (1<<_VGCF_online)
+ uint32_t flags; /* VGCF_* */
+
+ struct vcpu_guest_core_regs user_regs; /* Core CPU registers */
+
+ uint64_t sctlr;
+ uint64_t ttbcr, ttbr0, ttbr1;
+};
+typedef struct vcpu_guest_context vcpu_guest_context_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
+
+/*
+ * struct xen_arch_domainconfig's ABI is covered by
+ * XEN_DOMCTL_INTERFACE_VERSION.
+ */
+#define XEN_DOMCTL_CONFIG_GIC_NATIVE 0
+#define XEN_DOMCTL_CONFIG_GIC_V2 1
+#define XEN_DOMCTL_CONFIG_GIC_V3 2
+
+#define XEN_DOMCTL_CONFIG_TEE_NONE 0
+#define XEN_DOMCTL_CONFIG_TEE_OPTEE 1
+
+struct xen_arch_domainconfig {
+ /* IN/OUT */
+ uint8_t gic_version;
+ /* IN */
+ uint16_t tee_type;
+ /* IN */
+ uint32_t nr_spis;
+ /*
+ * OUT
+ * Based on the property clock-frequency in the DT timer node.
+ * The property may be present when the bootloader/firmware doesn't
+ * set correctly CNTFRQ which hold the timer frequency.
+ *
+ * As it's not possible to trap this register, we have to replicate
+ * the value in the guest DT.
+ *
+ * = 0 => property not present
+ * > 0 => Value of the property
+ *
+ */
+ uint32_t clock_frequency;
+};
+#endif /* __XEN__ || __XEN_TOOLS__ */
+
+struct arch_vcpu_info {
+};
+typedef struct arch_vcpu_info arch_vcpu_info_t;
+
+struct arch_shared_info {
+};
+typedef struct arch_shared_info arch_shared_info_t;
+typedef uint64_t xen_callback_t;
+
+#endif
+
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+
+/* PSR bits (CPSR, SPSR) */
+
+#define PSR_THUMB (1<<5) /* Thumb Mode enable */
+#define PSR_FIQ_MASK (1<<6) /* Fast Interrupt mask */
+#define PSR_IRQ_MASK (1<<7) /* Interrupt mask */
+#define PSR_ABT_MASK (1<<8) /* Asynchronous Abort mask */
+#define PSR_BIG_ENDIAN (1<<9) /* arm32: Big Endian Mode */
+#define PSR_DBG_MASK (1<<9) /* arm64: Debug Exception mask */
+#define PSR_IT_MASK (0x0600fc00) /* Thumb If-Then Mask */
+#define PSR_JAZELLE (1<<24) /* Jazelle Mode */
+#define PSR_Z (1<<30) /* Zero condition flag */
+
+/* 32 bit modes */
+#define PSR_MODE_USR 0x10
+#define PSR_MODE_FIQ 0x11
+#define PSR_MODE_IRQ 0x12
+#define PSR_MODE_SVC 0x13
+#define PSR_MODE_MON 0x16
+#define PSR_MODE_ABT 0x17
+#define PSR_MODE_HYP 0x1a
+#define PSR_MODE_UND 0x1b
+#define PSR_MODE_SYS 0x1f
+
+/* 64 bit modes */
+#define PSR_MODE_BIT 0x10 /* Set iff AArch32 */
+#define PSR_MODE_EL3h 0x0d
+#define PSR_MODE_EL3t 0x0c
+#define PSR_MODE_EL2h 0x09
+#define PSR_MODE_EL2t 0x08
+#define PSR_MODE_EL1h 0x05
+#define PSR_MODE_EL1t 0x04
+#define PSR_MODE_EL0t 0x00
+
+/*
+ * We set PSR_Z to be able to boot Linux kernel versions with an invalid
+ * encoding of the first 8 NOP instructions. See commit a92882a4d270 in
+ * Linux.
+ *
+ * Note that PSR_Z is also set by U-Boot and QEMU -kernel when loading
+ * zImage kernels on aarch32.
+ */
+#define PSR_GUEST32_INIT (PSR_Z|PSR_ABT_MASK|PSR_FIQ_MASK|PSR_IRQ_MASK|PSR_MODE_SVC)
+#define PSR_GUEST64_INIT (PSR_ABT_MASK|PSR_FIQ_MASK|PSR_IRQ_MASK|PSR_MODE_EL1h)
+
+#define SCTLR_GUEST_INIT xen_mk_ullong(0x00c50078)
+
+/*
+ * Virtual machine platform (memory layout, interrupts)
+ *
+ * These are defined for consistency between the tools and the
+ * hypervisor. Guests must not rely on these hardcoded values but
+ * should instead use the FDT.
+ */
+
+/* Physical Address Space */
+
+/* Virtio MMIO mappings */
+#define GUEST_VIRTIO_MMIO_BASE xen_mk_ullong(0x02000000)
+#define GUEST_VIRTIO_MMIO_SIZE xen_mk_ullong(0x00100000)
+
+/*
+ * vGIC mappings: Only one set of mapping is used by the guest.
+ * Therefore they can overlap.
+ */
+
+/* vGIC v2 mappings */
+#define GUEST_GICD_BASE xen_mk_ullong(0x03001000)
+#define GUEST_GICD_SIZE xen_mk_ullong(0x00001000)
+#define GUEST_GICC_BASE xen_mk_ullong(0x03002000)
+#define GUEST_GICC_SIZE xen_mk_ullong(0x00002000)
+
+/* vGIC v3 mappings */
+#define GUEST_GICV3_GICD_BASE xen_mk_ullong(0x03001000)
+#define GUEST_GICV3_GICD_SIZE xen_mk_ullong(0x00010000)
+
+#define GUEST_GICV3_RDIST_REGIONS 1
+
+#define GUEST_GICV3_GICR0_BASE xen_mk_ullong(0x03020000) /* vCPU0..127 */
+#define GUEST_GICV3_GICR0_SIZE xen_mk_ullong(0x01000000)
+
+/*
+ * 256 MB is reserved for VPCI configuration space based on calculation
+ * 256 buses x 32 devices x 8 functions x 4 KB = 256 MB
+ */
+#define GUEST_VPCI_ECAM_BASE xen_mk_ullong(0x10000000)
+#define GUEST_VPCI_ECAM_SIZE xen_mk_ullong(0x10000000)
+
+/* ACPI tables physical address */
+#define GUEST_ACPI_BASE xen_mk_ullong(0x20000000)
+#define GUEST_ACPI_SIZE xen_mk_ullong(0x02000000)
+
+/* PL011 mappings */
+#define GUEST_PL011_BASE xen_mk_ullong(0x22000000)
+#define GUEST_PL011_SIZE xen_mk_ullong(0x00001000)
+
+/* Guest PCI-PCIe memory space where config space and BAR will be available.*/
+#define GUEST_VPCI_ADDR_TYPE_MEM xen_mk_ullong(0x02000000)
+#define GUEST_VPCI_MEM_ADDR xen_mk_ullong(0x23000000)
+#define GUEST_VPCI_MEM_SIZE xen_mk_ullong(0x10000000)
+
+/*
+ * 16MB == 4096 pages reserved for guest to use as a region to map its
+ * grant table in.
+ */
+#define GUEST_GNTTAB_BASE xen_mk_ullong(0x38000000)
+#define GUEST_GNTTAB_SIZE xen_mk_ullong(0x01000000)
+
+#define GUEST_MAGIC_BASE xen_mk_ullong(0x39000000)
+#define GUEST_MAGIC_SIZE xen_mk_ullong(0x01000000)
+
+#define GUEST_RAM_BANKS 2
+
+/*
+ * The way to find the extended regions (to be exposed to the guest as unused
+ * address space) relies on the fact that the regions reserved for the RAM
+ * below are big enough to also accommodate such regions.
+ */
+#define GUEST_RAM0_BASE xen_mk_ullong(0x40000000) /* 3GB of low RAM @ 1GB */
+#define GUEST_RAM0_SIZE xen_mk_ullong(0xc0000000)
+
+/* 4GB @ 4GB Prefetch Memory for VPCI */
+#define GUEST_VPCI_ADDR_TYPE_PREFETCH_MEM xen_mk_ullong(0x42000000)
+#define GUEST_VPCI_PREFETCH_MEM_ADDR xen_mk_ullong(0x100000000)
+#define GUEST_VPCI_PREFETCH_MEM_SIZE xen_mk_ullong(0x100000000)
+
+#define GUEST_RAM1_BASE xen_mk_ullong(0x0200000000) /* 1016GB of RAM @ 8GB */
+#define GUEST_RAM1_SIZE xen_mk_ullong(0xfe00000000)
+
+#define GUEST_RAM_BASE GUEST_RAM0_BASE /* Lowest RAM address */
+/* Largest amount of actual RAM, not including holes */
+#define GUEST_RAM_MAX (GUEST_RAM0_SIZE + GUEST_RAM1_SIZE)
+/* Suitable for e.g. const uint64_t ramfoo[] = GUEST_RAM_BANK_FOOS; */
+#define GUEST_RAM_BANK_BASES { GUEST_RAM0_BASE, GUEST_RAM1_BASE }
+#define GUEST_RAM_BANK_SIZES { GUEST_RAM0_SIZE, GUEST_RAM1_SIZE }
+
+/* Current supported guest VCPUs */
+#define GUEST_MAX_VCPUS 128
+
+/* Interrupts */
+#define GUEST_TIMER_VIRT_PPI 27
+#define GUEST_TIMER_PHYS_S_PPI 29
+#define GUEST_TIMER_PHYS_NS_PPI 30
+#define GUEST_EVTCHN_PPI 31
+
+#define GUEST_VPL011_SPI 32
+
+#define GUEST_VIRTIO_MMIO_SPI_FIRST 33
+#define GUEST_VIRTIO_MMIO_SPI_LAST 43
+
+/* PSCI functions */
+#define PSCI_cpu_suspend 0
+#define PSCI_cpu_off 1
+#define PSCI_cpu_on 2
+#define PSCI_migrate 3
+
+#endif
+
+#ifndef __ASSEMBLY__
+/* Stub definition of PMU structure */
+typedef struct xen_pmu_arch { uint8_t dummy; } xen_pmu_arch_t;
+#endif
+
+#endif /* __XEN_PUBLIC_ARCH_ARM_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/hw/xen/interface/arch-x86/cpuid.h b/include/hw/xen/interface/arch-x86/cpuid.h
new file mode 100644
index 0000000000..7ecd16ae05
--- /dev/null
+++ b/include/hw/xen/interface/arch-x86/cpuid.h
@@ -0,0 +1,113 @@
+/* SPDX-License-Identifier: MIT */
+/******************************************************************************
+ * arch-x86/cpuid.h
+ *
+ * CPUID interface to Xen.
+ *
+ * Copyright (c) 2007 Citrix Systems, Inc.
+ *
+ * Authors:
+ * Keir Fraser <keir@xen.org>
+ */
+
+#ifndef __XEN_PUBLIC_ARCH_X86_CPUID_H__
+#define __XEN_PUBLIC_ARCH_X86_CPUID_H__
+
+/*
+ * For compatibility with other hypervisor interfaces, the Xen cpuid leaves
+ * can be found at the first otherwise unused 0x100 aligned boundary starting
+ * from 0x40000000.
+ *
+ * e.g If viridian extensions are enabled for an HVM domain, the Xen cpuid
+ * leaves will start at 0x40000100
+ */
+
+#define XEN_CPUID_FIRST_LEAF 0x40000000
+#define XEN_CPUID_LEAF(i) (XEN_CPUID_FIRST_LEAF + (i))
+
+/*
+ * Leaf 1 (0x40000x00)
+ * EAX: Largest Xen-information leaf. All leaves up to an including @EAX
+ * are supported by the Xen host.
+ * EBX-EDX: "XenVMMXenVMM" signature, allowing positive identification
+ * of a Xen host.
+ */
+#define XEN_CPUID_SIGNATURE_EBX 0x566e6558 /* "XenV" */
+#define XEN_CPUID_SIGNATURE_ECX 0x65584d4d /* "MMXe" */
+#define XEN_CPUID_SIGNATURE_EDX 0x4d4d566e /* "nVMM" */
+
+/*
+ * Leaf 2 (0x40000x01)
+ * EAX[31:16]: Xen major version.
+ * EAX[15: 0]: Xen minor version.
+ * EBX-EDX: Reserved (currently all zeroes).
+ */
+
+/*
+ * Leaf 3 (0x40000x02)
+ * EAX: Number of hypercall transfer pages. This register is always guaranteed
+ * to specify one hypercall page.
+ * EBX: Base address of Xen-specific MSRs.
+ * ECX: Features 1. Unused bits are set to zero.
+ * EDX: Features 2. Unused bits are set to zero.
+ */
+
+/* Does the host support MMU_PT_UPDATE_PRESERVE_AD for this guest? */
+#define _XEN_CPUID_FEAT1_MMU_PT_UPDATE_PRESERVE_AD 0
+#define XEN_CPUID_FEAT1_MMU_PT_UPDATE_PRESERVE_AD (1u<<0)
+
+/*
+ * Leaf 4 (0x40000x03)
+ * Sub-leaf 0: EAX: bit 0: emulated tsc
+ * bit 1: host tsc is known to be reliable
+ * bit 2: RDTSCP instruction available
+ * EBX: tsc_mode: 0=default (emulate if necessary), 1=emulate,
+ * 2=no emulation, 3=no emulation + TSC_AUX support
+ * ECX: guest tsc frequency in kHz
+ * EDX: guest tsc incarnation (migration count)
+ * Sub-leaf 1: EAX: tsc offset low part
+ * EBX: tsc offset high part
+ * ECX: multiplicator for tsc->ns conversion
+ * EDX: shift amount for tsc->ns conversion
+ * Sub-leaf 2: EAX: host tsc frequency in kHz
+ */
+
+/*
+ * Leaf 5 (0x40000x04)
+ * HVM-specific features
+ * Sub-leaf 0: EAX: Features
+ * Sub-leaf 0: EBX: vcpu id (iff EAX has XEN_HVM_CPUID_VCPU_ID_PRESENT flag)
+ * Sub-leaf 0: ECX: domain id (iff EAX has XEN_HVM_CPUID_DOMID_PRESENT flag)
+ */
+#define XEN_HVM_CPUID_APIC_ACCESS_VIRT (1u << 0) /* Virtualized APIC registers */
+#define XEN_HVM_CPUID_X2APIC_VIRT (1u << 1) /* Virtualized x2APIC accesses */
+/* Memory mapped from other domains has valid IOMMU entries */
+#define XEN_HVM_CPUID_IOMMU_MAPPINGS (1u << 2)
+#define XEN_HVM_CPUID_VCPU_ID_PRESENT (1u << 3) /* vcpu id is present in EBX */
+#define XEN_HVM_CPUID_DOMID_PRESENT (1u << 4) /* domid is present in ECX */
+/*
+ * With interrupt format set to 0 (non-remappable) bits 55:49 from the
+ * IO-APIC RTE and bits 11:5 from the MSI address can be used to store
+ * high bits for the Destination ID. This expands the Destination ID
+ * field from 8 to 15 bits, allowing to target APIC IDs up 32768.
+ */
+#define XEN_HVM_CPUID_EXT_DEST_ID (1u << 5)
+/*
+ * Per-vCPU event channel upcalls work correctly with physical IRQs
+ * bound to event channels.
+ */
+#define XEN_HVM_CPUID_UPCALL_VECTOR (1u << 6)
+
+/*
+ * Leaf 6 (0x40000x05)
+ * PV-specific parameters
+ * Sub-leaf 0: EAX: max available sub-leaf
+ * Sub-leaf 0: EBX: bits 0-7: max machine address width
+ */
+
+/* Max. address width in bits taking memory hotplug into account. */
+#define XEN_CPUID_MACHINE_ADDRESS_WIDTH_MASK (0xffu << 0)
+
+#define XEN_CPUID_MAX_NUM_LEAVES 5
+
+#endif /* __XEN_PUBLIC_ARCH_X86_CPUID_H__ */
diff --git a/include/hw/xen/interface/arch-x86/xen-x86_32.h b/include/hw/xen/interface/arch-x86/xen-x86_32.h
new file mode 100644
index 0000000000..139438e835
--- /dev/null
+++ b/include/hw/xen/interface/arch-x86/xen-x86_32.h
@@ -0,0 +1,177 @@
+/* SPDX-License-Identifier: MIT */
+/******************************************************************************
+ * xen-x86_32.h
+ *
+ * Guest OS interface to x86 32-bit Xen.
+ *
+ * Copyright (c) 2004-2007, K A Fraser
+ */
+
+#ifndef __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__
+#define __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__
+
+/*
+ * Hypercall interface:
+ * Input: %ebx, %ecx, %edx, %esi, %edi, %ebp (arguments 1-6)
+ * Output: %eax
+ * Access is via hypercall page (set up by guest loader or via a Xen MSR):
+ * call hypercall_page + hypercall-number * 32
+ * Clobbered: Argument registers (e.g., 2-arg hypercall clobbers %ebx,%ecx)
+ */
+
+/*
+ * These flat segments are in the Xen-private section of every GDT. Since these
+ * are also present in the initial GDT, many OSes will be able to avoid
+ * installing their own GDT.
+ */
+#define FLAT_RING1_CS 0xe019 /* GDT index 259 */
+#define FLAT_RING1_DS 0xe021 /* GDT index 260 */
+#define FLAT_RING1_SS 0xe021 /* GDT index 260 */
+#define FLAT_RING3_CS 0xe02b /* GDT index 261 */
+#define FLAT_RING3_DS 0xe033 /* GDT index 262 */
+#define FLAT_RING3_SS 0xe033 /* GDT index 262 */
+
+#define FLAT_KERNEL_CS FLAT_RING1_CS
+#define FLAT_KERNEL_DS FLAT_RING1_DS
+#define FLAT_KERNEL_SS FLAT_RING1_SS
+#define FLAT_USER_CS FLAT_RING3_CS
+#define FLAT_USER_DS FLAT_RING3_DS
+#define FLAT_USER_SS FLAT_RING3_SS
+
+#define __HYPERVISOR_VIRT_START_PAE 0xF5800000
+#define __MACH2PHYS_VIRT_START_PAE 0xF5800000
+#define __MACH2PHYS_VIRT_END_PAE 0xF6800000
+#define HYPERVISOR_VIRT_START_PAE xen_mk_ulong(__HYPERVISOR_VIRT_START_PAE)
+#define MACH2PHYS_VIRT_START_PAE xen_mk_ulong(__MACH2PHYS_VIRT_START_PAE)
+#define MACH2PHYS_VIRT_END_PAE xen_mk_ulong(__MACH2PHYS_VIRT_END_PAE)
+
+/* Non-PAE bounds are obsolete. */
+#define __HYPERVISOR_VIRT_START_NONPAE 0xFC000000
+#define __MACH2PHYS_VIRT_START_NONPAE 0xFC000000
+#define __MACH2PHYS_VIRT_END_NONPAE 0xFC400000
+#define HYPERVISOR_VIRT_START_NONPAE \
+ xen_mk_ulong(__HYPERVISOR_VIRT_START_NONPAE)
+#define MACH2PHYS_VIRT_START_NONPAE \
+ xen_mk_ulong(__MACH2PHYS_VIRT_START_NONPAE)
+#define MACH2PHYS_VIRT_END_NONPAE \
+ xen_mk_ulong(__MACH2PHYS_VIRT_END_NONPAE)
+
+#define __HYPERVISOR_VIRT_START __HYPERVISOR_VIRT_START_PAE
+#define __MACH2PHYS_VIRT_START __MACH2PHYS_VIRT_START_PAE
+#define __MACH2PHYS_VIRT_END __MACH2PHYS_VIRT_END_PAE
+
+#ifndef HYPERVISOR_VIRT_START
+#define HYPERVISOR_VIRT_START xen_mk_ulong(__HYPERVISOR_VIRT_START)
+#endif
+
+#define MACH2PHYS_VIRT_START xen_mk_ulong(__MACH2PHYS_VIRT_START)
+#define MACH2PHYS_VIRT_END xen_mk_ulong(__MACH2PHYS_VIRT_END)
+#define MACH2PHYS_NR_ENTRIES ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>2)
+#ifndef machine_to_phys_mapping
+#define machine_to_phys_mapping ((unsigned long *)MACH2PHYS_VIRT_START)
+#endif
+
+/* 32-/64-bit invariability for control interfaces (domctl/sysctl). */
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+#undef ___DEFINE_XEN_GUEST_HANDLE
+#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
+ typedef struct { type *p; } \
+ __guest_handle_ ## name; \
+ typedef struct { union { type *p; uint64_aligned_t q; }; } \
+ __guest_handle_64_ ## name
+#undef set_xen_guest_handle_raw
+#define set_xen_guest_handle_raw(hnd, val) \
+ do { if ( sizeof(hnd) == 8 ) *(uint64_t *)&(hnd) = 0; \
+ (hnd).p = val; \
+ } while ( 0 )
+#define int64_aligned_t int64_t __attribute__((aligned(8)))
+#define uint64_aligned_t uint64_t __attribute__((aligned(8)))
+#define __XEN_GUEST_HANDLE_64(name) __guest_handle_64_ ## name
+#define XEN_GUEST_HANDLE_64(name) __XEN_GUEST_HANDLE_64(name)
+#endif
+
+#ifndef __ASSEMBLY__
+
+#if defined(XEN_GENERATING_COMPAT_HEADERS)
+/* nothing */
+#elif defined(__XEN__) || defined(__XEN_TOOLS__)
+/* Anonymous unions include all permissible names (e.g., al/ah/ax/eax). */
+#define __DECL_REG_LO8(which) union { \
+ uint32_t e ## which ## x; \
+ uint16_t which ## x; \
+ struct { \
+ uint8_t which ## l; \
+ uint8_t which ## h; \
+ }; \
+}
+#define __DECL_REG_LO16(name) union { \
+ uint32_t e ## name, _e ## name; \
+ uint16_t name; \
+}
+#else
+/* Other sources must always use the proper 32-bit name (e.g., eax). */
+#define __DECL_REG_LO8(which) uint32_t e ## which ## x
+#define __DECL_REG_LO16(name) uint32_t e ## name
+#endif
+
+struct cpu_user_regs {
+ __DECL_REG_LO8(b);
+ __DECL_REG_LO8(c);
+ __DECL_REG_LO8(d);
+ __DECL_REG_LO16(si);
+ __DECL_REG_LO16(di);
+ __DECL_REG_LO16(bp);
+ __DECL_REG_LO8(a);
+ uint16_t error_code; /* private */
+ uint16_t entry_vector; /* private */
+ __DECL_REG_LO16(ip);
+ uint16_t cs;
+ uint8_t saved_upcall_mask;
+ uint8_t _pad0;
+ __DECL_REG_LO16(flags); /* eflags.IF == !saved_upcall_mask */
+ __DECL_REG_LO16(sp);
+ uint16_t ss, _pad1;
+ uint16_t es, _pad2;
+ uint16_t ds, _pad3;
+ uint16_t fs, _pad4;
+ uint16_t gs, _pad5;
+};
+typedef struct cpu_user_regs cpu_user_regs_t;
+DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t);
+
+#undef __DECL_REG_LO8
+#undef __DECL_REG_LO16
+
+/*
+ * Page-directory addresses above 4GB do not fit into architectural %cr3.
+ * When accessing %cr3, or equivalent field in vcpu_guest_context, guests
+ * must use the following accessor macros to pack/unpack valid MFNs.
+ */
+#define xen_pfn_to_cr3(pfn) (((unsigned)(pfn) << 12) | ((unsigned)(pfn) >> 20))
+#define xen_cr3_to_pfn(cr3) (((unsigned)(cr3) >> 12) | ((unsigned)(cr3) << 20))
+
+struct arch_vcpu_info {
+ unsigned long cr2;
+ unsigned long pad[5]; /* sizeof(vcpu_info_t) == 64 */
+};
+typedef struct arch_vcpu_info arch_vcpu_info_t;
+
+struct xen_callback {
+ unsigned long cs;
+ unsigned long eip;
+};
+typedef struct xen_callback xen_callback_t;
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/hw/xen/interface/arch-x86/xen-x86_64.h b/include/hw/xen/interface/arch-x86/xen-x86_64.h
new file mode 100644
index 0000000000..5d9035ed22
--- /dev/null
+++ b/include/hw/xen/interface/arch-x86/xen-x86_64.h
@@ -0,0 +1,224 @@
+/* SPDX-License-Identifier: MIT */
+/******************************************************************************
+ * xen-x86_64.h
+ *
+ * Guest OS interface to x86 64-bit Xen.
+ *
+ * Copyright (c) 2004-2006, K A Fraser
+ */
+
+#ifndef __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__
+#define __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__
+
+/*
+ * Hypercall interface:
+ * Input: %rdi, %rsi, %rdx, %r10, %r8, %r9 (arguments 1-6)
+ * Output: %rax
+ * Access is via hypercall page (set up by guest loader or via a Xen MSR):
+ * call hypercall_page + hypercall-number * 32
+ * Clobbered: argument registers (e.g., 2-arg hypercall clobbers %rdi,%rsi)
+ */
+
+/*
+ * 64-bit segment selectors
+ * These flat segments are in the Xen-private section of every GDT. Since these
+ * are also present in the initial GDT, many OSes will be able to avoid
+ * installing their own GDT.
+ */
+
+#define FLAT_RING3_CS32 0xe023 /* GDT index 260 */
+#define FLAT_RING3_CS64 0xe033 /* GDT index 262 */
+#define FLAT_RING3_DS32 0xe02b /* GDT index 261 */
+#define FLAT_RING3_DS64 0x0000 /* NULL selector */
+#define FLAT_RING3_SS32 0xe02b /* GDT index 261 */
+#define FLAT_RING3_SS64 0xe02b /* GDT index 261 */
+
+#define FLAT_KERNEL_DS64 FLAT_RING3_DS64
+#define FLAT_KERNEL_DS32 FLAT_RING3_DS32
+#define FLAT_KERNEL_DS FLAT_KERNEL_DS64
+#define FLAT_KERNEL_CS64 FLAT_RING3_CS64
+#define FLAT_KERNEL_CS32 FLAT_RING3_CS32
+#define FLAT_KERNEL_CS FLAT_KERNEL_CS64
+#define FLAT_KERNEL_SS64 FLAT_RING3_SS64
+#define FLAT_KERNEL_SS32 FLAT_RING3_SS32
+#define FLAT_KERNEL_SS FLAT_KERNEL_SS64
+
+#define FLAT_USER_DS64 FLAT_RING3_DS64
+#define FLAT_USER_DS32 FLAT_RING3_DS32
+#define FLAT_USER_DS FLAT_USER_DS64
+#define FLAT_USER_CS64 FLAT_RING3_CS64
+#define FLAT_USER_CS32 FLAT_RING3_CS32
+#define FLAT_USER_CS FLAT_USER_CS64
+#define FLAT_USER_SS64 FLAT_RING3_SS64
+#define FLAT_USER_SS32 FLAT_RING3_SS32
+#define FLAT_USER_SS FLAT_USER_SS64
+
+#define __HYPERVISOR_VIRT_START 0xFFFF800000000000
+#define __HYPERVISOR_VIRT_END 0xFFFF880000000000
+#define __MACH2PHYS_VIRT_START 0xFFFF800000000000
+#define __MACH2PHYS_VIRT_END 0xFFFF804000000000
+
+#ifndef HYPERVISOR_VIRT_START
+#define HYPERVISOR_VIRT_START xen_mk_ulong(__HYPERVISOR_VIRT_START)
+#define HYPERVISOR_VIRT_END xen_mk_ulong(__HYPERVISOR_VIRT_END)
+#endif
+
+#define MACH2PHYS_VIRT_START xen_mk_ulong(__MACH2PHYS_VIRT_START)
+#define MACH2PHYS_VIRT_END xen_mk_ulong(__MACH2PHYS_VIRT_END)
+#define MACH2PHYS_NR_ENTRIES ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>3)
+#ifndef machine_to_phys_mapping
+#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
+#endif
+
+/*
+ * int HYPERVISOR_set_segment_base(unsigned int which, unsigned long base)
+ * @which == SEGBASE_* ; @base == 64-bit base address
+ * Returns 0 on success.
+ */
+#define SEGBASE_FS 0
+#define SEGBASE_GS_USER 1
+#define SEGBASE_GS_KERNEL 2
+#define SEGBASE_GS_USER_SEL 3 /* Set user %gs specified in base[15:0] */
+
+/*
+ * int HYPERVISOR_iret(void)
+ * All arguments are on the kernel stack, in the following format.
+ * Never returns if successful. Current kernel context is lost.
+ * The saved CS is mapped as follows:
+ * RING0 -> RING3 kernel mode.
+ * RING1 -> RING3 kernel mode.
+ * RING2 -> RING3 kernel mode.
+ * RING3 -> RING3 user mode.
+ * However RING0 indicates that the guest kernel should return to iteself
+ * directly with
+ * orb $3,1*8(%rsp)
+ * iretq
+ * If flags contains VGCF_in_syscall:
+ * Restore RAX, RIP, RFLAGS, RSP.
+ * Discard R11, RCX, CS, SS.
+ * Otherwise:
+ * Restore RAX, R11, RCX, CS:RIP, RFLAGS, SS:RSP.
+ * All other registers are saved on hypercall entry and restored to user.
+ */
+/* Guest exited in SYSCALL context? Return to guest with SYSRET? */
+#define _VGCF_in_syscall 8
+#define VGCF_in_syscall (1<<_VGCF_in_syscall)
+#define VGCF_IN_SYSCALL VGCF_in_syscall
+
+#ifndef __ASSEMBLY__
+
+struct iret_context {
+ /* Top of stack (%rsp at point of hypercall). */
+ uint64_t rax, r11, rcx, flags, rip, cs, rflags, rsp, ss;
+ /* Bottom of iret stack frame. */
+};
+
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+/* Anonymous unions include all permissible names (e.g., al/ah/ax/eax/rax). */
+#define __DECL_REG_LOHI(which) union { \
+ uint64_t r ## which ## x; \
+ uint32_t e ## which ## x; \
+ uint16_t which ## x; \
+ struct { \
+ uint8_t which ## l; \
+ uint8_t which ## h; \
+ }; \
+}
+#define __DECL_REG_LO8(name) union { \
+ uint64_t r ## name; \
+ uint32_t e ## name; \
+ uint16_t name; \
+ uint8_t name ## l; \
+}
+#define __DECL_REG_LO16(name) union { \
+ uint64_t r ## name; \
+ uint32_t e ## name; \
+ uint16_t name; \
+}
+#define __DECL_REG_HI(num) union { \
+ uint64_t r ## num; \
+ uint32_t r ## num ## d; \
+ uint16_t r ## num ## w; \
+ uint8_t r ## num ## b; \
+}
+#elif defined(__GNUC__) && !defined(__STRICT_ANSI__)
+/* Anonymous union includes both 32- and 64-bit names (e.g., eax/rax). */
+#define __DECL_REG(name) union { \
+ uint64_t r ## name, e ## name; \
+ uint32_t _e ## name; \
+}
+#else
+/* Non-gcc sources must always use the proper 64-bit name (e.g., rax). */
+#define __DECL_REG(name) uint64_t r ## name
+#endif
+
+#ifndef __DECL_REG_LOHI
+#define __DECL_REG_LOHI(name) __DECL_REG(name ## x)
+#define __DECL_REG_LO8 __DECL_REG
+#define __DECL_REG_LO16 __DECL_REG
+#define __DECL_REG_HI(num) uint64_t r ## num
+#endif
+
+struct cpu_user_regs {
+ __DECL_REG_HI(15);
+ __DECL_REG_HI(14);
+ __DECL_REG_HI(13);
+ __DECL_REG_HI(12);
+ __DECL_REG_LO8(bp);
+ __DECL_REG_LOHI(b);
+ __DECL_REG_HI(11);
+ __DECL_REG_HI(10);
+ __DECL_REG_HI(9);
+ __DECL_REG_HI(8);
+ __DECL_REG_LOHI(a);
+ __DECL_REG_LOHI(c);
+ __DECL_REG_LOHI(d);
+ __DECL_REG_LO8(si);
+ __DECL_REG_LO8(di);
+ uint32_t error_code; /* private */
+ uint32_t entry_vector; /* private */
+ __DECL_REG_LO16(ip);
+ uint16_t cs, _pad0[1];
+ uint8_t saved_upcall_mask;
+ uint8_t _pad1[3];
+ __DECL_REG_LO16(flags); /* rflags.IF == !saved_upcall_mask */
+ __DECL_REG_LO8(sp);
+ uint16_t ss, _pad2[3];
+ uint16_t es, _pad3[3];
+ uint16_t ds, _pad4[3];
+ uint16_t fs, _pad5[3];
+ uint16_t gs, _pad6[3];
+};
+typedef struct cpu_user_regs cpu_user_regs_t;
+DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t);
+
+#undef __DECL_REG
+#undef __DECL_REG_LOHI
+#undef __DECL_REG_LO8
+#undef __DECL_REG_LO16
+#undef __DECL_REG_HI
+
+#define xen_pfn_to_cr3(pfn) ((unsigned long)(pfn) << 12)
+#define xen_cr3_to_pfn(cr3) ((unsigned long)(cr3) >> 12)
+
+struct arch_vcpu_info {
+ unsigned long cr2;
+ unsigned long pad; /* sizeof(vcpu_info_t) == 64 */
+};
+typedef struct arch_vcpu_info arch_vcpu_info_t;
+
+typedef unsigned long xen_callback_t;
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/hw/xen/interface/arch-x86/xen.h b/include/hw/xen/interface/arch-x86/xen.h
new file mode 100644
index 0000000000..c0f4551247
--- /dev/null
+++ b/include/hw/xen/interface/arch-x86/xen.h
@@ -0,0 +1,378 @@
+/* SPDX-License-Identifier: MIT */
+/******************************************************************************
+ * arch-x86/xen.h
+ *
+ * Guest OS interface to x86 Xen.
+ *
+ * Copyright (c) 2004-2006, K A Fraser
+ */
+
+#include "../xen.h"
+
+#ifndef __XEN_PUBLIC_ARCH_X86_XEN_H__
+#define __XEN_PUBLIC_ARCH_X86_XEN_H__
+
+/* Structural guest handles introduced in 0x00030201. */
+#if __XEN_INTERFACE_VERSION__ >= 0x00030201
+#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
+ typedef struct { type *p; } __guest_handle_ ## name
+#else
+#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
+ typedef type * __guest_handle_ ## name
+#endif
+
+/*
+ * XEN_GUEST_HANDLE represents a guest pointer, when passed as a field
+ * in a struct in memory.
+ * XEN_GUEST_HANDLE_PARAM represent a guest pointer, when passed as an
+ * hypercall argument.
+ * XEN_GUEST_HANDLE_PARAM and XEN_GUEST_HANDLE are the same on X86 but
+ * they might not be on other architectures.
+ */
+#define __DEFINE_XEN_GUEST_HANDLE(name, type) \
+ ___DEFINE_XEN_GUEST_HANDLE(name, type); \
+ ___DEFINE_XEN_GUEST_HANDLE(const_##name, const type)
+#define DEFINE_XEN_GUEST_HANDLE(name) __DEFINE_XEN_GUEST_HANDLE(name, name)
+#define __XEN_GUEST_HANDLE(name) __guest_handle_ ## name
+#define XEN_GUEST_HANDLE(name) __XEN_GUEST_HANDLE(name)
+#define XEN_GUEST_HANDLE_PARAM(name) XEN_GUEST_HANDLE(name)
+#define set_xen_guest_handle_raw(hnd, val) do { (hnd).p = val; } while (0)
+#define set_xen_guest_handle(hnd, val) set_xen_guest_handle_raw(hnd, val)
+
+#if defined(__i386__)
+# ifdef __XEN__
+__DeFiNe__ __DECL_REG_LO8(which) uint32_t e ## which ## x
+__DeFiNe__ __DECL_REG_LO16(name) union { uint32_t e ## name; }
+# endif
+#include "xen-x86_32.h"
+# ifdef __XEN__
+__UnDeF__ __DECL_REG_LO8
+__UnDeF__ __DECL_REG_LO16
+__DeFiNe__ __DECL_REG_LO8(which) e ## which ## x
+__DeFiNe__ __DECL_REG_LO16(name) e ## name
+# endif
+#elif defined(__x86_64__)
+#include "xen-x86_64.h"
+#endif
+
+#ifndef __ASSEMBLY__
+typedef unsigned long xen_pfn_t;
+#define PRI_xen_pfn "lx"
+#define PRIu_xen_pfn "lu"
+#endif
+
+#define XEN_HAVE_PV_GUEST_ENTRY 1
+
+#define XEN_HAVE_PV_UPCALL_MASK 1
+
+/*
+ * `incontents 200 segdesc Segment Descriptor Tables
+ */
+/*
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_set_gdt(const xen_pfn_t frames[], unsigned int entries);
+ * `
+ */
+/*
+ * A number of GDT entries are reserved by Xen. These are not situated at the
+ * start of the GDT because some stupid OSes export hard-coded selector values
+ * in their ABI. These hard-coded values are always near the start of the GDT,
+ * so Xen places itself out of the way, at the far end of the GDT.
+ *
+ * NB The LDT is set using the MMUEXT_SET_LDT op of HYPERVISOR_mmuext_op
+ */
+#define FIRST_RESERVED_GDT_PAGE 14
+#define FIRST_RESERVED_GDT_BYTE (FIRST_RESERVED_GDT_PAGE * 4096)
+#define FIRST_RESERVED_GDT_ENTRY (FIRST_RESERVED_GDT_BYTE / 8)
+
+
+/*
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_update_descriptor(u64 pa, u64 desc);
+ * `
+ * ` @pa The machine physical address of the descriptor to
+ * ` update. Must be either a descriptor page or writable.
+ * ` @desc The descriptor value to update, in the same format as a
+ * ` native descriptor table entry.
+ */
+
+/* Maximum number of virtual CPUs in legacy multi-processor guests. */
+#define XEN_LEGACY_MAX_VCPUS 32
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned long xen_ulong_t;
+#define PRI_xen_ulong "lx"
+
+/*
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp);
+ * `
+ * Sets the stack segment and pointer for the current vcpu.
+ */
+
+/*
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_set_trap_table(const struct trap_info traps[]);
+ * `
+ */
+/*
+ * Send an array of these to HYPERVISOR_set_trap_table().
+ * Terminate the array with a sentinel entry, with traps[].address==0.
+ * The privilege level specifies which modes may enter a trap via a software
+ * interrupt. On x86/64, since rings 1 and 2 are unavailable, we allocate
+ * privilege levels as follows:
+ * Level == 0: Noone may enter
+ * Level == 1: Kernel may enter
+ * Level == 2: Kernel may enter
+ * Level == 3: Everyone may enter
+ *
+ * Note: For compatibility with kernels not setting up exception handlers
+ * early enough, Xen will avoid trying to inject #GP (and hence crash
+ * the domain) when an RDMSR would require this, but no handler was
+ * set yet. The precise conditions are implementation specific, and
+ * new code may not rely on such behavior anyway.
+ */
+#define TI_GET_DPL(_ti) ((_ti)->flags & 3)
+#define TI_GET_IF(_ti) ((_ti)->flags & 4)
+#define TI_SET_DPL(_ti,_dpl) ((_ti)->flags |= (_dpl))
+#define TI_SET_IF(_ti,_if) ((_ti)->flags |= ((!!(_if))<<2))
+struct trap_info {
+ uint8_t vector; /* exception vector */
+ uint8_t flags; /* 0-3: privilege level; 4: clear event enable? */
+ uint16_t cs; /* code selector */
+ unsigned long address; /* code offset */
+};
+typedef struct trap_info trap_info_t;
+DEFINE_XEN_GUEST_HANDLE(trap_info_t);
+
+typedef uint64_t tsc_timestamp_t; /* RDTSC timestamp */
+
+/*
+ * The following is all CPU context. Note that the fpu_ctxt block is filled
+ * in by FXSAVE if the CPU has feature FXSR; otherwise FSAVE is used.
+ *
+ * Also note that when calling DOMCTL_setvcpucontext for HVM guests, not all
+ * information in this structure is updated, the fields read include: fpu_ctxt
+ * (if VGCT_I387_VALID is set), flags, user_regs and debugreg[*].
+ *
+ * Note: VCPUOP_initialise for HVM guests is non-symetric with
+ * DOMCTL_setvcpucontext, and uses struct vcpu_hvm_context from hvm/hvm_vcpu.h
+ */
+struct vcpu_guest_context {
+ /* FPU registers come first so they can be aligned for FXSAVE/FXRSTOR. */
+ struct { char x[512]; } fpu_ctxt; /* User-level FPU registers */
+#define VGCF_I387_VALID (1<<0)
+#define VGCF_IN_KERNEL (1<<2)
+#define _VGCF_i387_valid 0
+#define VGCF_i387_valid (1<<_VGCF_i387_valid)
+#define _VGCF_in_kernel 2
+#define VGCF_in_kernel (1<<_VGCF_in_kernel)
+#define _VGCF_failsafe_disables_events 3
+#define VGCF_failsafe_disables_events (1<<_VGCF_failsafe_disables_events)
+#define _VGCF_syscall_disables_events 4
+#define VGCF_syscall_disables_events (1<<_VGCF_syscall_disables_events)
+#define _VGCF_online 5
+#define VGCF_online (1<<_VGCF_online)
+ unsigned long flags; /* VGCF_* flags */
+ struct cpu_user_regs user_regs; /* User-level CPU registers */
+ struct trap_info trap_ctxt[256]; /* Virtual IDT */
+ unsigned long ldt_base, ldt_ents; /* LDT (linear address, # ents) */
+ unsigned long gdt_frames[16], gdt_ents; /* GDT (machine frames, # ents) */
+ unsigned long kernel_ss, kernel_sp; /* Virtual TSS (only SS1/SP1) */
+ /* NB. User pagetable on x86/64 is placed in ctrlreg[1]. */
+ unsigned long ctrlreg[8]; /* CR0-CR7 (control registers) */
+ unsigned long debugreg[8]; /* DB0-DB7 (debug registers) */
+#ifdef __i386__
+ unsigned long event_callback_cs; /* CS:EIP of event callback */
+ unsigned long event_callback_eip;
+ unsigned long failsafe_callback_cs; /* CS:EIP of failsafe callback */
+ unsigned long failsafe_callback_eip;
+#else
+ unsigned long event_callback_eip;
+ unsigned long failsafe_callback_eip;
+#ifdef __XEN__
+ union {
+ unsigned long syscall_callback_eip;
+ struct {
+ unsigned int event_callback_cs; /* compat CS of event cb */
+ unsigned int failsafe_callback_cs; /* compat CS of failsafe cb */
+ };
+ };
+#else
+ unsigned long syscall_callback_eip;
+#endif
+#endif
+ unsigned long vm_assist; /* VMASST_TYPE_* bitmap */
+#ifdef __x86_64__
+ /* Segment base addresses. */
+ uint64_t fs_base;
+ uint64_t gs_base_kernel;
+ uint64_t gs_base_user;
+#endif
+};
+typedef struct vcpu_guest_context vcpu_guest_context_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
+
+struct arch_shared_info {
+ /*
+ * Number of valid entries in the p2m table(s) anchored at
+ * pfn_to_mfn_frame_list_list and/or p2m_vaddr.
+ */
+ unsigned long max_pfn;
+ /*
+ * Frame containing list of mfns containing list of mfns containing p2m.
+ * A value of 0 indicates it has not yet been set up, ~0 indicates it has
+ * been set to invalid e.g. due to the p2m being too large for the 3-level
+ * p2m tree. In this case the linear mapper p2m list anchored at p2m_vaddr
+ * is to be used.
+ */
+ xen_pfn_t pfn_to_mfn_frame_list_list;
+ unsigned long nmi_reason;
+ /*
+ * Following three fields are valid if p2m_cr3 contains a value different
+ * from 0.
+ * p2m_cr3 is the root of the address space where p2m_vaddr is valid.
+ * p2m_cr3 is in the same format as a cr3 value in the vcpu register state
+ * and holds the folded machine frame number (via xen_pfn_to_cr3) of a
+ * L3 or L4 page table.
+ * p2m_vaddr holds the virtual address of the linear p2m list. All entries
+ * in the range [0...max_pfn[ are accessible via this pointer.
+ * p2m_generation will be incremented by the guest before and after each
+ * change of the mappings of the p2m list. p2m_generation starts at 0 and
+ * a value with the least significant bit set indicates that a mapping
+ * update is in progress. This allows guest external software (e.g. in Dom0)
+ * to verify that read mappings are consistent and whether they have changed
+ * since the last check.
+ * Modifying a p2m element in the linear p2m list is allowed via an atomic
+ * write only.
+ */
+ unsigned long p2m_cr3; /* cr3 value of the p2m address space */
+ unsigned long p2m_vaddr; /* virtual address of the p2m list */
+ unsigned long p2m_generation; /* generation count of p2m mapping */
+#ifdef __i386__
+ /* There's no room for this field in the generic structure. */
+ uint32_t wc_sec_hi;
+#endif
+};
+typedef struct arch_shared_info arch_shared_info_t;
+
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+/*
+ * struct xen_arch_domainconfig's ABI is covered by
+ * XEN_DOMCTL_INTERFACE_VERSION.
+ */
+struct xen_arch_domainconfig {
+#define _XEN_X86_EMU_LAPIC 0
+#define XEN_X86_EMU_LAPIC (1U<<_XEN_X86_EMU_LAPIC)
+#define _XEN_X86_EMU_HPET 1
+#define XEN_X86_EMU_HPET (1U<<_XEN_X86_EMU_HPET)
+#define _XEN_X86_EMU_PM 2
+#define XEN_X86_EMU_PM (1U<<_XEN_X86_EMU_PM)
+#define _XEN_X86_EMU_RTC 3
+#define XEN_X86_EMU_RTC (1U<<_XEN_X86_EMU_RTC)
+#define _XEN_X86_EMU_IOAPIC 4
+#define XEN_X86_EMU_IOAPIC (1U<<_XEN_X86_EMU_IOAPIC)
+#define _XEN_X86_EMU_PIC 5
+#define XEN_X86_EMU_PIC (1U<<_XEN_X86_EMU_PIC)
+#define _XEN_X86_EMU_VGA 6
+#define XEN_X86_EMU_VGA (1U<<_XEN_X86_EMU_VGA)
+#define _XEN_X86_EMU_IOMMU 7
+#define XEN_X86_EMU_IOMMU (1U<<_XEN_X86_EMU_IOMMU)
+#define _XEN_X86_EMU_PIT 8
+#define XEN_X86_EMU_PIT (1U<<_XEN_X86_EMU_PIT)
+#define _XEN_X86_EMU_USE_PIRQ 9
+#define XEN_X86_EMU_USE_PIRQ (1U<<_XEN_X86_EMU_USE_PIRQ)
+#define _XEN_X86_EMU_VPCI 10
+#define XEN_X86_EMU_VPCI (1U<<_XEN_X86_EMU_VPCI)
+
+#define XEN_X86_EMU_ALL (XEN_X86_EMU_LAPIC | XEN_X86_EMU_HPET | \
+ XEN_X86_EMU_PM | XEN_X86_EMU_RTC | \
+ XEN_X86_EMU_IOAPIC | XEN_X86_EMU_PIC | \
+ XEN_X86_EMU_VGA | XEN_X86_EMU_IOMMU | \
+ XEN_X86_EMU_PIT | XEN_X86_EMU_USE_PIRQ |\
+ XEN_X86_EMU_VPCI)
+ uint32_t emulation_flags;
+
+/*
+ * Select whether to use a relaxed behavior for accesses to MSRs not explicitly
+ * handled by Xen instead of injecting a #GP to the guest. Note this option
+ * doesn't allow the guest to read or write to the underlying MSR.
+ */
+#define XEN_X86_MSR_RELAXED (1u << 0)
+ uint32_t misc_flags;
+};
+
+/* Max XEN_X86_* constant. Used for ABI checking. */
+#define XEN_X86_MISC_FLAGS_MAX XEN_X86_MSR_RELAXED
+
+#endif
+
+/*
+ * Representations of architectural CPUID and MSR information. Used as the
+ * serialised version of Xen's internal representation.
+ */
+typedef struct xen_cpuid_leaf {
+#define XEN_CPUID_NO_SUBLEAF 0xffffffffu
+ uint32_t leaf, subleaf;
+ uint32_t a, b, c, d;
+} xen_cpuid_leaf_t;
+DEFINE_XEN_GUEST_HANDLE(xen_cpuid_leaf_t);
+
+typedef struct xen_msr_entry {
+ uint32_t idx;
+ uint32_t flags; /* Reserved MBZ. */
+ uint64_t val;
+} xen_msr_entry_t;
+DEFINE_XEN_GUEST_HANDLE(xen_msr_entry_t);
+
+#endif /* !__ASSEMBLY__ */
+
+/*
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_fpu_taskswitch(int set);
+ * `
+ * Sets (if set!=0) or clears (if set==0) CR0.TS.
+ */
+
+/*
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_set_debugreg(int regno, unsigned long value);
+ *
+ * ` unsigned long
+ * ` HYPERVISOR_get_debugreg(int regno);
+ * For 0<=reg<=7, returns the debug register value.
+ * For other values of reg, returns ((unsigned long)-EINVAL).
+ * (Unfortunately, this interface is defective.)
+ */
+
+/*
+ * Prefix forces emulation of some non-trapping instructions.
+ * Currently only CPUID.
+ */
+#ifdef __ASSEMBLY__
+#define XEN_EMULATE_PREFIX .byte 0x0f,0x0b,0x78,0x65,0x6e ;
+#define XEN_CPUID XEN_EMULATE_PREFIX cpuid
+#else
+#define XEN_EMULATE_PREFIX ".byte 0x0f,0x0b,0x78,0x65,0x6e ; "
+#define XEN_CPUID XEN_EMULATE_PREFIX "cpuid"
+#endif
+
+/*
+ * Debug console IO port, also called "port E9 hack". Each character written
+ * to this IO port will be printed on the hypervisor console, subject to log
+ * level restrictions.
+ */
+#define XEN_HVM_DEBUGCONS_IOPORT 0xe9
+
+#endif /* __XEN_PUBLIC_ARCH_X86_XEN_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/hw/xen/interface/event_channel.h b/include/hw/xen/interface/event_channel.h
new file mode 100644
index 0000000000..0d91a1c4af
--- /dev/null
+++ b/include/hw/xen/interface/event_channel.h
@@ -0,0 +1,371 @@
+/* SPDX-License-Identifier: MIT */
+/******************************************************************************
+ * event_channel.h
+ *
+ * Event channels between domains.
+ *
+ * Copyright (c) 2003-2004, K A Fraser.
+ */
+
+#ifndef __XEN_PUBLIC_EVENT_CHANNEL_H__
+#define __XEN_PUBLIC_EVENT_CHANNEL_H__
+
+#include "xen.h"
+
+/*
+ * `incontents 150 evtchn Event Channels
+ *
+ * Event channels are the basic primitive provided by Xen for event
+ * notifications. An event is the Xen equivalent of a hardware
+ * interrupt. They essentially store one bit of information, the event
+ * of interest is signalled by transitioning this bit from 0 to 1.
+ *
+ * Notifications are received by a guest via an upcall from Xen,
+ * indicating when an event arrives (setting the bit). Further
+ * notifications are masked until the bit is cleared again (therefore,
+ * guests must check the value of the bit after re-enabling event
+ * delivery to ensure no missed notifications).
+ *
+ * Event notifications can be masked by setting a flag; this is
+ * equivalent to disabling interrupts and can be used to ensure
+ * atomicity of certain operations in the guest kernel.
+ *
+ * Event channels are represented by the evtchn_* fields in
+ * struct shared_info and struct vcpu_info.
+ */
+
+/*
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_event_channel_op(enum event_channel_op cmd, void *args)
+ * `
+ * @cmd == EVTCHNOP_* (event-channel operation).
+ * @args == struct evtchn_* Operation-specific extra arguments (NULL if none).
+ */
+
+/* ` enum event_channel_op { // EVTCHNOP_* => struct evtchn_* */
+#define EVTCHNOP_bind_interdomain 0
+#define EVTCHNOP_bind_virq 1
+#define EVTCHNOP_bind_pirq 2
+#define EVTCHNOP_close 3
+#define EVTCHNOP_send 4
+#define EVTCHNOP_status 5
+#define EVTCHNOP_alloc_unbound 6
+#define EVTCHNOP_bind_ipi 7
+#define EVTCHNOP_bind_vcpu 8
+#define EVTCHNOP_unmask 9
+#define EVTCHNOP_reset 10
+#define EVTCHNOP_init_control 11
+#define EVTCHNOP_expand_array 12
+#define EVTCHNOP_set_priority 13
+#ifdef __XEN__
+#define EVTCHNOP_reset_cont 14
+#endif
+/* ` } */
+
+typedef uint32_t evtchn_port_t;
+DEFINE_XEN_GUEST_HANDLE(evtchn_port_t);
+
+/*
+ * EVTCHNOP_alloc_unbound: Allocate a port in domain <dom> and mark as
+ * accepting interdomain bindings from domain <remote_dom>. A fresh port
+ * is allocated in <dom> and returned as <port>.
+ * NOTES:
+ * 1. If the caller is unprivileged then <dom> must be DOMID_SELF.
+ * 2. <remote_dom> may be DOMID_SELF, allowing loopback connections.
+ */
+struct evtchn_alloc_unbound {
+ /* IN parameters */
+ domid_t dom, remote_dom;
+ /* OUT parameters */
+ evtchn_port_t port;
+};
+typedef struct evtchn_alloc_unbound evtchn_alloc_unbound_t;
+
+/*
+ * EVTCHNOP_bind_interdomain: Construct an interdomain event channel between
+ * the calling domain and <remote_dom>. <remote_dom,remote_port> must identify
+ * a port that is unbound and marked as accepting bindings from the calling
+ * domain. A fresh port is allocated in the calling domain and returned as
+ * <local_port>.
+ *
+ * In case the peer domain has already tried to set our event channel
+ * pending, before it was bound, EVTCHNOP_bind_interdomain always sets
+ * the local event channel pending.
+ *
+ * The usual pattern of use, in the guest's upcall (or subsequent
+ * handler) is as follows: (Re-enable the event channel for subsequent
+ * signalling and then) check for the existence of whatever condition
+ * is being waited for by other means, and take whatever action is
+ * needed (if any).
+ *
+ * NOTES:
+ * 1. <remote_dom> may be DOMID_SELF, allowing loopback connections.
+ */
+struct evtchn_bind_interdomain {
+ /* IN parameters. */
+ domid_t remote_dom;
+ evtchn_port_t remote_port;
+ /* OUT parameters. */
+ evtchn_port_t local_port;
+};
+typedef struct evtchn_bind_interdomain evtchn_bind_interdomain_t;
+
+/*
+ * EVTCHNOP_bind_virq: Bind a local event channel to VIRQ <irq> on specified
+ * vcpu.
+ * NOTES:
+ * 1. Virtual IRQs are classified as per-vcpu or global. See the VIRQ list
+ * in xen.h for the classification of each VIRQ.
+ * 2. Global VIRQs must be allocated on VCPU0 but can subsequently be
+ * re-bound via EVTCHNOP_bind_vcpu.
+ * 3. Per-vcpu VIRQs may be bound to at most one event channel per vcpu.
+ * The allocated event channel is bound to the specified vcpu and the
+ * binding cannot be changed.
+ */
+struct evtchn_bind_virq {
+ /* IN parameters. */
+ uint32_t virq; /* enum virq */
+ uint32_t vcpu;
+ /* OUT parameters. */
+ evtchn_port_t port;
+};
+typedef struct evtchn_bind_virq evtchn_bind_virq_t;
+
+/*
+ * EVTCHNOP_bind_pirq: Bind a local event channel to a real IRQ (PIRQ <irq>).
+ * NOTES:
+ * 1. A physical IRQ may be bound to at most one event channel per domain.
+ * 2. Only a sufficiently-privileged domain may bind to a physical IRQ.
+ */
+struct evtchn_bind_pirq {
+ /* IN parameters. */
+ uint32_t pirq;
+#define BIND_PIRQ__WILL_SHARE 1
+ uint32_t flags; /* BIND_PIRQ__* */
+ /* OUT parameters. */
+ evtchn_port_t port;
+};
+typedef struct evtchn_bind_pirq evtchn_bind_pirq_t;
+
+/*
+ * EVTCHNOP_bind_ipi: Bind a local event channel to receive events.
+ * NOTES:
+ * 1. The allocated event channel is bound to the specified vcpu. The binding
+ * may not be changed.
+ */
+struct evtchn_bind_ipi {
+ uint32_t vcpu;
+ /* OUT parameters. */
+ evtchn_port_t port;
+};
+typedef struct evtchn_bind_ipi evtchn_bind_ipi_t;
+
+/*
+ * EVTCHNOP_close: Close a local event channel <port>. If the channel is
+ * interdomain then the remote end is placed in the unbound state
+ * (EVTCHNSTAT_unbound), awaiting a new connection.
+ */
+struct evtchn_close {
+ /* IN parameters. */
+ evtchn_port_t port;
+};
+typedef struct evtchn_close evtchn_close_t;
+
+/*
+ * EVTCHNOP_send: Send an event to the remote end of the channel whose local
+ * endpoint is <port>.
+ */
+struct evtchn_send {
+ /* IN parameters. */
+ evtchn_port_t port;
+};
+typedef struct evtchn_send evtchn_send_t;
+
+/*
+ * EVTCHNOP_status: Get the current status of the communication channel which
+ * has an endpoint at <dom, port>.
+ * NOTES:
+ * 1. <dom> may be specified as DOMID_SELF.
+ * 2. Only a sufficiently-privileged domain may obtain the status of an event
+ * channel for which <dom> is not DOMID_SELF.
+ */
+struct evtchn_status {
+ /* IN parameters */
+ domid_t dom;
+ evtchn_port_t port;
+ /* OUT parameters */
+#define EVTCHNSTAT_closed 0 /* Channel is not in use. */
+#define EVTCHNSTAT_unbound 1 /* Channel is waiting interdom connection.*/
+#define EVTCHNSTAT_interdomain 2 /* Channel is connected to remote domain. */
+#define EVTCHNSTAT_pirq 3 /* Channel is bound to a phys IRQ line. */
+#define EVTCHNSTAT_virq 4 /* Channel is bound to a virtual IRQ line */
+#define EVTCHNSTAT_ipi 5 /* Channel is bound to a virtual IPI line */
+ uint32_t status;
+ uint32_t vcpu; /* VCPU to which this channel is bound. */
+ union {
+ struct {
+ domid_t dom;
+ } unbound; /* EVTCHNSTAT_unbound */
+ struct {
+ domid_t dom;
+ evtchn_port_t port;
+ } interdomain; /* EVTCHNSTAT_interdomain */
+ uint32_t pirq; /* EVTCHNSTAT_pirq */
+ uint32_t virq; /* EVTCHNSTAT_virq */
+ } u;
+};
+typedef struct evtchn_status evtchn_status_t;
+
+/*
+ * EVTCHNOP_bind_vcpu: Specify which vcpu a channel should notify when an
+ * event is pending.
+ * NOTES:
+ * 1. IPI-bound channels always notify the vcpu specified at bind time.
+ * This binding cannot be changed.
+ * 2. Per-VCPU VIRQ channels always notify the vcpu specified at bind time.
+ * This binding cannot be changed.
+ * 3. All other channels notify vcpu0 by default. This default is set when
+ * the channel is allocated (a port that is freed and subsequently reused
+ * has its binding reset to vcpu0).
+ */
+struct evtchn_bind_vcpu {
+ /* IN parameters. */
+ evtchn_port_t port;
+ uint32_t vcpu;
+};
+typedef struct evtchn_bind_vcpu evtchn_bind_vcpu_t;
+
+/*
+ * EVTCHNOP_unmask: Unmask the specified local event-channel port and deliver
+ * a notification to the appropriate VCPU if an event is pending.
+ */
+struct evtchn_unmask {
+ /* IN parameters. */
+ evtchn_port_t port;
+};
+typedef struct evtchn_unmask evtchn_unmask_t;
+
+/*
+ * EVTCHNOP_reset: Close all event channels associated with specified domain.
+ * NOTES:
+ * 1. <dom> may be specified as DOMID_SELF.
+ * 2. Only a sufficiently-privileged domain may specify other than DOMID_SELF.
+ * 3. Destroys all control blocks and event array, resets event channel
+ * operations to 2-level ABI if called with <dom> == DOMID_SELF and FIFO
+ * ABI was used. Guests should not bind events during EVTCHNOP_reset call
+ * as these events are likely to be lost.
+ */
+struct evtchn_reset {
+ /* IN parameters. */
+ domid_t dom;
+};
+typedef struct evtchn_reset evtchn_reset_t;
+
+/*
+ * EVTCHNOP_init_control: initialize the control block for the FIFO ABI.
+ *
+ * Note: any events that are currently pending will not be resent and
+ * will be lost. Guests should call this before binding any event to
+ * avoid losing any events.
+ */
+struct evtchn_init_control {
+ /* IN parameters. */
+ uint64_t control_gfn;
+ uint32_t offset;
+ uint32_t vcpu;
+ /* OUT parameters. */
+ uint8_t link_bits;
+ uint8_t _pad[7];
+};
+typedef struct evtchn_init_control evtchn_init_control_t;
+
+/*
+ * EVTCHNOP_expand_array: add an additional page to the event array.
+ */
+struct evtchn_expand_array {
+ /* IN parameters. */
+ uint64_t array_gfn;
+};
+typedef struct evtchn_expand_array evtchn_expand_array_t;
+
+/*
+ * EVTCHNOP_set_priority: set the priority for an event channel.
+ */
+struct evtchn_set_priority {
+ /* IN parameters. */
+ evtchn_port_t port;
+ uint32_t priority;
+};
+typedef struct evtchn_set_priority evtchn_set_priority_t;
+
+/*
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_event_channel_op_compat(struct evtchn_op *op)
+ * `
+ * Superceded by new event_channel_op() hypercall since 0x00030202.
+ */
+struct evtchn_op {
+ uint32_t cmd; /* enum event_channel_op */
+ union {
+ evtchn_alloc_unbound_t alloc_unbound;
+ evtchn_bind_interdomain_t bind_interdomain;
+ evtchn_bind_virq_t bind_virq;
+ evtchn_bind_pirq_t bind_pirq;
+ evtchn_bind_ipi_t bind_ipi;
+ evtchn_close_t close;
+ evtchn_send_t send;
+ evtchn_status_t status;
+ evtchn_bind_vcpu_t bind_vcpu;
+ evtchn_unmask_t unmask;
+ } u;
+};
+typedef struct evtchn_op evtchn_op_t;
+DEFINE_XEN_GUEST_HANDLE(evtchn_op_t);
+
+/*
+ * 2-level ABI
+ */
+
+#define EVTCHN_2L_NR_CHANNELS (sizeof(xen_ulong_t) * sizeof(xen_ulong_t) * 64)
+
+/*
+ * FIFO ABI
+ */
+
+/* Events may have priorities from 0 (highest) to 15 (lowest). */
+#define EVTCHN_FIFO_PRIORITY_MAX 0
+#define EVTCHN_FIFO_PRIORITY_DEFAULT 7
+#define EVTCHN_FIFO_PRIORITY_MIN 15
+
+#define EVTCHN_FIFO_MAX_QUEUES (EVTCHN_FIFO_PRIORITY_MIN + 1)
+
+typedef uint32_t event_word_t;
+
+#define EVTCHN_FIFO_PENDING 31
+#define EVTCHN_FIFO_MASKED 30
+#define EVTCHN_FIFO_LINKED 29
+#define EVTCHN_FIFO_BUSY 28
+
+#define EVTCHN_FIFO_LINK_BITS 17
+#define EVTCHN_FIFO_LINK_MASK ((1 << EVTCHN_FIFO_LINK_BITS) - 1)
+
+#define EVTCHN_FIFO_NR_CHANNELS (1 << EVTCHN_FIFO_LINK_BITS)
+
+struct evtchn_fifo_control_block {
+ uint32_t ready;
+ uint32_t _rsvd;
+ uint32_t head[EVTCHN_FIFO_MAX_QUEUES];
+};
+typedef struct evtchn_fifo_control_block evtchn_fifo_control_block_t;
+
+#endif /* __XEN_PUBLIC_EVENT_CHANNEL_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/hw/xen/interface/features.h b/include/hw/xen/interface/features.h
new file mode 100644
index 0000000000..d2a9175aae
--- /dev/null
+++ b/include/hw/xen/interface/features.h
@@ -0,0 +1,126 @@
+/* SPDX-License-Identifier: MIT */
+/******************************************************************************
+ * features.h
+ *
+ * Feature flags, reported by XENVER_get_features.
+ *
+ * Copyright (c) 2006, Keir Fraser <keir@xensource.com>
+ */
+
+#ifndef __XEN_PUBLIC_FEATURES_H__
+#define __XEN_PUBLIC_FEATURES_H__
+
+/*
+ * `incontents 200 elfnotes_features XEN_ELFNOTE_FEATURES
+ *
+ * The list of all the features the guest supports. They are set by
+ * parsing the XEN_ELFNOTE_FEATURES and XEN_ELFNOTE_SUPPORTED_FEATURES
+ * string. The format is the feature names (as given here without the
+ * "XENFEAT_" prefix) separated by '|' characters.
+ * If a feature is required for the kernel to function then the feature name
+ * must be preceded by a '!' character.
+ *
+ * Note that if XEN_ELFNOTE_SUPPORTED_FEATURES is used, then in the
+ * XENFEAT_dom0 MUST be set if the guest is to be booted as dom0,
+ */
+
+/*
+ * If set, the guest does not need to write-protect its pagetables, and can
+ * update them via direct writes.
+ */
+#define XENFEAT_writable_page_tables 0
+
+/*
+ * If set, the guest does not need to write-protect its segment descriptor
+ * tables, and can update them via direct writes.
+ */
+#define XENFEAT_writable_descriptor_tables 1
+
+/*
+ * If set, translation between the guest's 'pseudo-physical' address space
+ * and the host's machine address space are handled by the hypervisor. In this
+ * mode the guest does not need to perform phys-to/from-machine translations
+ * when performing page table operations.
+ */
+#define XENFEAT_auto_translated_physmap 2
+
+/* If set, the guest is running in supervisor mode (e.g., x86 ring 0). */
+#define XENFEAT_supervisor_mode_kernel 3
+
+/*
+ * If set, the guest does not need to allocate x86 PAE page directories
+ * below 4GB. This flag is usually implied by auto_translated_physmap.
+ */
+#define XENFEAT_pae_pgdir_above_4gb 4
+
+/* x86: Does this Xen host support the MMU_PT_UPDATE_PRESERVE_AD hypercall? */
+#define XENFEAT_mmu_pt_update_preserve_ad 5
+
+/* x86: Does this Xen host support the MMU_{CLEAR,COPY}_PAGE hypercall? */
+#define XENFEAT_highmem_assist 6
+
+/*
+ * If set, GNTTABOP_map_grant_ref honors flags to be placed into guest kernel
+ * available pte bits.
+ */
+#define XENFEAT_gnttab_map_avail_bits 7
+
+/* x86: Does this Xen host support the HVM callback vector type? */
+#define XENFEAT_hvm_callback_vector 8
+
+/* x86: pvclock algorithm is safe to use on HVM */
+#define XENFEAT_hvm_safe_pvclock 9
+
+/* x86: pirq can be used by HVM guests */
+#define XENFEAT_hvm_pirqs 10
+
+/* operation as Dom0 is supported */
+#define XENFEAT_dom0 11
+
+/* Xen also maps grant references at pfn = mfn.
+ * This feature flag is deprecated and should not be used.
+#define XENFEAT_grant_map_identity 12
+ */
+
+/* Guest can use XENMEMF_vnode to specify virtual node for memory op. */
+#define XENFEAT_memory_op_vnode_supported 13
+
+/* arm: Hypervisor supports ARM SMC calling convention. */
+#define XENFEAT_ARM_SMCCC_supported 14
+
+/*
+ * x86/PVH: If set, ACPI RSDP can be placed at any address. Otherwise RSDP
+ * must be located in lower 1MB, as required by ACPI Specification for IA-PC
+ * systems.
+ * This feature flag is only consulted if XEN_ELFNOTE_GUEST_OS contains
+ * the "linux" string.
+ */
+#define XENFEAT_linux_rsdp_unrestricted 15
+
+/*
+ * A direct-mapped (or 1:1 mapped) domain is a domain for which its
+ * local pages have gfn == mfn. If a domain is direct-mapped,
+ * XENFEAT_direct_mapped is set; otherwise XENFEAT_not_direct_mapped
+ * is set.
+ *
+ * If neither flag is set (e.g. older Xen releases) the assumptions are:
+ * - not auto_translated domains (x86 only) are always direct-mapped
+ * - on x86, auto_translated domains are not direct-mapped
+ * - on ARM, Dom0 is direct-mapped, DomUs are not
+ */
+#define XENFEAT_not_direct_mapped 16
+#define XENFEAT_direct_mapped 17
+
+#define XENFEAT_NR_SUBMAPS 1
+
+#endif /* __XEN_PUBLIC_FEATURES_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/hw/xen/interface/grant_table.h b/include/hw/xen/interface/grant_table.h
index 2af0cbdde3..1dfa17a6d0 100644
--- a/include/hw/xen/interface/grant_table.h
+++ b/include/hw/xen/interface/grant_table.h
@@ -1,36 +1,669 @@
+/* SPDX-License-Identifier: MIT */
/******************************************************************************
* grant_table.h
*
* Interface for granting foreign access to page frames, and receiving
* page-ownership transfers.
*
- * 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.
- *
* Copyright (c) 2004, K A Fraser
*/
#ifndef __XEN_PUBLIC_GRANT_TABLE_H__
#define __XEN_PUBLIC_GRANT_TABLE_H__
+#include "xen.h"
+
+/*
+ * `incontents 150 gnttab Grant Tables
+ *
+ * Xen's grant tables provide a generic mechanism to memory sharing
+ * between domains. This shared memory interface underpins the split
+ * device drivers for block and network IO.
+ *
+ * Each domain has its own grant table. This is a data structure that
+ * is shared with Xen; it allows the domain to tell Xen what kind of
+ * permissions other domains have on its pages. Entries in the grant
+ * table are identified by grant references. A grant reference is an
+ * integer, which indexes into the grant table. It acts as a
+ * capability which the grantee can use to perform operations on the
+ * granter's memory.
+ *
+ * This capability-based system allows shared-memory communications
+ * between unprivileged domains. A grant reference also encapsulates
+ * the details of a shared page, removing the need for a domain to
+ * know the real machine address of a page it is sharing. This makes
+ * it possible to share memory correctly with domains running in
+ * fully virtualised memory.
+ */
+
+/***********************************
+ * GRANT TABLE REPRESENTATION
+ */
+
+/* Some rough guidelines on accessing and updating grant-table entries
+ * in a concurrency-safe manner. For more information, Linux contains a
+ * reference implementation for guest OSes (drivers/xen/grant_table.c, see
+ * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/xen/grant-table.c;hb=HEAD
+ *
+ * NB. WMB is a no-op on current-generation x86 processors. However, a
+ * compiler barrier will still be required.
+ *
+ * Introducing a valid entry into the grant table:
+ * 1. Write ent->domid.
+ * 2. Write ent->frame:
+ * GTF_permit_access: Frame to which access is permitted.
+ * GTF_accept_transfer: Pseudo-phys frame slot being filled by new
+ * frame, or zero if none.
+ * 3. Write memory barrier (WMB).
+ * 4. Write ent->flags, inc. valid type.
+ *
+ * Invalidating an unused GTF_permit_access entry:
+ * 1. flags = ent->flags.
+ * 2. Observe that !(flags & (GTF_reading|GTF_writing)).
+ * 3. Check result of SMP-safe CMPXCHG(&ent->flags, flags, 0).
+ * NB. No need for WMB as reuse of entry is control-dependent on success of
+ * step 3, and all architectures guarantee ordering of ctrl-dep writes.
+ *
+ * Invalidating an in-use GTF_permit_access entry:
+ * This cannot be done directly. Request assistance from the domain controller
+ * which can set a timeout on the use of a grant entry and take necessary
+ * action. (NB. This is not yet implemented!).
+ *
+ * Invalidating an unused GTF_accept_transfer entry:
+ * 1. flags = ent->flags.
+ * 2. Observe that !(flags & GTF_transfer_committed). [*]
+ * 3. Check result of SMP-safe CMPXCHG(&ent->flags, flags, 0).
+ * NB. No need for WMB as reuse of entry is control-dependent on success of
+ * step 3, and all architectures guarantee ordering of ctrl-dep writes.
+ * [*] If GTF_transfer_committed is set then the grant entry is 'committed'.
+ * The guest must /not/ modify the grant entry until the address of the
+ * transferred frame is written. It is safe for the guest to spin waiting
+ * for this to occur (detect by observing GTF_transfer_completed in
+ * ent->flags).
+ *
+ * Invalidating a committed GTF_accept_transfer entry:
+ * 1. Wait for (ent->flags & GTF_transfer_completed).
+ *
+ * Changing a GTF_permit_access from writable to read-only:
+ * Use SMP-safe CMPXCHG to set GTF_readonly, while checking !GTF_writing.
+ *
+ * Changing a GTF_permit_access from read-only to writable:
+ * Use SMP-safe bit-setting instruction.
+ */
+
/*
* Reference to a grant entry in a specified domain's grant table.
*/
typedef uint32_t grant_ref_t;
+/*
+ * A grant table comprises a packed array of grant entries in one or more
+ * page frames shared between Xen and a guest.
+ * [XEN]: This field is written by Xen and read by the sharing guest.
+ * [GST]: This field is written by the guest and read by Xen.
+ */
+
+/*
+ * Version 1 of the grant table entry structure is maintained largely for
+ * backwards compatibility. New guests are recommended to support using
+ * version 2 to overcome version 1 limitations, but to default to version 1.
+ */
+#if __XEN_INTERFACE_VERSION__ < 0x0003020a
+#define grant_entry_v1 grant_entry
+#define grant_entry_v1_t grant_entry_t
+#endif
+struct grant_entry_v1 {
+ /* GTF_xxx: various type and flag information. [XEN,GST] */
+ uint16_t flags;
+ /* The domain being granted foreign privileges. [GST] */
+ domid_t domid;
+ /*
+ * GTF_permit_access: GFN that @domid is allowed to map and access. [GST]
+ * GTF_accept_transfer: GFN that @domid is allowed to transfer into. [GST]
+ * GTF_transfer_completed: MFN whose ownership transferred by @domid
+ * (non-translated guests only). [XEN]
+ */
+ uint32_t frame;
+};
+typedef struct grant_entry_v1 grant_entry_v1_t;
+
+/* The first few grant table entries will be preserved across grant table
+ * version changes and may be pre-populated at domain creation by tools.
+ */
+#define GNTTAB_NR_RESERVED_ENTRIES 8
+#define GNTTAB_RESERVED_CONSOLE 0
+#define GNTTAB_RESERVED_XENSTORE 1
+
+/*
+ * Type of grant entry.
+ * GTF_invalid: This grant entry grants no privileges.
+ * GTF_permit_access: Allow @domid to map/access @frame.
+ * GTF_accept_transfer: Allow @domid to transfer ownership of one page frame
+ * to this guest. Xen writes the page number to @frame.
+ * GTF_transitive: Allow @domid to transitively access a subrange of
+ * @trans_grant in @trans_domid. No mappings are allowed.
+ */
+#define GTF_invalid (0U<<0)
+#define GTF_permit_access (1U<<0)
+#define GTF_accept_transfer (2U<<0)
+#define GTF_transitive (3U<<0)
+#define GTF_type_mask (3U<<0)
+
+/*
+ * Subflags for GTF_permit_access and GTF_transitive.
+ * GTF_readonly: Restrict @domid to read-only mappings and accesses. [GST]
+ * GTF_reading: Grant entry is currently mapped for reading by @domid. [XEN]
+ * GTF_writing: Grant entry is currently mapped for writing by @domid. [XEN]
+ * Further subflags for GTF_permit_access only.
+ * GTF_PAT, GTF_PWT, GTF_PCD: (x86) cache attribute flags to be used for
+ * mappings of the grant [GST]
+ * GTF_sub_page: Grant access to only a subrange of the page. @domid
+ * will only be allowed to copy from the grant, and not
+ * map it. [GST]
+ */
+#define _GTF_readonly (2)
+#define GTF_readonly (1U<<_GTF_readonly)
+#define _GTF_reading (3)
+#define GTF_reading (1U<<_GTF_reading)
+#define _GTF_writing (4)
+#define GTF_writing (1U<<_GTF_writing)
+#define _GTF_PWT (5)
+#define GTF_PWT (1U<<_GTF_PWT)
+#define _GTF_PCD (6)
+#define GTF_PCD (1U<<_GTF_PCD)
+#define _GTF_PAT (7)
+#define GTF_PAT (1U<<_GTF_PAT)
+#define _GTF_sub_page (8)
+#define GTF_sub_page (1U<<_GTF_sub_page)
+
+/*
+ * Subflags for GTF_accept_transfer:
+ * GTF_transfer_committed: Xen sets this flag to indicate that it is committed
+ * to transferring ownership of a page frame. When a guest sees this flag
+ * it must /not/ modify the grant entry until GTF_transfer_completed is
+ * set by Xen.
+ * GTF_transfer_completed: It is safe for the guest to spin-wait on this flag
+ * after reading GTF_transfer_committed. Xen will always write the frame
+ * address, followed by ORing this flag, in a timely manner.
+ */
+#define _GTF_transfer_committed (2)
+#define GTF_transfer_committed (1U<<_GTF_transfer_committed)
+#define _GTF_transfer_completed (3)
+#define GTF_transfer_completed (1U<<_GTF_transfer_completed)
+
+/*
+ * Version 2 grant table entries. These fulfil the same role as
+ * version 1 entries, but can represent more complicated operations.
+ * Any given domain will have either a version 1 or a version 2 table,
+ * and every entry in the table will be the same version.
+ *
+ * The interface by which domains use grant references does not depend
+ * on the grant table version in use by the other domain.
+ */
+#if __XEN_INTERFACE_VERSION__ >= 0x0003020a
+/*
+ * Version 1 and version 2 grant entries share a common prefix. The
+ * fields of the prefix are documented as part of struct
+ * grant_entry_v1.
+ */
+struct grant_entry_header {
+ uint16_t flags;
+ domid_t domid;
+};
+typedef struct grant_entry_header grant_entry_header_t;
+
+/*
+ * Version 2 of the grant entry structure.
+ */
+union grant_entry_v2 {
+ grant_entry_header_t hdr;
+
+ /*
+ * This member is used for V1-style full page grants, where either:
+ *
+ * -- hdr.type is GTF_accept_transfer, or
+ * -- hdr.type is GTF_permit_access and GTF_sub_page is not set.
+ *
+ * In that case, the frame field has the same semantics as the
+ * field of the same name in the V1 entry structure.
+ */
+ struct {
+ grant_entry_header_t hdr;
+ uint32_t pad0;
+ uint64_t frame;
+ } full_page;
+
+ /*
+ * If the grant type is GTF_grant_access and GTF_sub_page is set,
+ * @domid is allowed to access bytes [@page_off,@page_off+@length)
+ * in frame @frame.
+ */
+ struct {
+ grant_entry_header_t hdr;
+ uint16_t page_off;
+ uint16_t length;
+ uint64_t frame;
+ } sub_page;
+
+ /*
+ * If the grant is GTF_transitive, @domid is allowed to use the
+ * grant @gref in domain @trans_domid, as if it was the local
+ * domain. Obviously, the transitive access must be compatible
+ * with the original grant.
+ *
+ * The current version of Xen does not allow transitive grants
+ * to be mapped.
+ */
+ struct {
+ grant_entry_header_t hdr;
+ domid_t trans_domid;
+ uint16_t pad0;
+ grant_ref_t gref;
+ } transitive;
+
+ uint32_t __spacer[4]; /* Pad to a power of two */
+};
+typedef union grant_entry_v2 grant_entry_v2_t;
+
+typedef uint16_t grant_status_t;
+
+#endif /* __XEN_INTERFACE_VERSION__ */
+
+/***********************************
+ * GRANT TABLE QUERIES AND USES
+ */
+
+/* ` enum neg_errnoval
+ * ` HYPERVISOR_grant_table_op(enum grant_table_op cmd,
+ * ` void *args,
+ * ` unsigned int count)
+ * `
+ *
+ * @args points to an array of a per-command data structure. The array
+ * has @count members
+ */
+
+/* ` enum grant_table_op { // GNTTABOP_* => struct gnttab_* */
+#define GNTTABOP_map_grant_ref 0
+#define GNTTABOP_unmap_grant_ref 1
+#define GNTTABOP_setup_table 2
+#define GNTTABOP_dump_table 3
+#define GNTTABOP_transfer 4
+#define GNTTABOP_copy 5
+#define GNTTABOP_query_size 6
+#define GNTTABOP_unmap_and_replace 7
+#if __XEN_INTERFACE_VERSION__ >= 0x0003020a
+#define GNTTABOP_set_version 8
+#define GNTTABOP_get_status_frames 9
+#define GNTTABOP_get_version 10
+#define GNTTABOP_swap_grant_ref 11
+#define GNTTABOP_cache_flush 12
+#endif /* __XEN_INTERFACE_VERSION__ */
+/* ` } */
+
+/*
+ * Handle to track a mapping created via a grant reference.
+ */
+typedef uint32_t grant_handle_t;
+
+/*
+ * GNTTABOP_map_grant_ref: Map the grant entry (<dom>,<ref>) for access
+ * by devices and/or host CPUs. If successful, <handle> is a tracking number
+ * that must be presented later to destroy the mapping(s). On error, <status>
+ * is a negative status code.
+ * NOTES:
+ * 1. If GNTMAP_device_map is specified then <dev_bus_addr> is the address
+ * via which I/O devices may access the granted frame.
+ * 2. If GNTMAP_host_map is specified then a mapping will be added at
+ * either a host virtual address in the current address space, or at
+ * a PTE at the specified machine address. The type of mapping to
+ * perform is selected through the GNTMAP_contains_pte flag, and the
+ * address is specified in <host_addr>.
+ * 3. Mappings should only be destroyed via GNTTABOP_unmap_grant_ref. If a
+ * host mapping is destroyed by other means then it is *NOT* guaranteed
+ * to be accounted to the correct grant reference!
+ */
+struct gnttab_map_grant_ref {
+ /* IN parameters. */
+ uint64_t host_addr;
+ uint32_t flags; /* GNTMAP_* */
+ grant_ref_t ref;
+ domid_t dom;
+ /* OUT parameters. */
+ int16_t status; /* => enum grant_status */
+ grant_handle_t handle;
+ uint64_t dev_bus_addr;
+};
+typedef struct gnttab_map_grant_ref gnttab_map_grant_ref_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_map_grant_ref_t);
+
+/*
+ * GNTTABOP_unmap_grant_ref: Destroy one or more grant-reference mappings
+ * tracked by <handle>. If <host_addr> or <dev_bus_addr> is zero, that
+ * field is ignored. If non-zero, they must refer to a device/host mapping
+ * that is tracked by <handle>
+ * NOTES:
+ * 1. The call may fail in an undefined manner if either mapping is not
+ * tracked by <handle>.
+ * 3. After executing a batch of unmaps, it is guaranteed that no stale
+ * mappings will remain in the device or host TLBs.
+ */
+struct gnttab_unmap_grant_ref {
+ /* IN parameters. */
+ uint64_t host_addr;
+ uint64_t dev_bus_addr;
+ grant_handle_t handle;
+ /* OUT parameters. */
+ int16_t status; /* => enum grant_status */
+};
+typedef struct gnttab_unmap_grant_ref gnttab_unmap_grant_ref_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_unmap_grant_ref_t);
+
+/*
+ * GNTTABOP_setup_table: Set up a grant table for <dom> comprising at least
+ * <nr_frames> pages. The frame addresses are written to the <frame_list>.
+ * Only <nr_frames> addresses are written, even if the table is larger.
+ * NOTES:
+ * 1. <dom> may be specified as DOMID_SELF.
+ * 2. Only a sufficiently-privileged domain may specify <dom> != DOMID_SELF.
+ * 3. Xen may not support more than a single grant-table page per domain.
+ */
+struct gnttab_setup_table {
+ /* IN parameters. */
+ domid_t dom;
+ uint32_t nr_frames;
+ /* OUT parameters. */
+ int16_t status; /* => enum grant_status */
+#if __XEN_INTERFACE_VERSION__ < 0x00040300
+ XEN_GUEST_HANDLE(ulong) frame_list;
+#else
+ XEN_GUEST_HANDLE(xen_pfn_t) frame_list;
+#endif
+};
+typedef struct gnttab_setup_table gnttab_setup_table_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_setup_table_t);
+
+/*
+ * GNTTABOP_dump_table: Dump the contents of the grant table to the
+ * xen console. Debugging use only.
+ */
+struct gnttab_dump_table {
+ /* IN parameters. */
+ domid_t dom;
+ /* OUT parameters. */
+ int16_t status; /* => enum grant_status */
+};
+typedef struct gnttab_dump_table gnttab_dump_table_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_dump_table_t);
+
+/*
+ * GNTTABOP_transfer: Transfer <frame> to a foreign domain. The foreign domain
+ * has previously registered its interest in the transfer via <domid, ref>.
+ *
+ * Note that, even if the transfer fails, the specified page no longer belongs
+ * to the calling domain *unless* the error is GNTST_bad_page.
+ *
+ * Note further that only PV guests can use this operation.
+ */
+struct gnttab_transfer {
+ /* IN parameters. */
+ xen_pfn_t mfn;
+ domid_t domid;
+ grant_ref_t ref;
+ /* OUT parameters. */
+ int16_t status;
+};
+typedef struct gnttab_transfer gnttab_transfer_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_transfer_t);
+
+
+/*
+ * GNTTABOP_copy: Hypervisor based copy
+ * source and destinations can be eithers MFNs or, for foreign domains,
+ * grant references. the foreign domain has to grant read/write access
+ * in its grant table.
+ *
+ * The flags specify what type source and destinations are (either MFN
+ * or grant reference).
+ *
+ * Note that this can also be used to copy data between two domains
+ * via a third party if the source and destination domains had previously
+ * grant appropriate access to their pages to the third party.
+ *
+ * source_offset specifies an offset in the source frame, dest_offset
+ * the offset in the target frame and len specifies the number of
+ * bytes to be copied.
+ */
+
+#define _GNTCOPY_source_gref (0)
+#define GNTCOPY_source_gref (1<<_GNTCOPY_source_gref)
+#define _GNTCOPY_dest_gref (1)
+#define GNTCOPY_dest_gref (1<<_GNTCOPY_dest_gref)
+
+struct gnttab_copy {
+ /* IN parameters. */
+ struct gnttab_copy_ptr {
+ union {
+ grant_ref_t ref;
+ xen_pfn_t gmfn;
+ } u;
+ domid_t domid;
+ uint16_t offset;
+ } source, dest;
+ uint16_t len;
+ uint16_t flags; /* GNTCOPY_* */
+ /* OUT parameters. */
+ int16_t status;
+};
+typedef struct gnttab_copy gnttab_copy_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_copy_t);
+
+/*
+ * GNTTABOP_query_size: Query the current and maximum sizes of the shared
+ * grant table.
+ * NOTES:
+ * 1. <dom> may be specified as DOMID_SELF.
+ * 2. Only a sufficiently-privileged domain may specify <dom> != DOMID_SELF.
+ */
+struct gnttab_query_size {
+ /* IN parameters. */
+ domid_t dom;
+ /* OUT parameters. */
+ uint32_t nr_frames;
+ uint32_t max_nr_frames;
+ int16_t status; /* => enum grant_status */
+};
+typedef struct gnttab_query_size gnttab_query_size_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_query_size_t);
+
+/*
+ * GNTTABOP_unmap_and_replace: Destroy one or more grant-reference mappings
+ * tracked by <handle> but atomically replace the page table entry with one
+ * pointing to the machine address under <new_addr>. <new_addr> will be
+ * redirected to the null entry.
+ * NOTES:
+ * 1. The call may fail in an undefined manner if either mapping is not
+ * tracked by <handle>.
+ * 2. After executing a batch of unmaps, it is guaranteed that no stale
+ * mappings will remain in the device or host TLBs.
+ */
+struct gnttab_unmap_and_replace {
+ /* IN parameters. */
+ uint64_t host_addr;
+ uint64_t new_addr;
+ grant_handle_t handle;
+ /* OUT parameters. */
+ int16_t status; /* => enum grant_status */
+};
+typedef struct gnttab_unmap_and_replace gnttab_unmap_and_replace_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_unmap_and_replace_t);
+
+#if __XEN_INTERFACE_VERSION__ >= 0x0003020a
+/*
+ * GNTTABOP_set_version: Request a particular version of the grant
+ * table shared table structure. This operation may be used to toggle
+ * between different versions, but must be performed while no grants
+ * are active. The only defined versions are 1 and 2.
+ */
+struct gnttab_set_version {
+ /* IN/OUT parameters */
+ uint32_t version;
+};
+typedef struct gnttab_set_version gnttab_set_version_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_set_version_t);
+
+
+/*
+ * GNTTABOP_get_status_frames: Get the list of frames used to store grant
+ * status for <dom>. In grant format version 2, the status is separated
+ * from the other shared grant fields to allow more efficient synchronization
+ * using barriers instead of atomic cmpexch operations.
+ * <nr_frames> specify the size of vector <frame_list>.
+ * The frame addresses are returned in the <frame_list>.
+ * Only <nr_frames> addresses are returned, even if the table is larger.
+ * NOTES:
+ * 1. <dom> may be specified as DOMID_SELF.
+ * 2. Only a sufficiently-privileged domain may specify <dom> != DOMID_SELF.
+ */
+struct gnttab_get_status_frames {
+ /* IN parameters. */
+ uint32_t nr_frames;
+ domid_t dom;
+ /* OUT parameters. */
+ int16_t status; /* => enum grant_status */
+ XEN_GUEST_HANDLE(uint64_t) frame_list;
+};
+typedef struct gnttab_get_status_frames gnttab_get_status_frames_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_get_status_frames_t);
+
+/*
+ * GNTTABOP_get_version: Get the grant table version which is in
+ * effect for domain <dom>.
+ */
+struct gnttab_get_version {
+ /* IN parameters */
+ domid_t dom;
+ uint16_t pad;
+ /* OUT parameters */
+ uint32_t version;
+};
+typedef struct gnttab_get_version gnttab_get_version_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_get_version_t);
+
+/*
+ * GNTTABOP_swap_grant_ref: Swap the contents of two grant entries.
+ */
+struct gnttab_swap_grant_ref {
+ /* IN parameters */
+ grant_ref_t ref_a;
+ grant_ref_t ref_b;
+ /* OUT parameters */
+ int16_t status; /* => enum grant_status */
+};
+typedef struct gnttab_swap_grant_ref gnttab_swap_grant_ref_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_swap_grant_ref_t);
+
+/*
+ * Issue one or more cache maintenance operations on a portion of a
+ * page granted to the calling domain by a foreign domain.
+ */
+struct gnttab_cache_flush {
+ union {
+ uint64_t dev_bus_addr;
+ grant_ref_t ref;
+ } a;
+ uint16_t offset; /* offset from start of grant */
+ uint16_t length; /* size within the grant */
+#define GNTTAB_CACHE_CLEAN (1u<<0)
+#define GNTTAB_CACHE_INVAL (1u<<1)
+#define GNTTAB_CACHE_SOURCE_GREF (1u<<31)
+ uint32_t op;
+};
+typedef struct gnttab_cache_flush gnttab_cache_flush_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_cache_flush_t);
+
+#endif /* __XEN_INTERFACE_VERSION__ */
+
+/*
+ * Bitfield values for gnttab_map_grant_ref.flags.
+ */
+ /* Map the grant entry for access by I/O devices. */
+#define _GNTMAP_device_map (0)
+#define GNTMAP_device_map (1<<_GNTMAP_device_map)
+ /* Map the grant entry for access by host CPUs. */
+#define _GNTMAP_host_map (1)
+#define GNTMAP_host_map (1<<_GNTMAP_host_map)
+ /* Accesses to the granted frame will be restricted to read-only access. */
+#define _GNTMAP_readonly (2)
+#define GNTMAP_readonly (1<<_GNTMAP_readonly)
+ /*
+ * GNTMAP_host_map subflag:
+ * 0 => The host mapping is usable only by the guest OS.
+ * 1 => The host mapping is usable by guest OS + current application.
+ */
+#define _GNTMAP_application_map (3)
+#define GNTMAP_application_map (1<<_GNTMAP_application_map)
+
+ /*
+ * GNTMAP_contains_pte subflag:
+ * 0 => This map request contains a host virtual address.
+ * 1 => This map request contains the machine addess of the PTE to update.
+ */
+#define _GNTMAP_contains_pte (4)
+#define GNTMAP_contains_pte (1<<_GNTMAP_contains_pte)
+
+/*
+ * Bits to be placed in guest kernel available PTE bits (architecture
+ * dependent; only supported when XENFEAT_gnttab_map_avail_bits is set).
+ */
+#define _GNTMAP_guest_avail0 (16)
+#define GNTMAP_guest_avail_mask ((uint32_t)~0 << _GNTMAP_guest_avail0)
+
+/*
+ * Values for error status returns. All errors are -ve.
+ */
+/* ` enum grant_status { */
+#define GNTST_okay (0) /* Normal return. */
+#define GNTST_general_error (-1) /* General undefined error. */
+#define GNTST_bad_domain (-2) /* Unrecognsed domain id. */
+#define GNTST_bad_gntref (-3) /* Unrecognised or inappropriate gntref. */
+#define GNTST_bad_handle (-4) /* Unrecognised or inappropriate handle. */
+#define GNTST_bad_virt_addr (-5) /* Inappropriate virtual address to map. */
+#define GNTST_bad_dev_addr (-6) /* Inappropriate device address to unmap.*/
+#define GNTST_no_device_space (-7) /* Out of space in I/O MMU. */
+#define GNTST_permission_denied (-8) /* Not enough privilege for operation. */
+#define GNTST_bad_page (-9) /* Specified page was invalid for op. */
+#define GNTST_bad_copy_arg (-10) /* copy arguments cross page boundary. */
+#define GNTST_address_too_big (-11) /* transfer page address too large. */
+#define GNTST_eagain (-12) /* Operation not done; try again. */
+#define GNTST_no_space (-13) /* Out of space (handles etc). */
+/* ` } */
+
+#define GNTTABOP_error_msgs { \
+ "okay", \
+ "undefined error", \
+ "unrecognised domain id", \
+ "invalid grant reference", \
+ "invalid mapping handle", \
+ "invalid virtual address", \
+ "invalid device address", \
+ "no spare translation slot in the I/O MMU", \
+ "permission denied", \
+ "bad page", \
+ "copy arguments cross page boundary", \
+ "page address size too large", \
+ "operation not done; try again", \
+ "out of space", \
+}
+
#endif /* __XEN_PUBLIC_GRANT_TABLE_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/hw/xen/interface/hvm/hvm_op.h b/include/hw/xen/interface/hvm/hvm_op.h
new file mode 100644
index 0000000000..e22adf0319
--- /dev/null
+++ b/include/hw/xen/interface/hvm/hvm_op.h
@@ -0,0 +1,378 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (c) 2007, Keir Fraser
+ */
+
+#ifndef __XEN_PUBLIC_HVM_HVM_OP_H__
+#define __XEN_PUBLIC_HVM_HVM_OP_H__
+
+#include "../xen.h"
+#include "../trace.h"
+#include "../event_channel.h"
+
+/* Get/set subcommands: extra argument == pointer to xen_hvm_param struct. */
+#define HVMOP_set_param 0
+#define HVMOP_get_param 1
+struct xen_hvm_param {
+ domid_t domid; /* IN */
+ uint16_t pad;
+ uint32_t index; /* IN */
+ uint64_t value; /* IN/OUT */
+};
+typedef struct xen_hvm_param xen_hvm_param_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_param_t);
+
+struct xen_hvm_altp2m_suppress_ve {
+ uint16_t view;
+ uint8_t suppress_ve; /* Boolean type. */
+ uint8_t pad1;
+ uint32_t pad2;
+ uint64_t gfn;
+};
+
+struct xen_hvm_altp2m_suppress_ve_multi {
+ uint16_t view;
+ uint8_t suppress_ve; /* Boolean type. */
+ uint8_t pad1;
+ int32_t first_error; /* Should be set to 0. */
+ uint64_t first_gfn; /* Value may be updated. */
+ uint64_t last_gfn;
+ uint64_t first_error_gfn; /* Gfn of the first error. */
+};
+
+#if __XEN_INTERFACE_VERSION__ < 0x00040900
+
+/* Set the logical level of one of a domain's PCI INTx wires. */
+#define HVMOP_set_pci_intx_level 2
+struct xen_hvm_set_pci_intx_level {
+ /* Domain to be updated. */
+ domid_t domid;
+ /* PCI INTx identification in PCI topology (domain:bus:device:intx). */
+ uint8_t domain, bus, device, intx;
+ /* Assertion level (0 = unasserted, 1 = asserted). */
+ uint8_t level;
+};
+typedef struct xen_hvm_set_pci_intx_level xen_hvm_set_pci_intx_level_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_pci_intx_level_t);
+
+/* Set the logical level of one of a domain's ISA IRQ wires. */
+#define HVMOP_set_isa_irq_level 3
+struct xen_hvm_set_isa_irq_level {
+ /* Domain to be updated. */
+ domid_t domid;
+ /* ISA device identification, by ISA IRQ (0-15). */
+ uint8_t isa_irq;
+ /* Assertion level (0 = unasserted, 1 = asserted). */
+ uint8_t level;
+};
+typedef struct xen_hvm_set_isa_irq_level xen_hvm_set_isa_irq_level_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_isa_irq_level_t);
+
+#define HVMOP_set_pci_link_route 4
+struct xen_hvm_set_pci_link_route {
+ /* Domain to be updated. */
+ domid_t domid;
+ /* PCI link identifier (0-3). */
+ uint8_t link;
+ /* ISA IRQ (1-15), or 0 (disable link). */
+ uint8_t isa_irq;
+};
+typedef struct xen_hvm_set_pci_link_route xen_hvm_set_pci_link_route_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_pci_link_route_t);
+
+#endif /* __XEN_INTERFACE_VERSION__ < 0x00040900 */
+
+/* Flushes all VCPU TLBs: @arg must be NULL. */
+#define HVMOP_flush_tlbs 5
+
+/*
+ * hvmmem_type_t should not be defined when generating the corresponding
+ * compat header. This will ensure that the improperly named HVMMEM_(*)
+ * values are defined only once.
+ */
+#ifndef XEN_GENERATING_COMPAT_HEADERS
+
+typedef enum {
+ HVMMEM_ram_rw, /* Normal read/write guest RAM */
+ HVMMEM_ram_ro, /* Read-only; writes are discarded */
+ HVMMEM_mmio_dm, /* Reads and write go to the device model */
+#if __XEN_INTERFACE_VERSION__ < 0x00040700
+ HVMMEM_mmio_write_dm, /* Read-only; writes go to the device model */
+#else
+ HVMMEM_unused, /* Placeholder; setting memory to this type
+ will fail for code after 4.7.0 */
+#endif
+ HVMMEM_ioreq_server /* Memory type claimed by an ioreq server; type
+ changes to this value are only allowed after
+ an ioreq server has claimed its ownership.
+ Only pages with HVMMEM_ram_rw are allowed to
+ change to this type; conversely, pages with
+ this type are only allowed to be changed back
+ to HVMMEM_ram_rw. */
+} hvmmem_type_t;
+
+#endif /* XEN_GENERATING_COMPAT_HEADERS */
+
+/* Hint from PV drivers for pagetable destruction. */
+#define HVMOP_pagetable_dying 9
+struct xen_hvm_pagetable_dying {
+ /* Domain with a pagetable about to be destroyed. */
+ domid_t domid;
+ uint16_t pad[3]; /* align next field on 8-byte boundary */
+ /* guest physical address of the toplevel pagetable dying */
+ uint64_t gpa;
+};
+typedef struct xen_hvm_pagetable_dying xen_hvm_pagetable_dying_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_pagetable_dying_t);
+
+/* Get the current Xen time, in nanoseconds since system boot. */
+#define HVMOP_get_time 10
+struct xen_hvm_get_time {
+ uint64_t now; /* OUT */
+};
+typedef struct xen_hvm_get_time xen_hvm_get_time_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_time_t);
+
+#define HVMOP_xentrace 11
+struct xen_hvm_xentrace {
+ uint16_t event, extra_bytes;
+ uint8_t extra[TRACE_EXTRA_MAX * sizeof(uint32_t)];
+};
+typedef struct xen_hvm_xentrace xen_hvm_xentrace_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_xentrace_t);
+
+/* Following tools-only interfaces may change in future. */
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+
+/* Deprecated by XENMEM_access_op_set_access */
+#define HVMOP_set_mem_access 12
+
+/* Deprecated by XENMEM_access_op_get_access */
+#define HVMOP_get_mem_access 13
+
+#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
+
+#define HVMOP_get_mem_type 15
+/* Return hvmmem_type_t for the specified pfn. */
+struct xen_hvm_get_mem_type {
+ /* Domain to be queried. */
+ domid_t domid;
+ /* OUT variable. */
+ uint16_t mem_type;
+ uint16_t pad[2]; /* align next field on 8-byte boundary */
+ /* IN variable. */
+ uint64_t pfn;
+};
+typedef struct xen_hvm_get_mem_type xen_hvm_get_mem_type_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_mem_type_t);
+
+/* Following tools-only interfaces may change in future. */
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+
+/*
+ * Definitions relating to DMOP_create_ioreq_server. (Defined here for
+ * backwards compatibility).
+ */
+
+#define HVM_IOREQSRV_BUFIOREQ_OFF 0
+#define HVM_IOREQSRV_BUFIOREQ_LEGACY 1
+/*
+ * Use this when read_pointer gets updated atomically and
+ * the pointer pair gets read atomically:
+ */
+#define HVM_IOREQSRV_BUFIOREQ_ATOMIC 2
+
+#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
+
+#if defined(__i386__) || defined(__x86_64__)
+
+/*
+ * HVMOP_set_evtchn_upcall_vector: Set a <vector> that should be used for event
+ * channel upcalls on the specified <vcpu>. If set,
+ * this vector will be used in preference to the
+ * domain global callback via (see
+ * HVM_PARAM_CALLBACK_IRQ).
+ */
+#define HVMOP_set_evtchn_upcall_vector 23
+struct xen_hvm_evtchn_upcall_vector {
+ uint32_t vcpu;
+ uint8_t vector;
+};
+typedef struct xen_hvm_evtchn_upcall_vector xen_hvm_evtchn_upcall_vector_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_evtchn_upcall_vector_t);
+
+#endif /* defined(__i386__) || defined(__x86_64__) */
+
+#define HVMOP_guest_request_vm_event 24
+
+/* HVMOP_altp2m: perform altp2m state operations */
+#define HVMOP_altp2m 25
+
+#define HVMOP_ALTP2M_INTERFACE_VERSION 0x00000001
+
+struct xen_hvm_altp2m_domain_state {
+ /* IN or OUT variable on/off */
+ uint8_t state;
+};
+typedef struct xen_hvm_altp2m_domain_state xen_hvm_altp2m_domain_state_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_altp2m_domain_state_t);
+
+struct xen_hvm_altp2m_vcpu_enable_notify {
+ uint32_t vcpu_id;
+ uint32_t pad;
+ /* #VE info area gfn */
+ uint64_t gfn;
+};
+typedef struct xen_hvm_altp2m_vcpu_enable_notify xen_hvm_altp2m_vcpu_enable_notify_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_altp2m_vcpu_enable_notify_t);
+
+struct xen_hvm_altp2m_vcpu_disable_notify {
+ uint32_t vcpu_id;
+};
+typedef struct xen_hvm_altp2m_vcpu_disable_notify xen_hvm_altp2m_vcpu_disable_notify_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_altp2m_vcpu_disable_notify_t);
+
+struct xen_hvm_altp2m_view {
+ /* IN/OUT variable */
+ uint16_t view;
+ uint16_t hvmmem_default_access; /* xenmem_access_t */
+};
+typedef struct xen_hvm_altp2m_view xen_hvm_altp2m_view_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_altp2m_view_t);
+
+#if __XEN_INTERFACE_VERSION__ < 0x00040a00
+struct xen_hvm_altp2m_set_mem_access {
+ /* view */
+ uint16_t view;
+ /* Memory type */
+ uint16_t access; /* xenmem_access_t */
+ uint32_t pad;
+ /* gfn */
+ uint64_t gfn;
+};
+typedef struct xen_hvm_altp2m_set_mem_access xen_hvm_altp2m_set_mem_access_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_altp2m_set_mem_access_t);
+#endif /* __XEN_INTERFACE_VERSION__ < 0x00040a00 */
+
+struct xen_hvm_altp2m_mem_access {
+ /* view */
+ uint16_t view;
+ /* Memory type */
+ uint16_t access; /* xenmem_access_t */
+ uint32_t pad;
+ /* gfn */
+ uint64_t gfn;
+};
+typedef struct xen_hvm_altp2m_mem_access xen_hvm_altp2m_mem_access_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_altp2m_mem_access_t);
+
+struct xen_hvm_altp2m_set_mem_access_multi {
+ /* view */
+ uint16_t view;
+ uint16_t pad;
+ /* Number of pages */
+ uint32_t nr;
+ /*
+ * Used for continuation purposes.
+ * Must be set to zero upon initial invocation.
+ */
+ uint64_t opaque;
+ /* List of pfns to set access for */
+ XEN_GUEST_HANDLE(const_uint64) pfn_list;
+ /* Corresponding list of access settings for pfn_list */
+ XEN_GUEST_HANDLE(const_uint8) access_list;
+};
+
+struct xen_hvm_altp2m_change_gfn {
+ /* view */
+ uint16_t view;
+ uint16_t pad1;
+ uint32_t pad2;
+ /* old gfn */
+ uint64_t old_gfn;
+ /* new gfn, INVALID_GFN (~0UL) means revert */
+ uint64_t new_gfn;
+};
+typedef struct xen_hvm_altp2m_change_gfn xen_hvm_altp2m_change_gfn_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_altp2m_change_gfn_t);
+
+struct xen_hvm_altp2m_get_vcpu_p2m_idx {
+ uint32_t vcpu_id;
+ uint16_t altp2m_idx;
+};
+
+struct xen_hvm_altp2m_set_visibility {
+ uint16_t altp2m_idx;
+ uint8_t visible;
+ uint8_t pad;
+};
+
+struct xen_hvm_altp2m_op {
+ uint32_t version; /* HVMOP_ALTP2M_INTERFACE_VERSION */
+ uint32_t cmd;
+/* Get/set the altp2m state for a domain */
+#define HVMOP_altp2m_get_domain_state 1
+#define HVMOP_altp2m_set_domain_state 2
+/* Set a given VCPU to receive altp2m event notifications */
+#define HVMOP_altp2m_vcpu_enable_notify 3
+/* Create a new view */
+#define HVMOP_altp2m_create_p2m 4
+/* Destroy a view */
+#define HVMOP_altp2m_destroy_p2m 5
+/* Switch view for an entire domain */
+#define HVMOP_altp2m_switch_p2m 6
+/* Notify that a page of memory is to have specific access types */
+#define HVMOP_altp2m_set_mem_access 7
+/* Change a p2m entry to have a different gfn->mfn mapping */
+#define HVMOP_altp2m_change_gfn 8
+/* Set access for an array of pages */
+#define HVMOP_altp2m_set_mem_access_multi 9
+/* Set the "Suppress #VE" bit on a page */
+#define HVMOP_altp2m_set_suppress_ve 10
+/* Get the "Suppress #VE" bit of a page */
+#define HVMOP_altp2m_get_suppress_ve 11
+/* Get the access of a page of memory from a certain view */
+#define HVMOP_altp2m_get_mem_access 12
+/* Disable altp2m event notifications for a given VCPU */
+#define HVMOP_altp2m_vcpu_disable_notify 13
+/* Get the active vcpu p2m index */
+#define HVMOP_altp2m_get_p2m_idx 14
+/* Set the "Supress #VE" bit for a range of pages */
+#define HVMOP_altp2m_set_suppress_ve_multi 15
+/* Set visibility for a given altp2m view */
+#define HVMOP_altp2m_set_visibility 16
+ domid_t domain;
+ uint16_t pad1;
+ uint32_t pad2;
+ union {
+ struct xen_hvm_altp2m_domain_state domain_state;
+ struct xen_hvm_altp2m_vcpu_enable_notify enable_notify;
+ struct xen_hvm_altp2m_view view;
+#if __XEN_INTERFACE_VERSION__ < 0x00040a00
+ struct xen_hvm_altp2m_set_mem_access set_mem_access;
+#endif /* __XEN_INTERFACE_VERSION__ < 0x00040a00 */
+ struct xen_hvm_altp2m_mem_access mem_access;
+ struct xen_hvm_altp2m_change_gfn change_gfn;
+ struct xen_hvm_altp2m_set_mem_access_multi set_mem_access_multi;
+ struct xen_hvm_altp2m_suppress_ve suppress_ve;
+ struct xen_hvm_altp2m_suppress_ve_multi suppress_ve_multi;
+ struct xen_hvm_altp2m_vcpu_disable_notify disable_notify;
+ struct xen_hvm_altp2m_get_vcpu_p2m_idx get_vcpu_p2m_idx;
+ struct xen_hvm_altp2m_set_visibility set_visibility;
+ uint8_t pad[64];
+ } u;
+};
+typedef struct xen_hvm_altp2m_op xen_hvm_altp2m_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_altp2m_op_t);
+
+#endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/hw/xen/interface/hvm/params.h b/include/hw/xen/interface/hvm/params.h
new file mode 100644
index 0000000000..a22b4ed45d
--- /dev/null
+++ b/include/hw/xen/interface/hvm/params.h
@@ -0,0 +1,301 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (c) 2007, Keir Fraser
+ */
+
+#ifndef __XEN_PUBLIC_HVM_PARAMS_H__
+#define __XEN_PUBLIC_HVM_PARAMS_H__
+
+#include "hvm_op.h"
+
+/* These parameters are deprecated and their meaning is undefined. */
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+
+#define HVM_PARAM_PAE_ENABLED 4
+#define HVM_PARAM_DM_DOMAIN 13
+#define HVM_PARAM_MEMORY_EVENT_CR0 20
+#define HVM_PARAM_MEMORY_EVENT_CR3 21
+#define HVM_PARAM_MEMORY_EVENT_CR4 22
+#define HVM_PARAM_MEMORY_EVENT_INT3 23
+#define HVM_PARAM_NESTEDHVM 24
+#define HVM_PARAM_MEMORY_EVENT_SINGLE_STEP 25
+#define HVM_PARAM_BUFIOREQ_EVTCHN 26
+#define HVM_PARAM_MEMORY_EVENT_MSR 30
+
+#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
+
+/*
+ * Parameter space for HVMOP_{set,get}_param.
+ */
+
+#define HVM_PARAM_CALLBACK_IRQ 0
+#define HVM_PARAM_CALLBACK_IRQ_TYPE_MASK xen_mk_ullong(0xFF00000000000000)
+/*
+ * How should CPU0 event-channel notifications be delivered?
+ *
+ * If val == 0 then CPU0 event-channel notifications are not delivered.
+ * If val != 0, val[63:56] encodes the type, as follows:
+ */
+
+#define HVM_PARAM_CALLBACK_TYPE_GSI 0
+/*
+ * val[55:0] is a delivery GSI. GSI 0 cannot be used, as it aliases val == 0,
+ * and disables all notifications.
+ */
+
+#define HVM_PARAM_CALLBACK_TYPE_PCI_INTX 1
+/*
+ * val[55:0] is a delivery PCI INTx line:
+ * Domain = val[47:32], Bus = val[31:16] DevFn = val[15:8], IntX = val[1:0]
+ */
+
+#if defined(__i386__) || defined(__x86_64__)
+#define HVM_PARAM_CALLBACK_TYPE_VECTOR 2
+/*
+ * val[7:0] is a vector number. Check for XENFEAT_hvm_callback_vector to know
+ * if this delivery method is available.
+ */
+#elif defined(__arm__) || defined(__aarch64__)
+#define HVM_PARAM_CALLBACK_TYPE_PPI 2
+/*
+ * val[55:16] needs to be zero.
+ * val[15:8] is interrupt flag of the PPI used by event-channel:
+ * bit 8: the PPI is edge(1) or level(0) triggered
+ * bit 9: the PPI is active low(1) or high(0)
+ * val[7:0] is a PPI number used by event-channel.
+ * This is only used by ARM/ARM64 and masking/eoi the interrupt associated to
+ * the notification is handled by the interrupt controller.
+ */
+#define HVM_PARAM_CALLBACK_TYPE_PPI_FLAG_MASK 0xFF00
+#define HVM_PARAM_CALLBACK_TYPE_PPI_FLAG_LOW_LEVEL 2
+#endif
+
+/*
+ * These are not used by Xen. They are here for convenience of HVM-guest
+ * xenbus implementations.
+ */
+#define HVM_PARAM_STORE_PFN 1
+#define HVM_PARAM_STORE_EVTCHN 2
+
+#define HVM_PARAM_IOREQ_PFN 5
+
+#define HVM_PARAM_BUFIOREQ_PFN 6
+
+#if defined(__i386__) || defined(__x86_64__)
+
+/*
+ * Viridian enlightenments
+ *
+ * (See http://download.microsoft.com/download/A/B/4/AB43A34E-BDD0-4FA6-BDEF-79EEF16E880B/Hypervisor%20Top%20Level%20Functional%20Specification%20v4.0.docx)
+ *
+ * To expose viridian enlightenments to the guest set this parameter
+ * to the desired feature mask. The base feature set must be present
+ * in any valid feature mask.
+ */
+#define HVM_PARAM_VIRIDIAN 9
+
+/* Base+Freq viridian feature sets:
+ *
+ * - Hypercall MSRs (HV_X64_MSR_GUEST_OS_ID and HV_X64_MSR_HYPERCALL)
+ * - APIC access MSRs (HV_X64_MSR_EOI, HV_X64_MSR_ICR and HV_X64_MSR_TPR)
+ * - Virtual Processor index MSR (HV_X64_MSR_VP_INDEX)
+ * - Timer frequency MSRs (HV_X64_MSR_TSC_FREQUENCY and
+ * HV_X64_MSR_APIC_FREQUENCY)
+ */
+#define _HVMPV_base_freq 0
+#define HVMPV_base_freq (1 << _HVMPV_base_freq)
+
+/* Feature set modifications */
+
+/* Disable timer frequency MSRs (HV_X64_MSR_TSC_FREQUENCY and
+ * HV_X64_MSR_APIC_FREQUENCY).
+ * This modification restores the viridian feature set to the
+ * original 'base' set exposed in releases prior to Xen 4.4.
+ */
+#define _HVMPV_no_freq 1
+#define HVMPV_no_freq (1 << _HVMPV_no_freq)
+
+/* Enable Partition Time Reference Counter (HV_X64_MSR_TIME_REF_COUNT) */
+#define _HVMPV_time_ref_count 2
+#define HVMPV_time_ref_count (1 << _HVMPV_time_ref_count)
+
+/* Enable Reference TSC Page (HV_X64_MSR_REFERENCE_TSC) */
+#define _HVMPV_reference_tsc 3
+#define HVMPV_reference_tsc (1 << _HVMPV_reference_tsc)
+
+/* Use Hypercall for remote TLB flush */
+#define _HVMPV_hcall_remote_tlb_flush 4
+#define HVMPV_hcall_remote_tlb_flush (1 << _HVMPV_hcall_remote_tlb_flush)
+
+/* Use APIC assist */
+#define _HVMPV_apic_assist 5
+#define HVMPV_apic_assist (1 << _HVMPV_apic_assist)
+
+/* Enable crash MSRs */
+#define _HVMPV_crash_ctl 6
+#define HVMPV_crash_ctl (1 << _HVMPV_crash_ctl)
+
+/* Enable SYNIC MSRs */
+#define _HVMPV_synic 7
+#define HVMPV_synic (1 << _HVMPV_synic)
+
+/* Enable STIMER MSRs */
+#define _HVMPV_stimer 8
+#define HVMPV_stimer (1 << _HVMPV_stimer)
+
+/* Use Synthetic Cluster IPI Hypercall */
+#define _HVMPV_hcall_ipi 9
+#define HVMPV_hcall_ipi (1 << _HVMPV_hcall_ipi)
+
+/* Enable ExProcessorMasks */
+#define _HVMPV_ex_processor_masks 10
+#define HVMPV_ex_processor_masks (1 << _HVMPV_ex_processor_masks)
+
+/* Allow more than 64 VPs */
+#define _HVMPV_no_vp_limit 11
+#define HVMPV_no_vp_limit (1 << _HVMPV_no_vp_limit)
+
+/* Enable vCPU hotplug */
+#define _HVMPV_cpu_hotplug 12
+#define HVMPV_cpu_hotplug (1 << _HVMPV_cpu_hotplug)
+
+#define HVMPV_feature_mask \
+ (HVMPV_base_freq | \
+ HVMPV_no_freq | \
+ HVMPV_time_ref_count | \
+ HVMPV_reference_tsc | \
+ HVMPV_hcall_remote_tlb_flush | \
+ HVMPV_apic_assist | \
+ HVMPV_crash_ctl | \
+ HVMPV_synic | \
+ HVMPV_stimer | \
+ HVMPV_hcall_ipi | \
+ HVMPV_ex_processor_masks | \
+ HVMPV_no_vp_limit | \
+ HVMPV_cpu_hotplug)
+
+#endif
+
+/*
+ * Set mode for virtual timers (currently x86 only):
+ * delay_for_missed_ticks (default):
+ * Do not advance a vcpu's time beyond the correct delivery time for
+ * interrupts that have been missed due to preemption. Deliver missed
+ * interrupts when the vcpu is rescheduled and advance the vcpu's virtual
+ * time stepwise for each one.
+ * no_delay_for_missed_ticks:
+ * As above, missed interrupts are delivered, but guest time always tracks
+ * wallclock (i.e., real) time while doing so.
+ * no_missed_ticks_pending:
+ * No missed interrupts are held pending. Instead, to ensure ticks are
+ * delivered at some non-zero rate, if we detect missed ticks then the
+ * internal tick alarm is not disabled if the VCPU is preempted during the
+ * next tick period.
+ * one_missed_tick_pending:
+ * Missed interrupts are collapsed together and delivered as one 'late tick'.
+ * Guest time always tracks wallclock (i.e., real) time.
+ */
+#define HVM_PARAM_TIMER_MODE 10
+#define HVMPTM_delay_for_missed_ticks 0
+#define HVMPTM_no_delay_for_missed_ticks 1
+#define HVMPTM_no_missed_ticks_pending 2
+#define HVMPTM_one_missed_tick_pending 3
+
+/* Boolean: Enable virtual HPET (high-precision event timer)? (x86-only) */
+#define HVM_PARAM_HPET_ENABLED 11
+
+/* Identity-map page directory used by Intel EPT when CR0.PG=0. */
+#define HVM_PARAM_IDENT_PT 12
+
+/* ACPI S state: currently support S0 and S3 on x86. */
+#define HVM_PARAM_ACPI_S_STATE 14
+
+/* TSS used on Intel when CR0.PE=0. */
+#define HVM_PARAM_VM86_TSS 15
+
+/* Boolean: Enable aligning all periodic vpts to reduce interrupts */
+#define HVM_PARAM_VPT_ALIGN 16
+
+/* Console debug shared memory ring and event channel */
+#define HVM_PARAM_CONSOLE_PFN 17
+#define HVM_PARAM_CONSOLE_EVTCHN 18
+
+/*
+ * Select location of ACPI PM1a and TMR control blocks. Currently two locations
+ * are supported, specified by version 0 or 1 in this parameter:
+ * - 0: default, use the old addresses
+ * PM1A_EVT == 0x1f40; PM1A_CNT == 0x1f44; PM_TMR == 0x1f48
+ * - 1: use the new default qemu addresses
+ * PM1A_EVT == 0xb000; PM1A_CNT == 0xb004; PM_TMR == 0xb008
+ * You can find these address definitions in <hvm/ioreq.h>
+ */
+#define HVM_PARAM_ACPI_IOPORTS_LOCATION 19
+
+/* Params for the mem event rings */
+#define HVM_PARAM_PAGING_RING_PFN 27
+#define HVM_PARAM_MONITOR_RING_PFN 28
+#define HVM_PARAM_SHARING_RING_PFN 29
+
+/* SHUTDOWN_* action in case of a triple fault */
+#define HVM_PARAM_TRIPLE_FAULT_REASON 31
+
+#define HVM_PARAM_IOREQ_SERVER_PFN 32
+#define HVM_PARAM_NR_IOREQ_SERVER_PAGES 33
+
+/* Location of the VM Generation ID in guest physical address space. */
+#define HVM_PARAM_VM_GENERATION_ID_ADDR 34
+
+/*
+ * Set mode for altp2m:
+ * disabled: don't activate altp2m (default)
+ * mixed: allow access to all altp2m ops for both in-guest and external tools
+ * external: allow access to external privileged tools only
+ * limited: guest only has limited access (ie. control VMFUNC and #VE)
+ *
+ * Note that 'mixed' mode has not been evaluated for safety from a
+ * security perspective. Before using this mode in a
+ * security-critical environment, each subop should be evaluated for
+ * safety, with unsafe subops blacklisted in XSM.
+ */
+#define HVM_PARAM_ALTP2M 35
+#define XEN_ALTP2M_disabled 0
+#define XEN_ALTP2M_mixed 1
+#define XEN_ALTP2M_external 2
+#define XEN_ALTP2M_limited 3
+
+/*
+ * Size of the x87 FPU FIP/FDP registers that the hypervisor needs to
+ * save/restore. This is a workaround for a hardware limitation that
+ * does not allow the full FIP/FDP and FCS/FDS to be restored.
+ *
+ * Valid values are:
+ *
+ * 8: save/restore 64-bit FIP/FDP and clear FCS/FDS (default if CPU
+ * has FPCSDS feature).
+ *
+ * 4: save/restore 32-bit FIP/FDP, FCS/FDS, and clear upper 32-bits of
+ * FIP/FDP.
+ *
+ * 0: allow hypervisor to choose based on the value of FIP/FDP
+ * (default if CPU does not have FPCSDS).
+ *
+ * If FPCSDS (bit 13 in CPUID leaf 0x7, subleaf 0x0) is set, the CPU
+ * never saves FCS/FDS and this parameter should be left at the
+ * default of 8.
+ */
+#define HVM_PARAM_X87_FIP_WIDTH 36
+
+/*
+ * TSS (and its size) used on Intel when CR0.PE=0. The address occupies
+ * the low 32 bits, while the size is in the high 32 ones.
+ */
+#define HVM_PARAM_VM86_TSS_SIZED 37
+
+/* Enable MCA capabilities. */
+#define HVM_PARAM_MCA_CAP 38
+#define XEN_HVM_MCA_CAP_LMCE (xen_mk_ullong(1) << 0)
+#define XEN_HVM_MCA_CAP_MASK XEN_HVM_MCA_CAP_LMCE
+
+#define HVM_NR_PARAMS 39
+
+#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
diff --git a/include/hw/xen/interface/io/blkif.h b/include/hw/xen/interface/io/blkif.h
index d07fa1e078..22f1eef0c0 100644
--- a/include/hw/xen/interface/io/blkif.h
+++ b/include/hw/xen/interface/io/blkif.h
@@ -1,26 +1,9 @@
+/* SPDX-License-Identifier: MIT */
/******************************************************************************
* blkif.h
*
* Unified block-device I/O interface for Xen guest OSes.
*
- * 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.
- *
* Copyright (c) 2003-2004, Keir Fraser
* Copyright (c) 2012, Spectra Logic Corporation
*/
@@ -118,7 +101,7 @@
*
* The underlying storage is not affected by the direct IO memory
* lifetime bug. See:
- * http://lists.xen.org/archives/html/xen-devel/2012-12/msg01154.html
+ * https://lists.xen.org/archives/html/xen-devel/2012-12/msg01154.html
*
* Therefore this option gives the backend permission to use
* O_DIRECT, notwithstanding that bug.
@@ -341,7 +324,7 @@
* access (even when it should be read-only). If the frontend hits the
* maximum number of allowed persistently mapped grants, it can fallback
* to non persistent mode. This will cause a performance degradation,
- * since the backend driver will still try to map those grants
+ * since the the backend driver will still try to map those grants
* persistently. Since the persistent grants protocol is compatible with
* the previous protocol, a frontend driver can choose to work in
* persistent mode even when the backend doesn't support it.
@@ -363,6 +346,14 @@
* that the frontend requires that the logical block size is 512 as it
* is hardcoded (which is the case in some frontend implementations).
*
+ * trusted
+ * Values: 0/1 (boolean)
+ * Default value: 1
+ *
+ * A value of "0" indicates that the frontend should not trust the
+ * backend, and should deploy whatever measures available to protect from
+ * a malicious backend on the other end.
+ *
*------------------------- Virtual Device Properties -------------------------
*
* device-type
@@ -710,3 +701,13 @@ DEFINE_RING_TYPES(blkif, struct blkif_request, struct blkif_response);
#define VDISK_READONLY 0x4
#endif /* __XEN_PUBLIC_IO_BLKIF_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/hw/xen/interface/io/console.h b/include/hw/xen/interface/io/console.h
index e2155d1cf5..4509b4b689 100644
--- a/include/hw/xen/interface/io/console.h
+++ b/include/hw/xen/interface/io/console.h
@@ -1,26 +1,9 @@
+/* SPDX-License-Identifier: MIT */
/******************************************************************************
* console.h
*
* Console I/O interface for Xen guest OSes.
*
- * 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.
- *
* Copyright (c) 2005, Keir Fraser
*/
@@ -44,3 +27,13 @@ DEFINE_XEN_FLEX_RING(xencons);
#endif
#endif /* __XEN_PUBLIC_IO_CONSOLE_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/hw/xen/interface/io/fbif.h b/include/hw/xen/interface/io/fbif.h
index ea87ebec0a..93c73195d8 100644
--- a/include/hw/xen/interface/io/fbif.h
+++ b/include/hw/xen/interface/io/fbif.h
@@ -1,24 +1,7 @@
+/* SPDX-License-Identifier: MIT */
/*
* fbif.h -- Xen virtual frame buffer device
*
- * 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.
- *
* Copyright (C) 2005 Anthony Liguori <aliguori@us.ibm.com>
* Copyright (C) 2006 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
*/
@@ -153,4 +136,24 @@ struct xenfb_page
unsigned long pd[256];
};
+/*
+ * Wart: xenkbd needs to know default resolution. Put it here until a
+ * better solution is found, but don't leak it to the backend.
+ */
+#ifdef __KERNEL__
+#define XENFB_WIDTH 800
+#define XENFB_HEIGHT 600
+#define XENFB_DEPTH 32
+#endif
+
#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/hw/xen/interface/io/kbdif.h b/include/hw/xen/interface/io/kbdif.h
index 1d68cd458e..4bde6b3821 100644
--- a/include/hw/xen/interface/io/kbdif.h
+++ b/include/hw/xen/interface/io/kbdif.h
@@ -1,24 +1,7 @@
+/* SPDX-License-Identifier: MIT */
/*
* kbdif.h -- Xen virtual keyboard/mouse
*
- * 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.
- *
* Copyright (C) 2005 Anthony Liguori <aliguori@us.ibm.com>
* Copyright (C) 2006 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
*/
@@ -564,3 +547,13 @@ struct xenkbd_page
};
#endif /* __XEN_PUBLIC_IO_KBDIF_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/hw/xen/interface/io/netif.h b/include/hw/xen/interface/io/netif.h
index 48fa530950..c13b85061d 100644
--- a/include/hw/xen/interface/io/netif.h
+++ b/include/hw/xen/interface/io/netif.h
@@ -1,26 +1,9 @@
+/* SPDX-License-Identifier: MIT */
/******************************************************************************
* netif.h
*
* Unified network-device I/O interface for Xen guest OSes.
*
- * 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.
- *
* Copyright (c) 2003-2004, Keir Fraser
*/
@@ -161,6 +144,12 @@
*/
/*
+ * The setting of "trusted" node to "0" in the frontend path signals that the
+ * frontend should not trust the backend, and should deploy whatever measures
+ * available to protect from a malicious backend on the other end.
+ */
+
+/*
* Control ring
* ============
*
@@ -171,7 +160,7 @@
* The ability of the backend to use a control ring is advertised by
* setting:
*
- * /local/domain/X/backend/<domid>/<vif>/feature-ctrl-ring = "1"
+ * /local/domain/X/backend/vif/<domid>/<vif>/feature-ctrl-ring = "1"
*
* The frontend provides a control ring to the backend by setting:
*
@@ -191,6 +180,32 @@
*/
/*
+ * Link state
+ * ==========
+ *
+ * The backend can advertise its current link (carrier) state to the
+ * frontend using the /local/domain/X/backend/vif/<domid>/<vif>/carrier
+ * node. If this node is not present, then the frontend should assume that
+ * the link is up (for compatibility with backends that do not implement
+ * this feature). If this node is present, then a value of "0" should be
+ * interpreted by the frontend as the link being down (no carrier) and a
+ * value of "1" should be interpreted as the link being up (carrier
+ * present).
+ */
+
+/*
+ * MTU
+ * ===
+ *
+ * The toolstack may set a value of MTU for the frontend by setting the
+ * /local/domain/<domid>/device/vif/<vif>/mtu node with the MTU value in
+ * octets. If this node is absent the frontend should assume an MTU value
+ * of 1500 octets. A frontend is also at liberty to ignore this value so
+ * it is only suitable for informing the frontend that a packet payload
+ * >1500 octets is permitted.
+ */
+
+/*
* Hash types
* ==========
*
@@ -268,6 +283,62 @@
#define XEN_NETIF_CTRL_HASH_ALGORITHM_TOEPLITZ 1
/*
+ * This algorithm uses a 'key' as well as the data buffer itself.
+ * (Buffer[] and Key[] are treated as shift-registers where the MSB of
+ * Buffer/Key[0] is considered 'left-most' and the LSB of Buffer/Key[N-1]
+ * is the 'right-most').
+ *
+ * Value = 0
+ * For number of bits in Buffer[]
+ * If (left-most bit of Buffer[] is 1)
+ * Value ^= left-most 32 bits of Key[]
+ * Key[] << 1
+ * Buffer[] << 1
+ *
+ * The code below is provided for convenience where an operating system
+ * does not already provide an implementation.
+ */
+#ifdef XEN_NETIF_DEFINE_TOEPLITZ
+static uint32_t xen_netif_toeplitz_hash(const uint8_t *key,
+ unsigned int keylen,
+ const uint8_t *buf,
+ unsigned int buflen)
+{
+ unsigned int keyi, bufi;
+ uint64_t prefix = 0;
+ uint64_t hash = 0;
+
+ /* Pre-load prefix with the first 8 bytes of the key */
+ for (keyi = 0; keyi < 8; keyi++) {
+ prefix <<= 8;
+ prefix |= (keyi < keylen) ? key[keyi] : 0;
+ }
+
+ for (bufi = 0; bufi < buflen; bufi++) {
+ uint8_t byte = buf[bufi];
+ unsigned int bit;
+
+ for (bit = 0; bit < 8; bit++) {
+ if (byte & 0x80)
+ hash ^= prefix;
+ prefix <<= 1;
+ byte <<=1;
+ }
+
+ /*
+ * 'prefix' has now been left-shifted by 8, so
+ * OR in the next byte.
+ */
+ prefix |= (keyi < keylen) ? key[keyi] : 0;
+ keyi++;
+ }
+
+ /* The valid part of the hash is in the upper 32 bits. */
+ return hash >> 32;
+}
+#endif /* XEN_NETIF_DEFINE_TOEPLITZ */
+
+/*
* Control requests (struct xen_netif_ctrl_request)
* ================================================
*
@@ -1008,3 +1079,13 @@ DEFINE_RING_TYPES(netif_rx, struct netif_rx_request, struct netif_rx_response);
#define NETIF_RSP_NULL 1
#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/hw/xen/interface/io/protocols.h b/include/hw/xen/interface/io/protocols.h
index 52b4de0f81..7815e1ff0f 100644
--- a/include/hw/xen/interface/io/protocols.h
+++ b/include/hw/xen/interface/io/protocols.h
@@ -1,24 +1,7 @@
+/* SPDX-License-Identifier: MIT */
/******************************************************************************
* protocols.h
*
- * 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.
- *
* Copyright (c) 2008, Keir Fraser
*/
diff --git a/include/hw/xen/interface/io/ring.h b/include/hw/xen/interface/io/ring.h
index 5d048b335c..025939278b 100644
--- a/include/hw/xen/interface/io/ring.h
+++ b/include/hw/xen/interface/io/ring.h
@@ -1,25 +1,8 @@
+/* SPDX-License-Identifier: MIT */
/******************************************************************************
* ring.h
- *
- * Shared producer-consumer ring macros.
- *
- * 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.
+ * Shared producer-consumer ring macros.
*
* Tim Deegan and Andrew Warfield November 2004.
*/
@@ -33,13 +16,6 @@
* - standard integers types (uint8_t, uint16_t, etc)
* They are provided by stdint.h of the standard headers.
*
- * Before using the different macros, you need to provide the following
- * macros:
- * - xen_mb() a memory barrier
- * - xen_rmb() a read memory barrier
- * - xen_wmb() a write memory barrier
- * Example of those can be found in xenctrl.h.
- *
* In addition, if you intend to use the FLEX macros, you also need to
* provide the following, before invoking the FLEX macros:
* - size_t
@@ -49,6 +25,14 @@
* and grant_table.h from the Xen public headers.
*/
+#include "../xen-compat.h"
+
+#if __XEN_INTERFACE_VERSION__ < 0x00030208
+#define xen_mb() mb()
+#define xen_rmb() rmb()
+#define xen_wmb() wmb()
+#endif
+
typedef unsigned int RING_IDX;
/* Round a 32-bit unsigned constant down to the nearest power of two. */
@@ -61,12 +45,12 @@ typedef unsigned int RING_IDX;
/*
* Calculate size of a shared ring, given the total available space for the
* ring and indexes (_sz), and the name tag of the request/response structure.
- * A ring contains as many entries as will fit, rounded down to the nearest
+ * A ring contains as many entries as will fit, rounded down to the nearest
* power of two (so we can mask with (size-1) to loop around).
*/
#define __CONST_RING_SIZE(_s, _sz) \
(__RD32(((_sz) - offsetof(struct _s##_sring, ring)) / \
- sizeof_field(struct _s##_sring, ring[0])))
+ sizeof(((struct _s##_sring *)0)->ring[0])))
/*
* The same for passing in an actual pointer instead of a name tag.
*/
@@ -75,7 +59,7 @@ typedef unsigned int RING_IDX;
/*
* Macros to make the correct C datatypes for a new kind of ring.
- *
+ *
* To make a new ring datatype, you need to have two message structures,
* let's say request_t, and response_t already defined.
*
@@ -85,7 +69,7 @@ typedef unsigned int RING_IDX;
*
* These expand out to give you a set of types, as you can see below.
* The most important of these are:
- *
+ *
* mytag_sring_t - The shared ring.
* mytag_front_ring_t - The 'front' half of the ring.
* mytag_back_ring_t - The 'back' half of the ring.
@@ -94,9 +78,8 @@ typedef unsigned int RING_IDX;
* of the shared memory area (PAGE_SIZE, for instance). To initialise
* the front half:
*
- * mytag_front_ring_t front_ring;
- * SHARED_RING_INIT((mytag_sring_t *)shared_page);
- * FRONT_RING_INIT(&front_ring, (mytag_sring_t *)shared_page, PAGE_SIZE);
+ * mytag_front_ring_t ring;
+ * XEN_FRONT_RING_INIT(&ring, (mytag_sring_t *)shared_page, PAGE_SIZE);
*
* Initializing the back follows similarly (note that only the front
* initializes the shared ring):
@@ -153,15 +136,15 @@ typedef struct __name##_back_ring __name##_back_ring_t
/*
* Macros for manipulating rings.
- *
- * FRONT_RING_whatever works on the "front end" of a ring: here
+ *
+ * FRONT_RING_whatever works on the "front end" of a ring: here
* requests are pushed on to the ring and responses taken off it.
- *
- * BACK_RING_whatever works on the "back end" of a ring: here
+ *
+ * BACK_RING_whatever works on the "back end" of a ring: here
* requests are taken off the ring and responses put on.
- *
- * N.B. these macros do NO INTERLOCKS OR FLOW CONTROL.
- * This is OK in 1-for-1 request-response situations where the
+ *
+ * N.B. these macros do NO INTERLOCKS OR FLOW CONTROL.
+ * This is OK in 1-for-1 request-response situations where the
* requestor (front end) never has more than RING_SIZE()-1
* outstanding requests.
*/
@@ -174,20 +157,29 @@ typedef struct __name##_back_ring __name##_back_ring_t
(void)memset((_s)->__pad, 0, sizeof((_s)->__pad)); \
} while(0)
-#define FRONT_RING_INIT(_r, _s, __size) do { \
- (_r)->req_prod_pvt = 0; \
- (_r)->rsp_cons = 0; \
+#define FRONT_RING_ATTACH(_r, _s, _i, __size) do { \
+ (_r)->req_prod_pvt = (_i); \
+ (_r)->rsp_cons = (_i); \
(_r)->nr_ents = __RING_SIZE(_s, __size); \
(_r)->sring = (_s); \
} while (0)
-#define BACK_RING_INIT(_r, _s, __size) do { \
- (_r)->rsp_prod_pvt = 0; \
- (_r)->req_cons = 0; \
+#define FRONT_RING_INIT(_r, _s, __size) FRONT_RING_ATTACH(_r, _s, 0, __size)
+
+#define XEN_FRONT_RING_INIT(r, s, size) do { \
+ SHARED_RING_INIT(s); \
+ FRONT_RING_INIT(r, s, size); \
+} while (0)
+
+#define BACK_RING_ATTACH(_r, _s, _i, __size) do { \
+ (_r)->rsp_prod_pvt = (_i); \
+ (_r)->req_cons = (_i); \
(_r)->nr_ents = __RING_SIZE(_s, __size); \
(_r)->sring = (_s); \
} while (0)
+#define BACK_RING_INIT(_r, _s, __size) BACK_RING_ATTACH(_r, _s, 0, __size)
+
/* How big is this ring? */
#define RING_SIZE(_r) \
((_r)->nr_ents)
@@ -203,11 +195,11 @@ typedef struct __name##_back_ring __name##_back_ring_t
(RING_FREE_REQUESTS(_r) == 0)
/* Test if there are outstanding messages to be processed on a ring. */
-#define RING_HAS_UNCONSUMED_RESPONSES(_r) \
+#define XEN_RING_NR_UNCONSUMED_RESPONSES(_r) \
((_r)->sring->rsp_prod - (_r)->rsp_cons)
#ifdef __GNUC__
-#define RING_HAS_UNCONSUMED_REQUESTS(_r) ({ \
+#define XEN_RING_NR_UNCONSUMED_REQUESTS(_r) ({ \
unsigned int req = (_r)->sring->req_prod - (_r)->req_cons; \
unsigned int rsp = RING_SIZE(_r) - \
((_r)->req_cons - (_r)->rsp_prod_pvt); \
@@ -215,33 +207,50 @@ typedef struct __name##_back_ring __name##_back_ring_t
})
#else
/* Same as above, but without the nice GCC ({ ... }) syntax. */
-#define RING_HAS_UNCONSUMED_REQUESTS(_r) \
+#define XEN_RING_NR_UNCONSUMED_REQUESTS(_r) \
((((_r)->sring->req_prod - (_r)->req_cons) < \
(RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt))) ? \
((_r)->sring->req_prod - (_r)->req_cons) : \
(RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt)))
#endif
+#ifdef XEN_RING_HAS_UNCONSUMED_IS_BOOL
+/*
+ * These variants should only be used in case no caller is abusing them for
+ * obtaining the number of unconsumed responses/requests.
+ */
+#define RING_HAS_UNCONSUMED_RESPONSES(_r) \
+ (!!XEN_RING_NR_UNCONSUMED_RESPONSES(_r))
+#define RING_HAS_UNCONSUMED_REQUESTS(_r) \
+ (!!XEN_RING_NR_UNCONSUMED_REQUESTS(_r))
+#else
+#define RING_HAS_UNCONSUMED_RESPONSES(_r) XEN_RING_NR_UNCONSUMED_RESPONSES(_r)
+#define RING_HAS_UNCONSUMED_REQUESTS(_r) XEN_RING_NR_UNCONSUMED_REQUESTS(_r)
+#endif
+
/* Direct access to individual ring elements, by index. */
#define RING_GET_REQUEST(_r, _idx) \
(&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].req))
+#define RING_GET_RESPONSE(_r, _idx) \
+ (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].rsp))
+
/*
- * Get a local copy of a request.
+ * Get a local copy of a request/response.
*
- * Use this in preference to RING_GET_REQUEST() so all processing is
+ * Use this in preference to RING_GET_{REQUEST,RESPONSE}() so all processing is
* done on a local copy that cannot be modified by the other end.
*
* Note that https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58145 may cause this
- * to be ineffective where _req is a struct which consists of only bitfields.
+ * to be ineffective where dest is a struct which consists of only bitfields.
*/
-#define RING_COPY_REQUEST(_r, _idx, _req) do { \
- /* Use volatile to force the copy into _req. */ \
- *(_req) = *(volatile typeof(_req))RING_GET_REQUEST(_r, _idx); \
+#define RING_COPY_(type, r, idx, dest) do { \
+ /* Use volatile to force the copy into dest. */ \
+ *(dest) = *(volatile __typeof__(dest))RING_GET_##type(r, idx); \
} while (0)
-#define RING_GET_RESPONSE(_r, _idx) \
- (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].rsp))
+#define RING_COPY_REQUEST(r, idx, req) RING_COPY_(REQUEST, r, idx, req)
+#define RING_COPY_RESPONSE(r, idx, rsp) RING_COPY_(RESPONSE, r, idx, rsp)
/* Loop termination condition: Would the specified index overflow the ring? */
#define RING_REQUEST_CONS_OVERFLOW(_r, _cons) \
@@ -251,6 +260,10 @@ typedef struct __name##_back_ring __name##_back_ring_t
#define RING_REQUEST_PROD_OVERFLOW(_r, _prod) \
(((_prod) - (_r)->rsp_prod_pvt) > RING_SIZE(_r))
+/* Ill-behaved backend determination: Can there be this many responses? */
+#define RING_RESPONSE_PROD_OVERFLOW(_r, _prod) \
+ (((_prod) - (_r)->rsp_cons) > RING_SIZE(_r))
+
#define RING_PUSH_REQUESTS(_r) do { \
xen_wmb(); /* back sees requests /before/ updated producer index */ \
(_r)->sring->req_prod = (_r)->req_prod_pvt; \
@@ -263,26 +276,26 @@ typedef struct __name##_back_ring __name##_back_ring_t
/*
* Notification hold-off (req_event and rsp_event):
- *
+ *
* When queueing requests or responses on a shared ring, it may not always be
* necessary to notify the remote end. For example, if requests are in flight
* in a backend, the front may be able to queue further requests without
* notifying the back (if the back checks for new requests when it queues
* responses).
- *
+ *
* When enqueuing requests or responses:
- *
+ *
* Use RING_PUSH_{REQUESTS,RESPONSES}_AND_CHECK_NOTIFY(). The second argument
* is a boolean return value. True indicates that the receiver requires an
* asynchronous notification.
- *
+ *
* After dequeuing requests or responses (before sleeping the connection):
- *
+ *
* Use RING_FINAL_CHECK_FOR_REQUESTS() or RING_FINAL_CHECK_FOR_RESPONSES().
* The second argument is a boolean return value. True indicates that there
* are pending messages on the ring (i.e., the connection should not be put
* to sleep).
- *
+ *
* These macros will set the req_event/rsp_event field to trigger a
* notification on the very next message that is enqueued. If you want to
* create batches of work (i.e., only receive a notification after several
diff --git a/include/hw/xen/interface/io/usbif.h b/include/hw/xen/interface/io/usbif.h
index c6a58639d6..875af0dc7c 100644
--- a/include/hw/xen/interface/io/usbif.h
+++ b/include/hw/xen/interface/io/usbif.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: MIT */
/*
* usbif.h
*
@@ -5,24 +6,6 @@
*
* Copyright (C) 2009, FUJITSU LABORATORIES LTD.
* Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
- *
- * 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.
*/
#ifndef __XEN_PUBLIC_IO_USBIF_H__
@@ -32,6 +15,34 @@
#include "../grant_table.h"
/*
+ * Detailed Interface Description
+ * ==============================
+ * The pvUSB interface is using a split driver design: a frontend driver in
+ * the guest and a backend driver in a driver domain (normally dom0) having
+ * access to the physical USB device(s) being passed to the guest.
+ *
+ * The frontend and backend drivers use XenStore to initiate the connection
+ * between them, the I/O activity is handled via two shared ring pages and an
+ * event channel. As the interface between frontend and backend is at the USB
+ * host connector level, multiple (up to 31) physical USB devices can be
+ * handled by a single connection.
+ *
+ * The Xen pvUSB device name is "qusb", so the frontend's XenStore entries are
+ * to be found under "device/qusb", while the backend's XenStore entries are
+ * under "backend/<guest-dom-id>/qusb".
+ *
+ * When a new pvUSB connection is established, the frontend needs to setup the
+ * two shared ring pages for communication and the event channel. The ring
+ * pages need to be made available to the backend via the grant table
+ * interface.
+ *
+ * One of the shared ring pages is used by the backend to inform the frontend
+ * about USB device plug events (device to be added or removed). This is the
+ * "conn-ring".
+ *
+ * The other ring page is used for USB I/O communication (requests and
+ * responses). This is the "urb-ring".
+ *
* Feature and Parameter Negotiation
* =================================
* The two halves of a Xen pvUSB driver utilize nodes within the XenStore to
@@ -99,130 +110,273 @@
* The machine ABI rules governing the format of all ring request and
* response structures.
*
+ * Protocol Description
+ * ====================
+ *
+ *-------------------------- USB device plug events --------------------------
+ *
+ * USB device plug events are send via the "conn-ring" shared page. As only
+ * events are being sent, the respective requests from the frontend to the
+ * backend are just dummy ones.
+ * The events sent to the frontend have the following layout:
+ * 0 1 2 3 octet
+ * +----------------+----------------+----------------+----------------+
+ * | id | portnum | speed | 4
+ * +----------------+----------------+----------------+----------------+
+ * id - uint16_t, event id (taken from the actual frontend dummy request)
+ * portnum - uint8_t, port number (1 ... 31)
+ * speed - uint8_t, device USBIF_SPEED_*, USBIF_SPEED_NONE == unplug
+ *
+ * The dummy request:
+ * 0 1 octet
+ * +----------------+----------------+
+ * | id | 2
+ * +----------------+----------------+
+ * id - uint16_t, guest supplied value (no need for being unique)
+ *
+ *-------------------------- USB I/O request ---------------------------------
+ *
+ * A single USB I/O request on the "urb-ring" has the following layout:
+ * 0 1 2 3 octet
+ * +----------------+----------------+----------------+----------------+
+ * | id | nr_buffer_segs | 4
+ * +----------------+----------------+----------------+----------------+
+ * | pipe | 8
+ * +----------------+----------------+----------------+----------------+
+ * | transfer_flags | buffer_length | 12
+ * +----------------+----------------+----------------+----------------+
+ * | request type specific | 16
+ * | data | 20
+ * +----------------+----------------+----------------+----------------+
+ * | seg[0] | 24
+ * | data | 28
+ * +----------------+----------------+----------------+----------------+
+ * |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/|
+ * +----------------+----------------+----------------+----------------+
+ * | seg[USBIF_MAX_SEGMENTS_PER_REQUEST - 1] | 144
+ * | data | 148
+ * +----------------+----------------+----------------+----------------+
+ * Bit field bit number 0 is always least significant bit, undefined bits must
+ * be zero.
+ * id - uint16_t, guest supplied value
+ * nr_buffer_segs - uint16_t, number of segment entries in seg[] array
+ * pipe - uint32_t, bit field with multiple information:
+ * bits 0-4: port request to send to
+ * bit 5: unlink request with specified id (cancel I/O) if set (see below)
+ * bit 7: direction (1 = read from device)
+ * bits 8-14: device number on port
+ * bits 15-18: endpoint of device
+ * bits 30-31: request type: 00 = isochronous, 01 = interrupt,
+ * 10 = control, 11 = bulk
+ * transfer_flags - uint16_t, bit field with processing flags:
+ * bit 0: less data than specified allowed
+ * buffer_length - uint16_t, total length of data
+ * request type specific data - 8 bytes, see below
+ * seg[] - array with 8 byte elements, see below
+ *
+ * Request type specific data for isochronous request:
+ * 0 1 2 3 octet
+ * +----------------+----------------+----------------+----------------+
+ * | interval | start_frame | 4
+ * +----------------+----------------+----------------+----------------+
+ * | number_of_packets | nr_frame_desc_segs | 8
+ * +----------------+----------------+----------------+----------------+
+ * interval - uint16_t, time interval in msecs between frames
+ * start_frame - uint16_t, start frame number
+ * number_of_packets - uint16_t, number of packets to transfer
+ * nr_frame_desc_segs - uint16_t number of seg[] frame descriptors elements
+ *
+ * Request type specific data for interrupt request:
+ * 0 1 2 3 octet
+ * +----------------+----------------+----------------+----------------+
+ * | interval | 0 | 4
+ * +----------------+----------------+----------------+----------------+
+ * | 0 | 8
+ * +----------------+----------------+----------------+----------------+
+ * interval - uint16_t, time in msecs until interruption
+ *
+ * Request type specific data for control request:
+ * 0 1 2 3 octet
+ * +----------------+----------------+----------------+----------------+
+ * | data of setup packet | 4
+ * | | 8
+ * +----------------+----------------+----------------+----------------+
+ *
+ * Request type specific data for bulk request:
+ * 0 1 2 3 octet
+ * +----------------+----------------+----------------+----------------+
+ * | 0 | 4
+ * | 0 | 8
+ * +----------------+----------------+----------------+----------------+
+ *
+ * Request type specific data for unlink request:
+ * 0 1 2 3 octet
+ * +----------------+----------------+----------------+----------------+
+ * | unlink_id | 0 | 4
+ * +----------------+----------------+----------------+----------------+
+ * | 0 | 8
+ * +----------------+----------------+----------------+----------------+
+ * unlink_id - uint16_t, request id of request to terminate
+ *
+ * seg[] array element layout:
+ * 0 1 2 3 octet
+ * +----------------+----------------+----------------+----------------+
+ * | gref | 4
+ * +----------------+----------------+----------------+----------------+
+ * | offset | length | 8
+ * +----------------+----------------+----------------+----------------+
+ * gref - uint32_t, grant reference of buffer page
+ * offset - uint16_t, offset of buffer start in page
+ * length - uint16_t, length of buffer in page
+ *
+ *-------------------------- USB I/O response --------------------------------
+ *
+ * 0 1 2 3 octet
+ * +----------------+----------------+----------------+----------------+
+ * | id | start_frame | 4
+ * +----------------+----------------+----------------+----------------+
+ * | status | 8
+ * +----------------+----------------+----------------+----------------+
+ * | actual_length | 12
+ * +----------------+----------------+----------------+----------------+
+ * | error_count | 16
+ * +----------------+----------------+----------------+----------------+
+ * id - uint16_t, id of the request this response belongs to
+ * start_frame - uint16_t, start_frame this response (iso requests only)
+ * status - int32_t, USBIF_STATUS_* (non-iso requests)
+ * actual_length - uint32_t, actual size of data transferred
+ * error_count - uint32_t, number of errors (iso requests)
*/
enum usb_spec_version {
- USB_VER_UNKNOWN = 0,
- USB_VER_USB11,
- USB_VER_USB20,
- USB_VER_USB30, /* not supported yet */
+ USB_VER_UNKNOWN = 0,
+ USB_VER_USB11,
+ USB_VER_USB20,
+ USB_VER_USB30, /* not supported yet */
};
/*
* USB pipe in usbif_request
*
- * - port number: bits 0-4
- * (USB_MAXCHILDREN is 31)
+ * - port number: bits 0-4
+ * (USB_MAXCHILDREN is 31)
*
- * - operation flag: bit 5
- * (0 = submit urb,
- * 1 = unlink urb)
+ * - operation flag: bit 5
+ * (0 = submit urb,
+ * 1 = unlink urb)
*
- * - direction: bit 7
- * (0 = Host-to-Device [Out]
- * 1 = Device-to-Host [In])
+ * - direction: bit 7
+ * (0 = Host-to-Device [Out]
+ * 1 = Device-to-Host [In])
*
- * - device address: bits 8-14
+ * - device address: bits 8-14
*
- * - endpoint: bits 15-18
+ * - endpoint: bits 15-18
*
- * - pipe type: bits 30-31
- * (00 = isochronous, 01 = interrupt,
- * 10 = control, 11 = bulk)
+ * - pipe type: bits 30-31
+ * (00 = isochronous, 01 = interrupt,
+ * 10 = control, 11 = bulk)
*/
-#define USBIF_PIPE_PORT_MASK 0x0000001f
-#define USBIF_PIPE_UNLINK 0x00000020
-#define USBIF_PIPE_DIR 0x00000080
-#define USBIF_PIPE_DEV_MASK 0x0000007f
-#define USBIF_PIPE_DEV_SHIFT 8
-#define USBIF_PIPE_EP_MASK 0x0000000f
-#define USBIF_PIPE_EP_SHIFT 15
-#define USBIF_PIPE_TYPE_MASK 0x00000003
-#define USBIF_PIPE_TYPE_SHIFT 30
-#define USBIF_PIPE_TYPE_ISOC 0
-#define USBIF_PIPE_TYPE_INT 1
-#define USBIF_PIPE_TYPE_CTRL 2
-#define USBIF_PIPE_TYPE_BULK 3
-
-#define usbif_pipeportnum(pipe) ((pipe) & USBIF_PIPE_PORT_MASK)
-#define usbif_setportnum_pipe(pipe, portnum) ((pipe) | (portnum))
-
-#define usbif_pipeunlink(pipe) ((pipe) & USBIF_PIPE_UNLINK)
-#define usbif_pipesubmit(pipe) (!usbif_pipeunlink(pipe))
-#define usbif_setunlink_pipe(pipe) ((pipe) | USBIF_PIPE_UNLINK)
-
-#define usbif_pipein(pipe) ((pipe) & USBIF_PIPE_DIR)
-#define usbif_pipeout(pipe) (!usbif_pipein(pipe))
-
-#define usbif_pipedevice(pipe) \
- (((pipe) >> USBIF_PIPE_DEV_SHIFT) & USBIF_PIPE_DEV_MASK)
-
-#define usbif_pipeendpoint(pipe) \
- (((pipe) >> USBIF_PIPE_EP_SHIFT) & USBIF_PIPE_EP_MASK)
-
-#define usbif_pipetype(pipe) \
- (((pipe) >> USBIF_PIPE_TYPE_SHIFT) & USBIF_PIPE_TYPE_MASK)
-#define usbif_pipeisoc(pipe) (usbif_pipetype(pipe) == USBIF_PIPE_TYPE_ISOC)
-#define usbif_pipeint(pipe) (usbif_pipetype(pipe) == USBIF_PIPE_TYPE_INT)
-#define usbif_pipectrl(pipe) (usbif_pipetype(pipe) == USBIF_PIPE_TYPE_CTRL)
-#define usbif_pipebulk(pipe) (usbif_pipetype(pipe) == USBIF_PIPE_TYPE_BULK)
+#define USBIF_PIPE_PORT_MASK 0x0000001f
+#define USBIF_PIPE_UNLINK 0x00000020
+#define USBIF_PIPE_DIR 0x00000080
+#define USBIF_PIPE_DEV_MASK 0x0000007f
+#define USBIF_PIPE_DEV_SHIFT 8
+#define USBIF_PIPE_EP_MASK 0x0000000f
+#define USBIF_PIPE_EP_SHIFT 15
+#define USBIF_PIPE_TYPE_MASK 0x00000003
+#define USBIF_PIPE_TYPE_SHIFT 30
+#define USBIF_PIPE_TYPE_ISOC 0
+#define USBIF_PIPE_TYPE_INT 1
+#define USBIF_PIPE_TYPE_CTRL 2
+#define USBIF_PIPE_TYPE_BULK 3
+
+#define usbif_pipeportnum(pipe) ((pipe) & USBIF_PIPE_PORT_MASK)
+#define usbif_setportnum_pipe(pipe, portnum) ((pipe) | (portnum))
+
+#define usbif_pipeunlink(pipe) ((pipe) & USBIF_PIPE_UNLINK)
+#define usbif_pipesubmit(pipe) (!usbif_pipeunlink(pipe))
+#define usbif_setunlink_pipe(pipe) ((pipe) | USBIF_PIPE_UNLINK)
+
+#define usbif_pipein(pipe) ((pipe) & USBIF_PIPE_DIR)
+#define usbif_pipeout(pipe) (!usbif_pipein(pipe))
+
+#define usbif_pipedevice(pipe) \
+ (((pipe) >> USBIF_PIPE_DEV_SHIFT) & USBIF_PIPE_DEV_MASK)
+
+#define usbif_pipeendpoint(pipe) \
+ (((pipe) >> USBIF_PIPE_EP_SHIFT) & USBIF_PIPE_EP_MASK)
+
+#define usbif_pipetype(pipe) \
+ (((pipe) >> USBIF_PIPE_TYPE_SHIFT) & USBIF_PIPE_TYPE_MASK)
+#define usbif_pipeisoc(pipe) (usbif_pipetype(pipe) == USBIF_PIPE_TYPE_ISOC)
+#define usbif_pipeint(pipe) (usbif_pipetype(pipe) == USBIF_PIPE_TYPE_INT)
+#define usbif_pipectrl(pipe) (usbif_pipetype(pipe) == USBIF_PIPE_TYPE_CTRL)
+#define usbif_pipebulk(pipe) (usbif_pipetype(pipe) == USBIF_PIPE_TYPE_BULK)
#define USBIF_MAX_SEGMENTS_PER_REQUEST (16)
-#define USBIF_MAX_PORTNR 31
-#define USBIF_RING_SIZE 4096
+#define USBIF_MAX_PORTNR 31
+#define USBIF_RING_SIZE 4096
/*
* RING for transferring urbs.
*/
struct usbif_request_segment {
- grant_ref_t gref;
- uint16_t offset;
- uint16_t length;
+ grant_ref_t gref;
+ uint16_t offset;
+ uint16_t length;
};
struct usbif_urb_request {
- uint16_t id; /* request id */
- uint16_t nr_buffer_segs; /* number of urb->transfer_buffer segments */
-
- /* basic urb parameter */
- uint32_t pipe;
- uint16_t transfer_flags;
-#define USBIF_SHORT_NOT_OK 0x0001
- uint16_t buffer_length;
- union {
- uint8_t ctrl[8]; /* setup_packet (Ctrl) */
-
- struct {
- uint16_t interval; /* maximum (1024*8) in usb core */
- uint16_t start_frame; /* start frame */
- uint16_t number_of_packets; /* number of ISO packet */
- uint16_t nr_frame_desc_segs; /* number of iso_frame_desc segments */
- } isoc;
-
- struct {
- uint16_t interval; /* maximum (1024*8) in usb core */
- uint16_t pad[3];
- } intr;
-
- struct {
- uint16_t unlink_id; /* unlink request id */
- uint16_t pad[3];
- } unlink;
-
- } u;
-
- /* urb data segments */
- struct usbif_request_segment seg[USBIF_MAX_SEGMENTS_PER_REQUEST];
+ uint16_t id; /* request id */
+ uint16_t nr_buffer_segs; /* number of urb->transfer_buffer segments */
+
+ /* basic urb parameter */
+ uint32_t pipe;
+ uint16_t transfer_flags;
+#define USBIF_SHORT_NOT_OK 0x0001
+ uint16_t buffer_length;
+ union {
+ uint8_t ctrl[8]; /* setup_packet (Ctrl) */
+
+ struct {
+ uint16_t interval; /* maximum (1024*8) in usb core */
+ uint16_t start_frame; /* start frame */
+ uint16_t number_of_packets; /* number of ISO packet */
+ uint16_t nr_frame_desc_segs; /* number of iso_frame_desc segments */
+ } isoc;
+
+ struct {
+ uint16_t interval; /* maximum (1024*8) in usb core */
+ uint16_t pad[3];
+ } intr;
+
+ struct {
+ uint16_t unlink_id; /* unlink request id */
+ uint16_t pad[3];
+ } unlink;
+
+ } u;
+
+ /* urb data segments */
+ struct usbif_request_segment seg[USBIF_MAX_SEGMENTS_PER_REQUEST];
};
typedef struct usbif_urb_request usbif_urb_request_t;
struct usbif_urb_response {
- uint16_t id; /* request id */
- uint16_t start_frame; /* start frame (ISO) */
- int32_t status; /* status (non-ISO) */
- int32_t actual_length; /* actual transfer length */
- int32_t error_count; /* number of ISO errors */
+ uint16_t id; /* request id */
+ uint16_t start_frame; /* start frame (ISO) */
+ int32_t status; /* status (non-ISO) */
+#define USBIF_STATUS_OK 0
+#define USBIF_STATUS_NODEV (-19)
+#define USBIF_STATUS_INVAL (-22)
+#define USBIF_STATUS_STALL (-32)
+#define USBIF_STATUS_IOERROR (-71)
+#define USBIF_STATUS_BABBLE (-75)
+#define USBIF_STATUS_SHUTDOWN (-108)
+ int32_t actual_length; /* actual transfer length */
+ int32_t error_count; /* number of ISO errors */
};
typedef struct usbif_urb_response usbif_urb_response_t;
@@ -233,18 +387,18 @@ DEFINE_RING_TYPES(usbif_urb, struct usbif_urb_request, struct usbif_urb_response
* RING for notifying connect/disconnect events to frontend
*/
struct usbif_conn_request {
- uint16_t id;
+ uint16_t id;
};
typedef struct usbif_conn_request usbif_conn_request_t;
struct usbif_conn_response {
- uint16_t id; /* request id */
- uint8_t portnum; /* port number */
- uint8_t speed; /* usb_device_speed */
-#define USBIF_SPEED_NONE 0
-#define USBIF_SPEED_LOW 1
-#define USBIF_SPEED_FULL 2
-#define USBIF_SPEED_HIGH 3
+ uint16_t id; /* request id */
+ uint8_t portnum; /* port number */
+ uint8_t speed; /* usb_device_speed */
+#define USBIF_SPEED_NONE 0
+#define USBIF_SPEED_LOW 1
+#define USBIF_SPEED_FULL 2
+#define USBIF_SPEED_HIGH 3
};
typedef struct usbif_conn_response usbif_conn_response_t;
diff --git a/include/hw/xen/interface/io/xenbus.h b/include/hw/xen/interface/io/xenbus.h
index 2fbf2a7fdc..9cd0cd7c67 100644
--- a/include/hw/xen/interface/io/xenbus.h
+++ b/include/hw/xen/interface/io/xenbus.h
@@ -1,26 +1,9 @@
+/* SPDX-License-Identifier: MIT */
/*****************************************************************************
* xenbus.h
*
* Xenbus protocol details.
*
- * 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.
- *
* Copyright (C) 2005 XenSource Ltd.
*/
@@ -68,3 +51,13 @@ enum xenbus_state {
typedef enum xenbus_state XenbusState;
#endif /* _XEN_PUBLIC_IO_XENBUS_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/hw/xen/interface/io/xs_wire.h b/include/hw/xen/interface/io/xs_wire.h
new file mode 100644
index 0000000000..04e6849feb
--- /dev/null
+++ b/include/hw/xen/interface/io/xs_wire.h
@@ -0,0 +1,147 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Details of the "wire" protocol between Xen Store Daemon and client
+ * library or guest kernel.
+ *
+ * Copyright (C) 2005 Rusty Russell IBM Corporation
+ */
+
+#ifndef _XS_WIRE_H
+#define _XS_WIRE_H
+
+enum xsd_sockmsg_type
+{
+ XS_CONTROL,
+#define XS_DEBUG XS_CONTROL
+ XS_DIRECTORY,
+ XS_READ,
+ XS_GET_PERMS,
+ XS_WATCH,
+ XS_UNWATCH,
+ XS_TRANSACTION_START,
+ XS_TRANSACTION_END,
+ XS_INTRODUCE,
+ XS_RELEASE,
+ XS_GET_DOMAIN_PATH,
+ XS_WRITE,
+ XS_MKDIR,
+ XS_RM,
+ XS_SET_PERMS,
+ XS_WATCH_EVENT,
+ XS_ERROR,
+ XS_IS_DOMAIN_INTRODUCED,
+ XS_RESUME,
+ XS_SET_TARGET,
+ /* XS_RESTRICT has been removed */
+ XS_RESET_WATCHES = XS_SET_TARGET + 2,
+ XS_DIRECTORY_PART,
+
+ XS_TYPE_COUNT, /* Number of valid types. */
+
+ XS_INVALID = 0xffff /* Guaranteed to remain an invalid type */
+};
+
+#define XS_WRITE_NONE "NONE"
+#define XS_WRITE_CREATE "CREATE"
+#define XS_WRITE_CREATE_EXCL "CREATE|EXCL"
+
+/* We hand errors as strings, for portability. */
+struct xsd_errors
+{
+ int errnum;
+ const char *errstring;
+};
+#ifdef EINVAL
+#define XSD_ERROR(x) { x, #x }
+/* LINTED: static unused */
+static const struct xsd_errors xsd_errors[]
+#if defined(__GNUC__)
+__attribute__((unused))
+#endif
+ = {
+ /* /!\ New errors should be added at the end of the array. */
+ XSD_ERROR(EINVAL),
+ XSD_ERROR(EACCES),
+ XSD_ERROR(EEXIST),
+ XSD_ERROR(EISDIR),
+ XSD_ERROR(ENOENT),
+ XSD_ERROR(ENOMEM),
+ XSD_ERROR(ENOSPC),
+ XSD_ERROR(EIO),
+ XSD_ERROR(ENOTEMPTY),
+ XSD_ERROR(ENOSYS),
+ XSD_ERROR(EROFS),
+ XSD_ERROR(EBUSY),
+ XSD_ERROR(EAGAIN),
+ XSD_ERROR(EISCONN),
+ XSD_ERROR(E2BIG),
+ XSD_ERROR(EPERM),
+};
+#endif
+
+struct xsd_sockmsg
+{
+ uint32_t type; /* XS_??? */
+ uint32_t req_id;/* Request identifier, echoed in daemon's response. */
+ uint32_t tx_id; /* Transaction id (0 if not related to a transaction). */
+ uint32_t len; /* Length of data following this. */
+
+ /* Generally followed by nul-terminated string(s). */
+};
+
+enum xs_watch_type
+{
+ XS_WATCH_PATH = 0,
+ XS_WATCH_TOKEN
+};
+
+/*
+ * `incontents 150 xenstore_struct XenStore wire protocol.
+ *
+ * Inter-domain shared memory communications. */
+#define XENSTORE_RING_SIZE 1024
+typedef uint32_t XENSTORE_RING_IDX;
+#define MASK_XENSTORE_IDX(idx) ((idx) & (XENSTORE_RING_SIZE-1))
+struct xenstore_domain_interface {
+ char req[XENSTORE_RING_SIZE]; /* Requests to xenstore daemon. */
+ char rsp[XENSTORE_RING_SIZE]; /* Replies and async watch events. */
+ XENSTORE_RING_IDX req_cons, req_prod;
+ XENSTORE_RING_IDX rsp_cons, rsp_prod;
+ uint32_t server_features; /* Bitmap of features supported by the server */
+ uint32_t connection;
+ uint32_t error;
+};
+
+/* Violating this is very bad. See docs/misc/xenstore.txt. */
+#define XENSTORE_PAYLOAD_MAX 4096
+
+/* Violating these just gets you an error back */
+#define XENSTORE_ABS_PATH_MAX 3072
+#define XENSTORE_REL_PATH_MAX 2048
+
+/* The ability to reconnect a ring */
+#define XENSTORE_SERVER_FEATURE_RECONNECTION 1
+/* The presence of the "error" field in the ring page */
+#define XENSTORE_SERVER_FEATURE_ERROR 2
+
+/* Valid values for the connection field */
+#define XENSTORE_CONNECTED 0 /* the steady-state */
+#define XENSTORE_RECONNECT 1 /* reconnect in progress */
+
+/* Valid values for the error field */
+#define XENSTORE_ERROR_NONE 0 /* No error */
+#define XENSTORE_ERROR_COMM 1 /* Communication problem */
+#define XENSTORE_ERROR_RINGIDX 2 /* Invalid ring index */
+#define XENSTORE_ERROR_PROTO 3 /* Protocol violation (payload too long) */
+
+#endif /* _XS_WIRE_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/hw/xen/interface/memory.h b/include/hw/xen/interface/memory.h
new file mode 100644
index 0000000000..29cf5c8239
--- /dev/null
+++ b/include/hw/xen/interface/memory.h
@@ -0,0 +1,746 @@
+/* SPDX-License-Identifier: MIT */
+/******************************************************************************
+ * memory.h
+ *
+ * Memory reservation and information.
+ *
+ * Copyright (c) 2005, Keir Fraser <keir@xensource.com>
+ */
+
+#ifndef __XEN_PUBLIC_MEMORY_H__
+#define __XEN_PUBLIC_MEMORY_H__
+
+#include "xen.h"
+#include "physdev.h"
+
+/*
+ * Increase or decrease the specified domain's memory reservation. Returns the
+ * number of extents successfully allocated or freed.
+ * arg == addr of struct xen_memory_reservation.
+ */
+#define XENMEM_increase_reservation 0
+#define XENMEM_decrease_reservation 1
+#define XENMEM_populate_physmap 6
+
+#if __XEN_INTERFACE_VERSION__ >= 0x00030209
+/*
+ * Maximum # bits addressable by the user of the allocated region (e.g., I/O
+ * devices often have a 32-bit limitation even in 64-bit systems). If zero
+ * then the user has no addressing restriction. This field is not used by
+ * XENMEM_decrease_reservation.
+ */
+#define XENMEMF_address_bits(x) (x)
+#define XENMEMF_get_address_bits(x) ((x) & 0xffu)
+/* NUMA node to allocate from. */
+#define XENMEMF_node(x) (((x) + 1) << 8)
+#define XENMEMF_get_node(x) ((((x) >> 8) - 1) & 0xffu)
+/* Flag to populate physmap with populate-on-demand entries */
+#define XENMEMF_populate_on_demand (1<<16)
+/* Flag to request allocation only from the node specified */
+#define XENMEMF_exact_node_request (1<<17)
+#define XENMEMF_exact_node(n) (XENMEMF_node(n) | XENMEMF_exact_node_request)
+/* Flag to indicate the node specified is virtual node */
+#define XENMEMF_vnode (1<<18)
+#endif
+
+struct xen_memory_reservation {
+
+ /*
+ * XENMEM_increase_reservation:
+ * OUT: MFN (*not* GMFN) bases of extents that were allocated
+ * XENMEM_decrease_reservation:
+ * IN: GMFN bases of extents to free
+ * XENMEM_populate_physmap:
+ * IN: GPFN bases of extents to populate with memory
+ * OUT: GMFN bases of extents that were allocated
+ * (NB. This command also updates the mach_to_phys translation table)
+ * XENMEM_claim_pages:
+ * IN: must be zero
+ */
+ XEN_GUEST_HANDLE(xen_pfn_t) extent_start;
+
+ /* Number of extents, and size/alignment of each (2^extent_order pages). */
+ xen_ulong_t nr_extents;
+ unsigned int extent_order;
+
+#if __XEN_INTERFACE_VERSION__ >= 0x00030209
+ /* XENMEMF flags. */
+ unsigned int mem_flags;
+#else
+ unsigned int address_bits;
+#endif
+
+ /*
+ * Domain whose reservation is being changed.
+ * Unprivileged domains can specify only DOMID_SELF.
+ */
+ domid_t domid;
+};
+typedef struct xen_memory_reservation xen_memory_reservation_t;
+DEFINE_XEN_GUEST_HANDLE(xen_memory_reservation_t);
+
+/*
+ * An atomic exchange of memory pages. If return code is zero then
+ * @out.extent_list provides GMFNs of the newly-allocated memory.
+ * Returns zero on complete success, otherwise a negative error code.
+ * On complete success then always @nr_exchanged == @in.nr_extents.
+ * On partial success @nr_exchanged indicates how much work was done.
+ *
+ * Note that only PV guests can use this operation.
+ */
+#define XENMEM_exchange 11
+struct xen_memory_exchange {
+ /*
+ * [IN] Details of memory extents to be exchanged (GMFN bases).
+ * Note that @in.address_bits is ignored and unused.
+ */
+ struct xen_memory_reservation in;
+
+ /*
+ * [IN/OUT] Details of new memory extents.
+ * We require that:
+ * 1. @in.domid == @out.domid
+ * 2. @in.nr_extents << @in.extent_order ==
+ * @out.nr_extents << @out.extent_order
+ * 3. @in.extent_start and @out.extent_start lists must not overlap
+ * 4. @out.extent_start lists GPFN bases to be populated
+ * 5. @out.extent_start is overwritten with allocated GMFN bases
+ */
+ struct xen_memory_reservation out;
+
+ /*
+ * [OUT] Number of input extents that were successfully exchanged:
+ * 1. The first @nr_exchanged input extents were successfully
+ * deallocated.
+ * 2. The corresponding first entries in the output extent list correctly
+ * indicate the GMFNs that were successfully exchanged.
+ * 3. All other input and output extents are untouched.
+ * 4. If not all input exents are exchanged then the return code of this
+ * command will be non-zero.
+ * 5. THIS FIELD MUST BE INITIALISED TO ZERO BY THE CALLER!
+ */
+ xen_ulong_t nr_exchanged;
+};
+typedef struct xen_memory_exchange xen_memory_exchange_t;
+DEFINE_XEN_GUEST_HANDLE(xen_memory_exchange_t);
+
+/*
+ * Returns the maximum machine frame number of mapped RAM in this system.
+ * This command always succeeds (it never returns an error code).
+ * arg == NULL.
+ */
+#define XENMEM_maximum_ram_page 2
+
+struct xen_memory_domain {
+ /* [IN] Domain information is being queried for. */
+ domid_t domid;
+};
+
+/*
+ * Returns the current or maximum memory reservation, in pages, of the
+ * specified domain (may be DOMID_SELF). Returns -ve errcode on failure.
+ * arg == addr of struct xen_memory_domain.
+ */
+#define XENMEM_current_reservation 3
+#define XENMEM_maximum_reservation 4
+
+/*
+ * Returns the maximum GFN in use by the specified domain (may be DOMID_SELF).
+ * Returns -ve errcode on failure.
+ * arg == addr of struct xen_memory_domain.
+ */
+#define XENMEM_maximum_gpfn 14
+
+/*
+ * Returns a list of MFN bases of 2MB extents comprising the machine_to_phys
+ * mapping table. Architectures which do not have a m2p table do not implement
+ * this command.
+ * arg == addr of xen_machphys_mfn_list_t.
+ */
+#define XENMEM_machphys_mfn_list 5
+struct xen_machphys_mfn_list {
+ /*
+ * Size of the 'extent_start' array. Fewer entries will be filled if the
+ * machphys table is smaller than max_extents * 2MB.
+ */
+ unsigned int max_extents;
+
+ /*
+ * Pointer to buffer to fill with list of extent starts. If there are
+ * any large discontiguities in the machine address space, 2MB gaps in
+ * the machphys table will be represented by an MFN base of zero.
+ */
+ XEN_GUEST_HANDLE(xen_pfn_t) extent_start;
+
+ /*
+ * Number of extents written to the above array. This will be smaller
+ * than 'max_extents' if the machphys table is smaller than max_e * 2MB.
+ */
+ unsigned int nr_extents;
+};
+typedef struct xen_machphys_mfn_list xen_machphys_mfn_list_t;
+DEFINE_XEN_GUEST_HANDLE(xen_machphys_mfn_list_t);
+
+/*
+ * For a compat caller, this is identical to XENMEM_machphys_mfn_list.
+ *
+ * For a non compat caller, this functions similarly to
+ * XENMEM_machphys_mfn_list, but returns the mfns making up the compatibility
+ * m2p table.
+ */
+#define XENMEM_machphys_compat_mfn_list 25
+
+/*
+ * Returns the location in virtual address space of the machine_to_phys
+ * mapping table. Architectures which do not have a m2p table, or which do not
+ * map it by default into guest address space, do not implement this command.
+ * arg == addr of xen_machphys_mapping_t.
+ */
+#define XENMEM_machphys_mapping 12
+struct xen_machphys_mapping {
+ xen_ulong_t v_start, v_end; /* Start and end virtual addresses. */
+ xen_ulong_t max_mfn; /* Maximum MFN that can be looked up. */
+};
+typedef struct xen_machphys_mapping xen_machphys_mapping_t;
+DEFINE_XEN_GUEST_HANDLE(xen_machphys_mapping_t);
+
+/* Source mapping space. */
+/* ` enum phys_map_space { */
+#define XENMAPSPACE_shared_info 0 /* shared info page */
+#define XENMAPSPACE_grant_table 1 /* grant table page */
+#define XENMAPSPACE_gmfn 2 /* GMFN */
+#define XENMAPSPACE_gmfn_range 3 /* GMFN range, XENMEM_add_to_physmap only. */
+#define XENMAPSPACE_gmfn_foreign 4 /* GMFN from another dom,
+ * XENMEM_add_to_physmap_batch only. */
+#define XENMAPSPACE_dev_mmio 5 /* device mmio region
+ ARM only; the region is mapped in
+ Stage-2 using the Normal Memory
+ Inner/Outer Write-Back Cacheable
+ memory attribute. */
+/* ` } */
+
+/*
+ * Sets the GPFN at which a particular page appears in the specified guest's
+ * physical address space (translated guests only).
+ * arg == addr of xen_add_to_physmap_t.
+ */
+#define XENMEM_add_to_physmap 7
+struct xen_add_to_physmap {
+ /* Which domain to change the mapping for. */
+ domid_t domid;
+
+ /* Number of pages to go through for gmfn_range */
+ uint16_t size;
+
+ unsigned int space; /* => enum phys_map_space */
+
+#define XENMAPIDX_grant_table_status 0x80000000
+
+ /* Index into space being mapped. */
+ xen_ulong_t idx;
+
+ /* GPFN in domid where the source mapping page should appear. */
+ xen_pfn_t gpfn;
+};
+typedef struct xen_add_to_physmap xen_add_to_physmap_t;
+DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_t);
+
+/* A batched version of add_to_physmap. */
+#define XENMEM_add_to_physmap_batch 23
+struct xen_add_to_physmap_batch {
+ /* IN */
+ /* Which domain to change the mapping for. */
+ domid_t domid;
+ uint16_t space; /* => enum phys_map_space */
+
+ /* Number of pages to go through */
+ uint16_t size;
+
+#if __XEN_INTERFACE_VERSION__ < 0x00040700
+ domid_t foreign_domid; /* IFF gmfn_foreign. Should be 0 for other spaces. */
+#else
+ union xen_add_to_physmap_batch_extra {
+ domid_t foreign_domid; /* gmfn_foreign */
+ uint16_t res0; /* All the other spaces. Should be 0 */
+ } u;
+#endif
+
+ /* Indexes into space being mapped. */
+ XEN_GUEST_HANDLE(xen_ulong_t) idxs;
+
+ /* GPFN in domid where the source mapping page should appear. */
+ XEN_GUEST_HANDLE(xen_pfn_t) gpfns;
+
+ /* OUT */
+
+ /* Per index error code. */
+ XEN_GUEST_HANDLE(int) errs;
+};
+typedef struct xen_add_to_physmap_batch xen_add_to_physmap_batch_t;
+DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_batch_t);
+
+#if __XEN_INTERFACE_VERSION__ < 0x00040400
+#define XENMEM_add_to_physmap_range XENMEM_add_to_physmap_batch
+#define xen_add_to_physmap_range xen_add_to_physmap_batch
+typedef struct xen_add_to_physmap_batch xen_add_to_physmap_range_t;
+DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_range_t);
+#endif
+
+/*
+ * Unmaps the page appearing at a particular GPFN from the specified guest's
+ * physical address space (translated guests only).
+ * arg == addr of xen_remove_from_physmap_t.
+ */
+#define XENMEM_remove_from_physmap 15
+struct xen_remove_from_physmap {
+ /* Which domain to change the mapping for. */
+ domid_t domid;
+
+ /* GPFN of the current mapping of the page. */
+ xen_pfn_t gpfn;
+};
+typedef struct xen_remove_from_physmap xen_remove_from_physmap_t;
+DEFINE_XEN_GUEST_HANDLE(xen_remove_from_physmap_t);
+
+/*** REMOVED ***/
+/*#define XENMEM_translate_gpfn_list 8*/
+
+/*
+ * Returns the pseudo-physical memory map as it was when the domain
+ * was started (specified by XENMEM_set_memory_map).
+ * arg == addr of xen_memory_map_t.
+ */
+#define XENMEM_memory_map 9
+struct xen_memory_map {
+ /*
+ * On call the number of entries which can be stored in buffer. On
+ * return the number of entries which have been stored in
+ * buffer.
+ */
+ unsigned int nr_entries;
+
+ /*
+ * Entries in the buffer are in the same format as returned by the
+ * BIOS INT 0x15 EAX=0xE820 call.
+ */
+ XEN_GUEST_HANDLE(void) buffer;
+};
+typedef struct xen_memory_map xen_memory_map_t;
+DEFINE_XEN_GUEST_HANDLE(xen_memory_map_t);
+
+/*
+ * Returns the real physical memory map. Passes the same structure as
+ * XENMEM_memory_map.
+ * Specifying buffer as NULL will return the number of entries required
+ * to store the complete memory map.
+ * arg == addr of xen_memory_map_t.
+ */
+#define XENMEM_machine_memory_map 10
+
+/*
+ * Set the pseudo-physical memory map of a domain, as returned by
+ * XENMEM_memory_map.
+ * arg == addr of xen_foreign_memory_map_t.
+ */
+#define XENMEM_set_memory_map 13
+struct xen_foreign_memory_map {
+ domid_t domid;
+ struct xen_memory_map map;
+};
+typedef struct xen_foreign_memory_map xen_foreign_memory_map_t;
+DEFINE_XEN_GUEST_HANDLE(xen_foreign_memory_map_t);
+
+#define XENMEM_set_pod_target 16
+#define XENMEM_get_pod_target 17
+struct xen_pod_target {
+ /* IN */
+ uint64_t target_pages;
+ /* OUT */
+ uint64_t tot_pages;
+ uint64_t pod_cache_pages;
+ uint64_t pod_entries;
+ /* IN */
+ domid_t domid;
+};
+typedef struct xen_pod_target xen_pod_target_t;
+
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+
+#ifndef uint64_aligned_t
+#define uint64_aligned_t uint64_t
+#endif
+
+/*
+ * Get the number of MFNs saved through memory sharing.
+ * The call never fails.
+ */
+#define XENMEM_get_sharing_freed_pages 18
+#define XENMEM_get_sharing_shared_pages 19
+
+#define XENMEM_paging_op 20
+#define XENMEM_paging_op_nominate 0
+#define XENMEM_paging_op_evict 1
+#define XENMEM_paging_op_prep 2
+
+struct xen_mem_paging_op {
+ uint8_t op; /* XENMEM_paging_op_* */
+ domid_t domain;
+
+ /* IN: (XENMEM_paging_op_prep) buffer to immediately fill page from */
+ XEN_GUEST_HANDLE_64(const_uint8) buffer;
+ /* IN: gfn of page being operated on */
+ uint64_aligned_t gfn;
+};
+typedef struct xen_mem_paging_op xen_mem_paging_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_mem_paging_op_t);
+
+#define XENMEM_access_op 21
+#define XENMEM_access_op_set_access 0
+#define XENMEM_access_op_get_access 1
+/*
+ * XENMEM_access_op_enable_emulate and XENMEM_access_op_disable_emulate are
+ * currently unused, but since they have been in use please do not reuse them.
+ *
+ * #define XENMEM_access_op_enable_emulate 2
+ * #define XENMEM_access_op_disable_emulate 3
+ */
+#define XENMEM_access_op_set_access_multi 4
+
+typedef enum {
+ XENMEM_access_n,
+ XENMEM_access_r,
+ XENMEM_access_w,
+ XENMEM_access_rw,
+ XENMEM_access_x,
+ XENMEM_access_rx,
+ XENMEM_access_wx,
+ XENMEM_access_rwx,
+ /*
+ * Page starts off as r-x, but automatically
+ * change to r-w on a write
+ */
+ XENMEM_access_rx2rw,
+ /*
+ * Log access: starts off as n, automatically
+ * goes to rwx, generating an event without
+ * pausing the vcpu
+ */
+ XENMEM_access_n2rwx,
+ /* Take the domain default */
+ XENMEM_access_default
+} xenmem_access_t;
+
+struct xen_mem_access_op {
+ /* XENMEM_access_op_* */
+ uint8_t op;
+ /* xenmem_access_t */
+ uint8_t access;
+ domid_t domid;
+ /*
+ * Number of pages for set op (or size of pfn_list for
+ * XENMEM_access_op_set_access_multi)
+ * Ignored on setting default access and other ops
+ */
+ uint32_t nr;
+ /*
+ * First pfn for set op
+ * pfn for get op
+ * ~0ull is used to set and get the default access for pages
+ */
+ uint64_aligned_t pfn;
+ /*
+ * List of pfns to set access for
+ * Used only with XENMEM_access_op_set_access_multi
+ */
+ XEN_GUEST_HANDLE(const_uint64) pfn_list;
+ /*
+ * Corresponding list of access settings for pfn_list
+ * Used only with XENMEM_access_op_set_access_multi
+ */
+ XEN_GUEST_HANDLE(const_uint8) access_list;
+};
+typedef struct xen_mem_access_op xen_mem_access_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_mem_access_op_t);
+
+#define XENMEM_sharing_op 22
+#define XENMEM_sharing_op_nominate_gfn 0
+#define XENMEM_sharing_op_nominate_gref 1
+#define XENMEM_sharing_op_share 2
+#define XENMEM_sharing_op_debug_gfn 3
+#define XENMEM_sharing_op_debug_mfn 4
+#define XENMEM_sharing_op_debug_gref 5
+#define XENMEM_sharing_op_add_physmap 6
+#define XENMEM_sharing_op_audit 7
+#define XENMEM_sharing_op_range_share 8
+#define XENMEM_sharing_op_fork 9
+#define XENMEM_sharing_op_fork_reset 10
+
+#define XENMEM_SHARING_OP_S_HANDLE_INVALID (-10)
+#define XENMEM_SHARING_OP_C_HANDLE_INVALID (-9)
+
+/* The following allows sharing of grant refs. This is useful
+ * for sharing utilities sitting as "filters" in IO backends
+ * (e.g. memshr + blktap(2)). The IO backend is only exposed
+ * to grant references, and this allows sharing of the grefs */
+#define XENMEM_SHARING_OP_FIELD_IS_GREF_FLAG (xen_mk_ullong(1) << 62)
+
+#define XENMEM_SHARING_OP_FIELD_MAKE_GREF(field, val) \
+ (field) = (XENMEM_SHARING_OP_FIELD_IS_GREF_FLAG | val)
+#define XENMEM_SHARING_OP_FIELD_IS_GREF(field) \
+ ((field) & XENMEM_SHARING_OP_FIELD_IS_GREF_FLAG)
+#define XENMEM_SHARING_OP_FIELD_GET_GREF(field) \
+ ((field) & (~XENMEM_SHARING_OP_FIELD_IS_GREF_FLAG))
+
+struct xen_mem_sharing_op {
+ uint8_t op; /* XENMEM_sharing_op_* */
+ domid_t domain;
+
+ union {
+ struct mem_sharing_op_nominate { /* OP_NOMINATE_xxx */
+ union {
+ uint64_aligned_t gfn; /* IN: gfn to nominate */
+ uint32_t grant_ref; /* IN: grant ref to nominate */
+ } u;
+ uint64_aligned_t handle; /* OUT: the handle */
+ } nominate;
+ struct mem_sharing_op_share { /* OP_SHARE/ADD_PHYSMAP */
+ uint64_aligned_t source_gfn; /* IN: the gfn of the source page */
+ uint64_aligned_t source_handle; /* IN: handle to the source page */
+ uint64_aligned_t client_gfn; /* IN: the client gfn */
+ uint64_aligned_t client_handle; /* IN: handle to the client page */
+ domid_t client_domain; /* IN: the client domain id */
+ } share;
+ struct mem_sharing_op_range { /* OP_RANGE_SHARE */
+ uint64_aligned_t first_gfn; /* IN: the first gfn */
+ uint64_aligned_t last_gfn; /* IN: the last gfn */
+ uint64_aligned_t opaque; /* Must be set to 0 */
+ domid_t client_domain; /* IN: the client domain id */
+ uint16_t _pad[3]; /* Must be set to 0 */
+ } range;
+ struct mem_sharing_op_debug { /* OP_DEBUG_xxx */
+ union {
+ uint64_aligned_t gfn; /* IN: gfn to debug */
+ uint64_aligned_t mfn; /* IN: mfn to debug */
+ uint32_t gref; /* IN: gref to debug */
+ } u;
+ } debug;
+ struct mem_sharing_op_fork { /* OP_FORK{,_RESET} */
+ domid_t parent_domain; /* IN: parent's domain id */
+/* Only makes sense for short-lived forks */
+#define XENMEM_FORK_WITH_IOMMU_ALLOWED (1u << 0)
+/* Only makes sense for short-lived forks */
+#define XENMEM_FORK_BLOCK_INTERRUPTS (1u << 1)
+#define XENMEM_FORK_RESET_STATE (1u << 2)
+#define XENMEM_FORK_RESET_MEMORY (1u << 3)
+ uint16_t flags; /* IN: optional settings */
+ uint32_t pad; /* Must be set to 0 */
+ } fork;
+ } u;
+};
+typedef struct xen_mem_sharing_op xen_mem_sharing_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_mem_sharing_op_t);
+
+/*
+ * Attempt to stake a claim for a domain on a quantity of pages
+ * of system RAM, but _not_ assign specific pageframes. Only
+ * arithmetic is performed so the hypercall is very fast and need
+ * not be preemptible, thus sidestepping time-of-check-time-of-use
+ * races for memory allocation. Returns 0 if the hypervisor page
+ * allocator has atomically and successfully claimed the requested
+ * number of pages, else non-zero.
+ *
+ * Any domain may have only one active claim. When sufficient memory
+ * has been allocated to resolve the claim, the claim silently expires.
+ * Claiming zero pages effectively resets any outstanding claim and
+ * is always successful.
+ *
+ * Note that a valid claim may be staked even after memory has been
+ * allocated for a domain. In this case, the claim is not incremental,
+ * i.e. if the domain's total page count is 3, and a claim is staked
+ * for 10, only 7 additional pages are claimed.
+ *
+ * Caller must be privileged or the hypercall fails.
+ */
+#define XENMEM_claim_pages 24
+
+/*
+ * XENMEM_claim_pages flags - the are no flags at this time.
+ * The zero value is appropriate.
+ */
+
+/*
+ * With some legacy devices, certain guest-physical addresses cannot safely
+ * be used for other purposes, e.g. to map guest RAM. This hypercall
+ * enumerates those regions so the toolstack can avoid using them.
+ */
+#define XENMEM_reserved_device_memory_map 27
+struct xen_reserved_device_memory {
+ xen_pfn_t start_pfn;
+ xen_ulong_t nr_pages;
+};
+typedef struct xen_reserved_device_memory xen_reserved_device_memory_t;
+DEFINE_XEN_GUEST_HANDLE(xen_reserved_device_memory_t);
+
+struct xen_reserved_device_memory_map {
+#define XENMEM_RDM_ALL 1 /* Request all regions (ignore dev union). */
+ /* IN */
+ uint32_t flags;
+ /*
+ * IN/OUT
+ *
+ * Gets set to the required number of entries when too low,
+ * signaled by error code -ERANGE.
+ */
+ unsigned int nr_entries;
+ /* OUT */
+ XEN_GUEST_HANDLE(xen_reserved_device_memory_t) buffer;
+ /* IN */
+ union {
+ physdev_pci_device_t pci;
+ } dev;
+};
+typedef struct xen_reserved_device_memory_map xen_reserved_device_memory_map_t;
+DEFINE_XEN_GUEST_HANDLE(xen_reserved_device_memory_map_t);
+
+#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
+
+/*
+ * Get the pages for a particular guest resource, so that they can be
+ * mapped directly by a tools domain.
+ */
+#define XENMEM_acquire_resource 28
+struct xen_mem_acquire_resource {
+ /* IN - The domain whose resource is to be mapped */
+ domid_t domid;
+ /* IN - the type of resource */
+ uint16_t type;
+
+#define XENMEM_resource_ioreq_server 0
+#define XENMEM_resource_grant_table 1
+#define XENMEM_resource_vmtrace_buf 2
+
+ /*
+ * IN - a type-specific resource identifier, which must be zero
+ * unless stated otherwise.
+ *
+ * type == XENMEM_resource_ioreq_server -> id == ioreq server id
+ * type == XENMEM_resource_grant_table -> id defined below
+ */
+ uint32_t id;
+
+#define XENMEM_resource_grant_table_id_shared 0
+#define XENMEM_resource_grant_table_id_status 1
+
+ /*
+ * IN/OUT
+ *
+ * As an IN parameter number of frames of the resource to be mapped.
+ * This value may be updated over the course of the operation.
+ *
+ * When frame_list is NULL and nr_frames is 0, this is interpreted as a
+ * request for the size of the resource, which shall be returned in the
+ * nr_frames field.
+ *
+ * The size of a resource will never be zero, but a nonzero result doesn't
+ * guarantee that a subsequent mapping request will be successful. There
+ * are further type/id specific constraints which may change between the
+ * two calls.
+ */
+ uint32_t nr_frames;
+ /*
+ * Padding field, must be zero on input.
+ * In a previous version this was an output field with the lowest bit
+ * named XENMEM_rsrc_acq_caller_owned. Future versions of this interface
+ * will not reuse this bit as an output with the field being zero on
+ * input.
+ */
+ uint32_t pad;
+ /*
+ * IN - the index of the initial frame to be mapped. This parameter
+ * is ignored if nr_frames is 0. This value may be updated
+ * over the course of the operation.
+ */
+ uint64_t frame;
+
+#define XENMEM_resource_ioreq_server_frame_bufioreq 0
+#define XENMEM_resource_ioreq_server_frame_ioreq(n) (1 + (n))
+
+ /*
+ * IN/OUT - If the tools domain is PV then, upon return, frame_list
+ * will be populated with the MFNs of the resource.
+ * If the tools domain is HVM then it is expected that, on
+ * entry, frame_list will be populated with a list of GFNs
+ * that will be mapped to the MFNs of the resource.
+ * If -EIO is returned then the frame_list has only been
+ * partially mapped and it is up to the caller to unmap all
+ * the GFNs.
+ * This parameter may be NULL if nr_frames is 0. This
+ * value may be updated over the course of the operation.
+ */
+ XEN_GUEST_HANDLE(xen_pfn_t) frame_list;
+};
+typedef struct xen_mem_acquire_resource xen_mem_acquire_resource_t;
+DEFINE_XEN_GUEST_HANDLE(xen_mem_acquire_resource_t);
+
+/*
+ * XENMEM_get_vnumainfo used by guest to get
+ * vNUMA topology from hypervisor.
+ */
+#define XENMEM_get_vnumainfo 26
+
+/* vNUMA node memory ranges */
+struct xen_vmemrange {
+ uint64_t start, end;
+ unsigned int flags;
+ unsigned int nid;
+};
+typedef struct xen_vmemrange xen_vmemrange_t;
+DEFINE_XEN_GUEST_HANDLE(xen_vmemrange_t);
+
+/*
+ * vNUMA topology specifies vNUMA node number, distance table,
+ * memory ranges and vcpu mapping provided for guests.
+ * XENMEM_get_vnumainfo hypercall expects to see from guest
+ * nr_vnodes, nr_vmemranges and nr_vcpus to indicate available memory.
+ * After filling guests structures, nr_vnodes, nr_vmemranges and nr_vcpus
+ * copied back to guest. Domain returns expected values of nr_vnodes,
+ * nr_vmemranges and nr_vcpus to guest if the values where incorrect.
+ */
+struct xen_vnuma_topology_info {
+ /* IN */
+ domid_t domid;
+ uint16_t pad;
+ /* IN/OUT */
+ unsigned int nr_vnodes;
+ unsigned int nr_vcpus;
+ unsigned int nr_vmemranges;
+ /* OUT */
+ union {
+ XEN_GUEST_HANDLE(uint) h;
+ uint64_t pad;
+ } vdistance;
+ union {
+ XEN_GUEST_HANDLE(uint) h;
+ uint64_t pad;
+ } vcpu_to_vnode;
+ union {
+ XEN_GUEST_HANDLE(xen_vmemrange_t) h;
+ uint64_t pad;
+ } vmemrange;
+};
+typedef struct xen_vnuma_topology_info xen_vnuma_topology_info_t;
+DEFINE_XEN_GUEST_HANDLE(xen_vnuma_topology_info_t);
+
+/* Next available subop number is 29 */
+
+#endif /* __XEN_PUBLIC_MEMORY_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/hw/xen/interface/physdev.h b/include/hw/xen/interface/physdev.h
new file mode 100644
index 0000000000..f0c0d4727c
--- /dev/null
+++ b/include/hw/xen/interface/physdev.h
@@ -0,0 +1,366 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (c) 2006, Keir Fraser
+ */
+
+#ifndef __XEN_PUBLIC_PHYSDEV_H__
+#define __XEN_PUBLIC_PHYSDEV_H__
+
+#include "xen.h"
+
+/*
+ * Prototype for this hypercall is:
+ * int physdev_op(int cmd, void *args)
+ * @cmd == PHYSDEVOP_??? (physdev operation).
+ * @args == Operation-specific extra arguments (NULL if none).
+ */
+
+/*
+ * Notify end-of-interrupt (EOI) for the specified IRQ.
+ * @arg == pointer to physdev_eoi structure.
+ */
+#define PHYSDEVOP_eoi 12
+struct physdev_eoi {
+ /* IN */
+ uint32_t irq;
+};
+typedef struct physdev_eoi physdev_eoi_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_eoi_t);
+
+/*
+ * Register a shared page for the hypervisor to indicate whether the guest
+ * must issue PHYSDEVOP_eoi. The semantics of PHYSDEVOP_eoi change slightly
+ * once the guest used this function in that the associated event channel
+ * will automatically get unmasked. The page registered is used as a bit
+ * array indexed by Xen's PIRQ value.
+ */
+#define PHYSDEVOP_pirq_eoi_gmfn_v1 17
+/*
+ * Register a shared page for the hypervisor to indicate whether the
+ * guest must issue PHYSDEVOP_eoi. This hypercall is very similar to
+ * PHYSDEVOP_pirq_eoi_gmfn_v1 but it doesn't change the semantics of
+ * PHYSDEVOP_eoi. The page registered is used as a bit array indexed by
+ * Xen's PIRQ value.
+ */
+#define PHYSDEVOP_pirq_eoi_gmfn_v2 28
+struct physdev_pirq_eoi_gmfn {
+ /* IN */
+ xen_pfn_t gmfn;
+};
+typedef struct physdev_pirq_eoi_gmfn physdev_pirq_eoi_gmfn_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_pirq_eoi_gmfn_t);
+
+/*
+ * Query the status of an IRQ line.
+ * @arg == pointer to physdev_irq_status_query structure.
+ */
+#define PHYSDEVOP_irq_status_query 5
+struct physdev_irq_status_query {
+ /* IN */
+ uint32_t irq;
+ /* OUT */
+ uint32_t flags; /* XENIRQSTAT_* */
+};
+typedef struct physdev_irq_status_query physdev_irq_status_query_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_irq_status_query_t);
+
+/* Need to call PHYSDEVOP_eoi when the IRQ has been serviced? */
+#define _XENIRQSTAT_needs_eoi (0)
+#define XENIRQSTAT_needs_eoi (1U<<_XENIRQSTAT_needs_eoi)
+
+/* IRQ shared by multiple guests? */
+#define _XENIRQSTAT_shared (1)
+#define XENIRQSTAT_shared (1U<<_XENIRQSTAT_shared)
+
+/*
+ * Set the current VCPU's I/O privilege level.
+ * @arg == pointer to physdev_set_iopl structure.
+ */
+#define PHYSDEVOP_set_iopl 6
+struct physdev_set_iopl {
+ /* IN */
+ uint32_t iopl;
+};
+typedef struct physdev_set_iopl physdev_set_iopl_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_set_iopl_t);
+
+/*
+ * Set the current VCPU's I/O-port permissions bitmap.
+ * @arg == pointer to physdev_set_iobitmap structure.
+ */
+#define PHYSDEVOP_set_iobitmap 7
+struct physdev_set_iobitmap {
+ /* IN */
+#if __XEN_INTERFACE_VERSION__ >= 0x00030205
+ XEN_GUEST_HANDLE(uint8) bitmap;
+#else
+ uint8_t *bitmap;
+#endif
+ uint32_t nr_ports;
+};
+typedef struct physdev_set_iobitmap physdev_set_iobitmap_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_set_iobitmap_t);
+
+/*
+ * Read or write an IO-APIC register.
+ * @arg == pointer to physdev_apic structure.
+ */
+#define PHYSDEVOP_apic_read 8
+#define PHYSDEVOP_apic_write 9
+struct physdev_apic {
+ /* IN */
+ unsigned long apic_physbase;
+ uint32_t reg;
+ /* IN or OUT */
+ uint32_t value;
+};
+typedef struct physdev_apic physdev_apic_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_apic_t);
+
+/*
+ * Allocate or free a physical upcall vector for the specified IRQ line.
+ * @arg == pointer to physdev_irq structure.
+ */
+#define PHYSDEVOP_alloc_irq_vector 10
+#define PHYSDEVOP_free_irq_vector 11
+struct physdev_irq {
+ /* IN */
+ uint32_t irq;
+ /* IN or OUT */
+ uint32_t vector;
+};
+typedef struct physdev_irq physdev_irq_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_irq_t);
+
+#define MAP_PIRQ_TYPE_MSI 0x0
+#define MAP_PIRQ_TYPE_GSI 0x1
+#define MAP_PIRQ_TYPE_UNKNOWN 0x2
+#define MAP_PIRQ_TYPE_MSI_SEG 0x3
+#define MAP_PIRQ_TYPE_MULTI_MSI 0x4
+
+#define PHYSDEVOP_map_pirq 13
+struct physdev_map_pirq {
+ domid_t domid;
+ /* IN */
+ int type;
+ /* IN (ignored for ..._MULTI_MSI) */
+ int index;
+ /* IN or OUT */
+ int pirq;
+ /* IN - high 16 bits hold segment for ..._MSI_SEG and ..._MULTI_MSI */
+ int bus;
+ /* IN */
+ int devfn;
+ /* IN (also OUT for ..._MULTI_MSI) */
+ int entry_nr;
+ /* IN */
+ uint64_t table_base;
+};
+typedef struct physdev_map_pirq physdev_map_pirq_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_map_pirq_t);
+
+#define PHYSDEVOP_unmap_pirq 14
+struct physdev_unmap_pirq {
+ domid_t domid;
+ /* IN */
+ int pirq;
+};
+
+typedef struct physdev_unmap_pirq physdev_unmap_pirq_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_unmap_pirq_t);
+
+#define PHYSDEVOP_manage_pci_add 15
+#define PHYSDEVOP_manage_pci_remove 16
+struct physdev_manage_pci {
+ /* IN */
+ uint8_t bus;
+ uint8_t devfn;
+};
+
+typedef struct physdev_manage_pci physdev_manage_pci_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_manage_pci_t);
+
+#define PHYSDEVOP_restore_msi 19
+struct physdev_restore_msi {
+ /* IN */
+ uint8_t bus;
+ uint8_t devfn;
+};
+typedef struct physdev_restore_msi physdev_restore_msi_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_restore_msi_t);
+
+#define PHYSDEVOP_manage_pci_add_ext 20
+struct physdev_manage_pci_ext {
+ /* IN */
+ uint8_t bus;
+ uint8_t devfn;
+ uint32_t is_extfn;
+ uint32_t is_virtfn;
+ struct {
+ uint8_t bus;
+ uint8_t devfn;
+ } physfn;
+};
+
+typedef struct physdev_manage_pci_ext physdev_manage_pci_ext_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_manage_pci_ext_t);
+
+/*
+ * Argument to physdev_op_compat() hypercall. Superceded by new physdev_op()
+ * hypercall since 0x00030202.
+ */
+struct physdev_op {
+ uint32_t cmd;
+ union {
+ physdev_irq_status_query_t irq_status_query;
+ physdev_set_iopl_t set_iopl;
+ physdev_set_iobitmap_t set_iobitmap;
+ physdev_apic_t apic_op;
+ physdev_irq_t irq_op;
+ } u;
+};
+typedef struct physdev_op physdev_op_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_op_t);
+
+#define PHYSDEVOP_setup_gsi 21
+struct physdev_setup_gsi {
+ int gsi;
+ /* IN */
+ uint8_t triggering;
+ /* IN */
+ uint8_t polarity;
+ /* IN */
+};
+
+typedef struct physdev_setup_gsi physdev_setup_gsi_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_setup_gsi_t);
+
+/* leave PHYSDEVOP 22 free */
+
+/* type is MAP_PIRQ_TYPE_GSI or MAP_PIRQ_TYPE_MSI
+ * the hypercall returns a free pirq */
+#define PHYSDEVOP_get_free_pirq 23
+struct physdev_get_free_pirq {
+ /* IN */
+ int type;
+ /* OUT */
+ uint32_t pirq;
+};
+
+typedef struct physdev_get_free_pirq physdev_get_free_pirq_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_get_free_pirq_t);
+
+#define XEN_PCI_MMCFG_RESERVED 0x1
+
+#define PHYSDEVOP_pci_mmcfg_reserved 24
+struct physdev_pci_mmcfg_reserved {
+ uint64_t address;
+ uint16_t segment;
+ uint8_t start_bus;
+ uint8_t end_bus;
+ uint32_t flags;
+};
+typedef struct physdev_pci_mmcfg_reserved physdev_pci_mmcfg_reserved_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_pci_mmcfg_reserved_t);
+
+#define XEN_PCI_DEV_EXTFN 0x1
+#define XEN_PCI_DEV_VIRTFN 0x2
+#define XEN_PCI_DEV_PXM 0x4
+
+#define PHYSDEVOP_pci_device_add 25
+struct physdev_pci_device_add {
+ /* IN */
+ uint16_t seg;
+ uint8_t bus;
+ uint8_t devfn;
+ uint32_t flags;
+ struct {
+ uint8_t bus;
+ uint8_t devfn;
+ } physfn;
+ /*
+ * Optional parameters array.
+ * First element ([0]) is PXM domain associated with the device (if
+ * XEN_PCI_DEV_PXM is set)
+ */
+ uint32_t optarr[XEN_FLEX_ARRAY_DIM];
+};
+typedef struct physdev_pci_device_add physdev_pci_device_add_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_pci_device_add_t);
+
+#define PHYSDEVOP_pci_device_remove 26
+#define PHYSDEVOP_restore_msi_ext 27
+/*
+ * Dom0 should use these two to announce MMIO resources assigned to
+ * MSI-X capable devices won't (prepare) or may (release) change.
+ */
+#define PHYSDEVOP_prepare_msix 30
+#define PHYSDEVOP_release_msix 31
+struct physdev_pci_device {
+ /* IN */
+ uint16_t seg;
+ uint8_t bus;
+ uint8_t devfn;
+};
+typedef struct physdev_pci_device physdev_pci_device_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_pci_device_t);
+
+#define PHYSDEVOP_DBGP_RESET_PREPARE 1
+#define PHYSDEVOP_DBGP_RESET_DONE 2
+
+#define PHYSDEVOP_DBGP_BUS_UNKNOWN 0
+#define PHYSDEVOP_DBGP_BUS_PCI 1
+
+#define PHYSDEVOP_dbgp_op 29
+struct physdev_dbgp_op {
+ /* IN */
+ uint8_t op;
+ uint8_t bus;
+ union {
+ physdev_pci_device_t pci;
+ } u;
+};
+typedef struct physdev_dbgp_op physdev_dbgp_op_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_dbgp_op_t);
+
+/*
+ * Notify that some PIRQ-bound event channels have been unmasked.
+ * ** This command is obsolete since interface version 0x00030202 and is **
+ * ** unsupported by newer versions of Xen. **
+ */
+#define PHYSDEVOP_IRQ_UNMASK_NOTIFY 4
+
+#if __XEN_INTERFACE_VERSION__ < 0x00040600
+/*
+ * These all-capitals physdev operation names are superceded by the new names
+ * (defined above) since interface version 0x00030202. The guard above was
+ * added post-4.5 only though and hence shouldn't check for 0x00030202.
+ */
+#define PHYSDEVOP_IRQ_STATUS_QUERY PHYSDEVOP_irq_status_query
+#define PHYSDEVOP_SET_IOPL PHYSDEVOP_set_iopl
+#define PHYSDEVOP_SET_IOBITMAP PHYSDEVOP_set_iobitmap
+#define PHYSDEVOP_APIC_READ PHYSDEVOP_apic_read
+#define PHYSDEVOP_APIC_WRITE PHYSDEVOP_apic_write
+#define PHYSDEVOP_ASSIGN_VECTOR PHYSDEVOP_alloc_irq_vector
+#define PHYSDEVOP_FREE_VECTOR PHYSDEVOP_free_irq_vector
+#define PHYSDEVOP_IRQ_NEEDS_UNMASK_NOTIFY XENIRQSTAT_needs_eoi
+#define PHYSDEVOP_IRQ_SHARED XENIRQSTAT_shared
+#endif
+
+#if __XEN_INTERFACE_VERSION__ < 0x00040200
+#define PHYSDEVOP_pirq_eoi_gmfn PHYSDEVOP_pirq_eoi_gmfn_v1
+#else
+#define PHYSDEVOP_pirq_eoi_gmfn PHYSDEVOP_pirq_eoi_gmfn_v2
+#endif
+
+#endif /* __XEN_PUBLIC_PHYSDEV_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/hw/xen/interface/sched.h b/include/hw/xen/interface/sched.h
new file mode 100644
index 0000000000..b4362c6a1d
--- /dev/null
+++ b/include/hw/xen/interface/sched.h
@@ -0,0 +1,185 @@
+/* SPDX-License-Identifier: MIT */
+/******************************************************************************
+ * sched.h
+ *
+ * Scheduler state interactions
+ *
+ * Copyright (c) 2005, Keir Fraser <keir@xensource.com>
+ */
+
+#ifndef __XEN_PUBLIC_SCHED_H__
+#define __XEN_PUBLIC_SCHED_H__
+
+#include "event_channel.h"
+
+/*
+ * `incontents 150 sched Guest Scheduler Operations
+ *
+ * The SCHEDOP interface provides mechanisms for a guest to interact
+ * with the scheduler, including yield, blocking and shutting itself
+ * down.
+ */
+
+/*
+ * The prototype for this hypercall is:
+ * ` long HYPERVISOR_sched_op(enum sched_op cmd, void *arg, ...)
+ *
+ * @cmd == SCHEDOP_??? (scheduler operation).
+ * @arg == Operation-specific extra argument(s), as described below.
+ * ... == Additional Operation-specific extra arguments, described below.
+ *
+ * Versions of Xen prior to 3.0.2 provided only the following legacy version
+ * of this hypercall, supporting only the commands yield, block and shutdown:
+ * long sched_op(int cmd, unsigned long arg)
+ * @cmd == SCHEDOP_??? (scheduler operation).
+ * @arg == 0 (SCHEDOP_yield and SCHEDOP_block)
+ * == SHUTDOWN_* code (SCHEDOP_shutdown)
+ *
+ * This legacy version is available to new guests as:
+ * ` long HYPERVISOR_sched_op_compat(enum sched_op cmd, unsigned long arg)
+ */
+
+/* ` enum sched_op { // SCHEDOP_* => struct sched_* */
+/*
+ * Voluntarily yield the CPU.
+ * @arg == NULL.
+ */
+#define SCHEDOP_yield 0
+
+/*
+ * Block execution of this VCPU until an event is received for processing.
+ * If called with event upcalls masked, this operation will atomically
+ * reenable event delivery and check for pending events before blocking the
+ * VCPU. This avoids a "wakeup waiting" race.
+ * @arg == NULL.
+ */
+#define SCHEDOP_block 1
+
+/*
+ * Halt execution of this domain (all VCPUs) and notify the system controller.
+ * @arg == pointer to sched_shutdown_t structure.
+ *
+ * If the sched_shutdown_t reason is SHUTDOWN_suspend then
+ * x86 PV guests must also set RDX (EDX for 32-bit guests) to the MFN
+ * of the guest's start info page. RDX/EDX is the third hypercall
+ * argument.
+ *
+ * In addition, which reason is SHUTDOWN_suspend this hypercall
+ * returns 1 if suspend was cancelled or the domain was merely
+ * checkpointed, and 0 if it is resuming in a new domain.
+ */
+#define SCHEDOP_shutdown 2
+
+/*
+ * Poll a set of event-channel ports. Return when one or more are pending. An
+ * optional timeout may be specified.
+ * @arg == pointer to sched_poll_t structure.
+ */
+#define SCHEDOP_poll 3
+
+/*
+ * Declare a shutdown for another domain. The main use of this function is
+ * in interpreting shutdown requests and reasons for fully-virtualized
+ * domains. A para-virtualized domain may use SCHEDOP_shutdown directly.
+ * @arg == pointer to sched_remote_shutdown_t structure.
+ */
+#define SCHEDOP_remote_shutdown 4
+
+/*
+ * Latch a shutdown code, so that when the domain later shuts down it
+ * reports this code to the control tools.
+ * @arg == sched_shutdown_t, as for SCHEDOP_shutdown.
+ */
+#define SCHEDOP_shutdown_code 5
+
+/*
+ * Setup, poke and destroy a domain watchdog timer.
+ * @arg == pointer to sched_watchdog_t structure.
+ * With id == 0, setup a domain watchdog timer to cause domain shutdown
+ * after timeout, returns watchdog id.
+ * With id != 0 and timeout == 0, destroy domain watchdog timer.
+ * With id != 0 and timeout != 0, poke watchdog timer and set new timeout.
+ */
+#define SCHEDOP_watchdog 6
+
+/*
+ * Override the current vcpu affinity by pinning it to one physical cpu or
+ * undo this override restoring the previous affinity.
+ * @arg == pointer to sched_pin_override_t structure.
+ *
+ * A negative pcpu value will undo a previous pin override and restore the
+ * previous cpu affinity.
+ * This call is allowed for the hardware domain only and requires the cpu
+ * to be part of the domain's cpupool.
+ */
+#define SCHEDOP_pin_override 7
+/* ` } */
+
+struct sched_shutdown {
+ unsigned int reason; /* SHUTDOWN_* => enum sched_shutdown_reason */
+};
+typedef struct sched_shutdown sched_shutdown_t;
+DEFINE_XEN_GUEST_HANDLE(sched_shutdown_t);
+
+struct sched_poll {
+ XEN_GUEST_HANDLE(evtchn_port_t) ports;
+ unsigned int nr_ports;
+ uint64_t timeout;
+};
+typedef struct sched_poll sched_poll_t;
+DEFINE_XEN_GUEST_HANDLE(sched_poll_t);
+
+struct sched_remote_shutdown {
+ domid_t domain_id; /* Remote domain ID */
+ unsigned int reason; /* SHUTDOWN_* => enum sched_shutdown_reason */
+};
+typedef struct sched_remote_shutdown sched_remote_shutdown_t;
+DEFINE_XEN_GUEST_HANDLE(sched_remote_shutdown_t);
+
+struct sched_watchdog {
+ uint32_t id; /* watchdog ID */
+ uint32_t timeout; /* timeout */
+};
+typedef struct sched_watchdog sched_watchdog_t;
+DEFINE_XEN_GUEST_HANDLE(sched_watchdog_t);
+
+struct sched_pin_override {
+ int32_t pcpu;
+};
+typedef struct sched_pin_override sched_pin_override_t;
+DEFINE_XEN_GUEST_HANDLE(sched_pin_override_t);
+
+/*
+ * Reason codes for SCHEDOP_shutdown. These may be interpreted by control
+ * software to determine the appropriate action. For the most part, Xen does
+ * not care about the shutdown code.
+ */
+/* ` enum sched_shutdown_reason { */
+#define SHUTDOWN_poweroff 0 /* Domain exited normally. Clean up and kill. */
+#define SHUTDOWN_reboot 1 /* Clean up, kill, and then restart. */
+#define SHUTDOWN_suspend 2 /* Clean up, save suspend info, kill. */
+#define SHUTDOWN_crash 3 /* Tell controller we've crashed. */
+#define SHUTDOWN_watchdog 4 /* Restart because watchdog time expired. */
+
+/*
+ * Domain asked to perform 'soft reset' for it. The expected behavior is to
+ * reset internal Xen state for the domain returning it to the point where it
+ * was created but leaving the domain's memory contents and vCPU contexts
+ * intact. This will allow the domain to start over and set up all Xen specific
+ * interfaces again.
+ */
+#define SHUTDOWN_soft_reset 5
+#define SHUTDOWN_MAX 5 /* Maximum valid shutdown reason. */
+/* ` } */
+
+#endif /* __XEN_PUBLIC_SCHED_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/hw/xen/interface/trace.h b/include/hw/xen/interface/trace.h
new file mode 100644
index 0000000000..62a179971d
--- /dev/null
+++ b/include/hw/xen/interface/trace.h
@@ -0,0 +1,324 @@
+/* SPDX-License-Identifier: MIT */
+/******************************************************************************
+ * include/public/trace.h
+ *
+ * Mark Williamson, (C) 2004 Intel Research Cambridge
+ * Copyright (C) 2005 Bin Ren
+ */
+
+#ifndef __XEN_PUBLIC_TRACE_H__
+#define __XEN_PUBLIC_TRACE_H__
+
+#define TRACE_EXTRA_MAX 7
+#define TRACE_EXTRA_SHIFT 28
+
+/* Trace classes */
+#define TRC_CLS_SHIFT 16
+#define TRC_GEN 0x0001f000 /* General trace */
+#define TRC_SCHED 0x0002f000 /* Xen Scheduler trace */
+#define TRC_DOM0OP 0x0004f000 /* Xen DOM0 operation trace */
+#define TRC_HVM 0x0008f000 /* Xen HVM trace */
+#define TRC_MEM 0x0010f000 /* Xen memory trace */
+#define TRC_PV 0x0020f000 /* Xen PV traces */
+#define TRC_SHADOW 0x0040f000 /* Xen shadow tracing */
+#define TRC_HW 0x0080f000 /* Xen hardware-related traces */
+#define TRC_GUEST 0x0800f000 /* Guest-generated traces */
+#define TRC_ALL 0x0ffff000
+#define TRC_HD_TO_EVENT(x) ((x)&0x0fffffff)
+#define TRC_HD_CYCLE_FLAG (1UL<<31)
+#define TRC_HD_INCLUDES_CYCLE_COUNT(x) ( !!( (x) & TRC_HD_CYCLE_FLAG ) )
+#define TRC_HD_EXTRA(x) (((x)>>TRACE_EXTRA_SHIFT)&TRACE_EXTRA_MAX)
+
+/* Trace subclasses */
+#define TRC_SUBCLS_SHIFT 12
+
+/* trace subclasses for SVM */
+#define TRC_HVM_ENTRYEXIT 0x00081000 /* VMENTRY and #VMEXIT */
+#define TRC_HVM_HANDLER 0x00082000 /* various HVM handlers */
+#define TRC_HVM_EMUL 0x00084000 /* emulated devices */
+
+#define TRC_SCHED_MIN 0x00021000 /* Just runstate changes */
+#define TRC_SCHED_CLASS 0x00022000 /* Scheduler-specific */
+#define TRC_SCHED_VERBOSE 0x00028000 /* More inclusive scheduling */
+
+/*
+ * The highest 3 bits of the last 12 bits of TRC_SCHED_CLASS above are
+ * reserved for encoding what scheduler produced the information. The
+ * actual event is encoded in the last 9 bits.
+ *
+ * This means we have 8 scheduling IDs available (which means at most 8
+ * schedulers generating events) and, in each scheduler, up to 512
+ * different events.
+ */
+#define TRC_SCHED_ID_BITS 3
+#define TRC_SCHED_ID_SHIFT (TRC_SUBCLS_SHIFT - TRC_SCHED_ID_BITS)
+#define TRC_SCHED_ID_MASK (((1UL<<TRC_SCHED_ID_BITS) - 1) << TRC_SCHED_ID_SHIFT)
+#define TRC_SCHED_EVT_MASK (~(TRC_SCHED_ID_MASK))
+
+/* Per-scheduler IDs, to identify scheduler specific events */
+#define TRC_SCHED_CSCHED 0
+#define TRC_SCHED_CSCHED2 1
+/* #define XEN_SCHEDULER_SEDF 2 (Removed) */
+#define TRC_SCHED_ARINC653 3
+#define TRC_SCHED_RTDS 4
+#define TRC_SCHED_SNULL 5
+
+/* Per-scheduler tracing */
+#define TRC_SCHED_CLASS_EVT(_c, _e) \
+ ( ( TRC_SCHED_CLASS | \
+ ((TRC_SCHED_##_c << TRC_SCHED_ID_SHIFT) & TRC_SCHED_ID_MASK) ) + \
+ (_e & TRC_SCHED_EVT_MASK) )
+
+/* Trace classes for DOM0 operations */
+#define TRC_DOM0_DOMOPS 0x00041000 /* Domains manipulations */
+
+/* Trace classes for Hardware */
+#define TRC_HW_PM 0x00801000 /* Power management traces */
+#define TRC_HW_IRQ 0x00802000 /* Traces relating to the handling of IRQs */
+
+/* Trace events per class */
+#define TRC_LOST_RECORDS (TRC_GEN + 1)
+#define TRC_TRACE_WRAP_BUFFER (TRC_GEN + 2)
+#define TRC_TRACE_CPU_CHANGE (TRC_GEN + 3)
+
+#define TRC_SCHED_RUNSTATE_CHANGE (TRC_SCHED_MIN + 1)
+#define TRC_SCHED_CONTINUE_RUNNING (TRC_SCHED_MIN + 2)
+#define TRC_SCHED_DOM_ADD (TRC_SCHED_VERBOSE + 1)
+#define TRC_SCHED_DOM_REM (TRC_SCHED_VERBOSE + 2)
+#define TRC_SCHED_SLEEP (TRC_SCHED_VERBOSE + 3)
+#define TRC_SCHED_WAKE (TRC_SCHED_VERBOSE + 4)
+#define TRC_SCHED_YIELD (TRC_SCHED_VERBOSE + 5)
+#define TRC_SCHED_BLOCK (TRC_SCHED_VERBOSE + 6)
+#define TRC_SCHED_SHUTDOWN (TRC_SCHED_VERBOSE + 7)
+#define TRC_SCHED_CTL (TRC_SCHED_VERBOSE + 8)
+#define TRC_SCHED_ADJDOM (TRC_SCHED_VERBOSE + 9)
+#define TRC_SCHED_SWITCH (TRC_SCHED_VERBOSE + 10)
+#define TRC_SCHED_S_TIMER_FN (TRC_SCHED_VERBOSE + 11)
+#define TRC_SCHED_T_TIMER_FN (TRC_SCHED_VERBOSE + 12)
+#define TRC_SCHED_DOM_TIMER_FN (TRC_SCHED_VERBOSE + 13)
+#define TRC_SCHED_SWITCH_INFPREV (TRC_SCHED_VERBOSE + 14)
+#define TRC_SCHED_SWITCH_INFNEXT (TRC_SCHED_VERBOSE + 15)
+#define TRC_SCHED_SHUTDOWN_CODE (TRC_SCHED_VERBOSE + 16)
+#define TRC_SCHED_SWITCH_INFCONT (TRC_SCHED_VERBOSE + 17)
+
+#define TRC_DOM0_DOM_ADD (TRC_DOM0_DOMOPS + 1)
+#define TRC_DOM0_DOM_REM (TRC_DOM0_DOMOPS + 2)
+
+#define TRC_MEM_PAGE_GRANT_MAP (TRC_MEM + 1)
+#define TRC_MEM_PAGE_GRANT_UNMAP (TRC_MEM + 2)
+#define TRC_MEM_PAGE_GRANT_TRANSFER (TRC_MEM + 3)
+#define TRC_MEM_SET_P2M_ENTRY (TRC_MEM + 4)
+#define TRC_MEM_DECREASE_RESERVATION (TRC_MEM + 5)
+#define TRC_MEM_POD_POPULATE (TRC_MEM + 16)
+#define TRC_MEM_POD_ZERO_RECLAIM (TRC_MEM + 17)
+#define TRC_MEM_POD_SUPERPAGE_SPLINTER (TRC_MEM + 18)
+
+#define TRC_PV_ENTRY 0x00201000 /* Hypervisor entry points for PV guests. */
+#define TRC_PV_SUBCALL 0x00202000 /* Sub-call in a multicall hypercall */
+
+#define TRC_PV_HYPERCALL (TRC_PV_ENTRY + 1)
+#define TRC_PV_TRAP (TRC_PV_ENTRY + 3)
+#define TRC_PV_PAGE_FAULT (TRC_PV_ENTRY + 4)
+#define TRC_PV_FORCED_INVALID_OP (TRC_PV_ENTRY + 5)
+#define TRC_PV_EMULATE_PRIVOP (TRC_PV_ENTRY + 6)
+#define TRC_PV_EMULATE_4GB (TRC_PV_ENTRY + 7)
+#define TRC_PV_MATH_STATE_RESTORE (TRC_PV_ENTRY + 8)
+#define TRC_PV_PAGING_FIXUP (TRC_PV_ENTRY + 9)
+#define TRC_PV_GDT_LDT_MAPPING_FAULT (TRC_PV_ENTRY + 10)
+#define TRC_PV_PTWR_EMULATION (TRC_PV_ENTRY + 11)
+#define TRC_PV_PTWR_EMULATION_PAE (TRC_PV_ENTRY + 12)
+#define TRC_PV_HYPERCALL_V2 (TRC_PV_ENTRY + 13)
+#define TRC_PV_HYPERCALL_SUBCALL (TRC_PV_SUBCALL + 14)
+
+/*
+ * TRC_PV_HYPERCALL_V2 format
+ *
+ * Only some of the hypercall argument are recorded. Bit fields A0 to
+ * A5 in the first extra word are set if the argument is present and
+ * the arguments themselves are packed sequentially in the following
+ * words.
+ *
+ * The TRC_64_FLAG bit is not set for these events (even if there are
+ * 64-bit arguments in the record).
+ *
+ * Word
+ * 0 bit 31 30|29 28|27 26|25 24|23 22|21 20|19 ... 0
+ * A5 |A4 |A3 |A2 |A1 |A0 |Hypercall op
+ * 1 First 32 bit (or low word of first 64 bit) arg in record
+ * 2 Second 32 bit (or high word of first 64 bit) arg in record
+ * ...
+ *
+ * A0-A5 bitfield values:
+ *
+ * 00b Argument not present
+ * 01b 32-bit argument present
+ * 10b 64-bit argument present
+ * 11b Reserved
+ */
+#define TRC_PV_HYPERCALL_V2_ARG_32(i) (0x1 << (20 + 2*(i)))
+#define TRC_PV_HYPERCALL_V2_ARG_64(i) (0x2 << (20 + 2*(i)))
+#define TRC_PV_HYPERCALL_V2_ARG_MASK (0xfff00000)
+
+#define TRC_SHADOW_NOT_SHADOW (TRC_SHADOW + 1)
+#define TRC_SHADOW_FAST_PROPAGATE (TRC_SHADOW + 2)
+#define TRC_SHADOW_FAST_MMIO (TRC_SHADOW + 3)
+#define TRC_SHADOW_FALSE_FAST_PATH (TRC_SHADOW + 4)
+#define TRC_SHADOW_MMIO (TRC_SHADOW + 5)
+#define TRC_SHADOW_FIXUP (TRC_SHADOW + 6)
+#define TRC_SHADOW_DOMF_DYING (TRC_SHADOW + 7)
+#define TRC_SHADOW_EMULATE (TRC_SHADOW + 8)
+#define TRC_SHADOW_EMULATE_UNSHADOW_USER (TRC_SHADOW + 9)
+#define TRC_SHADOW_EMULATE_UNSHADOW_EVTINJ (TRC_SHADOW + 10)
+#define TRC_SHADOW_EMULATE_UNSHADOW_UNHANDLED (TRC_SHADOW + 11)
+#define TRC_SHADOW_WRMAP_BF (TRC_SHADOW + 12)
+#define TRC_SHADOW_PREALLOC_UNPIN (TRC_SHADOW + 13)
+#define TRC_SHADOW_RESYNC_FULL (TRC_SHADOW + 14)
+#define TRC_SHADOW_RESYNC_ONLY (TRC_SHADOW + 15)
+
+/* trace events per subclass */
+#define TRC_HVM_NESTEDFLAG (0x400)
+#define TRC_HVM_VMENTRY (TRC_HVM_ENTRYEXIT + 0x01)
+#define TRC_HVM_VMEXIT (TRC_HVM_ENTRYEXIT + 0x02)
+#define TRC_HVM_VMEXIT64 (TRC_HVM_ENTRYEXIT + TRC_64_FLAG + 0x02)
+#define TRC_HVM_PF_XEN (TRC_HVM_HANDLER + 0x01)
+#define TRC_HVM_PF_XEN64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x01)
+#define TRC_HVM_PF_INJECT (TRC_HVM_HANDLER + 0x02)
+#define TRC_HVM_PF_INJECT64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x02)
+#define TRC_HVM_INJ_EXC (TRC_HVM_HANDLER + 0x03)
+#define TRC_HVM_INJ_VIRQ (TRC_HVM_HANDLER + 0x04)
+#define TRC_HVM_REINJ_VIRQ (TRC_HVM_HANDLER + 0x05)
+#define TRC_HVM_IO_READ (TRC_HVM_HANDLER + 0x06)
+#define TRC_HVM_IO_WRITE (TRC_HVM_HANDLER + 0x07)
+#define TRC_HVM_CR_READ (TRC_HVM_HANDLER + 0x08)
+#define TRC_HVM_CR_READ64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x08)
+#define TRC_HVM_CR_WRITE (TRC_HVM_HANDLER + 0x09)
+#define TRC_HVM_CR_WRITE64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x09)
+#define TRC_HVM_DR_READ (TRC_HVM_HANDLER + 0x0A)
+#define TRC_HVM_DR_WRITE (TRC_HVM_HANDLER + 0x0B)
+#define TRC_HVM_MSR_READ (TRC_HVM_HANDLER + 0x0C)
+#define TRC_HVM_MSR_WRITE (TRC_HVM_HANDLER + 0x0D)
+#define TRC_HVM_CPUID (TRC_HVM_HANDLER + 0x0E)
+#define TRC_HVM_INTR (TRC_HVM_HANDLER + 0x0F)
+#define TRC_HVM_NMI (TRC_HVM_HANDLER + 0x10)
+#define TRC_HVM_SMI (TRC_HVM_HANDLER + 0x11)
+#define TRC_HVM_VMMCALL (TRC_HVM_HANDLER + 0x12)
+#define TRC_HVM_HLT (TRC_HVM_HANDLER + 0x13)
+#define TRC_HVM_INVLPG (TRC_HVM_HANDLER + 0x14)
+#define TRC_HVM_INVLPG64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x14)
+#define TRC_HVM_MCE (TRC_HVM_HANDLER + 0x15)
+#define TRC_HVM_IOPORT_READ (TRC_HVM_HANDLER + 0x16)
+#define TRC_HVM_IOMEM_READ (TRC_HVM_HANDLER + 0x17)
+#define TRC_HVM_CLTS (TRC_HVM_HANDLER + 0x18)
+#define TRC_HVM_LMSW (TRC_HVM_HANDLER + 0x19)
+#define TRC_HVM_LMSW64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x19)
+#define TRC_HVM_RDTSC (TRC_HVM_HANDLER + 0x1a)
+#define TRC_HVM_INTR_WINDOW (TRC_HVM_HANDLER + 0x20)
+#define TRC_HVM_NPF (TRC_HVM_HANDLER + 0x21)
+#define TRC_HVM_REALMODE_EMULATE (TRC_HVM_HANDLER + 0x22)
+#define TRC_HVM_TRAP (TRC_HVM_HANDLER + 0x23)
+#define TRC_HVM_TRAP_DEBUG (TRC_HVM_HANDLER + 0x24)
+#define TRC_HVM_VLAPIC (TRC_HVM_HANDLER + 0x25)
+#define TRC_HVM_XCR_READ64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x26)
+#define TRC_HVM_XCR_WRITE64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x27)
+
+#define TRC_HVM_IOPORT_WRITE (TRC_HVM_HANDLER + 0x216)
+#define TRC_HVM_IOMEM_WRITE (TRC_HVM_HANDLER + 0x217)
+
+/* Trace events for emulated devices */
+#define TRC_HVM_EMUL_HPET_START_TIMER (TRC_HVM_EMUL + 0x1)
+#define TRC_HVM_EMUL_PIT_START_TIMER (TRC_HVM_EMUL + 0x2)
+#define TRC_HVM_EMUL_RTC_START_TIMER (TRC_HVM_EMUL + 0x3)
+#define TRC_HVM_EMUL_LAPIC_START_TIMER (TRC_HVM_EMUL + 0x4)
+#define TRC_HVM_EMUL_HPET_STOP_TIMER (TRC_HVM_EMUL + 0x5)
+#define TRC_HVM_EMUL_PIT_STOP_TIMER (TRC_HVM_EMUL + 0x6)
+#define TRC_HVM_EMUL_RTC_STOP_TIMER (TRC_HVM_EMUL + 0x7)
+#define TRC_HVM_EMUL_LAPIC_STOP_TIMER (TRC_HVM_EMUL + 0x8)
+#define TRC_HVM_EMUL_PIT_TIMER_CB (TRC_HVM_EMUL + 0x9)
+#define TRC_HVM_EMUL_LAPIC_TIMER_CB (TRC_HVM_EMUL + 0xA)
+#define TRC_HVM_EMUL_PIC_INT_OUTPUT (TRC_HVM_EMUL + 0xB)
+#define TRC_HVM_EMUL_PIC_KICK (TRC_HVM_EMUL + 0xC)
+#define TRC_HVM_EMUL_PIC_INTACK (TRC_HVM_EMUL + 0xD)
+#define TRC_HVM_EMUL_PIC_POSEDGE (TRC_HVM_EMUL + 0xE)
+#define TRC_HVM_EMUL_PIC_NEGEDGE (TRC_HVM_EMUL + 0xF)
+#define TRC_HVM_EMUL_PIC_PEND_IRQ_CALL (TRC_HVM_EMUL + 0x10)
+#define TRC_HVM_EMUL_LAPIC_PIC_INTR (TRC_HVM_EMUL + 0x11)
+
+/* trace events for per class */
+#define TRC_PM_FREQ_CHANGE (TRC_HW_PM + 0x01)
+#define TRC_PM_IDLE_ENTRY (TRC_HW_PM + 0x02)
+#define TRC_PM_IDLE_EXIT (TRC_HW_PM + 0x03)
+
+/* Trace events for IRQs */
+#define TRC_HW_IRQ_MOVE_CLEANUP_DELAY (TRC_HW_IRQ + 0x1)
+#define TRC_HW_IRQ_MOVE_CLEANUP (TRC_HW_IRQ + 0x2)
+#define TRC_HW_IRQ_BIND_VECTOR (TRC_HW_IRQ + 0x3)
+#define TRC_HW_IRQ_CLEAR_VECTOR (TRC_HW_IRQ + 0x4)
+#define TRC_HW_IRQ_MOVE_FINISH (TRC_HW_IRQ + 0x5)
+#define TRC_HW_IRQ_ASSIGN_VECTOR (TRC_HW_IRQ + 0x6)
+#define TRC_HW_IRQ_UNMAPPED_VECTOR (TRC_HW_IRQ + 0x7)
+#define TRC_HW_IRQ_HANDLED (TRC_HW_IRQ + 0x8)
+
+/*
+ * Event Flags
+ *
+ * Some events (e.g, TRC_PV_TRAP and TRC_HVM_IOMEM_READ) have multiple
+ * record formats. These event flags distinguish between the
+ * different formats.
+ */
+#define TRC_64_FLAG 0x100 /* Addresses are 64 bits (instead of 32 bits) */
+
+/* This structure represents a single trace buffer record. */
+struct t_rec {
+ uint32_t event:28;
+ uint32_t extra_u32:3; /* # entries in trailing extra_u32[] array */
+ uint32_t cycles_included:1; /* u.cycles or u.no_cycles? */
+ union {
+ struct {
+ uint32_t cycles_lo, cycles_hi; /* cycle counter timestamp */
+ uint32_t extra_u32[7]; /* event data items */
+ } cycles;
+ struct {
+ uint32_t extra_u32[7]; /* event data items */
+ } nocycles;
+ } u;
+};
+
+/*
+ * This structure contains the metadata for a single trace buffer. The head
+ * field, indexes into an array of struct t_rec's.
+ */
+struct t_buf {
+ /* Assume the data buffer size is X. X is generally not a power of 2.
+ * CONS and PROD are incremented modulo (2*X):
+ * 0 <= cons < 2*X
+ * 0 <= prod < 2*X
+ * This is done because addition modulo X breaks at 2^32 when X is not a
+ * power of 2:
+ * (((2^32 - 1) % X) + 1) % X != (2^32) % X
+ */
+ uint32_t cons; /* Offset of next item to be consumed by control tools. */
+ uint32_t prod; /* Offset of next item to be produced by Xen. */
+ /* Records follow immediately after the meta-data header. */
+};
+
+/* Structure used to pass MFNs to the trace buffers back to trace consumers.
+ * Offset is an offset into the mapped structure where the mfn list will be held.
+ * MFNs will be at ((unsigned long *)(t_info))+(t_info->cpu_offset[cpu]).
+ */
+struct t_info {
+ uint16_t tbuf_size; /* Size in pages of each trace buffer */
+ uint16_t mfn_offset[]; /* Offset within t_info structure of the page list per cpu */
+ /* MFN lists immediately after the header */
+};
+
+#endif /* __XEN_PUBLIC_TRACE_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/hw/xen/interface/vcpu.h b/include/hw/xen/interface/vcpu.h
new file mode 100644
index 0000000000..81a3b3a743
--- /dev/null
+++ b/include/hw/xen/interface/vcpu.h
@@ -0,0 +1,231 @@
+/* SPDX-License-Identifier: MIT */
+/******************************************************************************
+ * vcpu.h
+ *
+ * VCPU initialisation, query, and hotplug.
+ *
+ * Copyright (c) 2005, Keir Fraser <keir@xensource.com>
+ */
+
+#ifndef __XEN_PUBLIC_VCPU_H__
+#define __XEN_PUBLIC_VCPU_H__
+
+#include "xen.h"
+
+/*
+ * Prototype for this hypercall is:
+ * long vcpu_op(int cmd, unsigned int vcpuid, void *extra_args)
+ * @cmd == VCPUOP_??? (VCPU operation).
+ * @vcpuid == VCPU to operate on.
+ * @extra_args == Operation-specific extra arguments (NULL if none).
+ */
+
+/*
+ * Initialise a VCPU. Each VCPU can be initialised only once. A
+ * newly-initialised VCPU will not run until it is brought up by VCPUOP_up.
+ *
+ * @extra_arg == For PV or ARM guests this is a pointer to a vcpu_guest_context
+ * structure containing the initial state for the VCPU. For x86
+ * HVM based guests this is a pointer to a vcpu_hvm_context
+ * structure.
+ */
+#define VCPUOP_initialise 0
+
+/*
+ * Bring up a VCPU. This makes the VCPU runnable. This operation will fail
+ * if the VCPU has not been initialised (VCPUOP_initialise).
+ */
+#define VCPUOP_up 1
+
+/*
+ * Bring down a VCPU (i.e., make it non-runnable).
+ * There are a few caveats that callers should observe:
+ * 1. This operation may return, and VCPU_is_up may return false, before the
+ * VCPU stops running (i.e., the command is asynchronous). It is a good
+ * idea to ensure that the VCPU has entered a non-critical loop before
+ * bringing it down. Alternatively, this operation is guaranteed
+ * synchronous if invoked by the VCPU itself.
+ * 2. After a VCPU is initialised, there is currently no way to drop all its
+ * references to domain memory. Even a VCPU that is down still holds
+ * memory references via its pagetable base pointer and GDT. It is good
+ * practise to move a VCPU onto an 'idle' or default page table, LDT and
+ * GDT before bringing it down.
+ */
+#define VCPUOP_down 2
+
+/* Returns 1 if the given VCPU is up. */
+#define VCPUOP_is_up 3
+
+/*
+ * Return information about the state and running time of a VCPU.
+ * @extra_arg == pointer to vcpu_runstate_info structure.
+ */
+#define VCPUOP_get_runstate_info 4
+struct vcpu_runstate_info {
+ /* VCPU's current state (RUNSTATE_*). */
+ int state;
+ /* When was current state entered (system time, ns)? */
+ uint64_t state_entry_time;
+ /*
+ * Update indicator set in state_entry_time:
+ * When activated via VMASST_TYPE_runstate_update_flag, set during
+ * updates in guest memory mapped copy of vcpu_runstate_info.
+ */
+#define XEN_RUNSTATE_UPDATE (xen_mk_ullong(1) << 63)
+ /*
+ * Time spent in each RUNSTATE_* (ns). The sum of these times is
+ * guaranteed not to drift from system time.
+ */
+ uint64_t time[4];
+};
+typedef struct vcpu_runstate_info vcpu_runstate_info_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_runstate_info_t);
+
+/* VCPU is currently running on a physical CPU. */
+#define RUNSTATE_running 0
+
+/* VCPU is runnable, but not currently scheduled on any physical CPU. */
+#define RUNSTATE_runnable 1
+
+/* VCPU is blocked (a.k.a. idle). It is therefore not runnable. */
+#define RUNSTATE_blocked 2
+
+/*
+ * VCPU is not runnable, but it is not blocked.
+ * This is a 'catch all' state for things like hotplug and pauses by the
+ * system administrator (or for critical sections in the hypervisor).
+ * RUNSTATE_blocked dominates this state (it is the preferred state).
+ */
+#define RUNSTATE_offline 3
+
+/*
+ * Register a shared memory area from which the guest may obtain its own
+ * runstate information without needing to execute a hypercall.
+ * Notes:
+ * 1. The registered address may be virtual or physical or guest handle,
+ * depending on the platform. Virtual address or guest handle should be
+ * registered on x86 systems.
+ * 2. Only one shared area may be registered per VCPU. The shared area is
+ * updated by the hypervisor each time the VCPU is scheduled. Thus
+ * runstate.state will always be RUNSTATE_running and
+ * runstate.state_entry_time will indicate the system time at which the
+ * VCPU was last scheduled to run.
+ * @extra_arg == pointer to vcpu_register_runstate_memory_area structure.
+ */
+#define VCPUOP_register_runstate_memory_area 5
+struct vcpu_register_runstate_memory_area {
+ union {
+ XEN_GUEST_HANDLE(vcpu_runstate_info_t) h;
+ struct vcpu_runstate_info *v;
+ uint64_t p;
+ } addr;
+};
+typedef struct vcpu_register_runstate_memory_area vcpu_register_runstate_memory_area_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_register_runstate_memory_area_t);
+
+/*
+ * Set or stop a VCPU's periodic timer. Every VCPU has one periodic timer
+ * which can be set via these commands. Periods smaller than one millisecond
+ * may not be supported.
+ */
+#define VCPUOP_set_periodic_timer 6 /* arg == vcpu_set_periodic_timer_t */
+#define VCPUOP_stop_periodic_timer 7 /* arg == NULL */
+struct vcpu_set_periodic_timer {
+ uint64_t period_ns;
+};
+typedef struct vcpu_set_periodic_timer vcpu_set_periodic_timer_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_set_periodic_timer_t);
+
+/*
+ * Set or stop a VCPU's single-shot timer. Every VCPU has one single-shot
+ * timer which can be set via these commands.
+ */
+#define VCPUOP_set_singleshot_timer 8 /* arg == vcpu_set_singleshot_timer_t */
+#define VCPUOP_stop_singleshot_timer 9 /* arg == NULL */
+struct vcpu_set_singleshot_timer {
+ uint64_t timeout_abs_ns; /* Absolute system time value in nanoseconds. */
+ uint32_t flags; /* VCPU_SSHOTTMR_??? */
+};
+typedef struct vcpu_set_singleshot_timer vcpu_set_singleshot_timer_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_set_singleshot_timer_t);
+
+/* Flags to VCPUOP_set_singleshot_timer. */
+ /* Require the timeout to be in the future (return -ETIME if it's passed). */
+#define _VCPU_SSHOTTMR_future (0)
+#define VCPU_SSHOTTMR_future (1U << _VCPU_SSHOTTMR_future)
+
+/*
+ * Register a memory location in the guest address space for the
+ * vcpu_info structure. This allows the guest to place the vcpu_info
+ * structure in a convenient place, such as in a per-cpu data area.
+ * The pointer need not be page aligned, but the structure must not
+ * cross a page boundary.
+ *
+ * This may be called only once per vcpu.
+ */
+#define VCPUOP_register_vcpu_info 10 /* arg == vcpu_register_vcpu_info_t */
+struct vcpu_register_vcpu_info {
+ uint64_t mfn; /* mfn of page to place vcpu_info */
+ uint32_t offset; /* offset within page */
+ uint32_t rsvd; /* unused */
+};
+typedef struct vcpu_register_vcpu_info vcpu_register_vcpu_info_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_register_vcpu_info_t);
+
+/* Send an NMI to the specified VCPU. @extra_arg == NULL. */
+#define VCPUOP_send_nmi 11
+
+/*
+ * Get the physical ID information for a pinned vcpu's underlying physical
+ * processor. The physical ID informmation is architecture-specific.
+ * On x86: id[31:0]=apic_id, id[63:32]=acpi_id.
+ * This command returns -EINVAL if it is not a valid operation for this VCPU.
+ */
+#define VCPUOP_get_physid 12 /* arg == vcpu_get_physid_t */
+struct vcpu_get_physid {
+ uint64_t phys_id;
+};
+typedef struct vcpu_get_physid vcpu_get_physid_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_get_physid_t);
+#define xen_vcpu_physid_to_x86_apicid(physid) ((uint32_t)(physid))
+#define xen_vcpu_physid_to_x86_acpiid(physid) ((uint32_t)((physid) >> 32))
+
+/*
+ * Register a memory location to get a secondary copy of the vcpu time
+ * parameters. The master copy still exists as part of the vcpu shared
+ * memory area, and this secondary copy is updated whenever the master copy
+ * is updated (and using the same versioning scheme for synchronisation).
+ *
+ * The intent is that this copy may be mapped (RO) into userspace so
+ * that usermode can compute system time using the time info and the
+ * tsc. Usermode will see an array of vcpu_time_info structures, one
+ * for each vcpu, and choose the right one by an existing mechanism
+ * which allows it to get the current vcpu number (such as via a
+ * segment limit). It can then apply the normal algorithm to compute
+ * system time from the tsc.
+ *
+ * @extra_arg == pointer to vcpu_register_time_info_memory_area structure.
+ */
+#define VCPUOP_register_vcpu_time_memory_area 13
+DEFINE_XEN_GUEST_HANDLE(vcpu_time_info_t);
+struct vcpu_register_time_memory_area {
+ union {
+ XEN_GUEST_HANDLE(vcpu_time_info_t) h;
+ struct vcpu_time_info *v;
+ uint64_t p;
+ } addr;
+};
+typedef struct vcpu_register_time_memory_area vcpu_register_time_memory_area_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_register_time_memory_area_t);
+
+#endif /* __XEN_PUBLIC_VCPU_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/hw/xen/interface/version.h b/include/hw/xen/interface/version.h
new file mode 100644
index 0000000000..9c78b4f3b6
--- /dev/null
+++ b/include/hw/xen/interface/version.h
@@ -0,0 +1,96 @@
+/* SPDX-License-Identifier: MIT */
+/******************************************************************************
+ * version.h
+ *
+ * Xen version, type, and compile information.
+ *
+ * Copyright (c) 2005, Nguyen Anh Quynh <aquynh@gmail.com>
+ * Copyright (c) 2005, Keir Fraser <keir@xensource.com>
+ */
+
+#ifndef __XEN_PUBLIC_VERSION_H__
+#define __XEN_PUBLIC_VERSION_H__
+
+#include "xen.h"
+
+/* NB. All ops return zero on success, except XENVER_{version,pagesize}
+ * XENVER_{version,pagesize,build_id} */
+
+/* arg == NULL; returns major:minor (16:16). */
+#define XENVER_version 0
+
+/* arg == xen_extraversion_t. */
+#define XENVER_extraversion 1
+typedef char xen_extraversion_t[16];
+#define XEN_EXTRAVERSION_LEN (sizeof(xen_extraversion_t))
+
+/* arg == xen_compile_info_t. */
+#define XENVER_compile_info 2
+struct xen_compile_info {
+ char compiler[64];
+ char compile_by[16];
+ char compile_domain[32];
+ char compile_date[32];
+};
+typedef struct xen_compile_info xen_compile_info_t;
+
+#define XENVER_capabilities 3
+typedef char xen_capabilities_info_t[1024];
+#define XEN_CAPABILITIES_INFO_LEN (sizeof(xen_capabilities_info_t))
+
+#define XENVER_changeset 4
+typedef char xen_changeset_info_t[64];
+#define XEN_CHANGESET_INFO_LEN (sizeof(xen_changeset_info_t))
+
+#define XENVER_platform_parameters 5
+struct xen_platform_parameters {
+ xen_ulong_t virt_start;
+};
+typedef struct xen_platform_parameters xen_platform_parameters_t;
+
+#define XENVER_get_features 6
+struct xen_feature_info {
+ unsigned int submap_idx; /* IN: which 32-bit submap to return */
+ uint32_t submap; /* OUT: 32-bit submap */
+};
+typedef struct xen_feature_info xen_feature_info_t;
+
+/* Declares the features reported by XENVER_get_features. */
+#include "features.h"
+
+/* arg == NULL; returns host memory page size. */
+#define XENVER_pagesize 7
+
+/* arg == xen_domain_handle_t.
+ *
+ * The toolstack fills it out for guest consumption. It is intended to hold
+ * the UUID of the guest.
+ */
+#define XENVER_guest_handle 8
+
+#define XENVER_commandline 9
+typedef char xen_commandline_t[1024];
+
+/*
+ * Return value is the number of bytes written, or XEN_Exx on error.
+ * Calling with empty parameter returns the size of build_id.
+ */
+#define XENVER_build_id 10
+struct xen_build_id {
+ uint32_t len; /* IN: size of buf[]. */
+ unsigned char buf[XEN_FLEX_ARRAY_DIM];
+ /* OUT: Variable length buffer with build_id. */
+};
+typedef struct xen_build_id xen_build_id_t;
+
+#endif /* __XEN_PUBLIC_VERSION_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/hw/xen/interface/xen-compat.h b/include/hw/xen/interface/xen-compat.h
new file mode 100644
index 0000000000..97fe698498
--- /dev/null
+++ b/include/hw/xen/interface/xen-compat.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: MIT */
+/******************************************************************************
+ * xen-compat.h
+ *
+ * Guest OS interface to Xen. Compatibility layer.
+ *
+ * Copyright (c) 2006, Christian Limpach
+ */
+
+#ifndef __XEN_PUBLIC_XEN_COMPAT_H__
+#define __XEN_PUBLIC_XEN_COMPAT_H__
+
+#define __XEN_LATEST_INTERFACE_VERSION__ 0x00040e00
+
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+/* Xen is built with matching headers and implements the latest interface. */
+#define __XEN_INTERFACE_VERSION__ __XEN_LATEST_INTERFACE_VERSION__
+#elif !defined(__XEN_INTERFACE_VERSION__)
+/* Guests which do not specify a version get the legacy interface. */
+#define __XEN_INTERFACE_VERSION__ 0x00000000
+#endif
+
+#if __XEN_INTERFACE_VERSION__ > __XEN_LATEST_INTERFACE_VERSION__
+#error "These header files do not support the requested interface version."
+#endif
+
+#define COMPAT_FLEX_ARRAY_DIM XEN_FLEX_ARRAY_DIM
+
+#endif /* __XEN_PUBLIC_XEN_COMPAT_H__ */
diff --git a/include/hw/xen/interface/xen.h b/include/hw/xen/interface/xen.h
new file mode 100644
index 0000000000..920567e006
--- /dev/null
+++ b/include/hw/xen/interface/xen.h
@@ -0,0 +1,1032 @@
+/* SPDX-License-Identifier: MIT */
+/******************************************************************************
+ * xen.h
+ *
+ * Guest OS interface to Xen.
+ *
+ * Copyright (c) 2004, K A Fraser
+ */
+
+#ifndef __XEN_PUBLIC_XEN_H__
+#define __XEN_PUBLIC_XEN_H__
+
+#include "xen-compat.h"
+
+#if defined(__i386__) || defined(__x86_64__)
+#include "arch-x86/xen.h"
+#elif defined(__arm__) || defined (__aarch64__)
+#include "arch-arm.h"
+#else
+#error "Unsupported architecture"
+#endif
+
+#ifndef __ASSEMBLY__
+/* Guest handles for primitive C types. */
+DEFINE_XEN_GUEST_HANDLE(char);
+__DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char);
+DEFINE_XEN_GUEST_HANDLE(int);
+__DEFINE_XEN_GUEST_HANDLE(uint, unsigned int);
+#if __XEN_INTERFACE_VERSION__ < 0x00040300
+DEFINE_XEN_GUEST_HANDLE(long);
+__DEFINE_XEN_GUEST_HANDLE(ulong, unsigned long);
+#endif
+DEFINE_XEN_GUEST_HANDLE(void);
+
+DEFINE_XEN_GUEST_HANDLE(uint64_t);
+DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
+DEFINE_XEN_GUEST_HANDLE(xen_ulong_t);
+
+/* Define a variable length array (depends on compiler). */
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define XEN_FLEX_ARRAY_DIM
+#elif defined(__GNUC__)
+#define XEN_FLEX_ARRAY_DIM 0
+#else
+#define XEN_FLEX_ARRAY_DIM 1 /* variable size */
+#endif
+
+/* Turn a plain number into a C unsigned (long (long)) constant. */
+#define __xen_mk_uint(x) x ## U
+#define __xen_mk_ulong(x) x ## UL
+#ifndef __xen_mk_ullong
+# define __xen_mk_ullong(x) x ## ULL
+#endif
+#define xen_mk_uint(x) __xen_mk_uint(x)
+#define xen_mk_ulong(x) __xen_mk_ulong(x)
+#define xen_mk_ullong(x) __xen_mk_ullong(x)
+
+#else
+
+/* In assembly code we cannot use C numeric constant suffixes. */
+#define xen_mk_uint(x) x
+#define xen_mk_ulong(x) x
+#define xen_mk_ullong(x) x
+
+#endif
+
+/*
+ * HYPERCALLS
+ */
+
+/* `incontents 100 hcalls List of hypercalls
+ * ` enum hypercall_num { // __HYPERVISOR_* => HYPERVISOR_*()
+ */
+
+#define __HYPERVISOR_set_trap_table 0
+#define __HYPERVISOR_mmu_update 1
+#define __HYPERVISOR_set_gdt 2
+#define __HYPERVISOR_stack_switch 3
+#define __HYPERVISOR_set_callbacks 4
+#define __HYPERVISOR_fpu_taskswitch 5
+#define __HYPERVISOR_sched_op_compat 6 /* compat since 0x00030101 */
+#define __HYPERVISOR_platform_op 7
+#define __HYPERVISOR_set_debugreg 8
+#define __HYPERVISOR_get_debugreg 9
+#define __HYPERVISOR_update_descriptor 10
+#define __HYPERVISOR_memory_op 12
+#define __HYPERVISOR_multicall 13
+#define __HYPERVISOR_update_va_mapping 14
+#define __HYPERVISOR_set_timer_op 15
+#define __HYPERVISOR_event_channel_op_compat 16 /* compat since 0x00030202 */
+#define __HYPERVISOR_xen_version 17
+#define __HYPERVISOR_console_io 18
+#define __HYPERVISOR_physdev_op_compat 19 /* compat since 0x00030202 */
+#define __HYPERVISOR_grant_table_op 20
+#define __HYPERVISOR_vm_assist 21
+#define __HYPERVISOR_update_va_mapping_otherdomain 22
+#define __HYPERVISOR_iret 23 /* x86 only */
+#define __HYPERVISOR_vcpu_op 24
+#define __HYPERVISOR_set_segment_base 25 /* x86/64 only */
+#define __HYPERVISOR_mmuext_op 26
+#define __HYPERVISOR_xsm_op 27
+#define __HYPERVISOR_nmi_op 28
+#define __HYPERVISOR_sched_op 29
+#define __HYPERVISOR_callback_op 30
+#define __HYPERVISOR_xenoprof_op 31
+#define __HYPERVISOR_event_channel_op 32
+#define __HYPERVISOR_physdev_op 33
+#define __HYPERVISOR_hvm_op 34
+#define __HYPERVISOR_sysctl 35
+#define __HYPERVISOR_domctl 36
+#define __HYPERVISOR_kexec_op 37
+#define __HYPERVISOR_tmem_op 38
+#define __HYPERVISOR_argo_op 39
+#define __HYPERVISOR_xenpmu_op 40
+#define __HYPERVISOR_dm_op 41
+#define __HYPERVISOR_hypfs_op 42
+
+/* Architecture-specific hypercall definitions. */
+#define __HYPERVISOR_arch_0 48
+#define __HYPERVISOR_arch_1 49
+#define __HYPERVISOR_arch_2 50
+#define __HYPERVISOR_arch_3 51
+#define __HYPERVISOR_arch_4 52
+#define __HYPERVISOR_arch_5 53
+#define __HYPERVISOR_arch_6 54
+#define __HYPERVISOR_arch_7 55
+
+/* ` } */
+
+/*
+ * HYPERCALL COMPATIBILITY.
+ */
+
+/* New sched_op hypercall introduced in 0x00030101. */
+#if __XEN_INTERFACE_VERSION__ < 0x00030101
+#undef __HYPERVISOR_sched_op
+#define __HYPERVISOR_sched_op __HYPERVISOR_sched_op_compat
+#endif
+
+/* New event-channel and physdev hypercalls introduced in 0x00030202. */
+#if __XEN_INTERFACE_VERSION__ < 0x00030202
+#undef __HYPERVISOR_event_channel_op
+#define __HYPERVISOR_event_channel_op __HYPERVISOR_event_channel_op_compat
+#undef __HYPERVISOR_physdev_op
+#define __HYPERVISOR_physdev_op __HYPERVISOR_physdev_op_compat
+#endif
+
+/* New platform_op hypercall introduced in 0x00030204. */
+#if __XEN_INTERFACE_VERSION__ < 0x00030204
+#define __HYPERVISOR_dom0_op __HYPERVISOR_platform_op
+#endif
+
+/*
+ * VIRTUAL INTERRUPTS
+ *
+ * Virtual interrupts that a guest OS may receive from Xen.
+ *
+ * In the side comments, 'V.' denotes a per-VCPU VIRQ while 'G.' denotes a
+ * global VIRQ. The former can be bound once per VCPU and cannot be re-bound.
+ * The latter can be allocated only once per guest: they must initially be
+ * allocated to VCPU0 but can subsequently be re-bound.
+ */
+/* ` enum virq { */
+#define VIRQ_TIMER 0 /* V. Timebase update, and/or requested timeout. */
+#define VIRQ_DEBUG 1 /* V. Request guest to dump debug info. */
+#define VIRQ_CONSOLE 2 /* G. (DOM0) Bytes received on emergency console. */
+#define VIRQ_DOM_EXC 3 /* G. (DOM0) Exceptional event for some domain. */
+#define VIRQ_TBUF 4 /* G. (DOM0) Trace buffer has records available. */
+#define VIRQ_DEBUGGER 6 /* G. (DOM0) A domain has paused for debugging. */
+#define VIRQ_XENOPROF 7 /* V. XenOprofile interrupt: new sample available */
+#define VIRQ_CON_RING 8 /* G. (DOM0) Bytes received on console */
+#define VIRQ_PCPU_STATE 9 /* G. (DOM0) PCPU state changed */
+#define VIRQ_MEM_EVENT 10 /* G. (DOM0) A memory event has occurred */
+#define VIRQ_ARGO 11 /* G. Argo interdomain message notification */
+#define VIRQ_ENOMEM 12 /* G. (DOM0) Low on heap memory */
+#define VIRQ_XENPMU 13 /* V. PMC interrupt */
+
+/* Architecture-specific VIRQ definitions. */
+#define VIRQ_ARCH_0 16
+#define VIRQ_ARCH_1 17
+#define VIRQ_ARCH_2 18
+#define VIRQ_ARCH_3 19
+#define VIRQ_ARCH_4 20
+#define VIRQ_ARCH_5 21
+#define VIRQ_ARCH_6 22
+#define VIRQ_ARCH_7 23
+/* ` } */
+
+#define NR_VIRQS 24
+
+/*
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_mmu_update(const struct mmu_update reqs[],
+ * ` unsigned count, unsigned *done_out,
+ * ` unsigned foreigndom)
+ * `
+ * @reqs is an array of mmu_update_t structures ((ptr, val) pairs).
+ * @count is the length of the above array.
+ * @pdone is an output parameter indicating number of completed operations
+ * @foreigndom[15:0]: FD, the expected owner of data pages referenced in this
+ * hypercall invocation. Can be DOMID_SELF.
+ * @foreigndom[31:16]: PFD, the expected owner of pagetable pages referenced
+ * in this hypercall invocation. The value of this field
+ * (x) encodes the PFD as follows:
+ * x == 0 => PFD == DOMID_SELF
+ * x != 0 => PFD == x - 1
+ *
+ * Sub-commands: ptr[1:0] specifies the appropriate MMU_* command.
+ * -------------
+ * ptr[1:0] == MMU_NORMAL_PT_UPDATE:
+ * Updates an entry in a page table belonging to PFD. If updating an L1 table,
+ * and the new table entry is valid/present, the mapped frame must belong to
+ * FD. If attempting to map an I/O page then the caller assumes the privilege
+ * of the FD.
+ * FD == DOMID_IO: Permit /only/ I/O mappings, at the priv level of the caller.
+ * FD == DOMID_XEN: Map restricted areas of Xen's heap space.
+ * ptr[:2] -- Machine address of the page-table entry to modify.
+ * val -- Value to write.
+ *
+ * There also certain implicit requirements when using this hypercall. The
+ * pages that make up a pagetable must be mapped read-only in the guest.
+ * This prevents uncontrolled guest updates to the pagetable. Xen strictly
+ * enforces this, and will disallow any pagetable update which will end up
+ * mapping pagetable page RW, and will disallow using any writable page as a
+ * pagetable. In practice it means that when constructing a page table for a
+ * process, thread, etc, we MUST be very dilligient in following these rules:
+ * 1). Start with top-level page (PGD or in Xen language: L4). Fill out
+ * the entries.
+ * 2). Keep on going, filling out the upper (PUD or L3), and middle (PMD
+ * or L2).
+ * 3). Start filling out the PTE table (L1) with the PTE entries. Once
+ * done, make sure to set each of those entries to RO (so writeable bit
+ * is unset). Once that has been completed, set the PMD (L2) for this
+ * PTE table as RO.
+ * 4). When completed with all of the PMD (L2) entries, and all of them have
+ * been set to RO, make sure to set RO the PUD (L3). Do the same
+ * operation on PGD (L4) pagetable entries that have a PUD (L3) entry.
+ * 5). Now before you can use those pages (so setting the cr3), you MUST also
+ * pin them so that the hypervisor can verify the entries. This is done
+ * via the HYPERVISOR_mmuext_op(MMUEXT_PIN_L4_TABLE, guest physical frame
+ * number of the PGD (L4)). And this point the HYPERVISOR_mmuext_op(
+ * MMUEXT_NEW_BASEPTR, guest physical frame number of the PGD (L4)) can be
+ * issued.
+ * For 32-bit guests, the L4 is not used (as there is less pagetables), so
+ * instead use L3.
+ * At this point the pagetables can be modified using the MMU_NORMAL_PT_UPDATE
+ * hypercall. Also if so desired the OS can also try to write to the PTE
+ * and be trapped by the hypervisor (as the PTE entry is RO).
+ *
+ * To deallocate the pages, the operations are the reverse of the steps
+ * mentioned above. The argument is MMUEXT_UNPIN_TABLE for all levels and the
+ * pagetable MUST not be in use (meaning that the cr3 is not set to it).
+ *
+ * ptr[1:0] == MMU_MACHPHYS_UPDATE:
+ * Updates an entry in the machine->pseudo-physical mapping table.
+ * ptr[:2] -- Machine address within the frame whose mapping to modify.
+ * The frame must belong to the FD, if one is specified.
+ * val -- Value to write into the mapping entry.
+ *
+ * ptr[1:0] == MMU_PT_UPDATE_PRESERVE_AD:
+ * As MMU_NORMAL_PT_UPDATE above, but A/D bits currently in the PTE are ORed
+ * with those in @val.
+ *
+ * ptr[1:0] == MMU_PT_UPDATE_NO_TRANSLATE:
+ * As MMU_NORMAL_PT_UPDATE above, but @val is not translated though FD
+ * page tables.
+ *
+ * @val is usually the machine frame number along with some attributes.
+ * The attributes by default follow the architecture defined bits. Meaning that
+ * if this is a X86_64 machine and four page table layout is used, the layout
+ * of val is:
+ * - 63 if set means No execute (NX)
+ * - 46-13 the machine frame number
+ * - 12 available for guest
+ * - 11 available for guest
+ * - 10 available for guest
+ * - 9 available for guest
+ * - 8 global
+ * - 7 PAT (PSE is disabled, must use hypercall to make 4MB or 2MB pages)
+ * - 6 dirty
+ * - 5 accessed
+ * - 4 page cached disabled
+ * - 3 page write through
+ * - 2 userspace accessible
+ * - 1 writeable
+ * - 0 present
+ *
+ * The one bits that does not fit with the default layout is the PAGE_PSE
+ * also called PAGE_PAT). The MMUEXT_[UN]MARK_SUPER arguments to the
+ * HYPERVISOR_mmuext_op serve as mechanism to set a pagetable to be 4MB
+ * (or 2MB) instead of using the PAGE_PSE bit.
+ *
+ * The reason that the PAGE_PSE (bit 7) is not being utilized is due to Xen
+ * using it as the Page Attribute Table (PAT) bit - for details on it please
+ * refer to Intel SDM 10.12. The PAT allows to set the caching attributes of
+ * pages instead of using MTRRs.
+ *
+ * The PAT MSR is as follows (it is a 64-bit value, each entry is 8 bits):
+ * PAT4 PAT0
+ * +-----+-----+----+----+----+-----+----+----+
+ * | UC | UC- | WC | WB | UC | UC- | WC | WB | <= Linux
+ * +-----+-----+----+----+----+-----+----+----+
+ * | UC | UC- | WT | WB | UC | UC- | WT | WB | <= BIOS (default when machine boots)
+ * +-----+-----+----+----+----+-----+----+----+
+ * | rsv | rsv | WP | WC | UC | UC- | WT | WB | <= Xen
+ * +-----+-----+----+----+----+-----+----+----+
+ *
+ * The lookup of this index table translates to looking up
+ * Bit 7, Bit 4, and Bit 3 of val entry:
+ *
+ * PAT/PSE (bit 7) ... PCD (bit 4) .. PWT (bit 3).
+ *
+ * If all bits are off, then we are using PAT0. If bit 3 turned on,
+ * then we are using PAT1, if bit 3 and bit 4, then PAT2..
+ *
+ * As you can see, the Linux PAT1 translates to PAT4 under Xen. Which means
+ * that if a guest that follows Linux's PAT setup and would like to set Write
+ * Combined on pages it MUST use PAT4 entry. Meaning that Bit 7 (PAGE_PAT) is
+ * set. For example, under Linux it only uses PAT0, PAT1, and PAT2 for the
+ * caching as:
+ *
+ * WB = none (so PAT0)
+ * WC = PWT (bit 3 on)
+ * UC = PWT | PCD (bit 3 and 4 are on).
+ *
+ * To make it work with Xen, it needs to translate the WC bit as so:
+ *
+ * PWT (so bit 3 on) --> PAT (so bit 7 is on) and clear bit 3
+ *
+ * And to translate back it would:
+ *
+ * PAT (bit 7 on) --> PWT (bit 3 on) and clear bit 7.
+ */
+#define MMU_NORMAL_PT_UPDATE 0 /* checked '*ptr = val'. ptr is MA. */
+#define MMU_MACHPHYS_UPDATE 1 /* ptr = MA of frame to modify entry for */
+#define MMU_PT_UPDATE_PRESERVE_AD 2 /* atomically: *ptr = val | (*ptr&(A|D)) */
+#define MMU_PT_UPDATE_NO_TRANSLATE 3 /* checked '*ptr = val'. ptr is MA. */
+ /* val never translated. */
+
+/*
+ * MMU EXTENDED OPERATIONS
+ *
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_mmuext_op(mmuext_op_t uops[],
+ * ` unsigned int count,
+ * ` unsigned int *pdone,
+ * ` unsigned int foreigndom)
+ */
+/* HYPERVISOR_mmuext_op() accepts a list of mmuext_op structures.
+ * A foreigndom (FD) can be specified (or DOMID_SELF for none).
+ * Where the FD has some effect, it is described below.
+ *
+ * cmd: MMUEXT_(UN)PIN_*_TABLE
+ * mfn: Machine frame number to be (un)pinned as a p.t. page.
+ * The frame must belong to the FD, if one is specified.
+ *
+ * cmd: MMUEXT_NEW_BASEPTR
+ * mfn: Machine frame number of new page-table base to install in MMU.
+ *
+ * cmd: MMUEXT_NEW_USER_BASEPTR [x86/64 only]
+ * mfn: Machine frame number of new page-table base to install in MMU
+ * when in user space.
+ *
+ * cmd: MMUEXT_TLB_FLUSH_LOCAL
+ * No additional arguments. Flushes local TLB.
+ *
+ * cmd: MMUEXT_INVLPG_LOCAL
+ * linear_addr: Linear address to be flushed from the local TLB.
+ *
+ * cmd: MMUEXT_TLB_FLUSH_MULTI
+ * vcpumask: Pointer to bitmap of VCPUs to be flushed.
+ *
+ * cmd: MMUEXT_INVLPG_MULTI
+ * linear_addr: Linear address to be flushed.
+ * vcpumask: Pointer to bitmap of VCPUs to be flushed.
+ *
+ * cmd: MMUEXT_TLB_FLUSH_ALL
+ * No additional arguments. Flushes all VCPUs' TLBs.
+ *
+ * cmd: MMUEXT_INVLPG_ALL
+ * linear_addr: Linear address to be flushed from all VCPUs' TLBs.
+ *
+ * cmd: MMUEXT_FLUSH_CACHE
+ * No additional arguments. Writes back and flushes cache contents.
+ *
+ * cmd: MMUEXT_FLUSH_CACHE_GLOBAL
+ * No additional arguments. Writes back and flushes cache contents
+ * on all CPUs in the system.
+ *
+ * cmd: MMUEXT_SET_LDT
+ * linear_addr: Linear address of LDT base (NB. must be page-aligned).
+ * nr_ents: Number of entries in LDT.
+ *
+ * cmd: MMUEXT_CLEAR_PAGE
+ * mfn: Machine frame number to be cleared.
+ *
+ * cmd: MMUEXT_COPY_PAGE
+ * mfn: Machine frame number of the destination page.
+ * src_mfn: Machine frame number of the source page.
+ *
+ * cmd: MMUEXT_[UN]MARK_SUPER
+ * mfn: Machine frame number of head of superpage to be [un]marked.
+ */
+/* ` enum mmuext_cmd { */
+#define MMUEXT_PIN_L1_TABLE 0
+#define MMUEXT_PIN_L2_TABLE 1
+#define MMUEXT_PIN_L3_TABLE 2
+#define MMUEXT_PIN_L4_TABLE 3
+#define MMUEXT_UNPIN_TABLE 4
+#define MMUEXT_NEW_BASEPTR 5
+#define MMUEXT_TLB_FLUSH_LOCAL 6
+#define MMUEXT_INVLPG_LOCAL 7
+#define MMUEXT_TLB_FLUSH_MULTI 8
+#define MMUEXT_INVLPG_MULTI 9
+#define MMUEXT_TLB_FLUSH_ALL 10
+#define MMUEXT_INVLPG_ALL 11
+#define MMUEXT_FLUSH_CACHE 12
+#define MMUEXT_SET_LDT 13
+#define MMUEXT_NEW_USER_BASEPTR 15
+#define MMUEXT_CLEAR_PAGE 16
+#define MMUEXT_COPY_PAGE 17
+#define MMUEXT_FLUSH_CACHE_GLOBAL 18
+#define MMUEXT_MARK_SUPER 19
+#define MMUEXT_UNMARK_SUPER 20
+/* ` } */
+
+#ifndef __ASSEMBLY__
+struct mmuext_op {
+ unsigned int cmd; /* => enum mmuext_cmd */
+ union {
+ /* [UN]PIN_TABLE, NEW_BASEPTR, NEW_USER_BASEPTR
+ * CLEAR_PAGE, COPY_PAGE, [UN]MARK_SUPER */
+ xen_pfn_t mfn;
+ /* INVLPG_LOCAL, INVLPG_ALL, SET_LDT */
+ unsigned long linear_addr;
+ } arg1;
+ union {
+ /* SET_LDT */
+ unsigned int nr_ents;
+ /* TLB_FLUSH_MULTI, INVLPG_MULTI */
+#if __XEN_INTERFACE_VERSION__ >= 0x00030205
+ XEN_GUEST_HANDLE(const_void) vcpumask;
+#else
+ const void *vcpumask;
+#endif
+ /* COPY_PAGE */
+ xen_pfn_t src_mfn;
+ } arg2;
+};
+typedef struct mmuext_op mmuext_op_t;
+DEFINE_XEN_GUEST_HANDLE(mmuext_op_t);
+#endif
+
+/*
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_update_va_mapping(unsigned long va, u64 val,
+ * ` enum uvm_flags flags)
+ * `
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_update_va_mapping_otherdomain(unsigned long va, u64 val,
+ * ` enum uvm_flags flags,
+ * ` domid_t domid)
+ * `
+ * ` @va: The virtual address whose mapping we want to change
+ * ` @val: The new page table entry, must contain a machine address
+ * ` @flags: Control TLB flushes
+ */
+/* These are passed as 'flags' to update_va_mapping. They can be ORed. */
+/* When specifying UVMF_MULTI, also OR in a pointer to a CPU bitmap. */
+/* UVMF_LOCAL is merely UVMF_MULTI with a NULL bitmap pointer. */
+/* ` enum uvm_flags { */
+#define UVMF_NONE (xen_mk_ulong(0)<<0) /* No flushing at all. */
+#define UVMF_TLB_FLUSH (xen_mk_ulong(1)<<0) /* Flush entire TLB(s). */
+#define UVMF_INVLPG (xen_mk_ulong(2)<<0) /* Flush only one entry. */
+#define UVMF_FLUSHTYPE_MASK (xen_mk_ulong(3)<<0)
+#define UVMF_MULTI (xen_mk_ulong(0)<<2) /* Flush subset of TLBs. */
+#define UVMF_LOCAL (xen_mk_ulong(0)<<2) /* Flush local TLB. */
+#define UVMF_ALL (xen_mk_ulong(1)<<2) /* Flush all TLBs. */
+/* ` } */
+
+/*
+ * ` int
+ * ` HYPERVISOR_console_io(unsigned int cmd,
+ * ` unsigned int count,
+ * ` char buffer[]);
+ *
+ * @cmd: Command (see below)
+ * @count: Size of the buffer to read/write
+ * @buffer: Pointer in the guest memory
+ *
+ * List of commands:
+ *
+ * * CONSOLEIO_write: Write the buffer to Xen console.
+ * For the hardware domain, all the characters in the buffer will
+ * be written. Characters will be printed directly to the console.
+ * For all the other domains, only the printable characters will be
+ * written. Characters may be buffered until a newline (i.e '\n') is
+ * found.
+ * @return 0 on success, otherwise return an error code.
+ * * CONSOLEIO_read: Attempts to read up to @count characters from Xen
+ * console. The maximum buffer size (i.e. @count) supported is 2GB.
+ * @return the number of characters read on success, otherwise return
+ * an error code.
+ */
+#define CONSOLEIO_write 0
+#define CONSOLEIO_read 1
+
+/*
+ * Commands to HYPERVISOR_vm_assist().
+ */
+#define VMASST_CMD_enable 0
+#define VMASST_CMD_disable 1
+
+/* x86/32 guests: simulate full 4GB segment limits. */
+#define VMASST_TYPE_4gb_segments 0
+
+/* x86/32 guests: trap (vector 15) whenever above vmassist is used. */
+#define VMASST_TYPE_4gb_segments_notify 1
+
+/*
+ * x86 guests: support writes to bottom-level PTEs.
+ * NB1. Page-directory entries cannot be written.
+ * NB2. Guest must continue to remove all writable mappings of PTEs.
+ */
+#define VMASST_TYPE_writable_pagetables 2
+
+/* x86/PAE guests: support PDPTs above 4GB. */
+#define VMASST_TYPE_pae_extended_cr3 3
+
+/*
+ * x86 guests: Sane behaviour for virtual iopl
+ * - virtual iopl updated from do_iret() hypercalls.
+ * - virtual iopl reported in bounce frames.
+ * - guest kernels assumed to be level 0 for the purpose of iopl checks.
+ */
+#define VMASST_TYPE_architectural_iopl 4
+
+/*
+ * All guests: activate update indicator in vcpu_runstate_info
+ * Enable setting the XEN_RUNSTATE_UPDATE flag in guest memory mapped
+ * vcpu_runstate_info during updates of the runstate information.
+ */
+#define VMASST_TYPE_runstate_update_flag 5
+
+/*
+ * x86/64 guests: strictly hide M2P from user mode.
+ * This allows the guest to control respective hypervisor behavior:
+ * - when not set, L4 tables get created with the respective slot blank,
+ * and whenever the L4 table gets used as a kernel one the missing
+ * mapping gets inserted,
+ * - when set, L4 tables get created with the respective slot initialized
+ * as before, and whenever the L4 table gets used as a user one the
+ * mapping gets zapped.
+ */
+#define VMASST_TYPE_m2p_strict 32
+
+#if __XEN_INTERFACE_VERSION__ < 0x00040600
+#define MAX_VMASST_TYPE 3
+#endif
+
+/* Domain ids >= DOMID_FIRST_RESERVED cannot be used for ordinary domains. */
+#define DOMID_FIRST_RESERVED xen_mk_uint(0x7FF0)
+
+/* DOMID_SELF is used in certain contexts to refer to oneself. */
+#define DOMID_SELF xen_mk_uint(0x7FF0)
+
+/*
+ * DOMID_IO is used to restrict page-table updates to mapping I/O memory.
+ * Although no Foreign Domain need be specified to map I/O pages, DOMID_IO
+ * is useful to ensure that no mappings to the OS's own heap are accidentally
+ * installed. (e.g., in Linux this could cause havoc as reference counts
+ * aren't adjusted on the I/O-mapping code path).
+ * This only makes sense as HYPERVISOR_mmu_update()'s and
+ * HYPERVISOR_update_va_mapping_otherdomain()'s "foreigndom" argument. For
+ * HYPERVISOR_mmu_update() context it can be specified by any calling domain,
+ * otherwise it's only permitted if the caller is privileged.
+ */
+#define DOMID_IO xen_mk_uint(0x7FF1)
+
+/*
+ * DOMID_XEN is used to allow privileged domains to map restricted parts of
+ * Xen's heap space (e.g., the machine_to_phys table).
+ * This only makes sense as
+ * - HYPERVISOR_mmu_update()'s, HYPERVISOR_mmuext_op()'s, or
+ * HYPERVISOR_update_va_mapping_otherdomain()'s "foreigndom" argument,
+ * - with XENMAPSPACE_gmfn_foreign,
+ * and is only permitted if the caller is privileged.
+ */
+#define DOMID_XEN xen_mk_uint(0x7FF2)
+
+/*
+ * DOMID_COW is used as the owner of sharable pages */
+#define DOMID_COW xen_mk_uint(0x7FF3)
+
+/* DOMID_INVALID is used to identify pages with unknown owner. */
+#define DOMID_INVALID xen_mk_uint(0x7FF4)
+
+/* Idle domain. */
+#define DOMID_IDLE xen_mk_uint(0x7FFF)
+
+/* Mask for valid domain id values */
+#define DOMID_MASK xen_mk_uint(0x7FFF)
+
+#ifndef __ASSEMBLY__
+
+typedef uint16_t domid_t;
+
+/*
+ * Send an array of these to HYPERVISOR_mmu_update().
+ * NB. The fields are natural pointer/address size for this architecture.
+ */
+struct mmu_update {
+ uint64_t ptr; /* Machine address of PTE. */
+ uint64_t val; /* New contents of PTE. */
+};
+typedef struct mmu_update mmu_update_t;
+DEFINE_XEN_GUEST_HANDLE(mmu_update_t);
+
+/*
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_multicall(multicall_entry_t call_list[],
+ * ` uint32_t nr_calls);
+ *
+ * NB. The fields are logically the natural register size for this
+ * architecture. In cases where xen_ulong_t is larger than this then
+ * any unused bits in the upper portion must be zero.
+ */
+struct multicall_entry {
+ xen_ulong_t op, result;
+ xen_ulong_t args[6];
+};
+typedef struct multicall_entry multicall_entry_t;
+DEFINE_XEN_GUEST_HANDLE(multicall_entry_t);
+
+#if __XEN_INTERFACE_VERSION__ < 0x00040400
+/*
+ * Event channel endpoints per domain (when using the 2-level ABI):
+ * 1024 if a long is 32 bits; 4096 if a long is 64 bits.
+ */
+#define NR_EVENT_CHANNELS EVTCHN_2L_NR_CHANNELS
+#endif
+
+struct vcpu_time_info {
+ /*
+ * Updates to the following values are preceded and followed by an
+ * increment of 'version'. The guest can therefore detect updates by
+ * looking for changes to 'version'. If the least-significant bit of
+ * the version number is set then an update is in progress and the guest
+ * must wait to read a consistent set of values.
+ * The correct way to interact with the version number is similar to
+ * Linux's seqlock: see the implementations of read_seqbegin/read_seqretry.
+ */
+ uint32_t version;
+ uint32_t pad0;
+ uint64_t tsc_timestamp; /* TSC at last update of time vals. */
+ uint64_t system_time; /* Time, in nanosecs, since boot. */
+ /*
+ * Current system time:
+ * system_time +
+ * ((((tsc - tsc_timestamp) << tsc_shift) * tsc_to_system_mul) >> 32)
+ * CPU frequency (Hz):
+ * ((10^9 << 32) / tsc_to_system_mul) >> tsc_shift
+ */
+ uint32_t tsc_to_system_mul;
+ int8_t tsc_shift;
+#if __XEN_INTERFACE_VERSION__ > 0x040600
+ uint8_t flags;
+ uint8_t pad1[2];
+#else
+ int8_t pad1[3];
+#endif
+}; /* 32 bytes */
+typedef struct vcpu_time_info vcpu_time_info_t;
+
+#define XEN_PVCLOCK_TSC_STABLE_BIT (1 << 0)
+#define XEN_PVCLOCK_GUEST_STOPPED (1 << 1)
+
+struct vcpu_info {
+ /*
+ * 'evtchn_upcall_pending' is written non-zero by Xen to indicate
+ * a pending notification for a particular VCPU. It is then cleared
+ * by the guest OS /before/ checking for pending work, thus avoiding
+ * a set-and-check race. Note that the mask is only accessed by Xen
+ * on the CPU that is currently hosting the VCPU. This means that the
+ * pending and mask flags can be updated by the guest without special
+ * synchronisation (i.e., no need for the x86 LOCK prefix).
+ * This may seem suboptimal because if the pending flag is set by
+ * a different CPU then an IPI may be scheduled even when the mask
+ * is set. However, note:
+ * 1. The task of 'interrupt holdoff' is covered by the per-event-
+ * channel mask bits. A 'noisy' event that is continually being
+ * triggered can be masked at source at this very precise
+ * granularity.
+ * 2. The main purpose of the per-VCPU mask is therefore to restrict
+ * reentrant execution: whether for concurrency control, or to
+ * prevent unbounded stack usage. Whatever the purpose, we expect
+ * that the mask will be asserted only for short periods at a time,
+ * and so the likelihood of a 'spurious' IPI is suitably small.
+ * The mask is read before making an event upcall to the guest: a
+ * non-zero mask therefore guarantees that the VCPU will not receive
+ * an upcall activation. The mask is cleared when the VCPU requests
+ * to block: this avoids wakeup-waiting races.
+ */
+ uint8_t evtchn_upcall_pending;
+#ifdef XEN_HAVE_PV_UPCALL_MASK
+ uint8_t evtchn_upcall_mask;
+#else /* XEN_HAVE_PV_UPCALL_MASK */
+ uint8_t pad0;
+#endif /* XEN_HAVE_PV_UPCALL_MASK */
+ xen_ulong_t evtchn_pending_sel;
+ struct arch_vcpu_info arch;
+ vcpu_time_info_t time;
+}; /* 64 bytes (x86) */
+#ifndef __XEN__
+typedef struct vcpu_info vcpu_info_t;
+#endif
+
+/*
+ * `incontents 200 startofday_shared Start-of-day shared data structure
+ * Xen/kernel shared data -- pointer provided in start_info.
+ *
+ * This structure is defined to be both smaller than a page, and the
+ * only data on the shared page, but may vary in actual size even within
+ * compatible Xen versions; guests should not rely on the size
+ * of this structure remaining constant.
+ */
+struct shared_info {
+ struct vcpu_info vcpu_info[XEN_LEGACY_MAX_VCPUS];
+
+ /*
+ * A domain can create "event channels" on which it can send and receive
+ * asynchronous event notifications. There are three classes of event that
+ * are delivered by this mechanism:
+ * 1. Bi-directional inter- and intra-domain connections. Domains must
+ * arrange out-of-band to set up a connection (usually by allocating
+ * an unbound 'listener' port and avertising that via a storage service
+ * such as xenstore).
+ * 2. Physical interrupts. A domain with suitable hardware-access
+ * privileges can bind an event-channel port to a physical interrupt
+ * source.
+ * 3. Virtual interrupts ('events'). A domain can bind an event-channel
+ * port to a virtual interrupt source, such as the virtual-timer
+ * device or the emergency console.
+ *
+ * Event channels are addressed by a "port index". Each channel is
+ * associated with two bits of information:
+ * 1. PENDING -- notifies the domain that there is a pending notification
+ * to be processed. This bit is cleared by the guest.
+ * 2. MASK -- if this bit is clear then a 0->1 transition of PENDING
+ * will cause an asynchronous upcall to be scheduled. This bit is only
+ * updated by the guest. It is read-only within Xen. If a channel
+ * becomes pending while the channel is masked then the 'edge' is lost
+ * (i.e., when the channel is unmasked, the guest must manually handle
+ * pending notifications as no upcall will be scheduled by Xen).
+ *
+ * To expedite scanning of pending notifications, any 0->1 pending
+ * transition on an unmasked channel causes a corresponding bit in a
+ * per-vcpu selector word to be set. Each bit in the selector covers a
+ * 'C long' in the PENDING bitfield array.
+ */
+ xen_ulong_t evtchn_pending[sizeof(xen_ulong_t) * 8];
+ xen_ulong_t evtchn_mask[sizeof(xen_ulong_t) * 8];
+
+ /*
+ * Wallclock time: updated by control software or RTC emulation.
+ * Guests should base their gettimeofday() syscall on this
+ * wallclock-base value.
+ * The values of wc_sec and wc_nsec are offsets from the Unix epoch
+ * adjusted by the domain's 'time offset' (in seconds) as set either
+ * by XEN_DOMCTL_settimeoffset, or adjusted via a guest write to the
+ * emulated RTC.
+ */
+ uint32_t wc_version; /* Version counter: see vcpu_time_info_t. */
+ uint32_t wc_sec;
+ uint32_t wc_nsec;
+#if !defined(__i386__)
+ uint32_t wc_sec_hi;
+# define xen_wc_sec_hi wc_sec_hi
+#elif !defined(__XEN__) && !defined(__XEN_TOOLS__)
+# define xen_wc_sec_hi arch.wc_sec_hi
+#endif
+
+ struct arch_shared_info arch;
+
+};
+#ifndef __XEN__
+typedef struct shared_info shared_info_t;
+#endif
+
+/*
+ * `incontents 200 startofday Start-of-day memory layout
+ *
+ * 1. The domain is started within contiguous virtual-memory region.
+ * 2. The contiguous region ends on an aligned 4MB boundary.
+ * 3. This the order of bootstrap elements in the initial virtual region:
+ * a. relocated kernel image
+ * b. initial ram disk [mod_start, mod_len]
+ * (may be omitted)
+ * c. list of allocated page frames [mfn_list, nr_pages]
+ * (unless relocated due to XEN_ELFNOTE_INIT_P2M)
+ * d. start_info_t structure [register rSI (x86)]
+ * in case of dom0 this page contains the console info, too
+ * e. unless dom0: xenstore ring page
+ * f. unless dom0: console ring page
+ * g. bootstrap page tables [pt_base and CR3 (x86)]
+ * h. bootstrap stack [register ESP (x86)]
+ * 4. Bootstrap elements are packed together, but each is 4kB-aligned.
+ * 5. The list of page frames forms a contiguous 'pseudo-physical' memory
+ * layout for the domain. In particular, the bootstrap virtual-memory
+ * region is a 1:1 mapping to the first section of the pseudo-physical map.
+ * 6. All bootstrap elements are mapped read-writable for the guest OS. The
+ * only exception is the bootstrap page table, which is mapped read-only.
+ * 7. There is guaranteed to be at least 512kB padding after the final
+ * bootstrap element. If necessary, the bootstrap virtual region is
+ * extended by an extra 4MB to ensure this.
+ *
+ * Note: Prior to 25833:bb85bbccb1c9. ("x86/32-on-64 adjust Dom0 initial page
+ * table layout") a bug caused the pt_base (3.g above) and cr3 to not point
+ * to the start of the guest page tables (it was offset by two pages).
+ * This only manifested itself on 32-on-64 dom0 kernels and not 32-on-64 domU
+ * or 64-bit kernels of any colour. The page tables for a 32-on-64 dom0 got
+ * allocated in the order: 'first L1','first L2', 'first L3', so the offset
+ * to the page table base is by two pages back. The initial domain if it is
+ * 32-bit and runs under a 64-bit hypervisor should _NOT_ use two of the
+ * pages preceding pt_base and mark them as reserved/unused.
+ */
+#ifdef XEN_HAVE_PV_GUEST_ENTRY
+struct start_info {
+ /* THE FOLLOWING ARE FILLED IN BOTH ON INITIAL BOOT AND ON RESUME. */
+ char magic[32]; /* "xen-<version>-<platform>". */
+ unsigned long nr_pages; /* Total pages allocated to this domain. */
+ unsigned long shared_info; /* MACHINE address of shared info struct. */
+ uint32_t flags; /* SIF_xxx flags. */
+ xen_pfn_t store_mfn; /* MACHINE page number of shared page. */
+ uint32_t store_evtchn; /* Event channel for store communication. */
+ union {
+ struct {
+ xen_pfn_t mfn; /* MACHINE page number of console page. */
+ uint32_t evtchn; /* Event channel for console page. */
+ } domU;
+ struct {
+ uint32_t info_off; /* Offset of console_info struct. */
+ uint32_t info_size; /* Size of console_info struct from start.*/
+ } dom0;
+ } console;
+ /* THE FOLLOWING ARE ONLY FILLED IN ON INITIAL BOOT (NOT RESUME). */
+ unsigned long pt_base; /* VIRTUAL address of page directory. */
+ unsigned long nr_pt_frames; /* Number of bootstrap p.t. frames. */
+ unsigned long mfn_list; /* VIRTUAL address of page-frame list. */
+ unsigned long mod_start; /* VIRTUAL address of pre-loaded module */
+ /* (PFN of pre-loaded module if */
+ /* SIF_MOD_START_PFN set in flags). */
+ unsigned long mod_len; /* Size (bytes) of pre-loaded module. */
+#define MAX_GUEST_CMDLINE 1024
+ int8_t cmd_line[MAX_GUEST_CMDLINE];
+ /* The pfn range here covers both page table and p->m table frames. */
+ unsigned long first_p2m_pfn;/* 1st pfn forming initial P->M table. */
+ unsigned long nr_p2m_frames;/* # of pfns forming initial P->M table. */
+};
+typedef struct start_info start_info_t;
+
+/* New console union for dom0 introduced in 0x00030203. */
+#if __XEN_INTERFACE_VERSION__ < 0x00030203
+#define console_mfn console.domU.mfn
+#define console_evtchn console.domU.evtchn
+#endif
+#endif /* XEN_HAVE_PV_GUEST_ENTRY */
+
+/* These flags are passed in the 'flags' field of start_info_t. */
+#define SIF_PRIVILEGED (1<<0) /* Is the domain privileged? */
+#define SIF_INITDOMAIN (1<<1) /* Is this the initial control domain? */
+#define SIF_MULTIBOOT_MOD (1<<2) /* Is mod_start a multiboot module? */
+#define SIF_MOD_START_PFN (1<<3) /* Is mod_start a PFN? */
+#define SIF_VIRT_P2M_4TOOLS (1<<4) /* Do Xen tools understand a virt. mapped */
+ /* P->M making the 3 level tree obsolete? */
+#define SIF_PM_MASK (0xFF<<8) /* reserve 1 byte for xen-pm options */
+
+/*
+ * A multiboot module is a package containing modules very similar to a
+ * multiboot module array. The only differences are:
+ * - the array of module descriptors is by convention simply at the beginning
+ * of the multiboot module,
+ * - addresses in the module descriptors are based on the beginning of the
+ * multiboot module,
+ * - the number of modules is determined by a termination descriptor that has
+ * mod_start == 0.
+ *
+ * This permits to both build it statically and reference it in a configuration
+ * file, and let the PV guest easily rebase the addresses to virtual addresses
+ * and at the same time count the number of modules.
+ */
+struct xen_multiboot_mod_list
+{
+ /* Address of first byte of the module */
+ uint32_t mod_start;
+ /* Address of last byte of the module (inclusive) */
+ uint32_t mod_end;
+ /* Address of zero-terminated command line */
+ uint32_t cmdline;
+ /* Unused, must be zero */
+ uint32_t pad;
+};
+/*
+ * `incontents 200 startofday_dom0_console Dom0_console
+ *
+ * The console structure in start_info.console.dom0
+ *
+ * This structure includes a variety of information required to
+ * have a working VGA/VESA console.
+ */
+typedef struct dom0_vga_console_info {
+ uint8_t video_type; /* DOM0_VGA_CONSOLE_??? */
+#define XEN_VGATYPE_TEXT_MODE_3 0x03
+#define XEN_VGATYPE_VESA_LFB 0x23
+#define XEN_VGATYPE_EFI_LFB 0x70
+
+ union {
+ struct {
+ /* Font height, in pixels. */
+ uint16_t font_height;
+ /* Cursor location (column, row). */
+ uint16_t cursor_x, cursor_y;
+ /* Number of rows and columns (dimensions in characters). */
+ uint16_t rows, columns;
+ } text_mode_3;
+
+ struct {
+ /* Width and height, in pixels. */
+ uint16_t width, height;
+ /* Bytes per scan line. */
+ uint16_t bytes_per_line;
+ /* Bits per pixel. */
+ uint16_t bits_per_pixel;
+ /* LFB physical address, and size (in units of 64kB). */
+ uint32_t lfb_base;
+ uint32_t lfb_size;
+ /* RGB mask offsets and sizes, as defined by VBE 1.2+ */
+ uint8_t red_pos, red_size;
+ uint8_t green_pos, green_size;
+ uint8_t blue_pos, blue_size;
+ uint8_t rsvd_pos, rsvd_size;
+#if __XEN_INTERFACE_VERSION__ >= 0x00030206
+ /* VESA capabilities (offset 0xa, VESA command 0x4f00). */
+ uint32_t gbl_caps;
+ /* Mode attributes (offset 0x0, VESA command 0x4f01). */
+ uint16_t mode_attrs;
+ uint16_t pad;
+#endif
+#if __XEN_INTERFACE_VERSION__ >= 0x00040d00
+ /* high 32 bits of lfb_base */
+ uint32_t ext_lfb_base;
+#endif
+ } vesa_lfb;
+ } u;
+} dom0_vga_console_info_t;
+#define xen_vga_console_info dom0_vga_console_info
+#define xen_vga_console_info_t dom0_vga_console_info_t
+
+typedef uint8_t xen_domain_handle_t[16];
+
+__DEFINE_XEN_GUEST_HANDLE(uint8, uint8_t);
+__DEFINE_XEN_GUEST_HANDLE(uint16, uint16_t);
+__DEFINE_XEN_GUEST_HANDLE(uint32, uint32_t);
+__DEFINE_XEN_GUEST_HANDLE(uint64, uint64_t);
+
+typedef struct {
+ uint8_t a[16];
+} xen_uuid_t;
+
+/*
+ * XEN_DEFINE_UUID(0x00112233, 0x4455, 0x6677, 0x8899,
+ * 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff)
+ * will construct UUID 00112233-4455-6677-8899-aabbccddeeff presented as
+ * {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
+ * 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
+ *
+ * NB: This is compatible with Linux kernel and with libuuid, but it is not
+ * compatible with Microsoft, as they use mixed-endian encoding (some
+ * components are little-endian, some are big-endian).
+ */
+#define XEN_DEFINE_UUID_(a, b, c, d, e1, e2, e3, e4, e5, e6) \
+ {{((a) >> 24) & 0xFF, ((a) >> 16) & 0xFF, \
+ ((a) >> 8) & 0xFF, ((a) >> 0) & 0xFF, \
+ ((b) >> 8) & 0xFF, ((b) >> 0) & 0xFF, \
+ ((c) >> 8) & 0xFF, ((c) >> 0) & 0xFF, \
+ ((d) >> 8) & 0xFF, ((d) >> 0) & 0xFF, \
+ e1, e2, e3, e4, e5, e6}}
+
+#if defined(__STDC_VERSION__) ? __STDC_VERSION__ >= 199901L : defined(__GNUC__)
+#define XEN_DEFINE_UUID(a, b, c, d, e1, e2, e3, e4, e5, e6) \
+ ((xen_uuid_t)XEN_DEFINE_UUID_(a, b, c, d, e1, e2, e3, e4, e5, e6))
+#else
+#define XEN_DEFINE_UUID(a, b, c, d, e1, e2, e3, e4, e5, e6) \
+ XEN_DEFINE_UUID_(a, b, c, d, e1, e2, e3, e4, e5, e6)
+#endif /* __STDC_VERSION__ / __GNUC__ */
+
+#endif /* !__ASSEMBLY__ */
+
+/* Default definitions for macros used by domctl/sysctl. */
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+
+#ifndef int64_aligned_t
+#define int64_aligned_t int64_t
+#endif
+#ifndef uint64_aligned_t
+#define uint64_aligned_t uint64_t
+#endif
+#ifndef XEN_GUEST_HANDLE_64
+#define XEN_GUEST_HANDLE_64(name) XEN_GUEST_HANDLE(name)
+#endif
+
+#ifndef __ASSEMBLY__
+struct xenctl_bitmap {
+ XEN_GUEST_HANDLE_64(uint8) bitmap;
+ uint32_t nr_bits;
+};
+typedef struct xenctl_bitmap xenctl_bitmap_t;
+#endif
+
+#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
+
+#endif /* __XEN_PUBLIC_XEN_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/hw/xen/xen-backend.h b/include/hw/xen/xen-backend.h
index 010d712638..0f01631ae7 100644
--- a/include/hw/xen/xen-backend.h
+++ b/include/hw/xen/xen-backend.h
@@ -31,7 +31,9 @@ void xen_backend_set_device(XenBackendInstance *backend,
XenDevice *xen_backend_get_device(XenBackendInstance *backend);
void xen_backend_register(const XenBackendInfo *info);
+const char **xen_backend_get_types(unsigned int *nr);
+bool xen_backend_exists(const char *type, const char *name);
void xen_backend_device_create(XenBus *xenbus, const char *type,
const char *name, QDict *opts, Error **errp);
bool xen_backend_try_device_destroy(XenDevice *xendev, Error **errp);
diff --git a/include/hw/xen/xen-block.h b/include/hw/xen/xen-block.h
index 2cd2fc2701..d692ea7580 100644
--- a/include/hw/xen/xen-block.h
+++ b/include/hw/xen/xen-block.h
@@ -12,6 +12,7 @@
#include "hw/block/block.h"
#include "hw/block/dataplane/xen-block.h"
#include "sysemu/iothread.h"
+#include "qom/object.h"
typedef enum XenBlockVdevType {
XEN_BLOCK_VDEV_TYPE_INVALID,
@@ -46,7 +47,7 @@ typedef struct XenBlockIOThread {
char *id;
} XenBlockIOThread;
-typedef struct XenBlockDevice {
+struct XenBlockDevice {
XenDevice xendev;
XenBlockProperties props;
const char *device_type;
@@ -54,41 +55,35 @@ typedef struct XenBlockDevice {
XenBlockDataPlane *dataplane;
XenBlockDrive *drive;
XenBlockIOThread *iothread;
-} XenBlockDevice;
+};
+typedef struct XenBlockDevice XenBlockDevice;
typedef void (*XenBlockDeviceRealize)(XenBlockDevice *blockdev, Error **errp);
typedef void (*XenBlockDeviceUnrealize)(XenBlockDevice *blockdev);
-typedef struct XenBlockDeviceClass {
+struct XenBlockDeviceClass {
/*< private >*/
XenDeviceClass parent_class;
/*< public >*/
XenBlockDeviceRealize realize;
XenBlockDeviceUnrealize unrealize;
-} XenBlockDeviceClass;
+};
#define TYPE_XEN_BLOCK_DEVICE "xen-block"
-#define XEN_BLOCK_DEVICE(obj) \
- OBJECT_CHECK(XenBlockDevice, (obj), TYPE_XEN_BLOCK_DEVICE)
-#define XEN_BLOCK_DEVICE_CLASS(class) \
- OBJECT_CLASS_CHECK(XenBlockDeviceClass, (class), TYPE_XEN_BLOCK_DEVICE)
-#define XEN_BLOCK_DEVICE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(XenBlockDeviceClass, (obj), TYPE_XEN_BLOCK_DEVICE)
-
-typedef struct XenDiskDevice {
+OBJECT_DECLARE_TYPE(XenBlockDevice, XenBlockDeviceClass, XEN_BLOCK_DEVICE)
+
+struct XenDiskDevice {
XenBlockDevice blockdev;
-} XenDiskDevice;
+};
#define TYPE_XEN_DISK_DEVICE "xen-disk"
-#define XEN_DISK_DEVICE(obj) \
- OBJECT_CHECK(XenDiskDevice, (obj), TYPE_XEN_DISK_DEVICE)
+OBJECT_DECLARE_SIMPLE_TYPE(XenDiskDevice, XEN_DISK_DEVICE)
-typedef struct XenCDRomDevice {
+struct XenCDRomDevice {
XenBlockDevice blockdev;
-} XenCDRomDevice;
+};
#define TYPE_XEN_CDROM_DEVICE "xen-cdrom"
-#define XEN_CDROM_DEVICE(obj) \
- OBJECT_CHECK(XenCDRomDevice, (obj), TYPE_XEN_CDROM_DEVICE)
+OBJECT_DECLARE_SIMPLE_TYPE(XenCDRomDevice, XEN_CDROM_DEVICE)
#endif /* HW_XEN_BLOCK_H */
diff --git a/include/hw/xen/xen-bus-helper.h b/include/hw/xen/xen-bus-helper.h
index 4c0f747445..d8dcc2f010 100644
--- a/include/hw/xen/xen-bus-helper.h
+++ b/include/hw/xen/xen-bus-helper.h
@@ -8,38 +8,40 @@
#ifndef HW_XEN_BUS_HELPER_H
#define HW_XEN_BUS_HELPER_H
-#include "hw/xen/xen_common.h"
+#include "hw/xen/xen_backend_ops.h"
const char *xs_strstate(enum xenbus_state state);
-void xs_node_create(struct xs_handle *xsh, xs_transaction_t tid,
- const char *node, struct xs_permissions perms[],
- unsigned int nr_perms, Error **errp);
-void xs_node_destroy(struct xs_handle *xsh, xs_transaction_t tid,
+void xs_node_create(struct qemu_xs_handle *h, xs_transaction_t tid,
+ const char *node, unsigned int owner, unsigned int domid,
+ unsigned int perms, Error **errp);
+void xs_node_destroy(struct qemu_xs_handle *h, xs_transaction_t tid,
const char *node, Error **errp);
/* Write to node/key unless node is empty, in which case write to key */
-void xs_node_vprintf(struct xs_handle *xsh, xs_transaction_t tid,
+void xs_node_vprintf(struct qemu_xs_handle *h, xs_transaction_t tid,
const char *node, const char *key, Error **errp,
const char *fmt, va_list ap)
- GCC_FMT_ATTR(6, 0);
-void xs_node_printf(struct xs_handle *xsh, xs_transaction_t tid,
+ G_GNUC_PRINTF(6, 0);
+void xs_node_printf(struct qemu_xs_handle *h, xs_transaction_t tid,
const char *node, const char *key, Error **errp,
const char *fmt, ...)
- GCC_FMT_ATTR(6, 7);
+ G_GNUC_PRINTF(6, 7);
/* Read from node/key unless node is empty, in which case read from key */
-int xs_node_vscanf(struct xs_handle *xsh, xs_transaction_t tid,
+int xs_node_vscanf(struct qemu_xs_handle *h, xs_transaction_t tid,
const char *node, const char *key, Error **errp,
- const char *fmt, va_list ap);
-int xs_node_scanf(struct xs_handle *xsh, xs_transaction_t tid,
+ const char *fmt, va_list ap)
+ G_GNUC_SCANF(6, 0);
+int xs_node_scanf(struct qemu_xs_handle *h, xs_transaction_t tid,
const char *node, const char *key, Error **errp,
- const char *fmt, ...);
+ const char *fmt, ...)
+ G_GNUC_SCANF(6, 7);
/* Watch node/key unless node is empty, in which case watch key */
-void xs_node_watch(struct xs_handle *xsh, const char *node, const char *key,
- char *token, Error **errp);
-void xs_node_unwatch(struct xs_handle *xsh, const char *node, const char *key,
- const char *token, Error **errp);
+struct qemu_xs_watch *xs_node_watch(struct qemu_xs_handle *h, const char *node,
+ const char *key, xs_watch_fn fn,
+ void *opaque, Error **errp);
+void xs_node_unwatch(struct qemu_xs_handle *h, struct qemu_xs_watch *w);
#endif /* HW_XEN_BUS_HELPER_H */
diff --git a/include/hw/xen/xen-bus.h b/include/hw/xen/xen-bus.h
index 4ec0bb072f..38d40afa37 100644
--- a/include/hw/xen/xen-bus.h
+++ b/include/hw/xen/xen-bus.h
@@ -8,35 +8,32 @@
#ifndef HW_XEN_BUS_H
#define HW_XEN_BUS_H
-#include "hw/xen/xen_common.h"
+#include "hw/xen/xen_backend_ops.h"
#include "hw/sysbus.h"
#include "qemu/notify.h"
+#include "qom/object.h"
-typedef void (*XenWatchHandler)(void *opaque);
-
-typedef struct XenWatchList XenWatchList;
-typedef struct XenWatch XenWatch;
typedef struct XenEventChannel XenEventChannel;
-typedef struct XenDevice {
+struct XenDevice {
DeviceState qdev;
domid_t frontend_id;
char *name;
- struct xs_handle *xsh;
- XenWatchList *watch_list;
+ struct qemu_xs_handle *xsh;
char *backend_path, *frontend_path;
enum xenbus_state backend_state, frontend_state;
Notifier exit;
- XenWatch *backend_state_watch, *frontend_state_watch;
+ struct qemu_xs_watch *backend_state_watch, *frontend_state_watch;
bool backend_online;
- XenWatch *backend_online_watch;
+ struct qemu_xs_watch *backend_online_watch;
xengnttab_handle *xgth;
- bool feature_grant_copy;
bool inactive;
QLIST_HEAD(, XenEventChannel) event_channels;
QLIST_ENTRY(XenDevice) list;
-} XenDevice;
+};
+typedef struct XenDevice XenDevice;
+typedef char *(*XenDeviceGetFrontendPath)(XenDevice *xendev, Error **errp);
typedef char *(*XenDeviceGetName)(XenDevice *xendev, Error **errp);
typedef void (*XenDeviceRealize)(XenDevice *xendev, Error **errp);
typedef void (*XenDeviceFrontendChanged)(XenDevice *xendev,
@@ -44,47 +41,39 @@ typedef void (*XenDeviceFrontendChanged)(XenDevice *xendev,
Error **errp);
typedef void (*XenDeviceUnrealize)(XenDevice *xendev);
-typedef struct XenDeviceClass {
+struct XenDeviceClass {
/*< private >*/
DeviceClass parent_class;
/*< public >*/
const char *backend;
const char *device;
+ XenDeviceGetFrontendPath get_frontend_path;
XenDeviceGetName get_name;
XenDeviceRealize realize;
XenDeviceFrontendChanged frontend_changed;
XenDeviceUnrealize unrealize;
-} XenDeviceClass;
+};
#define TYPE_XEN_DEVICE "xen-device"
-#define XEN_DEVICE(obj) \
- OBJECT_CHECK(XenDevice, (obj), TYPE_XEN_DEVICE)
-#define XEN_DEVICE_CLASS(class) \
- OBJECT_CLASS_CHECK(XenDeviceClass, (class), TYPE_XEN_DEVICE)
-#define XEN_DEVICE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(XenDeviceClass, (obj), TYPE_XEN_DEVICE)
-
-typedef struct XenBus {
+OBJECT_DECLARE_TYPE(XenDevice, XenDeviceClass, XEN_DEVICE)
+
+struct XenBus {
BusState qbus;
domid_t backend_id;
- struct xs_handle *xsh;
- XenWatchList *watch_list;
- XenWatch *backend_watch;
+ struct qemu_xs_handle *xsh;
+ unsigned int backend_types;
+ struct qemu_xs_watch **backend_watch;
QLIST_HEAD(, XenDevice) inactive_devices;
-} XenBus;
+};
-typedef struct XenBusClass {
+struct XenBusClass {
/*< private >*/
BusClass parent_class;
-} XenBusClass;
+};
#define TYPE_XEN_BUS "xen-bus"
-#define XEN_BUS(obj) \
- OBJECT_CHECK(XenBus, (obj), TYPE_XEN_BUS)
-#define XEN_BUS_CLASS(class) \
- OBJECT_CLASS_CHECK(XenBusClass, (class), TYPE_XEN_BUS)
-#define XEN_BUS_GET_CLASS(obj) \
- OBJECT_GET_CLASS(XenBusClass, (obj), TYPE_XEN_BUS)
+OBJECT_DECLARE_TYPE(XenBus, XenBusClass,
+ XEN_BUS)
void xen_bus_init(void);
@@ -94,20 +83,21 @@ enum xenbus_state xen_device_backend_get_state(XenDevice *xendev);
void xen_device_backend_printf(XenDevice *xendev, const char *key,
const char *fmt, ...)
- GCC_FMT_ATTR(3, 4);
+ G_GNUC_PRINTF(3, 4);
void xen_device_frontend_printf(XenDevice *xendev, const char *key,
const char *fmt, ...)
- GCC_FMT_ATTR(3, 4);
+ G_GNUC_PRINTF(3, 4);
int xen_device_frontend_scanf(XenDevice *xendev, const char *key,
- const char *fmt, ...);
+ const char *fmt, ...)
+ G_GNUC_SCANF(3, 4);
void xen_device_set_max_grant_refs(XenDevice *xendev, unsigned int nr_refs,
Error **errp);
void *xen_device_map_grant_refs(XenDevice *xendev, uint32_t *refs,
unsigned int nr_refs, int prot,
Error **errp);
-void xen_device_unmap_grant_refs(XenDevice *xendev, void *map,
+void xen_device_unmap_grant_refs(XenDevice *xendev, void *map, uint32_t *refs,
unsigned int nr_refs, Error **errp);
typedef struct XenDeviceGrantCopySegment {
@@ -141,5 +131,6 @@ void xen_device_notify_event_channel(XenDevice *xendev,
void xen_device_unbind_event_channel(XenDevice *xendev,
XenEventChannel *channel,
Error **errp);
+unsigned int xen_event_channel_get_local_port(XenEventChannel *channel);
#endif /* HW_XEN_BUS_H */
diff --git a/include/hw/xen/xen-hvm-common.h b/include/hw/xen/xen-hvm-common.h
new file mode 100644
index 0000000000..65a51aac2e
--- /dev/null
+++ b/include/hw/xen/xen-hvm-common.h
@@ -0,0 +1,98 @@
+#ifndef HW_XEN_HVM_COMMON_H
+#define HW_XEN_HVM_COMMON_H
+
+#include "qemu/units.h"
+
+#include "cpu.h"
+#include "hw/pci/pci.h"
+#include "hw/hw.h"
+#include "hw/xen/xen_native.h"
+#include "hw/xen/xen-legacy-backend.h"
+#include "sysemu/runstate.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/xen.h"
+#include "sysemu/xen-mapcache.h"
+#include "qemu/error-report.h"
+#include <xen/hvm/ioreq.h>
+
+extern MemoryRegion xen_memory;
+extern MemoryListener xen_io_listener;
+extern DeviceListener xen_device_listener;
+
+//#define DEBUG_XEN_HVM
+
+#ifdef DEBUG_XEN_HVM
+#define DPRINTF(fmt, ...) \
+ do { fprintf(stderr, "xen: " fmt, ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) \
+ do { } while (0)
+#endif
+
+static inline uint32_t xen_vcpu_eport(shared_iopage_t *shared_page, int i)
+{
+ return shared_page->vcpu_ioreq[i].vp_eport;
+}
+static inline ioreq_t *xen_vcpu_ioreq(shared_iopage_t *shared_page, int vcpu)
+{
+ return &shared_page->vcpu_ioreq[vcpu];
+}
+
+#define BUFFER_IO_MAX_DELAY 100
+
+typedef struct XenPhysmap {
+ hwaddr start_addr;
+ ram_addr_t size;
+ const char *name;
+ hwaddr phys_offset;
+
+ QLIST_ENTRY(XenPhysmap) list;
+} XenPhysmap;
+
+typedef struct XenPciDevice {
+ PCIDevice *pci_dev;
+ uint32_t sbdf;
+ QLIST_ENTRY(XenPciDevice) entry;
+} XenPciDevice;
+
+typedef struct XenIOState {
+ ioservid_t ioservid;
+ shared_iopage_t *shared_page;
+ buffered_iopage_t *buffered_io_page;
+ xenforeignmemory_resource_handle *fres;
+ QEMUTimer *buffered_io_timer;
+ CPUState **cpu_by_vcpu_id;
+ /* the evtchn port for polling the notification, */
+ evtchn_port_t *ioreq_local_port;
+ /* evtchn remote and local ports for buffered io */
+ evtchn_port_t bufioreq_remote_port;
+ evtchn_port_t bufioreq_local_port;
+ /* the evtchn fd for polling */
+ xenevtchn_handle *xce_handle;
+ /* which vcpu we are serving */
+ int send_vcpu;
+
+ struct xs_handle *xenstore;
+ MemoryListener memory_listener;
+ MemoryListener io_listener;
+ QLIST_HEAD(, XenPciDevice) dev_list;
+ DeviceListener device_listener;
+
+ Notifier exit;
+} XenIOState;
+
+void xen_exit_notifier(Notifier *n, void *data);
+
+void xen_region_add(MemoryListener *listener, MemoryRegionSection *section);
+void xen_region_del(MemoryListener *listener, MemoryRegionSection *section);
+void xen_io_add(MemoryListener *listener, MemoryRegionSection *section);
+void xen_io_del(MemoryListener *listener, MemoryRegionSection *section);
+void xen_device_realize(DeviceListener *listener, DeviceState *dev);
+void xen_device_unrealize(DeviceListener *listener, DeviceState *dev);
+
+void xen_hvm_change_state_handler(void *opaque, bool running, RunState rstate);
+void xen_register_ioreq(XenIOState *state, unsigned int max_cpus,
+ const MemoryListener *xen_memory_listener);
+
+void cpu_ioreq_pio(ioreq_t *req);
+#endif /* HW_XEN_HVM_COMMON_H */
diff --git a/include/hw/xen/xen-legacy-backend.h b/include/hw/xen/xen-legacy-backend.h
index 5e6c56c4d6..2cca174778 100644
--- a/include/hw/xen/xen-legacy-backend.h
+++ b/include/hw/xen/xen-legacy-backend.h
@@ -1,19 +1,21 @@
#ifndef HW_XEN_LEGACY_BACKEND_H
#define HW_XEN_LEGACY_BACKEND_H
-#include "hw/xen/xen_common.h"
+#include "hw/xen/xen_backend_ops.h"
#include "hw/xen/xen_pvdev.h"
#include "net/net.h"
+#include "qom/object.h"
#define TYPE_XENSYSDEV "xen-sysdev"
#define TYPE_XENSYSBUS "xen-sysbus"
#define TYPE_XENBACKEND "xen-backend"
-#define XENBACKEND_DEVICE(obj) \
- OBJECT_CHECK(XenLegacyDevice, (obj), TYPE_XENBACKEND)
+typedef struct XenLegacyDevice XenLegacyDevice;
+DECLARE_INSTANCE_CHECKER(XenLegacyDevice, XENBACKEND,
+ TYPE_XENBACKEND)
/* variables */
-extern struct xs_handle *xenstore;
+extern struct qemu_xs_handle *xenstore;
extern const char *xen_protocol;
extern DeviceState *xen_sysdev;
extern BusState *xen_sysbus;
@@ -28,9 +30,6 @@ int xenstore_write_be_int64(struct XenLegacyDevice *xendev, const char *node,
char *xenstore_read_be_str(struct XenLegacyDevice *xendev, const char *node);
int xenstore_read_be_int(struct XenLegacyDevice *xendev, const char *node,
int *ival);
-void xenstore_update_fe(char *watch, struct XenLegacyDevice *xendev);
-void xenstore_update_be(char *watch, char *type, int dom,
- struct XenDevOps *ops);
char *xenstore_read_fe_str(struct XenLegacyDevice *xendev, const char *node);
int xenstore_read_fe_int(struct XenLegacyDevice *xendev, const char *node,
int *ival);
@@ -40,8 +39,7 @@ int xenstore_read_fe_uint64(struct XenLegacyDevice *xendev, const char *node,
void xen_be_check_state(struct XenLegacyDevice *xendev);
/* xen backend driver bits */
-int xen_be_init(void);
-void xen_be_register_common(void);
+void xen_be_init(void);
int xen_be_register(const char *type, struct XenDevOps *ops);
int xen_be_set_state(struct XenLegacyDevice *xendev, enum xenbus_state state);
int xen_be_bind_evtchn(struct XenLegacyDevice *xendev);
@@ -50,18 +48,7 @@ void xen_be_set_max_grant_refs(struct XenLegacyDevice *xendev,
void *xen_be_map_grant_refs(struct XenLegacyDevice *xendev, uint32_t *refs,
unsigned int nr_refs, int prot);
void xen_be_unmap_grant_refs(struct XenLegacyDevice *xendev, void *ptr,
- unsigned int nr_refs);
-
-typedef struct XenGrantCopySegment {
- union {
- void *virt;
- struct {
- uint32_t ref;
- off_t offset;
- } foreign;
- } source, dest;
- size_t len;
-} XenGrantCopySegment;
+ uint32_t *refs, unsigned int nr_refs);
int xen_be_copy_grant_refs(struct XenLegacyDevice *xendev,
bool to_domain, XenGrantCopySegment segs[],
@@ -74,9 +61,9 @@ static inline void *xen_be_map_grant_ref(struct XenLegacyDevice *xendev,
}
static inline void xen_be_unmap_grant_ref(struct XenLegacyDevice *xendev,
- void *ptr)
+ void *ptr, uint32_t ref)
{
- return xen_be_unmap_grant_refs(xendev, ptr, 1);
+ return xen_be_unmap_grant_refs(xendev, ptr, &ref, 1);
}
/* actual backend drivers */
@@ -94,8 +81,6 @@ extern struct XenDevOps xen_usb_ops; /* xen-usb.c */
/* configuration (aka xenbus setup) */
void xen_config_cleanup(void);
-int xen_config_dev_blk(DriveInfo *disk);
-int xen_config_dev_nic(NICInfo *nic);
int xen_config_dev_vfb(int vdev, const char *type);
int xen_config_dev_vkbd(int vdev);
int xen_config_dev_console(int vdev);
diff --git a/include/hw/xen/xen-x86.h b/include/hw/xen/xen-x86.h
new file mode 100644
index 0000000000..85e3db1b8d
--- /dev/null
+++ b/include/hw/xen/xen-x86.h
@@ -0,0 +1,15 @@
+/*
+ * Xen X86-specific
+ *
+ * Copyright 2020 Red Hat, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef QEMU_HW_XEN_X86_H
+#define QEMU_HW_XEN_X86_H
+
+#include "hw/i386/pc.h"
+
+void xen_hvm_init_pc(PCMachineState *pcms, MemoryRegion **ram_memory);
+
+#endif /* QEMU_HW_XEN_X86_H */
diff --git a/include/hw/xen/xen.h b/include/hw/xen/xen.h
index 771dd447f2..37ecc91fc3 100644
--- a/include/hw/xen/xen.h
+++ b/include/hw/xen/xen.h
@@ -1,19 +1,36 @@
-#ifndef QEMU_HW_XEN_H
-#define QEMU_HW_XEN_H
-
/*
* public xen header
* stuff needed outside xen-*.c, i.e. interfaces to qemu.
* must not depend on any xen headers being present in
* /usr/include/xen, so it can be included unconditionally.
*/
+#ifndef QEMU_HW_XEN_H
+#define QEMU_HW_XEN_H
+
+/*
+ * C files using Xen toolstack libraries will have included those headers
+ * already via xen_native.h, and having __XEM_TOOLS__ defined will have
+ * automatically set __XEN_INTERFACE_VERSION__ to the latest supported
+ * by the *system* Xen headers which were transitively included.
+ *
+ * C files which are part of the internal emulation, and which did not
+ * include xen_native.h, may need this defined so that the Xen headers
+ * imported to include/hw/xen/interface/ will expose the appropriate API
+ * version.
+ *
+ * This is why there's a rule that xen_native.h must be included first.
+ */
+#ifndef __XEN_INTERFACE_VERSION__
+#define __XEN_INTERFACE_VERSION__ 0x00040e00
+#endif
#include "exec/cpu-common.h"
/* xen-machine.c */
enum xen_mode {
- XEN_EMULATE = 0, // xen emulation, using xenner (default)
- XEN_ATTACH // attach to xen domain created by libxl
+ XEN_DISABLED = 0, /* xen support disabled (default) */
+ XEN_ATTACH, /* attach to xen domain created by libxl */
+ XEN_EMULATE, /* emulate Xen within QEMU */
};
extern uint32_t xen_domid;
@@ -21,17 +38,13 @@ extern enum xen_mode xen_mode;
extern bool xen_domid_restrict;
int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num);
-void xen_piix3_set_irq(void *opaque, int irq_num, int level);
-void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len);
+int xen_set_pci_link_route(uint8_t link, uint8_t irq);
+void xen_intx_set_irq(void *opaque, int irq_num, int level);
void xen_hvm_inject_msi(uint64_t addr, uint32_t data);
int xen_is_pirq_msi(uint32_t msi_data);
qemu_irq *xen_interrupt_controller_init(void);
-void xenstore_store_pv_console_info(int i, struct Chardev *chr);
-
-void xen_hvm_init(PCMachineState *pcms, MemoryRegion **ram_memory);
-
void xen_register_framebuffer(struct MemoryRegion *mr);
#endif /* QEMU_HW_XEN_H */
diff --git a/include/hw/xen/xen_backend_ops.h b/include/hw/xen/xen_backend_ops.h
new file mode 100644
index 0000000000..90cca85f52
--- /dev/null
+++ b/include/hw/xen/xen_backend_ops.h
@@ -0,0 +1,408 @@
+/*
+ * QEMU Xen backend support
+ *
+ * Copyright © 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Authors: David Woodhouse <dwmw2@infradead.org>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef QEMU_XEN_BACKEND_OPS_H
+#define QEMU_XEN_BACKEND_OPS_H
+
+#include "hw/xen/xen.h"
+#include "hw/xen/interface/xen.h"
+#include "hw/xen/interface/io/xenbus.h"
+
+/*
+ * For the time being, these operations map fairly closely to the API of
+ * the actual Xen libraries, e.g. libxenevtchn. As we complete the migration
+ * from XenLegacyDevice back ends to the new XenDevice model, they may
+ * evolve to slightly higher-level APIs.
+ *
+ * The internal emulations do not emulate the Xen APIs entirely faithfully;
+ * only enough to be used by the Xen backend devices. For example, only one
+ * event channel can be bound to each handle, since that's sufficient for
+ * the device support (only the true Xen HVM backend uses more). And the
+ * behaviour of unmask() and pending() is different too because the device
+ * backends don't care.
+ */
+
+typedef struct xenevtchn_handle xenevtchn_handle;
+typedef int xenevtchn_port_or_error_t;
+typedef uint32_t evtchn_port_t;
+typedef uint16_t domid_t;
+typedef uint32_t grant_ref_t;
+
+#define XEN_PAGE_SHIFT 12
+#define XEN_PAGE_SIZE (1UL << XEN_PAGE_SHIFT)
+#define XEN_PAGE_MASK (~(XEN_PAGE_SIZE - 1))
+
+#ifndef xen_rmb
+#define xen_rmb() smp_rmb()
+#endif
+#ifndef xen_wmb
+#define xen_wmb() smp_wmb()
+#endif
+#ifndef xen_mb
+#define xen_mb() smp_mb()
+#endif
+
+struct evtchn_backend_ops {
+ xenevtchn_handle *(*open)(void);
+ int (*bind_interdomain)(xenevtchn_handle *xc, uint32_t domid,
+ evtchn_port_t guest_port);
+ int (*unbind)(xenevtchn_handle *xc, evtchn_port_t port);
+ int (*close)(struct xenevtchn_handle *xc);
+ int (*get_fd)(struct xenevtchn_handle *xc);
+ int (*notify)(struct xenevtchn_handle *xc, evtchn_port_t port);
+ int (*unmask)(struct xenevtchn_handle *xc, evtchn_port_t port);
+ int (*pending)(struct xenevtchn_handle *xc);
+};
+
+extern struct evtchn_backend_ops *xen_evtchn_ops;
+
+static inline xenevtchn_handle *qemu_xen_evtchn_open(void)
+{
+ if (!xen_evtchn_ops) {
+ return NULL;
+ }
+ return xen_evtchn_ops->open();
+}
+
+static inline int qemu_xen_evtchn_bind_interdomain(xenevtchn_handle *xc,
+ uint32_t domid,
+ evtchn_port_t guest_port)
+{
+ if (!xen_evtchn_ops) {
+ return -ENOSYS;
+ }
+ return xen_evtchn_ops->bind_interdomain(xc, domid, guest_port);
+}
+
+static inline int qemu_xen_evtchn_unbind(xenevtchn_handle *xc,
+ evtchn_port_t port)
+{
+ if (!xen_evtchn_ops) {
+ return -ENOSYS;
+ }
+ return xen_evtchn_ops->unbind(xc, port);
+}
+
+static inline int qemu_xen_evtchn_close(xenevtchn_handle *xc)
+{
+ if (!xen_evtchn_ops) {
+ return -ENOSYS;
+ }
+ return xen_evtchn_ops->close(xc);
+}
+
+static inline int qemu_xen_evtchn_fd(xenevtchn_handle *xc)
+{
+ if (!xen_evtchn_ops) {
+ return -ENOSYS;
+ }
+ return xen_evtchn_ops->get_fd(xc);
+}
+
+static inline int qemu_xen_evtchn_notify(xenevtchn_handle *xc,
+ evtchn_port_t port)
+{
+ if (!xen_evtchn_ops) {
+ return -ENOSYS;
+ }
+ return xen_evtchn_ops->notify(xc, port);
+}
+
+static inline int qemu_xen_evtchn_unmask(xenevtchn_handle *xc,
+ evtchn_port_t port)
+{
+ if (!xen_evtchn_ops) {
+ return -ENOSYS;
+ }
+ return xen_evtchn_ops->unmask(xc, port);
+}
+
+static inline int qemu_xen_evtchn_pending(xenevtchn_handle *xc)
+{
+ if (!xen_evtchn_ops) {
+ return -ENOSYS;
+ }
+ return xen_evtchn_ops->pending(xc);
+}
+
+typedef struct xengntdev_handle xengnttab_handle;
+
+typedef struct XenGrantCopySegment {
+ union {
+ void *virt;
+ struct {
+ uint32_t ref;
+ off_t offset;
+ } foreign;
+ } source, dest;
+ size_t len;
+} XenGrantCopySegment;
+
+#define XEN_GNTTAB_OP_FEATURE_MAP_MULTIPLE (1U << 0)
+
+struct gnttab_backend_ops {
+ uint32_t features;
+ xengnttab_handle *(*open)(void);
+ int (*close)(xengnttab_handle *xgt);
+ int (*grant_copy)(xengnttab_handle *xgt, bool to_domain, uint32_t domid,
+ XenGrantCopySegment *segs, uint32_t nr_segs,
+ Error **errp);
+ int (*set_max_grants)(xengnttab_handle *xgt, uint32_t nr_grants);
+ void *(*map_refs)(xengnttab_handle *xgt, uint32_t count, uint32_t domid,
+ uint32_t *refs, int prot);
+ int (*unmap)(xengnttab_handle *xgt, void *start_address, uint32_t *refs,
+ uint32_t count);
+};
+
+extern struct gnttab_backend_ops *xen_gnttab_ops;
+
+static inline bool qemu_xen_gnttab_can_map_multi(void)
+{
+ return xen_gnttab_ops &&
+ !!(xen_gnttab_ops->features & XEN_GNTTAB_OP_FEATURE_MAP_MULTIPLE);
+}
+
+static inline xengnttab_handle *qemu_xen_gnttab_open(void)
+{
+ if (!xen_gnttab_ops) {
+ return NULL;
+ }
+ return xen_gnttab_ops->open();
+}
+
+static inline int qemu_xen_gnttab_close(xengnttab_handle *xgt)
+{
+ if (!xen_gnttab_ops) {
+ return -ENOSYS;
+ }
+ return xen_gnttab_ops->close(xgt);
+}
+
+static inline int qemu_xen_gnttab_grant_copy(xengnttab_handle *xgt,
+ bool to_domain, uint32_t domid,
+ XenGrantCopySegment *segs,
+ uint32_t nr_segs, Error **errp)
+{
+ if (!xen_gnttab_ops) {
+ return -ENOSYS;
+ }
+
+ return xen_gnttab_ops->grant_copy(xgt, to_domain, domid, segs, nr_segs,
+ errp);
+}
+
+static inline int qemu_xen_gnttab_set_max_grants(xengnttab_handle *xgt,
+ uint32_t nr_grants)
+{
+ if (!xen_gnttab_ops) {
+ return -ENOSYS;
+ }
+ return xen_gnttab_ops->set_max_grants(xgt, nr_grants);
+}
+
+static inline void *qemu_xen_gnttab_map_refs(xengnttab_handle *xgt,
+ uint32_t count, uint32_t domid,
+ uint32_t *refs, int prot)
+{
+ if (!xen_gnttab_ops) {
+ return NULL;
+ }
+ return xen_gnttab_ops->map_refs(xgt, count, domid, refs, prot);
+}
+
+static inline int qemu_xen_gnttab_unmap(xengnttab_handle *xgt,
+ void *start_address, uint32_t *refs,
+ uint32_t count)
+{
+ if (!xen_gnttab_ops) {
+ return -ENOSYS;
+ }
+ return xen_gnttab_ops->unmap(xgt, start_address, refs, count);
+}
+
+struct foreignmem_backend_ops {
+ void *(*map)(uint32_t dom, void *addr, int prot, size_t pages,
+ xen_pfn_t *pfns, int *errs);
+ int (*unmap)(void *addr, size_t pages);
+};
+
+extern struct foreignmem_backend_ops *xen_foreignmem_ops;
+
+static inline void *qemu_xen_foreignmem_map(uint32_t dom, void *addr, int prot,
+ size_t pages, xen_pfn_t *pfns,
+ int *errs)
+{
+ if (!xen_foreignmem_ops) {
+ return NULL;
+ }
+ return xen_foreignmem_ops->map(dom, addr, prot, pages, pfns, errs);
+}
+
+static inline int qemu_xen_foreignmem_unmap(void *addr, size_t pages)
+{
+ if (!xen_foreignmem_ops) {
+ return -ENOSYS;
+ }
+ return xen_foreignmem_ops->unmap(addr, pages);
+}
+
+typedef void (*xs_watch_fn)(void *opaque, const char *path);
+
+struct qemu_xs_handle;
+struct qemu_xs_watch;
+typedef uint32_t xs_transaction_t;
+
+#define XBT_NULL 0
+
+#define XS_PERM_NONE 0x00
+#define XS_PERM_READ 0x01
+#define XS_PERM_WRITE 0x02
+
+struct xenstore_backend_ops {
+ struct qemu_xs_handle *(*open)(void);
+ void (*close)(struct qemu_xs_handle *h);
+ char *(*get_domain_path)(struct qemu_xs_handle *h, unsigned int domid);
+ char **(*directory)(struct qemu_xs_handle *h, xs_transaction_t t,
+ const char *path, unsigned int *num);
+ void *(*read)(struct qemu_xs_handle *h, xs_transaction_t t,
+ const char *path, unsigned int *len);
+ bool (*write)(struct qemu_xs_handle *h, xs_transaction_t t,
+ const char *path, const void *data, unsigned int len);
+ bool (*create)(struct qemu_xs_handle *h, xs_transaction_t t,
+ unsigned int owner, unsigned int domid,
+ unsigned int perms, const char *path);
+ bool (*destroy)(struct qemu_xs_handle *h, xs_transaction_t t,
+ const char *path);
+ struct qemu_xs_watch *(*watch)(struct qemu_xs_handle *h, const char *path,
+ xs_watch_fn fn, void *opaque);
+ void (*unwatch)(struct qemu_xs_handle *h, struct qemu_xs_watch *w);
+ xs_transaction_t (*transaction_start)(struct qemu_xs_handle *h);
+ bool (*transaction_end)(struct qemu_xs_handle *h, xs_transaction_t t,
+ bool abort);
+};
+
+extern struct xenstore_backend_ops *xen_xenstore_ops;
+
+static inline struct qemu_xs_handle *qemu_xen_xs_open(void)
+{
+ if (!xen_xenstore_ops) {
+ return NULL;
+ }
+ return xen_xenstore_ops->open();
+}
+
+static inline void qemu_xen_xs_close(struct qemu_xs_handle *h)
+{
+ if (!xen_xenstore_ops) {
+ return;
+ }
+ xen_xenstore_ops->close(h);
+}
+
+static inline char *qemu_xen_xs_get_domain_path(struct qemu_xs_handle *h,
+ unsigned int domid)
+{
+ if (!xen_xenstore_ops) {
+ return NULL;
+ }
+ return xen_xenstore_ops->get_domain_path(h, domid);
+}
+
+static inline char **qemu_xen_xs_directory(struct qemu_xs_handle *h,
+ xs_transaction_t t, const char *path,
+ unsigned int *num)
+{
+ if (!xen_xenstore_ops) {
+ return NULL;
+ }
+ return xen_xenstore_ops->directory(h, t, path, num);
+}
+
+static inline void *qemu_xen_xs_read(struct qemu_xs_handle *h,
+ xs_transaction_t t, const char *path,
+ unsigned int *len)
+{
+ if (!xen_xenstore_ops) {
+ return NULL;
+ }
+ return xen_xenstore_ops->read(h, t, path, len);
+}
+
+static inline bool qemu_xen_xs_write(struct qemu_xs_handle *h,
+ xs_transaction_t t, const char *path,
+ const void *data, unsigned int len)
+{
+ if (!xen_xenstore_ops) {
+ return false;
+ }
+ return xen_xenstore_ops->write(h, t, path, data, len);
+}
+
+static inline bool qemu_xen_xs_create(struct qemu_xs_handle *h,
+ xs_transaction_t t, unsigned int owner,
+ unsigned int domid, unsigned int perms,
+ const char *path)
+{
+ if (!xen_xenstore_ops) {
+ return false;
+ }
+ return xen_xenstore_ops->create(h, t, owner, domid, perms, path);
+}
+
+static inline bool qemu_xen_xs_destroy(struct qemu_xs_handle *h,
+ xs_transaction_t t, const char *path)
+{
+ if (!xen_xenstore_ops) {
+ return false;
+ }
+ return xen_xenstore_ops->destroy(h, t, path);
+}
+
+static inline struct qemu_xs_watch *qemu_xen_xs_watch(struct qemu_xs_handle *h,
+ const char *path,
+ xs_watch_fn fn,
+ void *opaque)
+{
+ if (!xen_xenstore_ops) {
+ return NULL;
+ }
+ return xen_xenstore_ops->watch(h, path, fn, opaque);
+}
+
+static inline void qemu_xen_xs_unwatch(struct qemu_xs_handle *h,
+ struct qemu_xs_watch *w)
+{
+ if (!xen_xenstore_ops) {
+ return;
+ }
+ xen_xenstore_ops->unwatch(h, w);
+}
+
+static inline xs_transaction_t qemu_xen_xs_transaction_start(struct qemu_xs_handle *h)
+{
+ if (!xen_xenstore_ops) {
+ return XBT_NULL;
+ }
+ return xen_xenstore_ops->transaction_start(h);
+}
+
+static inline bool qemu_xen_xs_transaction_end(struct qemu_xs_handle *h,
+ xs_transaction_t t, bool abort)
+{
+ if (!xen_xenstore_ops) {
+ return false;
+ }
+ return xen_xenstore_ops->transaction_end(h, t, abort);
+}
+
+void setup_xen_backend_ops(void);
+
+#endif /* QEMU_XEN_BACKEND_OPS_H */
diff --git a/include/hw/xen/xen_igd.h b/include/hw/xen/xen_igd.h
new file mode 100644
index 0000000000..7ffca06c10
--- /dev/null
+++ b/include/hw/xen/xen_igd.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2007, Neocleus Corporation.
+ * Copyright (c) 2007, Intel Corporation.
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Alex Novik <alex@neocleus.com>
+ * Allen Kay <allen.m.kay@intel.com>
+ * Guy Zana <guy@neocleus.com>
+ */
+#ifndef XEN_IGD_H
+#define XEN_IGD_H
+
+#include "hw/xen/xen-host-pci-device.h"
+
+typedef struct XenPCIPassthroughState XenPCIPassthroughState;
+
+bool xen_igd_gfx_pt_enabled(void);
+void xen_igd_gfx_pt_set(bool value, Error **errp);
+
+uint32_t igd_read_opregion(XenPCIPassthroughState *s);
+void xen_igd_reserve_slot(PCIBus *pci_bus);
+void igd_write_opregion(XenPCIPassthroughState *s, uint32_t val);
+void xen_igd_passthrough_isa_bridge_create(XenPCIPassthroughState *s,
+ XenHostPCIDevice *dev);
+
+static inline bool is_igd_vga_passthrough(XenHostPCIDevice *dev)
+{
+ return (xen_igd_gfx_pt_enabled()
+ && ((dev->class_code >> 0x8) == PCI_CLASS_DISPLAY_VGA));
+}
+
+#endif
diff --git a/include/hw/xen/xen_common.h b/include/hw/xen/xen_native.h
index 82e56339dd..1a5ad693a4 100644
--- a/include/hw/xen/xen_common.h
+++ b/include/hw/xen/xen_native.h
@@ -1,5 +1,9 @@
-#ifndef QEMU_HW_XEN_COMMON_H
-#define QEMU_HW_XEN_COMMON_H
+#ifndef QEMU_HW_XEN_NATIVE_H
+#define QEMU_HW_XEN_NATIVE_H
+
+#ifdef __XEN_INTERFACE_VERSION__
+#error In Xen native files, include xen_native.h before other Xen headers
+#endif
/*
* If we have new enough libxenctrl then we do not want/need these compat
@@ -12,69 +16,19 @@
#include <xenctrl.h>
#include <xenstore.h>
-#include "hw/xen/interface/io/xenbus.h"
#include "hw/xen/xen.h"
-#include "hw/pci/pci.h"
+#include "hw/pci/pci_device.h"
#include "hw/xen/trace.h"
extern xc_interface *xen_xc;
/*
- * We don't support Xen prior to 4.2.0.
+ * We don't support Xen prior to 4.7.1.
*/
-/* Xen 4.2 through 4.6 */
-#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 40701
-
-typedef xc_interface xenforeignmemory_handle;
-typedef xc_evtchn xenevtchn_handle;
-typedef xc_gnttab xengnttab_handle;
-typedef evtchn_port_or_error_t xenevtchn_port_or_error_t;
-
-#define xenevtchn_open(l, f) xc_evtchn_open(l, f);
-#define xenevtchn_close(h) xc_evtchn_close(h)
-#define xenevtchn_fd(h) xc_evtchn_fd(h)
-#define xenevtchn_pending(h) xc_evtchn_pending(h)
-#define xenevtchn_notify(h, p) xc_evtchn_notify(h, p)
-#define xenevtchn_bind_interdomain(h, d, p) xc_evtchn_bind_interdomain(h, d, p)
-#define xenevtchn_unmask(h, p) xc_evtchn_unmask(h, p)
-#define xenevtchn_unbind(h, p) xc_evtchn_unbind(h, p)
-
-#define xengnttab_open(l, f) xc_gnttab_open(l, f)
-#define xengnttab_close(h) xc_gnttab_close(h)
-#define xengnttab_set_max_grants(h, n) xc_gnttab_set_max_grants(h, n)
-#define xengnttab_map_grant_ref(h, d, r, p) xc_gnttab_map_grant_ref(h, d, r, p)
-#define xengnttab_unmap(h, a, n) xc_gnttab_munmap(h, a, n)
-#define xengnttab_map_grant_refs(h, c, d, r, p) \
- xc_gnttab_map_grant_refs(h, c, d, r, p)
-#define xengnttab_map_domain_grant_refs(h, c, d, r, p) \
- xc_gnttab_map_domain_grant_refs(h, c, d, r, p)
-
-#define xenforeignmemory_open(l, f) xen_xc
-#define xenforeignmemory_close(h)
-
-static inline void *xenforeignmemory_map(xc_interface *h, uint32_t dom,
- int prot, size_t pages,
- const xen_pfn_t arr[/*pages*/],
- int err[/*pages*/])
-{
- if (err)
- return xc_map_foreign_bulk(h, dom, prot, arr, err, pages);
- else
- return xc_map_foreign_pages(h, dom, prot, arr, pages);
-}
-
-#define xenforeignmemory_unmap(h, p, s) munmap(p, s * XC_PAGE_SIZE)
-
-#else /* CONFIG_XEN_CTRL_INTERFACE_VERSION >= 40701 */
-
-#include <xenevtchn.h>
-#include <xengnttab.h>
#include <xenforeignmemory.h>
-#endif
-
extern xenforeignmemory_handle *xen_fmem;
#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 40900
@@ -134,6 +88,12 @@ static inline xenforeignmemory_resource_handle *xenforeignmemory_map_resource(
return NULL;
}
+static inline int xenforeignmemory_unmap_resource(
+ xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres)
+{
+ return 0;
+}
+
#endif /* CONFIG_XEN_CTRL_INTERFACE_VERSION < 41100 */
#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 41000
@@ -176,8 +136,6 @@ static inline xendevicemodel_handle *xendevicemodel_open(
return xen_xc;
}
-#if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 40500
-
static inline int xendevicemodel_create_ioreq_server(
xendevicemodel_handle *dmod, domid_t domid, int handle_bufioreq,
ioservid_t *id)
@@ -239,8 +197,6 @@ static inline int xendevicemodel_set_ioreq_server_state(
return xc_hvm_set_ioreq_server_state(dmod, domid, id, enabled);
}
-#endif /* CONFIG_XEN_CTRL_INTERFACE_VERSION >= 40500 */
-
static inline int xendevicemodel_set_pci_intx_level(
xendevicemodel_handle *dmod, domid_t domid, uint16_t segment,
uint8_t bus, uint8_t device, uint8_t intx, unsigned int level)
@@ -310,12 +266,6 @@ static inline int xen_set_pci_intx_level(domid_t domid, uint16_t segment,
device, intx, level);
}
-static inline int xen_set_pci_link_route(domid_t domid, uint8_t link,
- uint8_t irq)
-{
- return xendevicemodel_set_pci_link_route(xen_dmod, domid, link, irq);
-}
-
static inline int xen_inject_msi(domid_t domid, uint64_t msi_addr,
uint32_t msi_data)
{
@@ -352,7 +302,7 @@ static inline int xen_restrict(domid_t domid)
void destroy_hvm_domain(bool reboot);
/* shutdown/destroy current domain because of an error */
-void xen_shutdown_fatal_error(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
+void xen_shutdown_fatal_error(const char *fmt, ...) G_GNUC_PRINTF(1, 2);
#ifdef HVM_PARAM_VMPORT_REGS_PFN
static inline int xen_get_vmport_regs_pfn(xc_interface *xc, domid_t dom,
@@ -374,15 +324,6 @@ static inline int xen_get_vmport_regs_pfn(xc_interface *xc, domid_t dom,
}
#endif
-/* Xen before 4.6 */
-#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 40600
-
-#ifndef HVM_IOREQSRV_BUFIOREQ_ATOMIC
-#define HVM_IOREQSRV_BUFIOREQ_ATOMIC 2
-#endif
-
-#endif
-
static inline int xen_get_default_ioreq_server_info(domid_t dom,
xen_pfn_t *ioreq_pfn,
xen_pfn_t *bufioreq_pfn,
@@ -420,84 +361,6 @@ static inline int xen_get_default_ioreq_server_info(domid_t dom,
return 0;
}
-/* Xen before 4.5 */
-#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 40500
-
-#ifndef HVM_PARAM_BUFIOREQ_EVTCHN
-#define HVM_PARAM_BUFIOREQ_EVTCHN 26
-#endif
-
-#define IOREQ_TYPE_PCI_CONFIG 2
-
-typedef uint16_t ioservid_t;
-
-static inline void xen_map_memory_section(domid_t dom,
- ioservid_t ioservid,
- MemoryRegionSection *section)
-{
-}
-
-static inline void xen_unmap_memory_section(domid_t dom,
- ioservid_t ioservid,
- MemoryRegionSection *section)
-{
-}
-
-static inline void xen_map_io_section(domid_t dom,
- ioservid_t ioservid,
- MemoryRegionSection *section)
-{
-}
-
-static inline void xen_unmap_io_section(domid_t dom,
- ioservid_t ioservid,
- MemoryRegionSection *section)
-{
-}
-
-static inline void xen_map_pcidev(domid_t dom,
- ioservid_t ioservid,
- PCIDevice *pci_dev)
-{
-}
-
-static inline void xen_unmap_pcidev(domid_t dom,
- ioservid_t ioservid,
- PCIDevice *pci_dev)
-{
-}
-
-static inline void xen_create_ioreq_server(domid_t dom,
- ioservid_t *ioservid)
-{
-}
-
-static inline void xen_destroy_ioreq_server(domid_t dom,
- ioservid_t ioservid)
-{
-}
-
-static inline int xen_get_ioreq_server_info(domid_t dom,
- ioservid_t ioservid,
- xen_pfn_t *ioreq_pfn,
- xen_pfn_t *bufioreq_pfn,
- evtchn_port_t *bufioreq_evtchn)
-{
- return xen_get_default_ioreq_server_info(dom, ioreq_pfn,
- bufioreq_pfn,
- bufioreq_evtchn);
-}
-
-static inline int xen_set_ioreq_server_state(domid_t dom,
- ioservid_t ioservid,
- bool enable)
-{
- return 0;
-}
-
-/* Xen 4.5 */
-#else
-
static bool use_default_ioreq_server;
static inline void xen_map_memory_section(domid_t dom,
@@ -600,8 +463,8 @@ static inline void xen_unmap_pcidev(domid_t dom,
PCI_FUNC(pci_dev->devfn));
}
-static inline void xen_create_ioreq_server(domid_t dom,
- ioservid_t *ioservid)
+static inline int xen_create_ioreq_server(domid_t dom,
+ ioservid_t *ioservid)
{
int rc = xendevicemodel_create_ioreq_server(xen_dmod, dom,
HVM_IOREQSRV_BUFIOREQ_ATOMIC,
@@ -609,12 +472,14 @@ static inline void xen_create_ioreq_server(domid_t dom,
if (rc == 0) {
trace_xen_ioreq_server_create(*ioservid);
- return;
+ return rc;
}
*ioservid = 0;
use_default_ioreq_server = true;
trace_xen_default_ioreq_server();
+
+ return rc;
}
static inline void xen_destroy_ioreq_server(domid_t dom,
@@ -658,33 +523,28 @@ static inline int xen_set_ioreq_server_state(domid_t dom,
enable);
}
+#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 41500
+static inline int xendevicemodel_set_irq_level(xendevicemodel_handle *dmod,
+ domid_t domid, uint32_t irq,
+ unsigned int level)
+{
+ return -1;
+}
#endif
-/* Xen before 4.8 */
-
-#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 40800
-
-struct xengnttab_grant_copy_segment {
- union xengnttab_copy_ptr {
- void *virt;
- struct {
- uint32_t ref;
- uint16_t offset;
- uint16_t domid;
- } foreign;
- } source, dest;
- uint16_t len;
- uint16_t flags;
- int16_t status;
-};
-
-typedef struct xengnttab_grant_copy_segment xengnttab_grant_copy_segment_t;
+#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 41700
+#define GUEST_VIRTIO_MMIO_BASE xen_mk_ullong(0x02000000)
+#define GUEST_VIRTIO_MMIO_SIZE xen_mk_ullong(0x00100000)
+#define GUEST_VIRTIO_MMIO_SPI_FIRST 33
+#define GUEST_VIRTIO_MMIO_SPI_LAST 43
+#endif
-static inline int xengnttab_grant_copy(xengnttab_handle *xgt, uint32_t count,
- xengnttab_grant_copy_segment_t *segs)
-{
- return -ENOSYS;
-}
+#if defined(__i386__) || defined(__x86_64__)
+#define GUEST_RAM_BANKS 2
+#define GUEST_RAM0_BASE 0x40000000ULL /* 3GB of low RAM @ 1GB */
+#define GUEST_RAM0_SIZE 0xc0000000ULL
+#define GUEST_RAM1_BASE 0x0200000000ULL /* 1016GB of RAM @ 8GB */
+#define GUEST_RAM1_SIZE 0xfe00000000ULL
#endif
-#endif /* QEMU_HW_XEN_COMMON_H */
+#endif /* QEMU_HW_XEN_NATIVE_H */
diff --git a/include/hw/xen/xen_pvdev.h b/include/hw/xen/xen_pvdev.h
index 83e5174d90..ddad4b9f36 100644
--- a/include/hw/xen/xen_pvdev.h
+++ b/include/hw/xen/xen_pvdev.h
@@ -1,7 +1,9 @@
#ifndef QEMU_HW_XEN_PVDEV_H
#define QEMU_HW_XEN_PVDEV_H
-#include "hw/xen/xen_common.h"
+#include "hw/qdev-core.h"
+#include "hw/xen/xen_backend_ops.h"
+
/* ------------------------------------------------------------- */
#define XEN_BUFSIZE 1024
@@ -38,6 +40,7 @@ struct XenLegacyDevice {
char name[64];
int debug;
+ struct qemu_xs_watch *watch;
enum xenbus_state be_state;
enum xenbus_state fe_state;
int online;
@@ -63,7 +66,6 @@ int xenstore_write_int64(const char *base, const char *node, int64_t ival);
char *xenstore_read_str(const char *base, const char *node);
int xenstore_read_int(const char *base, const char *node, int *ival);
int xenstore_read_uint64(const char *base, const char *node, uint64_t *uval);
-void xenstore_update(void *unused);
const char *xenbus_strstate(enum xenbus_state state);
@@ -76,6 +78,6 @@ void xen_pv_unbind_evtchn(struct XenLegacyDevice *xendev);
int xen_pv_send_notify(struct XenLegacyDevice *xendev);
void xen_pv_printf(struct XenLegacyDevice *xendev, int msg_level,
- const char *fmt, ...) GCC_FMT_ATTR(3, 4);
+ const char *fmt, ...) G_GNUC_PRINTF(3, 4);
#endif /* QEMU_HW_XEN_PVDEV_H */