aboutsummaryrefslogtreecommitdiffstats
path: root/include/hw
diff options
context:
space:
mode:
Diffstat (limited to 'include/hw')
-rw-r--r--include/hw/acpi/acpi-defs.h95
-rw-r--r--include/hw/acpi/acpi.h203
-rw-r--r--include/hw/acpi/acpi_dev_interface.h59
-rw-r--r--include/hw/acpi/aml-build.h500
-rw-r--r--include/hw/acpi/bios-linker-loader.h39
-rw-r--r--include/hw/acpi/cpu.h70
-rw-r--r--include/hw/acpi/cpu_hotplug.h40
-rw-r--r--include/hw/acpi/generic_event_device.h121
-rw-r--r--include/hw/acpi/ghes.h84
-rw-r--r--include/hw/acpi/ich9.h94
-rw-r--r--include/hw/acpi/ipmi.h21
-rw-r--r--include/hw/acpi/memory_hotplug.h57
-rw-r--r--include/hw/acpi/pc-hotplug.h34
-rw-r--r--include/hw/acpi/pci.h39
-rw-r--r--include/hw/acpi/pcihp.h89
-rw-r--r--include/hw/acpi/tco.h82
-rw-r--r--include/hw/acpi/tpm.h216
-rw-r--r--include/hw/acpi/utils.h8
-rw-r--r--include/hw/acpi/vmgenid.h37
-rw-r--r--include/hw/adc/aspeed_adc.h55
-rw-r--r--include/hw/adc/max111x.h56
-rw-r--r--include/hw/adc/npcm7xx_adc.h69
-rw-r--r--include/hw/adc/stm32f2xx_adc.h89
-rw-r--r--include/hw/adc/zynq-xadc.h46
-rw-r--r--include/hw/arm/allwinner-a10.h44
-rw-r--r--include/hw/arm/allwinner-h3.h161
-rw-r--r--include/hw/arm/armsse-version.h42
-rw-r--r--include/hw/arm/armsse.h236
-rw-r--r--include/hw/arm/armv7m.h104
-rw-r--r--include/hw/arm/aspeed.h45
-rw-r--r--include/hw/arm/aspeed_soc.h144
-rw-r--r--include/hw/arm/bcm2835_peripherals.h79
-rw-r--r--include/hw/arm/bcm2836.h47
-rw-r--r--include/hw/arm/boot.h171
-rw-r--r--include/hw/arm/digic.h43
-rw-r--r--include/hw/arm/exynos4210.h141
-rw-r--r--include/hw/arm/fdt.h34
-rw-r--r--include/hw/arm/fsl-imx25.h279
-rw-r--r--include/hw/arm/fsl-imx31.h128
-rw-r--r--include/hw/arm/fsl-imx6.h464
-rw-r--r--include/hw/arm/fsl-imx6ul.h352
-rw-r--r--include/hw/arm/fsl-imx7.h255
-rw-r--r--include/hw/arm/linux-boot-if.h39
-rw-r--r--include/hw/arm/msf2-soc.h76
-rw-r--r--include/hw/arm/npcm7xx.h141
-rw-r--r--include/hw/arm/nrf51.h46
-rw-r--r--include/hw/arm/nrf51_soc.h57
-rw-r--r--include/hw/arm/omap.h1043
-rw-r--r--include/hw/arm/primecell.h12
-rw-r--r--include/hw/arm/pxa.h200
-rw-r--r--include/hw/arm/raspi_platform.h174
-rw-r--r--include/hw/arm/sharpsl.h17
-rw-r--r--include/hw/arm/smmu-common.h178
-rw-r--r--include/hw/arm/smmuv3.h86
-rw-r--r--include/hw/arm/soc_dma.h114
-rw-r--r--include/hw/arm/stm32f100_soc.h65
-rw-r--r--include/hw/arm/stm32f205_soc.h76
-rw-r--r--include/hw/arm/stm32f405_soc.h76
-rw-r--r--include/hw/arm/sysbus-fdt.h37
-rw-r--r--include/hw/arm/virt.h195
-rw-r--r--include/hw/arm/xlnx-versal.h194
-rw-r--r--include/hw/arm/xlnx-zynqmp.h138
-rw-r--r--include/hw/audio/pcspk.h40
-rw-r--r--include/hw/audio/soundhw.h15
-rw-r--r--include/hw/audio/wm8750.h30
-rw-r--r--include/hw/block/block.h105
-rw-r--r--include/hw/block/fdc.h21
-rw-r--r--include/hw/block/flash.h79
-rw-r--r--include/hw/block/swim.h74
-rw-r--r--include/hw/boards.h444
-rw-r--r--include/hw/char/avr_usart.h92
-rw-r--r--include/hw/char/bcm2835_aux.h35
-rw-r--r--include/hw/char/cadence_uart.h56
-rw-r--r--include/hw/char/cmsdk-apb-uart.h79
-rw-r--r--include/hw/char/digic-uart.h47
-rw-r--r--include/hw/char/escc.h61
-rw-r--r--include/hw/char/goldfish_tty.h35
-rw-r--r--include/hw/char/ibex_uart.h74
-rw-r--r--include/hw/char/imx_serial.h109
-rw-r--r--include/hw/char/mchp_pfsoc_mmuart.h68
-rw-r--r--include/hw/char/nrf51_uart.h78
-rw-r--r--include/hw/char/parallel.h13
-rw-r--r--include/hw/char/pl011.h91
-rw-r--r--include/hw/char/renesas_sci.h54
-rw-r--r--include/hw/char/riscv_htif.h59
-rw-r--r--include/hw/char/serial.h116
-rw-r--r--include/hw/char/shakti_uart.h74
-rw-r--r--include/hw/char/sifive_uart.h78
-rw-r--r--include/hw/char/stm32f2xx_usart.h77
-rw-r--r--include/hw/char/xilinx_uartlite.h38
-rw-r--r--include/hw/clock.h379
-rw-r--r--include/hw/core/accel-cpu.h38
-rw-r--r--include/hw/core/cpu.h1048
-rw-r--r--include/hw/core/generic-loader.h47
-rw-r--r--include/hw/core/split-irq.h55
-rw-r--r--include/hw/core/sysemu-cpu-ops.h92
-rw-r--r--include/hw/core/tcg-cpu-ops.h166
-rw-r--r--include/hw/cpu/a15mpcore.h44
-rw-r--r--include/hw/cpu/a9mpcore.h39
-rw-r--r--include/hw/cpu/arm11mpcore.h35
-rw-r--r--include/hw/cpu/cluster.h81
-rw-r--r--include/hw/cpu/core.h33
-rw-r--r--include/hw/cris/etraxfs.h53
-rw-r--r--include/hw/cris/etraxfs_dma.h36
-rw-r--r--include/hw/display/bcm2835_fb.h89
-rw-r--r--include/hw/display/blizzard.h21
-rw-r--r--include/hw/display/bochs-vbe.h69
-rw-r--r--include/hw/display/dpcd.h105
-rw-r--r--include/hw/display/edid.h32
-rw-r--r--include/hw/display/i2c-ddc.h41
-rw-r--r--include/hw/display/macfb.h101
-rw-r--r--include/hw/display/ramfb.h12
-rw-r--r--include/hw/display/tc6393xb.h21
-rw-r--r--include/hw/display/vga.h31
-rw-r--r--include/hw/display/xlnx_dp.h110
-rw-r--r--include/hw/dma/bcm2835_dma.h47
-rw-r--r--include/hw/dma/i8257.h50
-rw-r--r--include/hw/dma/pl080.h73
-rw-r--r--include/hw/dma/sifive_pdma.h57
-rw-r--r--include/hw/dma/xlnx-zdma.h84
-rw-r--r--include/hw/dma/xlnx-zynq-devcfg.h62
-rw-r--r--include/hw/dma/xlnx_csu_dma.h52
-rw-r--r--include/hw/dma/xlnx_dpdma.h86
-rw-r--r--include/hw/elf_ops.h611
-rw-r--r--include/hw/firmware/smbios.h289
-rw-r--r--include/hw/fw-path-provider.h44
-rw-r--r--include/hw/gpio/aspeed_gpio.h96
-rw-r--r--include/hw/gpio/bcm2835_gpio.h40
-rw-r--r--include/hw/gpio/imx_gpio.h64
-rw-r--r--include/hw/gpio/npcm7xx_gpio.h55
-rw-r--r--include/hw/gpio/nrf51_gpio.h70
-rw-r--r--include/hw/gpio/sifive_gpio.h79
-rw-r--r--include/hw/hotplug.h97
-rw-r--r--include/hw/hw.h10
-rw-r--r--include/hw/hyperv/hyperv-proto.h130
-rw-r--r--include/hw/hyperv/hyperv.h84
-rw-r--r--include/hw/hyperv/vmbus-bridge.h34
-rw-r--r--include/hw/hyperv/vmbus-proto.h222
-rw-r--r--include/hw/hyperv/vmbus.h229
-rw-r--r--include/hw/i2c/arm_sbcon_i2c.h37
-rw-r--r--include/hw/i2c/aspeed_i2c.h98
-rw-r--r--include/hw/i2c/bitbang_i2c.h50
-rw-r--r--include/hw/i2c/i2c.h194
-rw-r--r--include/hw/i2c/i2c_mux_pca954x.h19
-rw-r--r--include/hw/i2c/imx_i2c.h88
-rw-r--r--include/hw/i2c/microbit_i2c.h42
-rw-r--r--include/hw/i2c/npcm7xx_smbus.h113
-rw-r--r--include/hw/i2c/pm_smbus.h56
-rw-r--r--include/hw/i2c/pmbus_device.h517
-rw-r--r--include/hw/i2c/ppc4xx_i2c.h63
-rw-r--r--include/hw/i2c/smbus_eeprom.h36
-rw-r--r--include/hw/i2c/smbus_master.h55
-rw-r--r--include/hw/i2c/smbus_slave.h95
-rw-r--r--include/hw/i386/apic-msidef.h31
-rw-r--r--include/hw/i386/apic.h27
-rw-r--r--include/hw/i386/apic_internal.h231
-rw-r--r--include/hw/i386/hostmem-epc.h28
-rw-r--r--include/hw/i386/ich9.h256
-rw-r--r--include/hw/i386/intel_iommu.h282
-rw-r--r--include/hw/i386/ioapic.h33
-rw-r--r--include/hw/i386/ioapic_internal.h118
-rw-r--r--include/hw/i386/microvm.h116
-rw-r--r--include/hw/i386/pc.h307
-rw-r--r--include/hw/i386/sgx-epc.h67
-rw-r--r--include/hw/i386/topology.h170
-rw-r--r--include/hw/i386/vmport.h28
-rw-r--r--include/hw/i386/x86-iommu.h163
-rw-r--r--include/hw/i386/x86.h146
-rw-r--r--include/hw/ide.h24
-rw-r--r--include/hw/ide/ahci.h88
-rw-r--r--include/hw/ide/internal.h657
-rw-r--r--include/hw/ide/pci.h72
-rw-r--r--include/hw/input/adb-keys.h141
-rw-r--r--include/hw/input/adb.h108
-rw-r--r--include/hw/input/gamepad.h18
-rw-r--r--include/hw/input/hid.h83
-rw-r--r--include/hw/input/i8042.h26
-rw-r--r--include/hw/input/lasips2.h16
-rw-r--r--include/hw/input/lm832x.h28
-rw-r--r--include/hw/input/ps2.h52
-rw-r--r--include/hw/input/tsc2xxx.h41
-rw-r--r--include/hw/intc/allwinner-a10-pic.h43
-rw-r--r--include/hw/intc/arm_gic.h89
-rw-r--r--include/hw/intc/arm_gic_common.h168
-rw-r--r--include/hw/intc/arm_gicv3.h32
-rw-r--r--include/hw/intc/arm_gicv3_common.h321
-rw-r--r--include/hw/intc/arm_gicv3_its_common.h113
-rw-r--r--include/hw/intc/armv7m_nvic.h89
-rw-r--r--include/hw/intc/aspeed_vic.h49
-rw-r--r--include/hw/intc/bcm2835_ic.h36
-rw-r--r--include/hw/intc/bcm2836_control.h61
-rw-r--r--include/hw/intc/goldfish_pic.h33
-rw-r--r--include/hw/intc/heathrow_pic.h52
-rw-r--r--include/hw/intc/i8259.h12
-rw-r--r--include/hw/intc/ibex_plic.h67
-rw-r--r--include/hw/intc/imx_avic.h56
-rw-r--r--include/hw/intc/imx_gpcv2.h23
-rw-r--r--include/hw/intc/intc.h28
-rw-r--r--include/hw/intc/loongson_liointc.h22
-rw-r--r--include/hw/intc/m68k_irqc.h41
-rw-r--r--include/hw/intc/mips_gic.h218
-rw-r--r--include/hw/intc/ppc-uic.h80
-rw-r--r--include/hw/intc/realview_gic.h28
-rw-r--r--include/hw/intc/riscv_aclint.h80
-rw-r--r--include/hw/intc/rx_icu.h76
-rw-r--r--include/hw/intc/sifive_plic.h88
-rw-r--r--include/hw/intc/xlnx-pmu-iomod-intc.h57
-rw-r--r--include/hw/intc/xlnx-zynqmp-ipi.h56
-rw-r--r--include/hw/ipack/ipack.h81
-rw-r--r--include/hw/ipmi/ipmi.h305
-rw-r--r--include/hw/ipmi/ipmi_bt.h73
-rw-r--r--include/hw/ipmi/ipmi_kcs.h76
-rw-r--r--include/hw/irq.h76
-rw-r--r--include/hw/isa/apm.h25
-rw-r--r--include/hw/isa/i8259_internal.h79
-rw-r--r--include/hw/isa/isa.h152
-rw-r--r--include/hw/isa/pc87312.h56
-rw-r--r--include/hw/isa/superio.h60
-rw-r--r--include/hw/isa/vt82c686.h15
-rw-r--r--include/hw/kvm/clock.h28
-rw-r--r--include/hw/loader-fit.h41
-rw-r--r--include/hw/loader.h346
-rw-r--r--include/hw/m68k/mcf.h23
-rw-r--r--include/hw/m68k/mcf_fec.h19
-rw-r--r--include/hw/m68k/next-cube.h56
-rw-r--r--include/hw/mem/memory-device.h117
-rw-r--r--include/hw/mem/npcm7xx_mc.h36
-rw-r--r--include/hw/mem/nvdimm.h161
-rw-r--r--include/hw/mem/pc-dimm.h72
-rw-r--r--include/hw/mem/sparse-mem.h19
-rw-r--r--include/hw/mips/bios.h14
-rw-r--r--include/hw/mips/bootloader.h22
-rw-r--r--include/hw/mips/cps.h52
-rw-r--r--include/hw/mips/cpudevs.h14
-rw-r--r--include/hw/mips/mips.h25
-rw-r--r--include/hw/misc/a9scu.h32
-rw-r--r--include/hw/misc/allwinner-cpucfg.h51
-rw-r--r--include/hw/misc/allwinner-h3-ccu.h65
-rw-r--r--include/hw/misc/allwinner-h3-dramc.h105
-rw-r--r--include/hw/misc/allwinner-h3-sysctrl.h66
-rw-r--r--include/hw/misc/allwinner-sid.h59
-rw-r--r--include/hw/misc/arm11scu.h30
-rw-r--r--include/hw/misc/arm_integrator_debug.h19
-rw-r--r--include/hw/misc/armsse-cpu-pwrctrl.h40
-rw-r--r--include/hw/misc/armsse-cpuid.h42
-rw-r--r--include/hw/misc/armsse-mhu.h45
-rw-r--r--include/hw/misc/armv7m_ras.h37
-rw-r--r--include/hw/misc/aspeed_hace.h43
-rw-r--r--include/hw/misc/aspeed_lpc.h47
-rw-r--r--include/hw/misc/aspeed_scu.h319
-rw-r--r--include/hw/misc/aspeed_sdmc.h56
-rw-r--r--include/hw/misc/aspeed_xdma.h46
-rw-r--r--include/hw/misc/auxbus.h142
-rw-r--r--include/hw/misc/avr_power.h46
-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.h39
-rw-r--r--include/hw/misc/bcm2835_mbox_defs.h29
-rw-r--r--include/hw/misc/bcm2835_mphi.h44
-rw-r--r--include/hw/misc/bcm2835_powermgt.h29
-rw-r--r--include/hw/misc/bcm2835_property.h36
-rw-r--r--include/hw/misc/bcm2835_rng.h27
-rw-r--r--include/hw/misc/bcm2835_thermal.h27
-rw-r--r--include/hw/misc/cbus.h31
-rw-r--r--include/hw/misc/empty_slot.h19
-rw-r--r--include/hw/misc/grlib_ahb_apb_pnp.h57
-rw-r--r--include/hw/misc/imx25_ccm.h80
-rw-r--r--include/hw/misc/imx31_ccm.h89
-rw-r--r--include/hw/misc/imx6_ccm.h198
-rw-r--r--include/hw/misc/imx6_src.h74
-rw-r--r--include/hw/misc/imx6ul_ccm.h227
-rw-r--r--include/hw/misc/imx7_ccm.h140
-rw-r--r--include/hw/misc/imx7_gpr.h29
-rw-r--r--include/hw/misc/imx7_snvs.h36
-rw-r--r--include/hw/misc/imx_ccm.h63
-rw-r--r--include/hw/misc/imx_rngc.h36
-rw-r--r--include/hw/misc/iotkit-secctl.h127
-rw-r--r--include/hw/misc/iotkit-sysctl.h73
-rw-r--r--include/hw/misc/iotkit-sysinfo.h45
-rw-r--r--include/hw/misc/ivshmem.h25
-rw-r--r--include/hw/misc/led.h98
-rw-r--r--include/hw/misc/mac_via.h117
-rw-r--r--include/hw/misc/macio/cuda.h102
-rw-r--r--include/hw/misc/macio/gpio.h49
-rw-r--r--include/hw/misc/macio/macio.h123
-rw-r--r--include/hw/misc/macio/pmu.h236
-rw-r--r--include/hw/misc/mchp_pfsoc_dmc.h56
-rw-r--r--include/hw/misc/mchp_pfsoc_ioscb.h50
-rw-r--r--include/hw/misc/mchp_pfsoc_sysreg.h39
-rw-r--r--include/hw/misc/mips_cmgcr.h91
-rw-r--r--include/hw/misc/mips_cpc.h50
-rw-r--r--include/hw/misc/mips_itu.h83
-rw-r--r--include/hw/misc/mos6522.h150
-rw-r--r--include/hw/misc/mps2-fpgaio.h62
-rw-r--r--include/hw/misc/mps2-scc.h69
-rw-r--r--include/hw/misc/msf2-sysreg.h78
-rw-r--r--include/hw/misc/npcm7xx_clk.h180
-rw-r--r--include/hw/misc/npcm7xx_gcr.h43
-rw-r--r--include/hw/misc/npcm7xx_mft.h70
-rw-r--r--include/hw/misc/npcm7xx_pwm.h107
-rw-r--r--include/hw/misc/npcm7xx_rng.h34
-rw-r--r--include/hw/misc/nrf51_rng.h85
-rw-r--r--include/hw/misc/pca9552.h37
-rw-r--r--include/hw/misc/pca9552_regs.h32
-rw-r--r--include/hw/misc/pvpanic.h53
-rw-r--r--include/hw/misc/sifive_e_prci.h73
-rw-r--r--include/hw/misc/sifive_test.h47
-rw-r--r--include/hw/misc/sifive_u_otp.h87
-rw-r--r--include/hw/misc/sifive_u_prci.h93
-rw-r--r--include/hw/misc/stm32f2xx_syscfg.h58
-rw-r--r--include/hw/misc/stm32f4xx_exti.h59
-rw-r--r--include/hw/misc/stm32f4xx_syscfg.h60
-rw-r--r--include/hw/misc/tz-mpc.h80
-rw-r--r--include/hw/misc/tz-msc.h80
-rw-r--r--include/hw/misc/tz-ppc.h107
-rw-r--r--include/hw/misc/unimp.h54
-rw-r--r--include/hw/misc/virt_ctrl.h22
-rw-r--r--include/hw/misc/vmcoreinfo.h41
-rw-r--r--include/hw/misc/xlnx-versal-xramc.h97
-rw-r--r--include/hw/net/allwinner-sun8i-emac.h104
-rw-r--r--include/hw/net/allwinner_emac.h177
-rw-r--r--include/hw/net/cadence_gem.h97
-rw-r--r--include/hw/net/ftgmac100.h87
-rw-r--r--include/hw/net/imx_fec.h280
-rw-r--r--include/hw/net/lan9118.h20
-rw-r--r--include/hw/net/lance.h48
-rw-r--r--include/hw/net/lasi_82596.h31
-rw-r--r--include/hw/net/mii.h115
-rw-r--r--include/hw/net/msf2-emac.h53
-rw-r--r--include/hw/net/ne2000-isa.h39
-rw-r--r--include/hw/net/npcm7xx_emc.h286
-rw-r--r--include/hw/net/smc91c111.h18
-rw-r--r--include/hw/net/xlnx-zynqmp-can.h78
-rw-r--r--include/hw/nmi.h45
-rw-r--r--include/hw/nubus/mac-nubus-bridge.h29
-rw-r--r--include/hw/nubus/nubus.h75
-rw-r--r--include/hw/nvram/chrp_nvram.h57
-rw-r--r--include/hw/nvram/eeprom93xx.h40
-rw-r--r--include/hw/nvram/fw_cfg.h345
-rw-r--r--include/hw/nvram/npcm7xx_otp.h79
-rw-r--r--include/hw/nvram/nrf51_nvm.h65
-rw-r--r--include/hw/nvram/sun_nvram.h34
-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/or-irq.h51
-rw-r--r--include/hw/pci-bridge/simba.h42
-rw-r--r--include/hw/pci-host/designware.h99
-rw-r--r--include/hw/pci-host/gpex.h73
-rw-r--r--include/hw/pci-host/i440fx.h49
-rw-r--r--include/hw/pci-host/mv64361.h8
-rw-r--r--include/hw/pci-host/pam.h94
-rw-r--r--include/hw/pci-host/pnv_phb3.h167
-rw-r--r--include/hw/pci-host/pnv_phb3_regs.h450
-rw-r--r--include/hw/pci-host/pnv_phb4.h224
-rw-r--r--include/hw/pci-host/pnv_phb4_regs.h553
-rw-r--r--include/hw/pci-host/ppce500.h9
-rw-r--r--include/hw/pci-host/q35.h199
-rw-r--r--include/hw/pci-host/remote.h30
-rw-r--r--include/hw/pci-host/sabre.h53
-rw-r--r--include/hw/pci-host/spapr.h215
-rw-r--r--include/hw/pci-host/uninorth.h68
-rw-r--r--include/hw/pci-host/xilinx-pcie.h66
-rw-r--r--include/hw/pci/msi.h52
-rw-r--r--include/hw/pci/msix.h64
-rw-r--r--include/hw/pci/pci.h914
-rw-r--r--include/hw/pci/pci_bridge.h158
-rw-r--r--include/hw/pci/pci_bus.h66
-rw-r--r--include/hw/pci/pci_host.h71
-rw-r--r--include/hw/pci/pci_ids.h286
-rw-r--r--include/hw/pci/pci_regs.h8
-rw-r--r--include/hw/pci/pcie.h150
-rw-r--r--include/hw/pci/pcie_aer.h103
-rw-r--r--include/hw/pci/pcie_host.h81
-rw-r--r--include/hw/pci/pcie_port.h94
-rw-r--r--include/hw/pci/pcie_regs.h182
-rw-r--r--include/hw/pci/shpc.h65
-rw-r--r--include/hw/pci/slotid_cap.h11
-rw-r--r--include/hw/pcmcia.h66
-rw-r--r--include/hw/platform-bus.h52
-rw-r--r--include/hw/ppc/fdt.h29
-rw-r--r--include/hw/ppc/mac_dbdma.h183
-rw-r--r--include/hw/ppc/openpic.h176
-rw-r--r--include/hw/ppc/openpic_kvm.h7
-rw-r--r--include/hw/ppc/pef.h17
-rw-r--r--include/hw/ppc/pnv.h332
-rw-r--r--include/hw/ppc/pnv_core.h73
-rw-r--r--include/hw/ppc/pnv_homer.h56
-rw-r--r--include/hw/ppc/pnv_lpc.h108
-rw-r--r--include/hw/ppc/pnv_occ.h63
-rw-r--r--include/hw/ppc/pnv_pnor.h31
-rw-r--r--include/hw/ppc/pnv_psi.h120
-rw-r--r--include/hw/ppc/pnv_xive.h98
-rw-r--r--include/hw/ppc/pnv_xscom.h148
-rw-r--r--include/hw/ppc/ppc.h115
-rw-r--r--include/hw/ppc/ppc4xx.h52
-rw-r--r--include/hw/ppc/ppc_e500.h6
-rw-r--r--include/hw/ppc/spapr.h991
-rw-r--r--include/hw/ppc/spapr_cpu_core.h58
-rw-r--r--include/hw/ppc/spapr_drc.h259
-rw-r--r--include/hw/ppc/spapr_irq.h117
-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.h83
-rw-r--r--include/hw/ppc/spapr_rtas.h10
-rw-r--r--include/hw/ppc/spapr_tpm_proxy.h30
-rw-r--r--include/hw/ppc/spapr_vio.h141
-rw-r--r--include/hw/ppc/spapr_xive.h99
-rw-r--r--include/hw/ppc/vof.h60
-rw-r--r--include/hw/ppc/xics.h196
-rw-r--r--include/hw/ppc/xics_spapr.h43
-rw-r--r--include/hw/ppc/xive.h536
-rw-r--r--include/hw/ppc/xive_regs.h301
-rw-r--r--include/hw/ptimer.h301
-rw-r--r--include/hw/qdev-clock.h164
-rw-r--r--include/hw/qdev-core.h881
-rw-r--r--include/hw/qdev-dma.h16
-rw-r--r--include/hw/qdev-properties-system.h77
-rw-r--r--include/hw/qdev-properties.h257
-rw-r--r--include/hw/rdma/rdma.h37
-rw-r--r--include/hw/register.h229
-rw-r--r--include/hw/registerfields.h111
-rw-r--r--include/hw/remote/iohub.h42
-rw-r--r--include/hw/remote/machine.h38
-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/resettable.h246
-rw-r--r--include/hw/riscv/boot.h62
-rw-r--r--include/hw/riscv/boot_opensbi.h58
-rw-r--r--include/hw/riscv/microchip_pfsoc.h150
-rw-r--r--include/hw/riscv/numa.h113
-rw-r--r--include/hw/riscv/opentitan.h101
-rw-r--r--include/hw/riscv/riscv_hart.h44
-rw-r--r--include/hw/riscv/shakti_c.h75
-rw-r--r--include/hw/riscv/sifive_cpu.h31
-rw-r--r--include/hw/riscv/sifive_e.h93
-rw-r--r--include/hw/riscv/sifive_u.h168
-rw-r--r--include/hw/riscv/spike.h50
-rw-r--r--include/hw/riscv/virt.h94
-rw-r--r--include/hw/rtc/allwinner-rtc.h129
-rw-r--r--include/hw/rtc/aspeed_rtc.h28
-rw-r--r--include/hw/rtc/goldfish_rtc.h47
-rw-r--r--include/hw/rtc/m48t59.h50
-rw-r--r--include/hw/rtc/mc146818rtc.h58
-rw-r--r--include/hw/rtc/mc146818rtc_regs.h89
-rw-r--r--include/hw/rtc/pl031.h48
-rw-r--r--include/hw/rtc/sun4v-rtc.h19
-rw-r--r--include/hw/rtc/xlnx-zynqmp-rtc.h92
-rw-r--r--include/hw/rx/rx62n.h79
-rw-r--r--include/hw/s390x/3270-ccw.h48
-rw-r--r--include/hw/s390x/adapter.h23
-rw-r--r--include/hw/s390x/ap-bridge.h19
-rw-r--r--include/hw/s390x/ap-device.h27
-rw-r--r--include/hw/s390x/css-bridge.h37
-rw-r--r--include/hw/s390x/css.h336
-rw-r--r--include/hw/s390x/ebcdic.h104
-rw-r--r--include/hw/s390x/event-facility.h208
-rw-r--r--include/hw/s390x/ioinst.h258
-rw-r--r--include/hw/s390x/pv.h75
-rw-r--r--include/hw/s390x/s390-ccw.h42
-rw-r--r--include/hw/s390x/s390-pci-bus.h391
-rw-r--r--include/hw/s390x/s390-pci-clp.h215
-rw-r--r--include/hw/s390x/s390-pci-inst.h119
-rw-r--r--include/hw/s390x/s390-pci-vfio.h39
-rw-r--r--include/hw/s390x/s390-virtio-ccw.h57
-rw-r--r--include/hw/s390x/s390_flic.h142
-rw-r--r--include/hw/s390x/sclp.h232
-rw-r--r--include/hw/s390x/storage-attributes.h79
-rw-r--r--include/hw/s390x/storage-keys.h120
-rw-r--r--include/hw/s390x/tod.h54
-rw-r--r--include/hw/s390x/vfio-ccw.h27
-rw-r--r--include/hw/scsi/emulation.h16
-rw-r--r--include/hw/scsi/esp.h163
-rw-r--r--include/hw/scsi/scsi.h229
-rw-r--r--include/hw/sd/allwinner-sdhost.h136
-rw-r--r--include/hw/sd/aspeed_sdhci.h35
-rw-r--r--include/hw/sd/bcm2835_sdhost.h48
-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.h211
-rw-r--r--include/hw/sd/sdcard_legacy.h50
-rw-r--r--include/hw/sd/sdhci.h129
-rw-r--r--include/hw/sensor/emc141x_regs.h37
-rw-r--r--include/hw/sensor/tmp105.h55
-rw-r--r--include/hw/sensor/tmp105_regs.h51
-rw-r--r--include/hw/sh4/sh.h66
-rw-r--r--include/hw/sh4/sh_intc.h81
-rw-r--r--include/hw/southbridge/piix.h79
-rw-r--r--include/hw/sparc/grlib.h45
-rw-r--r--include/hw/sparc/sparc32_dma.h63
-rw-r--r--include/hw/sparc/sparc64.h12
-rw-r--r--include/hw/sparc/sun4m_iommu.h53
-rw-r--r--include/hw/sparc/sun4u_iommu.h52
-rw-r--r--include/hw/ssi/aspeed_smc.h116
-rw-r--r--include/hw/ssi/imx_spi.h107
-rw-r--r--include/hw/ssi/mss-spi.h59
-rw-r--r--include/hw/ssi/npcm7xx_fiu.h73
-rw-r--r--include/hw/ssi/pl022.h53
-rw-r--r--include/hw/ssi/sifive_spi.h47
-rw-r--r--include/hw/ssi/ssi.h109
-rw-r--r--include/hw/ssi/stm32f2xx_spi.h71
-rw-r--r--include/hw/ssi/xilinx_spips.h143
-rw-r--r--include/hw/stream.h53
-rw-r--r--include/hw/sysbus.h107
-rw-r--r--include/hw/timer/a9gtimer.h97
-rw-r--r--include/hw/timer/allwinner-a10-pit.h68
-rw-r--r--include/hw/timer/arm_mptimer.h51
-rw-r--r--include/hw/timer/armv7m_systick.h50
-rw-r--r--include/hw/timer/aspeed_timer.h77
-rw-r--r--include/hw/timer/avr_timer16.h93
-rw-r--r--include/hw/timer/bcm2835_systmr.h42
-rw-r--r--include/hw/timer/cmsdk-apb-dualtimer.h72
-rw-r--r--include/hw/timer/cmsdk-apb-timer.h46
-rw-r--r--include/hw/timer/digic-timer.h46
-rw-r--r--include/hw/timer/hpet.h86
-rw-r--r--include/hw/timer/i8254.h80
-rw-r--r--include/hw/timer/i8254_internal.h76
-rw-r--r--include/hw/timer/ibex_timer.h54
-rw-r--r--include/hw/timer/imx_epit.h81
-rw-r--r--include/hw/timer/imx_gpt.h119
-rw-r--r--include/hw/timer/mips_gictimer.h47
-rw-r--r--include/hw/timer/mss-timer.h63
-rw-r--r--include/hw/timer/npcm7xx_timer.h113
-rw-r--r--include/hw/timer/nrf51_timer.h82
-rw-r--r--include/hw/timer/renesas_cmt.h43
-rw-r--r--include/hw/timer/renesas_tmr.h58
-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.h53
-rw-r--r--include/hw/timer/stellaris-gptm.h51
-rw-r--r--include/hw/timer/stm32f2xx_timer.h102
-rw-r--r--include/hw/timer/tmu012.h23
-rw-r--r--include/hw/tricore/tc27x_soc.h129
-rw-r--r--include/hw/tricore/triboard.h50
-rw-r--r--include/hw/tricore/tricore.h10
-rw-r--r--include/hw/tricore/tricore_testdevice.h38
-rw-r--r--include/hw/usb.h585
-rw-r--r--include/hw/usb/chipidea.h17
-rw-r--r--include/hw/usb/dwc2-regs.h899
-rw-r--r--include/hw/usb/ehci-regs.h82
-rw-r--r--include/hw/usb/hcd-dwc3.h55
-rw-r--r--include/hw/usb/hcd-musb.h47
-rw-r--r--include/hw/usb/hid.h17
-rw-r--r--include/hw/usb/imx-usb-phy.h54
-rw-r--r--include/hw/usb/msd.h54
-rw-r--r--include/hw/usb/uhci-regs.h40
-rw-r--r--include/hw/usb/xhci.h21
-rw-r--r--include/hw/usb/xlnx-usb-subsystem.h45
-rw-r--r--include/hw/usb/xlnx-versal-usb2-ctrl-regs.h45
-rw-r--r--include/hw/vfio/vfio-amd-xgbe.h46
-rw-r--r--include/hw/vfio/vfio-calxeda-xgmac.h43
-rw-r--r--include/hw/vfio/vfio-common.h247
-rw-r--r--include/hw/vfio/vfio-platform.h76
-rw-r--r--include/hw/vfio/vfio.h7
-rw-r--r--include/hw/virtio/vhost-backend.h189
-rw-r--r--include/hw/virtio/vhost-scsi-common.h50
-rw-r--r--include/hw/virtio/vhost-scsi.h35
-rw-r--r--include/hw/virtio/vhost-user-blk.h56
-rw-r--r--include/hw/virtio/vhost-user-fs.h47
-rw-r--r--include/hw/virtio/vhost-user-i2c.h28
-rw-r--r--include/hw/virtio/vhost-user-rng.h33
-rw-r--r--include/hw/virtio/vhost-user-scsi.h34
-rw-r--r--include/hw/virtio/vhost-user-vsock.h36
-rw-r--r--include/hw/virtio/vhost-user.h29
-rw-r--r--include/hw/virtio/vhost-vdpa.h34
-rw-r--r--include/hw/virtio/vhost-vsock-common.h52
-rw-r--r--include/hw/virtio/vhost-vsock.h36
-rw-r--r--include/hw/virtio/vhost.h157
-rw-r--r--include/hw/virtio/virtio-access.h243
-rw-r--r--include/hw/virtio/virtio-balloon.h76
-rw-r--r--include/hw/virtio/virtio-blk.h96
-rw-r--r--include/hw/virtio/virtio-bus.h160
-rw-r--r--include/hw/virtio/virtio-crypto.h102
-rw-r--r--include/hw/virtio/virtio-gpu-bswap.h78
-rw-r--r--include/hw/virtio/virtio-gpu-pci.h39
-rw-r--r--include/hw/virtio/virtio-gpu-pixman.h45
-rw-r--r--include/hw/virtio/virtio-gpu.h288
-rw-r--r--include/hw/virtio/virtio-input.h115
-rw-r--r--include/hw/virtio/virtio-iommu.h63
-rw-r--r--include/hw/virtio/virtio-mem.h83
-rw-r--r--include/hw/virtio/virtio-mmio.h75
-rw-r--r--include/hw/virtio/virtio-net.h224
-rw-r--r--include/hw/virtio/virtio-pmem.h46
-rw-r--r--include/hw/virtio/virtio-rng.h51
-rw-r--r--include/hw/virtio/virtio-scsi.h166
-rw-r--r--include/hw/virtio/virtio-serial.h227
-rw-r--r--include/hw/virtio/virtio.h400
-rw-r--r--include/hw/vmstate-if.h39
-rw-r--r--include/hw/watchdog/cmsdk-apb-watchdog.h68
-rw-r--r--include/hw/watchdog/sbsa_gwdt.h79
-rw-r--r--include/hw/watchdog/wdt_aspeed.h50
-rw-r--r--include/hw/watchdog/wdt_diag288.h35
-rw-r--r--include/hw/watchdog/wdt_imx2.h91
-rw-r--r--include/hw/xen/interface/grant_table.h36
-rw-r--r--include/hw/xen/interface/io/blkif.h712
-rw-r--r--include/hw/xen/interface/io/console.h46
-rw-r--r--include/hw/xen/interface/io/fbif.h156
-rw-r--r--include/hw/xen/interface/io/kbdif.h566
-rw-r--r--include/hw/xen/interface/io/netif.h1010
-rw-r--r--include/hw/xen/interface/io/protocols.h42
-rw-r--r--include/hw/xen/interface/io/ring.h474
-rw-r--r--include/hw/xen/interface/io/usbif.h254
-rw-r--r--include/hw/xen/interface/io/xenbus.h70
-rw-r--r--include/hw/xen/start_info.h146
-rw-r--r--include/hw/xen/xen-backend.h40
-rw-r--r--include/hw/xen/xen-block.h89
-rw-r--r--include/hw/xen/xen-bus-helper.h45
-rw-r--r--include/hw/xen/xen-bus.h139
-rw-r--r--include/hw/xen/xen-legacy-backend.h105
-rw-r--r--include/hw/xen/xen-x86.h15
-rw-r--r--include/hw/xen/xen.h35
-rw-r--r--include/hw/xen/xen_common.h696
-rw-r--r--include/hw/xen/xen_pvdev.h81
-rw-r--r--include/hw/xtensa/mx_pic.h43
-rw-r--r--include/hw/xtensa/xtensa-isa.h836
618 files changed, 67048 insertions, 0 deletions
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
new file mode 100644
index 000000000..c97e8633a
--- /dev/null
+++ b/include/hw/acpi/acpi-defs.h
@@ -0,0 +1,95 @@
+/*
+ * 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 QEMU_ACPI_DEFS_H
+#define QEMU_ACPI_DEFS_H
+
+enum {
+ ACPI_FADT_F_WBINVD,
+ ACPI_FADT_F_WBINVD_FLUSH,
+ ACPI_FADT_F_PROC_C1,
+ ACPI_FADT_F_P_LVL2_UP,
+ ACPI_FADT_F_PWR_BUTTON,
+ ACPI_FADT_F_SLP_BUTTON,
+ ACPI_FADT_F_FIX_RTC,
+ ACPI_FADT_F_RTC_S4,
+ ACPI_FADT_F_TMR_VAL_EXT,
+ ACPI_FADT_F_DCK_CAP,
+ ACPI_FADT_F_RESET_REG_SUP,
+ ACPI_FADT_F_SEALED_CASE,
+ ACPI_FADT_F_HEADLESS,
+ ACPI_FADT_F_CPU_SW_SLP,
+ ACPI_FADT_F_PCI_EXP_WAK,
+ ACPI_FADT_F_USE_PLATFORM_CLOCK,
+ ACPI_FADT_F_S4_RTC_STS_VALID,
+ ACPI_FADT_F_REMOTE_POWER_ON_CAPABLE,
+ ACPI_FADT_F_FORCE_APIC_CLUSTER_MODEL,
+ ACPI_FADT_F_FORCE_APIC_PHYSICAL_DESTINATION_MODE,
+ ACPI_FADT_F_HW_REDUCED_ACPI,
+ ACPI_FADT_F_LOW_POWER_S0_IDLE_CAPABLE,
+};
+
+typedef struct AcpiRsdpData {
+ 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;
+
+struct AcpiGenericAddress {
+ uint8_t space_id; /* Address space where struct or register exists */
+ uint8_t bit_width; /* Size in bits of given register */
+ uint8_t bit_offset; /* Bit offset within the register */
+ 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 */
+};
+
+typedef struct AcpiFadtData {
+ struct AcpiGenericAddress pm1a_cnt; /* PM1a_CNT_BLK */
+ struct AcpiGenericAddress pm1a_evt; /* PM1a_EVT_BLK */
+ struct AcpiGenericAddress pm_tmr; /* PM_TMR_BLK */
+ struct AcpiGenericAddress gpe0_blk; /* GPE0_BLK */
+ struct AcpiGenericAddress reset_reg; /* RESET_REG */
+ struct AcpiGenericAddress sleep_ctl; /* SLEEP_CONTROL_REG */
+ struct AcpiGenericAddress sleep_sts; /* SLEEP_STATUS_REG */
+ uint8_t reset_val; /* RESET_VALUE */
+ uint8_t rev; /* Revision */
+ uint32_t flags; /* Flags */
+ uint32_t smi_cmd; /* SMI_CMD */
+ uint16_t sci_int; /* SCI_INT */
+ uint8_t int_model; /* INT_MODEL */
+ uint8_t acpi_enable_cmd; /* ACPI_ENABLE */
+ uint8_t acpi_disable_cmd; /* ACPI_DISABLE */
+ uint8_t rtc_century; /* CENTURY */
+ uint16_t plvl2_lat; /* P_LVL2_LAT */
+ uint16_t plvl3_lat; /* P_LVL3_LAT */
+ uint16_t arm_boot_arch; /* ARM_BOOT_ARCH */
+ uint8_t minor_ver; /* FADT Minor Version */
+
+ /*
+ * respective tables offsets within ACPI_BUILD_TABLE_FILE,
+ * NULL if table doesn't exist (in that case field's value
+ * won't be patched by linker and will be kept set to 0)
+ */
+ unsigned *facs_tbl_offset; /* FACS offset in */
+ unsigned *dsdt_tbl_offset;
+ unsigned *xdsdt_tbl_offset;
+} AcpiFadtData;
+
+#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
new file mode 100644
index 000000000..cc0d37074
--- /dev/null
+++ b/include/hw/acpi/acpi.h
@@ -0,0 +1,203 @@
+#ifndef QEMU_HW_ACPI_H
+#define QEMU_HW_ACPI_H
+
+/*
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * 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/>.
+ */
+
+#include "qemu/notify.h"
+#include "exec/memory.h"
+#include "hw/acpi/acpi_dev_interface.h"
+
+/*
+ * current device naming scheme supports up to 256 memory devices
+ */
+#define ACPI_MAX_RAM_SLOTS 256
+
+/* from linux include/acpi/actype.h */
+/* Default ACPI register widths */
+
+#define ACPI_GPE_REGISTER_WIDTH 8
+#define ACPI_PM1_REGISTER_WIDTH 16
+#define ACPI_PM2_REGISTER_WIDTH 8
+#define ACPI_PM_TIMER_WIDTH 32
+
+/* PC-style peripherals (also used by other machines). */
+#define ACPI_PM_PROP_S3_DISABLED "disable_s3"
+#define ACPI_PM_PROP_S4_DISABLED "disable_s4"
+#define ACPI_PM_PROP_S4_VAL "s4_val"
+#define ACPI_PM_PROP_SCI_INT "sci_int"
+#define ACPI_PM_PROP_ACPI_ENABLE_CMD "acpi_enable_cmd"
+#define ACPI_PM_PROP_ACPI_DISABLE_CMD "acpi_disable_cmd"
+#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
+
+
+/* ACPI fixed hardware registers */
+
+/* from linux/drivers/acpi/acpica/aclocal.h */
+/* Masks used to access the bit_registers */
+
+/* PM1x_STS */
+#define ACPI_BITMASK_TIMER_STATUS 0x0001
+#define ACPI_BITMASK_BUS_MASTER_STATUS 0x0010
+#define ACPI_BITMASK_GLOBAL_LOCK_STATUS 0x0020
+#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_WAKE_STATUS 0x8000
+
+#define ACPI_BITMASK_ALL_FIXED_STATUS (\
+ ACPI_BITMASK_TIMER_STATUS | \
+ ACPI_BITMASK_BUS_MASTER_STATUS | \
+ ACPI_BITMASK_GLOBAL_LOCK_STATUS | \
+ ACPI_BITMASK_POWER_BUTTON_STATUS | \
+ ACPI_BITMASK_SLEEP_BUTTON_STATUS | \
+ ACPI_BITMASK_RT_CLOCK_STATUS | \
+ ACPI_BITMASK_WAKE_STATUS)
+
+/* PM1x_EN */
+#define ACPI_BITMASK_TIMER_ENABLE 0x0001
+#define ACPI_BITMASK_GLOBAL_LOCK_ENABLE 0x0020
+#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_PM1_COMMON_ENABLED ( \
+ ACPI_BITMASK_RT_CLOCK_ENABLE | \
+ ACPI_BITMASK_POWER_BUTTON_ENABLE | \
+ ACPI_BITMASK_GLOBAL_LOCK_ENABLE | \
+ ACPI_BITMASK_TIMER_ENABLE)
+
+/* PM1x_CNT */
+#define ACPI_BITMASK_SCI_ENABLE 0x0001
+#define ACPI_BITMASK_BUS_MASTER_RLD 0x0002
+#define ACPI_BITMASK_GLOBAL_LOCK_RELEASE 0x0004
+#define ACPI_BITMASK_SLEEP_TYPE 0x1C00
+#define ACPI_BITMASK_SLEEP_ENABLE 0x2000
+
+/* PM2_CNT */
+#define ACPI_BITMASK_ARB_DISABLE 0x0001
+
+/* structs */
+typedef struct ACPIPMTimer ACPIPMTimer;
+typedef struct ACPIPM1EVT ACPIPM1EVT;
+typedef struct ACPIPM1CNT ACPIPM1CNT;
+typedef struct ACPIGPE ACPIGPE;
+typedef struct ACPIREGS ACPIREGS;
+
+typedef void (*acpi_update_sci_fn)(ACPIREGS *ar);
+
+struct ACPIPMTimer {
+ QEMUTimer *timer;
+ MemoryRegion io;
+ int64_t overflow_time;
+
+ acpi_update_sci_fn update_sci;
+};
+
+struct ACPIPM1EVT {
+ MemoryRegion io;
+ uint16_t sts;
+ uint16_t en;
+ acpi_update_sci_fn update_sci;
+};
+
+struct ACPIPM1CNT {
+ MemoryRegion io;
+ uint16_t cnt;
+ uint8_t s4_val;
+ bool acpi_only;
+};
+
+struct ACPIGPE {
+ uint8_t len;
+
+ uint8_t *sts;
+ uint8_t *en;
+};
+
+struct ACPIREGS {
+ ACPIPMTimer tmr;
+ ACPIGPE gpe;
+ struct {
+ ACPIPM1EVT evt;
+ ACPIPM1CNT cnt;
+ } pm1;
+ Notifier wakeup;
+};
+
+/* PM_TMR */
+void acpi_pm_tmr_update(ACPIREGS *ar, bool enable);
+void acpi_pm_tmr_calc_overflow_time(ACPIREGS *ar);
+void acpi_pm_tmr_init(ACPIREGS *ar, acpi_update_sci_fn update_sci,
+ MemoryRegion *parent);
+void acpi_pm_tmr_reset(ACPIREGS *ar);
+
+/* PM1a_EVT: piix and ich9 don't implement PM1b. */
+uint16_t acpi_pm1_evt_get_sts(ACPIREGS *ar);
+void acpi_pm1_evt_power_down(ACPIREGS *ar);
+void acpi_pm1_evt_reset(ACPIREGS *ar);
+void acpi_pm1_evt_init(ACPIREGS *ar, acpi_update_sci_fn update_sci,
+ MemoryRegion *parent);
+
+/* 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 acpi_only);
+void acpi_pm1_cnt_update(ACPIREGS *ar,
+ bool sci_enable, bool sci_disable);
+void acpi_pm1_cnt_reset(ACPIREGS *ar);
+
+/* GPE0 */
+void acpi_gpe_init(ACPIREGS *ar, uint8_t len);
+void acpi_gpe_reset(ACPIREGS *ar);
+
+void acpi_gpe_ioport_writeb(ACPIREGS *ar, uint32_t addr, uint32_t val);
+uint32_t acpi_gpe_ioport_readb(ACPIREGS *ar, uint32_t addr);
+
+void acpi_send_gpe_event(ACPIREGS *ar, qemu_irq irq,
+ AcpiEventStatusBits status);
+
+void acpi_update_sci(ACPIREGS *acpi_regs, qemu_irq irq);
+
+/* acpi.c */
+extern char unsigned *acpi_tables;
+extern size_t acpi_tables_len;
+
+uint8_t *acpi_table_first(void);
+uint8_t *acpi_table_next(uint8_t *current);
+unsigned acpi_table_len(void *current);
+void acpi_table_add(const QemuOpts *opts, Error **errp);
+
+typedef struct AcpiSlicOem AcpiSlicOem;
+struct AcpiSlicOem {
+ char *id;
+ char *table_id;
+};
+int acpi_get_slic_oem(AcpiSlicOem *oem);
+
+#endif /* QEMU_HW_ACPI_H */
diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h
new file mode 100644
index 000000000..ea6056ab9
--- /dev/null
+++ b/include/hw/acpi/acpi_dev_interface.h
@@ -0,0 +1,59 @@
+#ifndef ACPI_DEV_INTERFACE_H
+#define ACPI_DEV_INTERFACE_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 */
+typedef enum {
+ ACPI_PCI_HOTPLUG_STATUS = 2,
+ ACPI_CPU_HOTPLUG_STATUS = 4,
+ ACPI_MEMORY_HOTPLUG_STATUS = 8,
+ ACPI_NVDIMM_HOTPLUG_STATUS = 16,
+ ACPI_VMGENID_CHANGE_STATUS = 32,
+ ACPI_POWER_DOWN_STATUS = 64,
+} AcpiEventStatusBits;
+
+#define TYPE_ACPI_DEVICE_IF "acpi-device-interface"
+
+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)
+
+typedef struct AcpiDeviceIf AcpiDeviceIf;
+
+void acpi_send_event(DeviceState *dev, AcpiEventStatusBits event);
+
+/**
+ * AcpiDeviceIfClass:
+ *
+ * ospm_status: returns status of ACPI device objects, reported
+ * via _OST method if device supports it.
+ * send_event: inject a specified event into guest
+ * madt_cpu: fills @entry with Interrupt Controller Structure
+ * for CPU indexed by @uid in @apic_ids array,
+ * returned structure types are:
+ * 0 - Local APIC, 9 - Local x2APIC, 0xB - GICC
+ *
+ * Interface is designed for providing unified interface
+ * to generic ACPI functionality that could be used without
+ * knowledge about internals of actual device that implements
+ * ACPI interface.
+ */
+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,
+ bool force_enabled);
+};
+#endif
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
new file mode 100644
index 000000000..8346003a2
--- /dev/null
+++ b/include/hw/acpi/aml-build.h
@@ -0,0 +1,500 @@
+#ifndef HW_ACPI_AML_BUILD_H
+#define HW_ACPI_AML_BUILD_H
+
+#include "hw/acpi/acpi-defs.h"
+#include "hw/acpi/bios-linker-loader.h"
+
+#define ACPI_BUILD_APPNAME6 "BOCHS "
+#define ACPI_BUILD_APPNAME8 "BXPC "
+
+#define ACPI_BUILD_TABLE_FILE "etc/acpi/tables"
+#define ACPI_BUILD_RSDP_FILE "etc/acpi/rsdp"
+#define ACPI_BUILD_TPMLOG_FILE "etc/tpm/log"
+#define ACPI_BUILD_LOADER_FILE "etc/table-loader"
+
+#define AML_NOTIFY_METHOD "NTFY"
+
+typedef enum {
+ AML_NO_OPCODE = 0,/* has only data */
+ AML_OPCODE, /* has opcode optionally followed by data */
+ AML_PACKAGE, /* has opcode and uses PkgLength for its length */
+ AML_EXT_PACKAGE, /* Same as AML_PACKAGE but also has 'ExOpPrefix' */
+ AML_BUFFER, /* data encoded as 'DefBuffer' */
+ AML_RES_TEMPLATE, /* encoded as ResourceTemplate macro */
+} AmlBlockFlags;
+
+struct Aml {
+ GArray *buf;
+
+ /*< private >*/
+ uint8_t op;
+ AmlBlockFlags block_flags;
+};
+
+typedef enum {
+ AML_COMPATIBILITY = 0,
+ AML_TYPEA = 1,
+ AML_TYPEB = 2,
+ AML_TYPEF = 3,
+} AmlDmaType;
+
+typedef enum {
+ AML_NOTBUSMASTER = 0,
+ AML_BUSMASTER = 1,
+} AmlDmaBusMaster;
+
+typedef enum {
+ AML_TRANSFER8 = 0,
+ AML_TRANSFER8_16 = 1,
+ AML_TRANSFER16 = 2,
+} AmlTransferSize;
+
+typedef enum {
+ AML_DECODE10 = 0,
+ AML_DECODE16 = 1,
+} AmlIODecode;
+
+typedef enum {
+ AML_ANY_ACC = 0,
+ AML_BYTE_ACC = 1,
+ AML_WORD_ACC = 2,
+ AML_DWORD_ACC = 3,
+ AML_QWORD_ACC = 4,
+ AML_BUFFER_ACC = 5,
+} AmlAccessType;
+
+typedef enum {
+ AML_NOLOCK = 0,
+ AML_LOCK = 1,
+} AmlLockRule;
+
+typedef enum {
+ AML_PRESERVE = 0,
+ AML_WRITE_AS_ONES = 1,
+ AML_WRITE_AS_ZEROS = 2,
+} AmlUpdateRule;
+
+typedef enum {
+ AML_AS_SYSTEM_MEMORY = 0X00,
+ AML_AS_SYSTEM_IO = 0X01,
+ AML_AS_PCI_CONFIG = 0X02,
+ AML_AS_EMBEDDED_CTRL = 0X03,
+ AML_AS_SMBUS = 0X04,
+ AML_AS_FFH = 0X7F,
+} AmlAddressSpace;
+
+typedef enum {
+ AML_SYSTEM_MEMORY = 0X00,
+ AML_SYSTEM_IO = 0X01,
+ AML_PCI_CONFIG = 0X02,
+} AmlRegionSpace;
+
+typedef enum {
+ AML_MEMORY_RANGE = 0,
+ AML_IO_RANGE = 1,
+ AML_BUS_NUMBER_RANGE = 2,
+} AmlResourceType;
+
+typedef enum {
+ AML_SUB_DECODE = 1 << 1,
+ AML_POS_DECODE = 0
+} AmlDecode;
+
+typedef enum {
+ AML_MAX_FIXED = 1 << 3,
+ AML_MAX_NOT_FIXED = 0,
+} AmlMaxFixed;
+
+typedef enum {
+ AML_MIN_FIXED = 1 << 2,
+ AML_MIN_NOT_FIXED = 0
+} AmlMinFixed;
+
+/*
+ * ACPI 1.0b: Table 6-26 I/O Resource Flag (Resource Type = 1) Definitions
+ * _RNG field definition
+ */
+typedef enum {
+ AML_ISA_ONLY = 1,
+ AML_NON_ISA_ONLY = 2,
+ AML_ENTIRE_RANGE = 3,
+} AmlISARanges;
+
+/*
+ * ACPI 1.0b: Table 6-25 Memory Resource Flag (Resource Type = 0) Definitions
+ * _MEM field definition
+ */
+typedef enum {
+ AML_NON_CACHEABLE = 0,
+ AML_CACHEABLE = 1,
+ AML_WRITE_COMBINING = 2,
+ AML_PREFETCHABLE = 3,
+} AmlCacheable;
+
+/*
+ * ACPI 1.0b: Table 6-25 Memory Resource Flag (Resource Type = 0) Definitions
+ * _RW field definition
+ */
+typedef enum {
+ AML_READ_ONLY = 0,
+ AML_READ_WRITE = 1,
+} AmlReadAndWrite;
+
+/*
+ * ACPI 5.0: Table 6-187 Extended Interrupt Descriptor Definition
+ * Interrupt Vector Flags Bits[0] Consumer/Producer
+ */
+typedef enum {
+ AML_CONSUMER_PRODUCER = 0,
+ AML_CONSUMER = 1,
+} AmlConsumerAndProducer;
+
+/*
+ * ACPI 5.0: Table 6-187 Extended Interrupt Descriptor Definition
+ * _HE field definition
+ */
+typedef enum {
+ AML_LEVEL = 0,
+ AML_EDGE = 1,
+} AmlLevelAndEdge;
+
+/*
+ * ACPI 5.0: Table 6-187 Extended Interrupt Descriptor Definition
+ * _LL field definition
+ */
+typedef enum {
+ AML_ACTIVE_HIGH = 0,
+ AML_ACTIVE_LOW = 1,
+} AmlActiveHighAndLow;
+
+/*
+ * ACPI 5.0: Table 6-187 Extended Interrupt Descriptor Definition
+ * _SHR field definition
+ */
+typedef enum {
+ AML_EXCLUSIVE = 0,
+ AML_SHARED = 1,
+ AML_EXCLUSIVE_AND_WAKE = 2,
+ AML_SHARED_AND_WAKE = 3,
+} AmlShared;
+
+/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: MethodFlags */
+typedef enum {
+ AML_NOTSERIALIZED = 0,
+ AML_SERIALIZED = 1,
+} AmlSerializeFlag;
+
+/*
+ * ACPI 5.0: Table 6-189 GPIO Connection Descriptor Definition
+ * GPIO Connection Type
+ */
+typedef enum {
+ AML_INTERRUPT_CONNECTION = 0,
+ AML_IO_CONNECTION = 1,
+} AmlGpioConnectionType;
+
+/*
+ * ACPI 5.0: Table 6-189 GPIO Connection Descriptor Definition
+ * _PPI field definition
+ */
+typedef enum {
+ AML_PULL_DEFAULT = 0,
+ AML_PULL_UP = 1,
+ AML_PULL_DOWN = 2,
+ AML_PULL_NONE = 3,
+} AmlPinConfig;
+
+typedef enum {
+ MEM_AFFINITY_NOFLAGS = 0,
+ MEM_AFFINITY_ENABLED = (1 << 0),
+ MEM_AFFINITY_HOTPLUGGABLE = (1 << 1),
+ MEM_AFFINITY_NON_VOLATILE = (1 << 2),
+} MemoryAffinityFlags;
+
+typedef
+struct AcpiBuildTables {
+ GArray *table_data;
+ GArray *rsdp;
+ GArray *tcpalog;
+ GArray *vmgenid;
+ GArray *hardware_errors;
+ 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
+ */
+#define AML_SERIAL_BUS_TYPE_I2C 1
+#define AML_SERIAL_BUS_TYPE_SPI 2
+#define AML_SERIAL_BUS_TYPE_UART 3
+
+/*
+ * ACPI 5.0: 6.4.3.8.2 Serial Bus Connection Descriptors
+ * General Flags
+ */
+/* Slave Mode */
+#define AML_SERIAL_BUS_FLAG_MASTER_DEVICE (1 << 0)
+/* Consumer/Producer */
+#define AML_SERIAL_BUS_FLAG_CONSUME_ONLY (1 << 1)
+
+/**
+ * init_aml_allocator:
+ *
+ * Called for initializing API allocator which allow to use
+ * AML API.
+ * Returns: toplevel container which accumulates all other
+ * AML elements for a table.
+ */
+Aml *init_aml_allocator(void);
+
+/**
+ * free_aml_allocator:
+ *
+ * Releases all elements used by AML API, frees associated memory
+ * and invalidates AML allocator. After this call @init_aml_allocator
+ * should be called again if AML API is to be used again.
+ */
+void free_aml_allocator(void);
+
+/**
+ * aml_append:
+ * @parent_ctx: context to which @child element is added
+ * @child: element that is copied into @parent_ctx context
+ *
+ * Joins Aml elements together and helps to construct AML tables
+ * Examle of usage:
+ * Aml *table = aml_def_block("SSDT", ...);
+ * Aml *sb = aml_scope("\\_SB");
+ * Aml *dev = aml_device("PCI0");
+ *
+ * aml_append(dev, aml_name_decl("HID", aml_eisaid("PNP0A03")));
+ * aml_append(sb, dev);
+ * aml_append(table, sb);
+ */
+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_decl(const char *name, Aml *val);
+Aml *aml_debug(void);
+Aml *aml_return(Aml *val);
+Aml *aml_int(const uint64_t val);
+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);
+Aml *aml_lless(Aml *arg1, Aml *arg2);
+Aml *aml_add(Aml *arg1, Aml *arg2, Aml *dst);
+Aml *aml_subtract(Aml *arg1, Aml *arg2, Aml *dst);
+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);
+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,
+ AmlPinConfig pin_config, uint16_t debounce_timeout,
+ const uint32_t pin_list[], uint32_t pin_count,
+ const char *resource_source_name,
+ const uint8_t *vendor_data, uint16_t vendor_data_len);
+Aml *aml_memory32_fixed(uint32_t addr, uint32_t size,
+ AmlReadAndWrite read_and_write);
+Aml *aml_interrupt(AmlConsumerAndProducer con_and_pro,
+ AmlLevelAndEdge level_and_edge,
+ AmlActiveHighAndLow high_and_low, AmlShared shared,
+ uint32_t *irq_list, uint8_t irq_count);
+Aml *aml_io(AmlIODecode dec, uint16_t min_base, uint16_t max_base,
+ uint8_t aln, uint8_t len);
+Aml *aml_operation_region(const char *name, AmlRegionSpace rs,
+ Aml *offset, uint32_t len);
+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_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);
+Aml *aml_eisaid(const char *str);
+Aml *aml_word_bus_number(AmlMinFixed min_fixed, AmlMaxFixed max_fixed,
+ AmlDecode dec, uint16_t addr_gran,
+ uint16_t addr_min, uint16_t addr_max,
+ uint16_t addr_trans, uint16_t len);
+Aml *aml_word_io(AmlMinFixed min_fixed, AmlMaxFixed max_fixed,
+ AmlDecode dec, AmlISARanges isa_ranges,
+ uint16_t addr_gran, uint16_t addr_min,
+ uint16_t addr_max, uint16_t addr_trans,
+ uint16_t len);
+Aml *aml_dword_io(AmlMinFixed min_fixed, AmlMaxFixed max_fixed,
+ AmlDecode dec, AmlISARanges isa_ranges,
+ uint32_t addr_gran, uint32_t addr_min,
+ uint32_t addr_max, uint32_t addr_trans,
+ uint32_t len);
+Aml *aml_dword_memory(AmlDecode dec, AmlMinFixed min_fixed,
+ AmlMaxFixed max_fixed, AmlCacheable cacheable,
+ AmlReadAndWrite read_and_write,
+ uint32_t addr_gran, uint32_t addr_min,
+ uint32_t addr_max, uint32_t addr_trans,
+ uint32_t len);
+Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed,
+ AmlMaxFixed max_fixed, AmlCacheable cacheable,
+ AmlReadAndWrite read_and_write,
+ uint64_t addr_gran, uint64_t addr_min,
+ uint64_t addr_max, uint64_t addr_trans,
+ uint64_t len);
+Aml *aml_dma(AmlDmaType typ, AmlDmaBusMaster bm, AmlTransferSize sz,
+ uint8_t channel);
+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_method(const char *name, int arg_count, AmlSerializeFlag sflag);
+Aml *aml_if(Aml *predicate);
+Aml *aml_else(void);
+Aml *aml_while(Aml *predicate);
+Aml *aml_package(uint8_t num_elements);
+Aml *aml_buffer(int buffer_size, uint8_t *byte_list);
+Aml *aml_resource_template(void);
+Aml *aml_field(const char *name, AmlAccessType type, AmlLockRule lock,
+ AmlUpdateRule rule);
+Aml *aml_mutex(const char *name, uint8_t sync_level);
+Aml *aml_acquire(Aml *mutex, uint16_t timeout);
+Aml *aml_release(Aml *mutex);
+Aml *aml_alias(const char *source_object, const char *alias_object);
+Aml *aml_create_field(Aml *srcbuf, Aml *bit_index, Aml *num_bits,
+ const char *name);
+Aml *aml_create_dword_field(Aml *srcbuf, Aml *index, const char *name);
+Aml *aml_create_qword_field(Aml *srcbuf, Aml *index, const char *name);
+Aml *aml_varpackage(uint32_t num_elements);
+Aml *aml_touuid(const char *uuid);
+Aml *aml_unicode(const char *str);
+Aml *aml_refof(Aml *arg);
+Aml *aml_derefof(Aml *arg);
+Aml *aml_sizeof(Aml *arg);
+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);
+
+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);
+void acpi_build_tables_init(AcpiBuildTables *tables);
+void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre);
+void
+build_rsdp(GArray *tbl, BIOSLinker *linker, AcpiRsdpData *rsdp_data);
+void
+build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
+ const char *oem_id, const char *oem_table_id);
+void
+build_xsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
+ const char *oem_id, const char *oem_table_id);
+
+int
+build_append_named_dword(GArray *array, const char *name_format, ...)
+GCC_FMT_ATTR(2, 3);
+
+void build_append_gas(GArray *table, AmlAddressSpace as,
+ uint8_t bit_width, uint8_t bit_offset,
+ uint8_t access_width, uint64_t address);
+
+static inline void
+build_append_gas_from_struct(GArray *table, const struct AcpiGenericAddress *s)
+{
+ build_append_gas(table, s->space_id, s->bit_width, s->bit_offset,
+ s->access_width, s->address);
+}
+
+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,
+ 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,
+ const char *oem_id, const char *oem_table_id);
+#endif
diff --git a/include/hw/acpi/bios-linker-loader.h b/include/hw/acpi/bios-linker-loader.h
new file mode 100644
index 000000000..a711dbced
--- /dev/null
+++ b/include/hw/acpi/bios-linker-loader.h
@@ -0,0 +1,39 @@
+#ifndef BIOS_LINKER_LOADER_H
+#define BIOS_LINKER_LOADER_H
+
+
+typedef struct BIOSLinker {
+ GArray *cmd_blob;
+ GArray *file_list;
+} BIOSLinker;
+
+bool bios_linker_loader_can_write_pointer(void);
+
+BIOSLinker *bios_linker_loader_init(void);
+
+void bios_linker_loader_alloc(BIOSLinker *linker,
+ const char *file_name,
+ GArray *file_blob,
+ uint32_t alloc_align,
+ bool alloc_fseg);
+
+void bios_linker_loader_add_checksum(BIOSLinker *linker, const char *file,
+ unsigned start_offset, unsigned size,
+ unsigned checksum_offset);
+
+void bios_linker_loader_add_pointer(BIOSLinker *linker,
+ const char *dest_file,
+ uint32_t dst_patched_offset,
+ uint8_t dst_patched_size,
+ const char *src_file,
+ uint32_t src_offset);
+
+void bios_linker_loader_write_pointer(BIOSLinker *linker,
+ const char *dest_file,
+ uint32_t dst_patched_offset,
+ uint8_t dst_patched_size,
+ const char *src_file,
+ uint32_t src_offset);
+
+void bios_linker_loader_cleanup(BIOSLinker *linker);
+#endif
diff --git a/include/hw/acpi/cpu.h b/include/hw/acpi/cpu.h
new file mode 100644
index 000000000..999caaf51
--- /dev/null
+++ b/include/hw/acpi/cpu.h
@@ -0,0 +1,70 @@
+/*
+ * QEMU ACPI hotplug utilities
+ *
+ * Copyright (C) 2016 Red Hat Inc
+ *
+ * Authors:
+ * Igor Mammedov <imammedo@redhat.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 ACPI_CPU_H
+#define ACPI_CPU_H
+
+#include "hw/qdev-core.h"
+#include "hw/acpi/acpi.h"
+#include "hw/acpi/aml-build.h"
+#include "hw/hotplug.h"
+
+typedef struct AcpiCpuStatus {
+ struct CPUState *cpu;
+ uint64_t arch_id;
+ bool is_inserting;
+ bool is_removing;
+ bool fw_remove;
+ uint32_t ost_event;
+ uint32_t ost_status;
+} AcpiCpuStatus;
+
+typedef struct CPUHotplugState {
+ MemoryRegion ctrl_reg;
+ uint32_t selector;
+ uint8_t command;
+ uint32_t dev_count;
+ AcpiCpuStatus *devs;
+} CPUHotplugState;
+
+void acpi_cpu_plug_cb(HotplugHandler *hotplug_dev,
+ CPUHotplugState *cpu_st, DeviceState *dev, Error **errp);
+
+void acpi_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
+ CPUHotplugState *cpu_st,
+ DeviceState *dev, Error **errp);
+
+void acpi_cpu_unplug_cb(CPUHotplugState *cpu_st,
+ DeviceState *dev, Error **errp);
+
+void cpu_hotplug_hw_init(MemoryRegion *as, Object *owner,
+ CPUHotplugState *state, hwaddr base_addr);
+
+typedef struct CPUHotplugFeatures {
+ bool acpi_1_compatible;
+ bool has_legacy_cphp;
+ bool fw_unplugs_cpu;
+ const char *smi_path;
+} CPUHotplugFeatures;
+
+void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
+ hwaddr io_base,
+ const char *res_root,
+ const char *event_handler_method);
+
+void acpi_cpu_ospm_status(CPUHotplugState *cpu_st, ACPIOSTInfoList ***list);
+
+extern const VMStateDescription vmstate_cpu_hotplug;
+#define VMSTATE_CPU_HOTPLUG(cpuhp, state) \
+ VMSTATE_STRUCT(cpuhp, state, 1, \
+ vmstate_cpu_hotplug, CPUHotplugState)
+
+#endif
diff --git a/include/hw/acpi/cpu_hotplug.h b/include/hw/acpi/cpu_hotplug.h
new file mode 100644
index 000000000..3b932abbb
--- /dev/null
+++ b/include/hw/acpi/cpu_hotplug.h
@@ -0,0 +1,40 @@
+/*
+ * QEMU ACPI hotplug utilities
+ *
+ * Copyright (C) 2013 Red Hat Inc
+ *
+ * Authors:
+ * Igor Mammedov <imammedo@redhat.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_ACPI_CPU_HOTPLUG_H
+#define HW_ACPI_CPU_HOTPLUG_H
+
+#include "hw/acpi/acpi.h"
+#include "hw/acpi/pc-hotplug.h"
+#include "hw/acpi/aml-build.h"
+#include "hw/hotplug.h"
+#include "hw/acpi/cpu.h"
+
+typedef struct AcpiCpuHotplug {
+ Object *device;
+ MemoryRegion io;
+ uint8_t sts[ACPI_GPE_PROC_LEN];
+} AcpiCpuHotplug;
+
+void legacy_acpi_cpu_plug_cb(HotplugHandler *hotplug_dev,
+ AcpiCpuHotplug *g, DeviceState *dev, Error **errp);
+
+void legacy_acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner,
+ AcpiCpuHotplug *gpe_cpu, uint16_t base);
+
+void acpi_switch_to_modern_cphp(AcpiCpuHotplug *gpe_cpu,
+ CPUHotplugState *cpuhp_state,
+ uint16_t io_port);
+
+void build_legacy_cpu_hotplug_aml(Aml *ctx, MachineState *machine,
+ uint16_t io_base);
+#endif
diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h
new file mode 100644
index 000000000..d49217c44
--- /dev/null
+++ b/include/hw/acpi/generic_event_device.h
@@ -0,0 +1,121 @@
+/*
+ *
+ * Copyright (c) 2018 Intel Corporation
+ * Copyright (c) 2019 Huawei Technologies R & D (UK) Ltd
+ * Written by Samuel Ortiz, Shameer Kolothum
+ *
+ * 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.
+ *
+ * The ACPI Generic Event Device (GED) is a hardware-reduced specific
+ * device[ACPI v6.1 Section 5.6.9] that handles all platform events,
+ * including the hotplug ones. Generic Event Device allows platforms
+ * to handle interrupts in ACPI ASL statements. It follows a very
+ * similar approach like the _EVT method from GPIO events. All
+ * interrupts are listed in _CRS and the handler is written in _EVT
+ * method. Here, we use a single interrupt for the GED device, relying
+ * on IO memory region to communicate the type of device affected by
+ * the interrupt. This way, we can support up to 32 events with a
+ * unique interrupt.
+ *
+ * Here is an example.
+ *
+ * Device (\_SB.GED)
+ * {
+ * Name (_HID, "ACPI0013")
+ * Name (_UID, Zero)
+ * Name (_CRS, ResourceTemplate ()
+ * {
+ * Interrupt (ResourceConsumer, Edge, ActiveHigh, Exclusive, ,, )
+ * {
+ * 0x00000029,
+ * }
+ * })
+ * OperationRegion (EREG, SystemMemory, 0x09080000, 0x04)
+ * Field (EREG, DWordAcc, NoLock, WriteAsZeros)
+ * {
+ * ESEL, 32
+ * }
+ *
+ * Method (_EVT, 1, Serialized) // _EVT: Event
+ * {
+ * Local0 = ESEL // ESEL = IO memory region which specifies the
+ * // device type.
+ * If (((Local0 & One) == One))
+ * {
+ * MethodEvent1()
+ * }
+ * If ((Local0 & 0x2) == 0x2)
+ * {
+ * MethodEvent2()
+ * }
+ * ...
+ * }
+ * }
+ *
+ */
+
+#ifndef HW_ACPI_GED_H
+#define HW_ACPI_GED_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"
+OBJECT_DECLARE_SIMPLE_TYPE(AcpiGedState, ACPI_GED)
+
+#define TYPE_ACPI_GED_X86 "acpi-ged-x86"
+
+#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"
+
+/*
+ * Platforms need to specify the GED event bitmap
+ * to describe what kind of events they want to support
+ * through GED.
+ */
+#define ACPI_GED_MEM_HOTPLUG_EVT 0x1
+#define ACPI_GED_PWR_DOWN_EVT 0x2
+#define ACPI_GED_NVDIMM_HOTPLUG_EVT 0x4
+
+typedef struct GEDState {
+ MemoryRegion evt;
+ MemoryRegion regs;
+ uint32_t sel;
+} GEDState;
+
+struct AcpiGedState {
+ SysBusDevice parent_obj;
+ MemHotplugState memhp_state;
+ MemoryRegion container_memhp;
+ GEDState ged_state;
+ uint32_t ged_event_bitmap;
+ qemu_irq irq;
+ AcpiGhesState ghes_state;
+};
+
+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
new file mode 100644
index 000000000..674f6958e
--- /dev/null
+++ b/include/hw/acpi/ghes.h
@@ -0,0 +1,84 @@
+/*
+ * Support for generating APEI tables and recording CPER for Guests
+ *
+ * Copyright (c) 2020 HUAWEI TECHNOLOGIES CO., LTD.
+ *
+ * Author: Dongjiu Geng <gengdongjiu@huawei.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 ACPI_GHES_H
+#define ACPI_GHES_H
+
+#include "hw/acpi/bios-linker-loader.h"
+
+/*
+ * Values for Hardware Error Notification Type field
+ */
+enum AcpiGhesNotifyType {
+ /* Polled */
+ ACPI_GHES_NOTIFY_POLLED = 0,
+ /* External Interrupt */
+ ACPI_GHES_NOTIFY_EXTERNAL = 1,
+ /* Local Interrupt */
+ ACPI_GHES_NOTIFY_LOCAL = 2,
+ /* SCI */
+ ACPI_GHES_NOTIFY_SCI = 3,
+ /* NMI */
+ ACPI_GHES_NOTIFY_NMI = 4,
+ /* CMCI, ACPI 5.0: 18.3.2.7, Table 18-290 */
+ ACPI_GHES_NOTIFY_CMCI = 5,
+ /* MCE, ACPI 5.0: 18.3.2.7, Table 18-290 */
+ ACPI_GHES_NOTIFY_MCE = 6,
+ /* GPIO-Signal, ACPI 6.0: 18.3.2.7, Table 18-332 */
+ ACPI_GHES_NOTIFY_GPIO = 7,
+ /* ARMv8 SEA, ACPI 6.1: 18.3.2.9, Table 18-345 */
+ ACPI_GHES_NOTIFY_SEA = 8,
+ /* ARMv8 SEI, ACPI 6.1: 18.3.2.9, Table 18-345 */
+ ACPI_GHES_NOTIFY_SEI = 9,
+ /* External Interrupt - GSIV, ACPI 6.1: 18.3.2.9, Table 18-345 */
+ ACPI_GHES_NOTIFY_GSIV = 10,
+ /* Software Delegated Exception, ACPI 6.2: 18.3.2.9, Table 18-383 */
+ ACPI_GHES_NOTIFY_SDEI = 11,
+ /* 12 and greater are reserved */
+ ACPI_GHES_NOTIFY_RESERVED = 12
+};
+
+enum {
+ ACPI_HEST_SRC_ID_SEA = 0,
+ /* future ids go here */
+ ACPI_HEST_SRC_ID_RESERVED,
+};
+
+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,
+ 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
new file mode 100644
index 000000000..7ca92843c
--- /dev/null
+++ b/include/hw/acpi/ich9.h
@@ -0,0 +1,94 @@
+/*
+ * QEMU GMCH/ICH9 LPC PM Emulation
+ *
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * 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 HW_ACPI_ICH9_H
+#define HW_ACPI_ICH9_H
+
+#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"
+
+#define ACPI_PCIHP_ADDR_ICH9 0x0cc0
+
+typedef struct ICH9LPCPMRegs {
+ /*
+ * In ich9 spec says that pm1_cnt register is 32bit width and
+ * that the upper 16bits are reserved and unused.
+ * PM1a_CNT_BLK = 2 in FADT so it is defined as uint16_t.
+ */
+ ACPIREGS acpi_regs;
+
+ MemoryRegion io;
+ MemoryRegion io_gpe;
+ MemoryRegion io_smi;
+
+ uint32_t smi_en;
+ uint32_t smi_en_wmask;
+ uint32_t smi_sts;
+
+ qemu_irq irq; /* SCI */
+
+ uint32_t pm_io_base;
+ Notifier powerdown_notifier;
+
+ bool cpu_hotplug_legacy;
+ 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_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_iospace_update(ICH9LPCPMRegs *pm, uint32_t pm_io_base);
+extern const VMStateDescription vmstate_ich9_pm;
+
+void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm);
+
+void ich9_pm_device_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+ Error **errp);
+void ich9_pm_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+ Error **errp);
+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);
+
+void ich9_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list);
+#endif /* HW_ACPI_ICH9_H */
diff --git a/include/hw/acpi/ipmi.h b/include/hw/acpi/ipmi.h
new file mode 100644
index 000000000..c14ad682a
--- /dev/null
+++ b/include/hw/acpi/ipmi.h
@@ -0,0 +1,21 @@
+/*
+ * QEMU IPMI ACPI handling
+ *
+ * Copyright (c) 2015,2016 Corey Minyard <cminyard@mvista.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_ACPI_IPMI_H
+#define HW_ACPI_IPMI_H
+
+#include "hw/acpi/aml-build.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);
+
+#endif /* HW_ACPI_IPMI_H */
diff --git a/include/hw/acpi/memory_hotplug.h b/include/hw/acpi/memory_hotplug.h
new file mode 100644
index 000000000..dfe9cf3fd
--- /dev/null
+++ b/include/hw/acpi/memory_hotplug.h
@@ -0,0 +1,57 @@
+#ifndef QEMU_HW_ACPI_MEMORY_HOTPLUG_H
+#define QEMU_HW_ACPI_MEMORY_HOTPLUG_H
+
+#include "hw/qdev-core.h"
+#include "hw/acpi/acpi.h"
+#include "hw/acpi/aml-build.h"
+
+#define MEMORY_SLOT_SCAN_METHOD "MSCN"
+#define MEMORY_DEVICES_CONTAINER "\\_SB.MHPC"
+#define MEMORY_HOTPLUG_IO_LEN 24
+
+/**
+ * MemStatus:
+ * @is_removing: the memory device in slot has been requested to be ejected.
+ *
+ * This structure stores memory device's status.
+ */
+typedef struct MemStatus {
+ DeviceState *dimm;
+ bool is_enabled;
+ bool is_inserting;
+ bool is_removing;
+ uint32_t ost_event;
+ uint32_t ost_status;
+} MemStatus;
+
+typedef struct MemHotplugState {
+ bool is_enabled; /* true if memory hotplug is supported */
+ MemoryRegion io;
+ uint32_t selector;
+ uint32_t dev_count;
+ MemStatus *devs;
+} MemHotplugState;
+
+void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner,
+ MemHotplugState *state, hwaddr io_base);
+
+void acpi_memory_plug_cb(HotplugHandler *hotplug_dev, MemHotplugState *mem_st,
+ DeviceState *dev, Error **errp);
+void acpi_memory_unplug_request_cb(HotplugHandler *hotplug_dev,
+ MemHotplugState *mem_st,
+ DeviceState *dev, Error **errp);
+void acpi_memory_unplug_cb(MemHotplugState *mem_st,
+ DeviceState *dev, Error **errp);
+
+extern const VMStateDescription vmstate_memory_hotplug;
+#define VMSTATE_MEMORY_HOTPLUG(memhp, state) \
+ VMSTATE_STRUCT(memhp, state, 1, \
+ vmstate_memory_hotplug, MemHotplugState)
+
+void acpi_memory_ospm_status(MemHotplugState *mem_st, ACPIOSTInfoList ***list);
+
+void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem,
+ const char *res_root,
+ const char *event_handler_method,
+ AmlRegionSpace rs, hwaddr memhp_io_base);
+#endif
diff --git a/include/hw/acpi/pc-hotplug.h b/include/hw/acpi/pc-hotplug.h
new file mode 100644
index 000000000..31bc9191c
--- /dev/null
+++ b/include/hw/acpi/pc-hotplug.h
@@ -0,0 +1,34 @@
+/*
+ * QEMU ACPI hotplug utilities shared defines
+ *
+ * Copyright (C) 2014 Red Hat Inc
+ *
+ * Authors:
+ * Igor Mammedov <imammedo@redhat.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 PC_HOTPLUG_H
+#define PC_HOTPLUG_H
+
+/*
+ * ONLY DEFINEs are permited in this file since it's shared
+ * between C and ASL code.
+ */
+
+/* Limit for CPU arch IDs for CPU hotplug. All hotpluggable CPUs should
+ * have CPUClass.get_arch_id() < ACPI_CPU_HOTPLUG_ID_LIMIT.
+ */
+#define ACPI_CPU_HOTPLUG_ID_LIMIT 256
+
+/* 256 CPU IDs, 8 bits per entry: */
+#define ACPI_GPE_PROC_LEN 32
+
+#define ICH9_CPU_HOTPLUG_IO_BASE 0x0CD8
+#define PIIX4_CPU_HOTPLUG_IO_BASE 0xaf00
+#define CPU_HOTPLUG_RESOURCE_DEVICE PRES
+
+#define ACPI_MEMORY_HOTPLUG_BASE 0x0a00
+
+#endif
diff --git a/include/hw/acpi/pci.h b/include/hw/acpi/pci.h
new file mode 100644
index 000000000..b5deee0a9
--- /dev/null
+++ b/include/hw/acpi/pci.h
@@ -0,0 +1,39 @@
+/*
+ * Support for generating PCI related ACPI tables and passing them to Guests
+ *
+ * Copyright (C) 2006 Fabrice Bellard
+ * Copyright (C) 2008-2010 Kevin O'Connor <kevin@koconnor.net>
+ * Copyright (C) 2013-2019 Red Hat Inc
+ * Copyright (C) 2019 Intel Corporation
+ *
+ * Author: Wei Yang <richardw.yang@linux.intel.com>
+ * Author: Michael S. Tsirkin <mst@redhat.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_ACPI_PCI_H
+#define HW_ACPI_PCI_H
+
+#include "hw/acpi/bios-linker-loader.h"
+
+typedef struct AcpiMcfgInfo {
+ uint64_t base;
+ uint32_t size;
+} AcpiMcfgInfo;
+
+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);
+#endif
diff --git a/include/hw/acpi/pcihp.h b/include/hw/acpi/pcihp.h
new file mode 100644
index 000000000..af1a169fc
--- /dev/null
+++ b/include/hw/acpi/pcihp.h
@@ -0,0 +1,89 @@
+/*
+ * QEMU<->ACPI BIOS PCI hotplug interface
+ *
+ * QEMU supports PCI hotplug via ACPI. This module
+ * implements the interface between QEMU and the ACPI BIOS.
+ * Interface specification - see docs/specs/acpi_pci_hotplug.txt
+ *
+ * Copyright (c) 2013, Red Hat Inc, Michael S. Tsirkin (mst@redhat.com)
+ * 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_PCIHP_H
+#define HW_ACPI_PCIHP_H
+
+#include "hw/acpi/acpi.h"
+#include "hw/hotplug.h"
+
+#define ACPI_PCIHP_IO_BASE_PROP "acpi-pcihp-io-base"
+#define ACPI_PCIHP_IO_LEN_PROP "acpi-pcihp-io-len"
+
+typedef struct AcpiPciHpPciStatus {
+ uint32_t up;
+ uint32_t down;
+ uint32_t hotplug_enable;
+} AcpiPciHpPciStatus;
+
+#define ACPI_PCIHP_PROP_BSEL "acpi-pcihp-bsel"
+#define ACPI_PCIHP_MAX_HOTPLUG_BUS 256
+#define ACPI_PCIHP_BSEL_DEFAULT 0x0
+
+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;
+} AcpiPciHpState;
+
+void acpi_pcihp_init(Object *owner, AcpiPciHpState *, PCIBus *root,
+ MemoryRegion *address_space_io, bool bridges_enabled,
+ uint16_t io_base);
+
+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,
+ DeviceState *dev, Error **errp);
+void acpi_pcihp_device_unplug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
+ DeviceState *dev, Error **errp);
+void acpi_pcihp_device_unplug_request_cb(HotplugHandler *hotplug_dev,
+ AcpiPciHpState *s, DeviceState *dev,
+ Error **errp);
+
+/* Called on reset */
+void acpi_pcihp_reset(AcpiPciHpState *s, bool acpihp_root_off);
+
+extern const VMStateDescription vmstate_acpi_pcihp_pci_status;
+
+bool vmstate_acpi_pcihp_use_acpi_index(void *opaque, int version_id);
+
+#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), \
+ VMSTATE_UINT32_TEST(pcihp.acpi_index, state, \
+ test_acpi_index)
+
+#endif
diff --git a/include/hw/acpi/tco.h b/include/hw/acpi/tco.h
new file mode 100644
index 000000000..a1e0da821
--- /dev/null
+++ b/include/hw/acpi/tco.h
@@ -0,0 +1,82 @@
+/*
+ * QEMU ICH9 TCO emulation
+ *
+ * Copyright (c) 2015 Paulo Alcantara <pcacjr@zytor.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_ACPI_TCO_H
+#define HW_ACPI_TCO_H
+
+#include "exec/memory.h"
+
+/* As per ICH9 spec, the internal timer has an error of ~0.6s on every tick */
+#define TCO_TICK_NSEC 600000000LL
+
+/* TCO I/O register offsets */
+enum {
+ TCO_RLD = 0x00,
+ TCO_DAT_IN = 0x02,
+ TCO_DAT_OUT = 0x03,
+ TCO1_STS = 0x04,
+ TCO2_STS = 0x06,
+ TCO1_CNT = 0x08,
+ TCO2_CNT = 0x0a,
+ TCO_MESSAGE1 = 0x0c,
+ TCO_MESSAGE2 = 0x0d,
+ TCO_WDCNT = 0x0e,
+ SW_IRQ_GEN = 0x10,
+ TCO_TMR = 0x12,
+};
+
+/* TCO I/O register control/status bits */
+enum {
+ SW_TCO_SMI = 1 << 1,
+ TCO_INT_STS = 1 << 2,
+ TCO_LOCK = 1 << 12,
+ TCO_TMR_HLT = 1 << 11,
+ TCO_TIMEOUT = 1 << 3,
+ TCO_SECOND_TO_STS = 1 << 1,
+ TCO_BOOT_STS = 1 << 2,
+};
+
+/* TCO I/O registers mask bits */
+enum {
+ TCO_RLD_MASK = 0x3ff,
+ TCO1_STS_MASK = 0xe870,
+ TCO2_STS_MASK = 0xfff8,
+ TCO1_CNT_MASK = 0xfeff,
+ TCO_TMR_MASK = 0x3ff,
+};
+
+typedef struct TCOIORegs {
+ struct {
+ uint16_t rld;
+ uint8_t din;
+ uint8_t dout;
+ uint16_t sts1;
+ uint16_t sts2;
+ uint16_t cnt1;
+ uint16_t cnt2;
+ uint8_t msg1;
+ uint8_t msg2;
+ uint8_t wdcnt;
+ uint16_t tmr;
+ } tco;
+ uint8_t sw_irq_gen;
+
+ QEMUTimer *tco_timer;
+ int64_t expire_time;
+ uint8_t timeouts_no;
+
+ MemoryRegion io;
+} TCOIORegs;
+
+/* tco.c */
+void acpi_pm_tco_init(TCOIORegs *tr, MemoryRegion *parent);
+
+extern const VMStateDescription vmstate_tco_io_sts;
+
+#endif /* HW_ACPI_TCO_H */
diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
new file mode 100644
index 000000000..559ba6906
--- /dev/null
+++ b/include/hw/acpi/tpm.h
@@ -0,0 +1,216 @@
+/*
+ * tpm.h - TPM ACPI definitions
+ *
+ * Copyright (C) 2014 IBM Corporation
+ *
+ * Authors:
+ * Stefan Berger <stefanb@us.ibm.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.
+ *
+ * Implementation of the TIS interface according to specs found at
+ * http://www.trustedcomputinggroup.org
+ *
+ */
+#ifndef HW_ACPI_TPM_H
+#define HW_ACPI_TPM_H
+
+#include "qemu/units.h"
+#include "hw/registerfields.h"
+#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
+
+#define TPM_TIS_IRQ 5
+
+#define TPM_TIS_NUM_LOCALITIES 5 /* per spec */
+#define TPM_TIS_LOCALITY_SHIFT 12
+
+/* tis registers */
+#define TPM_TIS_REG_ACCESS 0x00
+#define TPM_TIS_REG_INT_ENABLE 0x08
+#define TPM_TIS_REG_INT_VECTOR 0x0c
+#define TPM_TIS_REG_INT_STATUS 0x10
+#define TPM_TIS_REG_INTF_CAPABILITY 0x14
+#define TPM_TIS_REG_STS 0x18
+#define TPM_TIS_REG_DATA_FIFO 0x24
+#define TPM_TIS_REG_INTERFACE_ID 0x30
+#define TPM_TIS_REG_DATA_XFIFO 0x80
+#define TPM_TIS_REG_DATA_XFIFO_END 0xbc
+#define TPM_TIS_REG_DID_VID 0xf00
+#define TPM_TIS_REG_RID 0xf04
+
+/* vendor-specific registers */
+#define TPM_TIS_REG_DEBUG 0xf90
+
+#define TPM_TIS_STS_TPM_FAMILY_MASK (0x3 << 26)/* TPM 2.0 */
+#define TPM_TIS_STS_TPM_FAMILY1_2 (0 << 26) /* TPM 2.0 */
+#define TPM_TIS_STS_TPM_FAMILY2_0 (1 << 26) /* TPM 2.0 */
+#define TPM_TIS_STS_RESET_ESTABLISHMENT_BIT (1 << 25) /* TPM 2.0 */
+#define TPM_TIS_STS_COMMAND_CANCEL (1 << 24) /* TPM 2.0 */
+
+#define TPM_TIS_STS_VALID (1 << 7)
+#define TPM_TIS_STS_COMMAND_READY (1 << 6)
+#define TPM_TIS_STS_TPM_GO (1 << 5)
+#define TPM_TIS_STS_DATA_AVAILABLE (1 << 4)
+#define TPM_TIS_STS_EXPECT (1 << 3)
+#define TPM_TIS_STS_SELFTEST_DONE (1 << 2)
+#define TPM_TIS_STS_RESPONSE_RETRY (1 << 1)
+
+#define TPM_TIS_BURST_COUNT_SHIFT 8
+#define TPM_TIS_BURST_COUNT(X) \
+ ((X) << TPM_TIS_BURST_COUNT_SHIFT)
+
+#define TPM_TIS_ACCESS_TPM_REG_VALID_STS (1 << 7)
+#define TPM_TIS_ACCESS_ACTIVE_LOCALITY (1 << 5)
+#define TPM_TIS_ACCESS_BEEN_SEIZED (1 << 4)
+#define TPM_TIS_ACCESS_SEIZE (1 << 3)
+#define TPM_TIS_ACCESS_PENDING_REQUEST (1 << 2)
+#define TPM_TIS_ACCESS_REQUEST_USE (1 << 1)
+#define TPM_TIS_ACCESS_TPM_ESTABLISHMENT (1 << 0)
+
+#define TPM_TIS_INT_ENABLED (1 << 31)
+#define TPM_TIS_INT_DATA_AVAILABLE (1 << 0)
+#define TPM_TIS_INT_STS_VALID (1 << 1)
+#define TPM_TIS_INT_LOCALITY_CHANGED (1 << 2)
+#define TPM_TIS_INT_COMMAND_READY (1 << 7)
+
+#define TPM_TIS_INT_POLARITY_MASK (3 << 3)
+#define TPM_TIS_INT_POLARITY_LOW_LEVEL (1 << 3)
+
+#define TPM_TIS_INTERRUPTS_SUPPORTED (TPM_TIS_INT_LOCALITY_CHANGED | \
+ TPM_TIS_INT_DATA_AVAILABLE | \
+ TPM_TIS_INT_STS_VALID | \
+ TPM_TIS_INT_COMMAND_READY)
+
+#define TPM_TIS_CAP_INTERFACE_VERSION1_3 (2 << 28)
+#define TPM_TIS_CAP_INTERFACE_VERSION1_3_FOR_TPM2_0 (3 << 28)
+#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_INTERRUPT_LOW_LEVEL (1 << 4) /* support is mandatory */
+#define TPM_TIS_CAPABILITIES_SUPPORTED1_3 \
+ (TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \
+ TPM_TIS_CAP_BURST_COUNT_DYNAMIC | \
+ TPM_TIS_CAP_DATA_TRANSFER_64B | \
+ TPM_TIS_CAP_INTERFACE_VERSION1_3 | \
+ TPM_TIS_INTERRUPTS_SUPPORTED)
+
+#define TPM_TIS_CAPABILITIES_SUPPORTED2_0 \
+ (TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \
+ TPM_TIS_CAP_BURST_COUNT_DYNAMIC | \
+ TPM_TIS_CAP_DATA_TRANSFER_64B | \
+ TPM_TIS_CAP_INTERFACE_VERSION1_3_FOR_TPM2_0 | \
+ TPM_TIS_INTERRUPTS_SUPPORTED)
+
+#define TPM_TIS_IFACE_ID_INTERFACE_TIS1_3 (0xf) /* TPM 2.0 */
+#define TPM_TIS_IFACE_ID_INTERFACE_FIFO (0x0) /* TPM 2.0 */
+#define TPM_TIS_IFACE_ID_INTERFACE_VER_FIFO (0 << 4) /* TPM 2.0 */
+#define TPM_TIS_IFACE_ID_CAP_5_LOCALITIES (1 << 8) /* TPM 2.0 */
+#define TPM_TIS_IFACE_ID_CAP_TIS_SUPPORTED (1 << 13) /* TPM 2.0 */
+#define TPM_TIS_IFACE_ID_INT_SEL_LOCK (1 << 19) /* TPM 2.0 */
+
+#define TPM_TIS_IFACE_ID_SUPPORTED_FLAGS1_3 \
+ (TPM_TIS_IFACE_ID_INTERFACE_TIS1_3 | \
+ (~0u << 4)/* all of it is don't care */)
+
+/* if backend was a TPM 2.0: */
+#define TPM_TIS_IFACE_ID_SUPPORTED_FLAGS2_0 \
+ (TPM_TIS_IFACE_ID_INTERFACE_FIFO | \
+ TPM_TIS_IFACE_ID_INTERFACE_VER_FIFO | \
+ TPM_TIS_IFACE_ID_CAP_5_LOCALITIES | \
+ TPM_TIS_IFACE_ID_CAP_TIS_SUPPORTED)
+
+#define TPM_TIS_TPM_DID 0x0001
+#define TPM_TIS_TPM_VID PCI_VENDOR_ID_IBM
+#define TPM_TIS_TPM_RID 0x0001
+
+#define TPM_TIS_NO_DATA_BYTE 0xff
+
+
+REG32(CRB_LOC_STATE, 0x00)
+ FIELD(CRB_LOC_STATE, tpmEstablished, 0, 1)
+ FIELD(CRB_LOC_STATE, locAssigned, 1, 1)
+ FIELD(CRB_LOC_STATE, activeLocality, 2, 3)
+ FIELD(CRB_LOC_STATE, reserved, 5, 2)
+ FIELD(CRB_LOC_STATE, tpmRegValidSts, 7, 1)
+REG32(CRB_LOC_CTRL, 0x08)
+REG32(CRB_LOC_STS, 0x0C)
+ FIELD(CRB_LOC_STS, Granted, 0, 1)
+ FIELD(CRB_LOC_STS, beenSeized, 1, 1)
+REG32(CRB_INTF_ID, 0x30)
+ FIELD(CRB_INTF_ID, InterfaceType, 0, 4)
+ FIELD(CRB_INTF_ID, InterfaceVersion, 4, 4)
+ FIELD(CRB_INTF_ID, CapLocality, 8, 1)
+ FIELD(CRB_INTF_ID, CapCRBIdleBypass, 9, 1)
+ FIELD(CRB_INTF_ID, Reserved1, 10, 1)
+ FIELD(CRB_INTF_ID, CapDataXferSizeSupport, 11, 2)
+ FIELD(CRB_INTF_ID, CapFIFO, 13, 1)
+ FIELD(CRB_INTF_ID, CapCRB, 14, 1)
+ FIELD(CRB_INTF_ID, CapIFRes, 15, 2)
+ FIELD(CRB_INTF_ID, InterfaceSelector, 17, 2)
+ FIELD(CRB_INTF_ID, IntfSelLock, 19, 1)
+ FIELD(CRB_INTF_ID, Reserved2, 20, 4)
+ FIELD(CRB_INTF_ID, RID, 24, 8)
+REG32(CRB_INTF_ID2, 0x34)
+ FIELD(CRB_INTF_ID2, VID, 0, 16)
+ FIELD(CRB_INTF_ID2, DID, 16, 16)
+REG32(CRB_CTRL_EXT, 0x38)
+REG32(CRB_CTRL_REQ, 0x40)
+REG32(CRB_CTRL_STS, 0x44)
+ FIELD(CRB_CTRL_STS, tpmSts, 0, 1)
+ FIELD(CRB_CTRL_STS, tpmIdle, 1, 1)
+REG32(CRB_CTRL_CANCEL, 0x48)
+REG32(CRB_CTRL_START, 0x4C)
+REG32(CRB_INT_ENABLED, 0x50)
+REG32(CRB_INT_STS, 0x54)
+REG32(CRB_CTRL_CMD_SIZE, 0x58)
+REG32(CRB_CTRL_CMD_LADDR, 0x5C)
+REG32(CRB_CTRL_CMD_HADDR, 0x60)
+REG32(CRB_CTRL_RSP_SIZE, 0x64)
+REG32(CRB_CTRL_RSP_ADDR, 0x68)
+REG32(CRB_DATA_BUFFER, 0x80)
+
+#define TPM_CRB_ADDR_BASE 0xFED40000
+#define TPM_CRB_ADDR_SIZE 0x1000
+#define TPM_CRB_ADDR_CTRL (TPM_CRB_ADDR_BASE + A_CRB_CTRL_REQ)
+#define TPM_CRB_R_MAX R_CRB_DATA_BUFFER
+
+#define TPM_LOG_AREA_MINIMUM_SIZE (64 * KiB)
+
+#define TPM_TCPA_ACPI_CLASS_CLIENT 0
+#define TPM_TCPA_ACPI_CLASS_SERVER 1
+
+#define TPM2_ACPI_CLASS_CLIENT 0
+#define TPM2_ACPI_CLASS_SERVER 1
+
+#define TPM2_START_METHOD_MMIO 6
+#define TPM2_START_METHOD_CRB 7
+
+/*
+ * Physical Presence Interface
+ */
+#define TPM_PPI_ADDR_SIZE 0x400
+#define TPM_PPI_ADDR_BASE 0xFED45000
+
+#define TPM_PPI_VERSION_NONE 0
+#define TPM_PPI_VERSION_1_30 1
+
+/* whether function is blocked by BIOS settings; bits 0, 1, 2 */
+#define TPM_PPI_FUNC_NOT_IMPLEMENTED (0 << 0)
+#define TPM_PPI_FUNC_BIOS_ONLY (1 << 0)
+#define TPM_PPI_FUNC_BLOCKED (2 << 0)
+#define TPM_PPI_FUNC_ALLOWED_USR_REQ (3 << 0)
+#define TPM_PPI_FUNC_ALLOWED_USR_NOT_REQ (4 << 0)
+#define TPM_PPI_FUNC_MASK (7 << 0)
+
+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
new file mode 100644
index 000000000..0022df027
--- /dev/null
+++ b/include/hw/acpi/utils.h
@@ -0,0 +1,8 @@
+#ifndef HW_ACPI_UTILS_H
+#define HW_ACPI_UTILS_H
+
+#include "hw/nvram/fw_cfg.h"
+
+MemoryRegion *acpi_add_rom_blob(FWCfgCallback update, void *opaque,
+ GArray *blob, const char *name);
+#endif
diff --git a/include/hw/acpi/vmgenid.h b/include/hw/acpi/vmgenid.h
new file mode 100644
index 000000000..dc8bb3433
--- /dev/null
+++ b/include/hw/acpi/vmgenid.h
@@ -0,0 +1,37 @@
+#ifndef ACPI_VMGENID_H
+#define ACPI_VMGENID_H
+
+#include "hw/acpi/bios-linker-loader.h"
+#include "hw/qdev-core.h"
+#include "qemu/uuid.h"
+#include "qom/object.h"
+
+#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
+ */
+
+OBJECT_DECLARE_SIMPLE_TYPE(VmGenIdState, VMGENID)
+
+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) */
+};
+
+/* returns NULL unless there is exactly one device */
+static inline Object *find_vmgenid_dev(void)
+{
+ return object_resolve_path_type("", TYPE_VMGENID, NULL);
+}
+
+void vmgenid_build_acpi(VmGenIdState *vms, GArray *table_data, GArray *guid,
+ 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 000000000..2f166e8be
--- /dev/null
+++ b/include/hw/adc/aspeed_adc.h
@@ -0,0 +1,55 @@
+/*
+ * 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"
+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/adc/max111x.h b/include/hw/adc/max111x.h
new file mode 100644
index 000000000..beff59c81
--- /dev/null
+++ b/include/hw/adc/max111x.h
@@ -0,0 +1,56 @@
+/*
+ * Maxim MAX1110/1111 ADC chip emulation.
+ *
+ * Copyright (c) 2006 Openedhand Ltd.
+ * Written by Andrzej Zaborowski <balrog@zabor.org>
+ *
+ * This code is licensed under the GNU GPLv2.
+ *
+ * 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_MISC_MAX111X_H
+#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
+ * is an SSI slave device. It has either 4 (max1110) or 8 (max1111)
+ * 8-bit ADC channels.
+ *
+ * QEMU interface:
+ * + GPIO inputs 0..3 (for max1110) or 0..7 (for max1111): set the value
+ * of each ADC input, as an unsigned 8-bit value
+ * + GPIO output 0: interrupt line
+ * + Properties "input0" to "input3" (max1110) or "input0" to "input7"
+ * (max1111): initial reset values for ADC inputs.
+ *
+ * Known bugs:
+ * + the interrupt line is not correctly implemented, and will never
+ * be lowered once it has been asserted.
+ */
+struct MAX111xState {
+ SSIPeripheral parent_obj;
+
+ qemu_irq interrupt;
+ /* Values of inputs at system reset (settable by QOM property) */
+ uint8_t reset_input[8];
+
+ uint8_t tb1, rb2, rb3;
+ int cycle;
+
+ uint8_t input[8];
+ int inputs, com;
+};
+
+#define TYPE_MAX_111X "max111x"
+
+OBJECT_DECLARE_SIMPLE_TYPE(MAX111xState, MAX_111X)
+
+#define TYPE_MAX_1110 "max1110"
+#define TYPE_MAX_1111 "max1111"
+
+#endif
diff --git a/include/hw/adc/npcm7xx_adc.h b/include/hw/adc/npcm7xx_adc.h
new file mode 100644
index 000000000..7d8442107
--- /dev/null
+++ b/include/hw/adc/npcm7xx_adc.h
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+typedef struct {
+ 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];
+} NPCM7xxADCState;
+
+#define TYPE_NPCM7XX_ADC "npcm7xx-adc"
+#define NPCM7XX_ADC(obj) \
+ OBJECT_CHECK(NPCM7xxADCState, (obj), TYPE_NPCM7XX_ADC)
+
+#endif /* NPCM7XX_ADC_H */
diff --git a/include/hw/adc/stm32f2xx_adc.h b/include/hw/adc/stm32f2xx_adc.h
new file mode 100644
index 000000000..42b48981f
--- /dev/null
+++ b/include/hw/adc/stm32f2xx_adc.h
@@ -0,0 +1,89 @@
+/*
+ * STM32F2XX ADC
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * 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_STM32F2XX_ADC_H
+#define HW_STM32F2XX_ADC_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define ADC_SR 0x00
+#define ADC_CR1 0x04
+#define ADC_CR2 0x08
+#define ADC_SMPR1 0x0C
+#define ADC_SMPR2 0x10
+#define ADC_JOFR1 0x14
+#define ADC_JOFR2 0x18
+#define ADC_JOFR3 0x1C
+#define ADC_JOFR4 0x20
+#define ADC_HTR 0x24
+#define ADC_LTR 0x28
+#define ADC_SQR1 0x2C
+#define ADC_SQR2 0x30
+#define ADC_SQR3 0x34
+#define ADC_JSQR 0x38
+#define ADC_JDR1 0x3C
+#define ADC_JDR2 0x40
+#define ADC_JDR3 0x44
+#define ADC_JDR4 0x48
+#define ADC_DR 0x4C
+
+#define ADC_CR2_ADON 0x01
+#define ADC_CR2_CONT 0x02
+#define ADC_CR2_ALIGN 0x800
+#define ADC_CR2_SWSTART 0x40000000
+
+#define ADC_CR1_RES 0x3000000
+
+#define ADC_COMMON_ADDRESS 0x100
+
+#define TYPE_STM32F2XX_ADC "stm32f2xx-adc"
+OBJECT_DECLARE_SIMPLE_TYPE(STM32F2XXADCState, STM32F2XX_ADC)
+
+struct STM32F2XXADCState {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /* <public> */
+ MemoryRegion mmio;
+
+ uint32_t adc_sr;
+ uint32_t adc_cr1;
+ uint32_t adc_cr2;
+ uint32_t adc_smpr1;
+ uint32_t adc_smpr2;
+ uint32_t adc_jofr[4];
+ uint32_t adc_htr;
+ uint32_t adc_ltr;
+ uint32_t adc_sqr1;
+ uint32_t adc_sqr2;
+ uint32_t adc_sqr3;
+ uint32_t adc_jsqr;
+ uint32_t adc_jdr[4];
+ uint32_t adc_dr;
+
+ qemu_irq irq;
+};
+
+#endif /* HW_STM32F2XX_ADC_H */
diff --git a/include/hw/adc/zynq-xadc.h b/include/hw/adc/zynq-xadc.h
new file mode 100644
index 000000000..2017b7a80
--- /dev/null
+++ b/include/hw/adc/zynq-xadc.h
@@ -0,0 +1,46 @@
+/*
+ * Device model for Zynq ADC controller
+ *
+ * Copyright (c) 2015 Guenter Roeck <linux@roeck-us.net>
+ *
+ * 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 ZYNQ_XADC_H
+#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"
+OBJECT_DECLARE_SIMPLE_TYPE(ZynqXADCState, ZYNQ_XADC)
+
+struct ZynqXADCState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+
+ uint32_t regs[ZYNQ_XADC_NUM_IO_REGS];
+ uint16_t xadc_regs[ZYNQ_XADC_NUM_ADC_REGS];
+ uint16_t xadc_read_reg_previous;
+ uint16_t xadc_dfifo[ZYNQ_XADC_FIFO_DEPTH];
+ uint16_t xadc_dfifo_entries;
+
+ struct IRQState *qemu_irq;
+
+};
+
+#endif /* ZYNQ_XADC_H */
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
new file mode 100644
index 000000000..a76dc7b84
--- /dev/null
+++ b/include/hw/arm/allwinner-a10.h
@@ -0,0 +1,44 @@
+#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/usb/hcd-ohci.h"
+#include "hw/usb/hcd-ehci.h"
+#include "hw/rtc/allwinner-rtc.h"
+
+#include "target/arm/cpu.h"
+#include "qom/object.h"
+
+
+#define AW_A10_SDRAM_BASE 0x40000000
+
+#define AW_A10_NUM_USB 2
+
+#define TYPE_AW_A10 "allwinner-a10"
+OBJECT_DECLARE_SIMPLE_TYPE(AwA10State, AW_A10)
+
+struct AwA10State {
+ /*< private >*/
+ DeviceState parent_obj;
+ /*< public >*/
+
+ ARMCPU cpu;
+ AwA10PITState timer;
+ AwA10PICState intc;
+ AwEmacState emac;
+ AllwinnerAHCIState sata;
+ AwSdHostState mmc0;
+ AwRtcState rtc;
+ MemoryRegion sram_a;
+ EHCISysBusState ehci[AW_A10_NUM_USB];
+ OHCISysBusState ohci[AW_A10_NUM_USB];
+};
+
+#endif
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
new file mode 100644
index 000000000..63025fb27
--- /dev/null
+++ b/include/hw/arm/allwinner-h3.h
@@ -0,0 +1,161 @@
+/*
+ * Allwinner H3 System on Chip emulation
+ *
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.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/>.
+ */
+
+/*
+ * 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.
+ *
+ * This implementation is based on the following datasheet:
+ *
+ * https://linux-sunxi.org/File:Allwinner_H3_Datasheet_V1.2.pdf
+ *
+ * The latest datasheet and more info can be found on the Linux Sunxi wiki:
+ *
+ * https://linux-sunxi.org/H3
+ */
+
+#ifndef HW_ARM_ALLWINNER_H3_H
+#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"
+#include "hw/misc/allwinner-cpucfg.h"
+#include "hw/misc/allwinner-h3-dramc.h"
+#include "hw/misc/allwinner-h3-sysctrl.h"
+#include "hw/misc/allwinner-sid.h"
+#include "hw/sd/allwinner-sdhost.h"
+#include "hw/net/allwinner-sun8i-emac.h"
+#include "hw/rtc/allwinner-rtc.h"
+#include "target/arm/cpu.h"
+#include "sysemu/block-backend.h"
+
+/**
+ * Allwinner H3 device list
+ *
+ * This enumeration is can be used refer to a particular device in the
+ * Allwinner H3 SoC. For example, the physical memory base address for
+ * each device can be found in the AwH3State object in the memmap member
+ * using the device enum value as index.
+ *
+ * @see AwH3State
+ */
+enum {
+ 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_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_SDRAM
+};
+
+/** Total number of CPU cores in the H3 SoC */
+#define AW_H3_NUM_CPUS (4)
+
+/**
+ * Allwinner H3 object model
+ * @{
+ */
+
+/** Object type for the Allwinner H3 SoC */
+#define TYPE_AW_H3 "allwinner-h3"
+
+/** Convert input object to Allwinner H3 state object */
+OBJECT_DECLARE_SIMPLE_TYPE(AwH3State, AW_H3)
+
+/** @} */
+
+/**
+ * Allwinner H3 object
+ *
+ * This struct contains the state of all the devices
+ * which are currently emulated by the H3 SoC code.
+ */
+struct AwH3State {
+ /*< private >*/
+ DeviceState parent_obj;
+ /*< public >*/
+
+ ARMCPU cpus[AW_H3_NUM_CPUS];
+ const hwaddr *memmap;
+ AwA10PITState timer;
+ AwH3ClockCtlState ccu;
+ AwCpuCfgState cpucfg;
+ AwH3DramCtlState dramc;
+ AwH3SysCtrlState sysctrl;
+ AwSidState sid;
+ AwSdHostState mmc0;
+ AwSun8iEmacState emac;
+ AwRtcState rtc;
+ GICState gic;
+ MemoryRegion sram_a1;
+ MemoryRegion sram_a2;
+ MemoryRegion sram_c;
+};
+
+/**
+ * Emulate Boot ROM firmware setup functionality.
+ *
+ * A real Allwinner H3 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 H3 state object pointer
+ * @blk: Block backend device object pointer
+ */
+void allwinner_h3_bootrom_setup(AwH3State *s, BlockBackend *blk);
+
+#endif /* HW_ARM_ALLWINNER_H3_H */
diff --git a/include/hw/arm/armsse-version.h b/include/hw/arm/armsse-version.h
new file mode 100644
index 000000000..60780fa98
--- /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
new file mode 100644
index 000000000..9648e7a41
--- /dev/null
+++ b/include/hw/arm/armsse.h
@@ -0,0 +1,236 @@
+/*
+ * ARM SSE (Subsystems for Embedded): IoTKit, SSE-200
+ *
+ * Copyright (c) 2018 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 Arm "Subsystems for Embedded" family of
+ * 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
+ * https://developer.arm.com/documentation/ecm0601256/latest
+ * - the SSE-200 which is documented in
+ * https://developer.arm.com/documentation/101104/latest/
+ *
+ * The IoTKit contains:
+ * a Cortex-M33
+ * the IDAU
+ * some timers and watchdogs
+ * two peripheral protection controllers
+ * a memory protection controller
+ * a security controller
+ * a bus fabric which arranges that some parts of the address
+ * space are secure and non-secure aliases of each other
+ * The SSE-200 additionally contains:
+ * a second Cortex-M33
+ * two Message Handling Units (MHUs)
+ * an optional CryptoCell (which we do not model)
+ * more SRAM banks with associated MPCs
+ * multiple Power Policy Units (PPUs)
+ * a control interface for an icache for each CPU
+ * 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 "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
+ * being the same for both, to avoid having to have separate Property
+ * lists for different variants. This restriction can be relaxed later
+ * if necessary.)
+ * + QOM property "SRAM_ADDR_WIDTH" sets the number of bits used for the
+ * address of each SRAM bank (and thus the total amount of internal SRAM)
+ * + QOM property "init-svtor" sets the initial value of the CPU SVTOR register
+ * (where it expects to load the PC and SP from the vector table on reset)
+ * + QOM properties "CPU0_FPU", "CPU0_DSP", "CPU1_FPU" and "CPU1_DSP" which
+ * set whether the CPUs have the FPU and DSP features present. The default
+ * (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.
+ * + 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
+ * CPU 1, which are wired to its NVIC lines 32 .. n+32
+ * + sysbus MMIO region 0 is the "AHB Slave Expansion" which allows
+ * bus master devices in the board model to make transactions into
+ * all the devices and memory areas in the IoTKit
+ * Controlling up to 4 AHB expansion PPBs which a system using the IoTKit
+ * might provide:
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_nonsec[0..15]
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_ap[0..15]
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_enable
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_clear
+ * + named GPIO inputs apb_ppcexp{0,1,2,3}_irq_status
+ * Controlling each of the 4 expansion AHB PPCs which a system using the IoTKit
+ * might provide:
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_nonsec[0..15]
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_ap[0..15]
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_enable
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_clear
+ * + named GPIO inputs ahb_ppcexp{0,1,2,3}_irq_status
+ * Controlling each of the 16 expansion MPCs which a system using the IoTKit
+ * might provide:
+ * + named GPIO inputs mpcexp_status[0..15]
+ * Controlling each of the 16 expansion MSCs which a system using the IoTKit
+ * might provide:
+ * + named GPIO inputs mscexp_status[0..15]
+ * + named GPIO outputs mscexp_clear[0..15]
+ * + named GPIO outputs mscexp_ns[0..15]
+ */
+
+#ifndef ARMSSE_H
+#define ARMSSE_H
+
+#include "hw/sysbus.h"
+#include "hw/arm/armv7m.h"
+#include "hw/misc/iotkit-secctl.h"
+#include "hw/misc/tz-ppc.h"
+#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_ARM_SSE "arm-sse"
+OBJECT_DECLARE_TYPE(ARMSSE, ARMSSEClass,
+ ARM_SSE)
+
+/*
+ * These type names are for specific IoTKit subsystems; other than
+ * instantiating them, code using these devices should always handle
+ * them via the ARMSSE base class, so they have no IOTKIT() etc macros.
+ */
+#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 + NUM_INTERNAL_PPCS)
+
+#define MAX_SRAM_BANKS 4
+#if MAX_SRAM_BANKS > IOTS_NUM_MPC
+#error Too many SRAM banks
+#endif
+
+#define SSE_MAX_CPUS 2
+
+#define NUM_PPUS 8
+
+/* Number of CPU IRQs used by the SSE itself */
+#define NUM_SSE_IRQS 32
+
+struct ARMSSE {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ ARMv7MState armv7m[SSE_MAX_CPUS];
+ CPUClusterState cluster[SSE_MAX_CPUS];
+ IoTKitSecCtl secctl;
+ TZPPC apb_ppc[NUM_INTERNAL_PPCS];
+ TZMPC mpc[IOTS_NUM_MPC];
+ CMSDKAPBTimer timer[3];
+ qemu_or_irq 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;
+
+ SplitIRQ cpu_irq_splitter[NUM_SSE_IRQS];
+
+ CMSDKAPBDualTimer dualtimer;
+
+ CMSDKAPBWatchdog cmsdk_watchdog[3];
+
+ SSECounter sse_counter;
+ SSETimer sse_timer[4];
+
+ IoTKitSysCtl sysctl;
+ IoTKitSysCtl sysinfo;
+
+ ARMSSEMHU mhu[2];
+ 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
+ * per-CPU devices of that CPU, plus as the background 'container'
+ * (or an alias of it, since we can only use it directly once).
+ * container_alias[i] is the alias of 'container' used by CPU i+1;
+ * CPU 0 can use 'container' directly.
+ */
+ MemoryRegion container;
+ MemoryRegion container_alias[SSE_MAX_CPUS - 1];
+ MemoryRegion cpu_container[SSE_MAX_CPUS];
+ MemoryRegion alias1;
+ 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;
+ qemu_irq ppc1_irq;
+ qemu_irq sec_resp_cfg;
+ qemu_irq sec_resp_cfg_in;
+ qemu_irq nsc_cfg_in;
+
+ qemu_irq irq_status_in[NUM_EXTERNAL_PPCS];
+ qemu_irq mpcexp_status_in[IOTS_NUM_EXP_MPC];
+
+ uint32_t nsccfg;
+
+ Clock *mainclk;
+ Clock *s32kclk;
+
+ /* Properties */
+ MemoryRegion *board_memory;
+ uint32_t exp_numirq;
+ uint32_t sram_addr_width;
+ uint32_t init_svtor;
+ bool cpu_fpu[SSE_MAX_CPUS];
+ bool cpu_dsp[SSE_MAX_CPUS];
+};
+
+typedef struct ARMSSEInfo ARMSSEInfo;
+
+struct ARMSSEClass {
+ SysBusDeviceClass parent_class;
+ const ARMSSEInfo *info;
+};
+
+
+#endif
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
new file mode 100644
index 000000000..b7ba0ff40
--- /dev/null
+++ b/include/hw/arm/armv7m.h
@@ -0,0 +1,104 @@
+/*
+ * ARMv7M CPU object
+ *
+ * Copyright (c) 2017 Linaro Ltd
+ * Written by Peter Maydell <peter.maydell@linaro.org>
+ *
+ * This code is licensed under the GPL version 2 or later.
+ */
+
+#ifndef HW_ARM_ARMV7M_H
+#define HW_ARM_ARMV7M_H
+
+#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"
+OBJECT_DECLARE_SIMPLE_TYPE(BitBandState, BITBAND)
+
+struct BitBandState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ AddressSpace source_as;
+ MemoryRegion iomem;
+ uint32_t base;
+ MemoryRegion *source_memory;
+};
+
+#define TYPE_ARMV7M "armv7m"
+OBJECT_DECLARE_SIMPLE_TYPE(ARMv7MState, ARMV7M)
+
+#define ARMV7M_NUM_BITBANDS 2
+
+/* ARMv7M container object.
+ * + Unnamed GPIO input lines: external IRQ lines for the NVIC
+ * + Named GPIO output SYSRESETREQ: signalled for guest AIRCR.SYSRESETREQ.
+ * If this GPIO is not wired up then the NVIC will default to performing
+ * 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 "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
+ * + Clock input "refclk" is the external reference clock for the systick timers
+ * + Clock input "cpuclk" is the main CPU clock
+ */
+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;
+ /* MemoryRegion the board provides to us (with its devices, RAM, etc) */
+ MemoryRegion *board_memory;
+ Object *idau;
+ uint32_t init_svtor;
+ uint32_t init_nsvtor;
+ bool enable_bitband;
+ bool start_powered_off;
+ bool vfp;
+ bool dsp;
+};
+
+#endif
diff --git a/include/hw/arm/aspeed.h b/include/hw/arm/aspeed.h
new file mode 100644
index 000000000..cbeacb214
--- /dev/null
+++ b/include/hw/arm/aspeed.h
@@ -0,0 +1,45 @@
+/*
+ * Aspeed Machines
+ *
+ * Copyright 2018 IBM Corp.
+ *
+ * This code is licensed under the GPL version 2 or later. See
+ * the COPYING file in the top-level directory.
+ */
+#ifndef ARM_ASPEED_H
+#define ARM_ASPEED_H
+
+#include "hw/boards.h"
+#include "qom/object.h"
+
+typedef struct AspeedMachineState AspeedMachineState;
+
+#define TYPE_ASPEED_MACHINE MACHINE_TYPE_NAME("aspeed")
+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)
+
+
+struct AspeedMachineClass {
+ MachineClass parent_obj;
+
+ const char *name;
+ const char *desc;
+ const char *soc_name;
+ uint32_t hw_strap1;
+ uint32_t hw_strap2;
+ const char *fmc_model;
+ const char *spi_model;
+ uint32_t num_cs;
+ uint32_t macs_mask;
+ void (*i2c_init)(AspeedMachineState *bmc);
+ uint32_t uart_default;
+};
+
+
+#endif
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
new file mode 100644
index 000000000..813935854
--- /dev/null
+++ b/include/hw/arm/aspeed_soc.h
@@ -0,0 +1,144 @@
+/*
+ * ASPEED SoC family
+ *
+ * Andrew Jeffery <andrew@aj.id.au>
+ *
+ * Copyright 2016 IBM Corp.
+ *
+ * This code is licensed under the GPL version 2 or later. See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef ASPEED_SOC_H
+#define ASPEED_SOC_H
+
+#include "hw/cpu/a15mpcore.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/ssi/aspeed_smc.h"
+#include "hw/misc/aspeed_hace.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"
+
+#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
+
+struct AspeedSoCState {
+ /*< private >*/
+ DeviceState parent;
+
+ /*< public >*/
+ ARMCPU cpu[ASPEED_CPUS_NUM];
+ A15MPPrivState a7mpcore;
+ MemoryRegion *dram_mr;
+ MemoryRegion sram;
+ AspeedVICState vic;
+ AspeedRtcState rtc;
+ AspeedTimerCtrlState timerctrl;
+ AspeedI2CState i2c;
+ AspeedSCUState scu;
+ AspeedHACEState hace;
+ AspeedXDMAState xdma;
+ AspeedADCState adc;
+ AspeedSMCState fmc;
+ AspeedSMCState spi[ASPEED_SPIS_NUM];
+ EHCISysBusState ehci[ASPEED_EHCIS_NUM];
+ AspeedSDMCState sdmc;
+ AspeedWDTState wdt[ASPEED_WDTS_NUM];
+ FTGMAC100State ftgmac100[ASPEED_MACS_NUM];
+ AspeedMiiState mii[ASPEED_MACS_NUM];
+ AspeedGPIOState gpio;
+ AspeedGPIOState gpio_1_8v;
+ AspeedSDHCIState sdhci;
+ AspeedSDHCIState emmc;
+ AspeedLPCState lpc;
+ uint32_t uart_default;
+};
+
+#define TYPE_ASPEED_SOC "aspeed-soc"
+OBJECT_DECLARE_TYPE(AspeedSoCState, AspeedSoCClass, ASPEED_SOC)
+
+struct AspeedSoCClass {
+ DeviceClass parent_class;
+
+ const char *name;
+ const char *cpu_type;
+ uint32_t silicon_rev;
+ uint64_t sram_size;
+ int spis_num;
+ int ehcis_num;
+ int wdts_num;
+ int macs_num;
+ const int *irqmap;
+ const hwaddr *memmap;
+ uint32_t num_cpus;
+};
+
+
+enum {
+ ASPEED_DEV_IOMEM,
+ ASPEED_DEV_UART1,
+ ASPEED_DEV_UART2,
+ ASPEED_DEV_UART3,
+ ASPEED_DEV_UART4,
+ ASPEED_DEV_UART5,
+ 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_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_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,
+};
+
+#endif /* ASPEED_SOC_H */
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
new file mode 100644
index 000000000..d86487942
--- /dev/null
+++ b/include/hw/arm/bcm2835_peripherals.h
@@ -0,0 +1,79 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * Upstreaming code cleanup [including bcm2835_*] (c) 2013 Jan Petrous
+ *
+ * Rasperry Pi 2 emulation and refactoring Copyright (c) 2015, Microsoft
+ * Written by Andrew Baumann
+ *
+ * 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_PERIPHERALS_H
+#define BCM2835_PERIPHERALS_H
+
+#include "hw/sysbus.h"
+#include "hw/char/pl011.h"
+#include "hw/char/bcm2835_aux.h"
+#include "hw/display/bcm2835_fb.h"
+#include "hw/dma/bcm2835_dma.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/misc/unimp.h"
+#include "qom/object.h"
+
+#define TYPE_BCM2835_PERIPHERALS "bcm2835-peripherals"
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835PeripheralState, BCM2835_PERIPHERALS)
+
+struct BCM2835PeripheralState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ MemoryRegion peri_mr, peri_mr_alias, gpu_bus_mr, mbox_mr;
+ MemoryRegion ram_alias[4];
+ qemu_irq irq, fiq;
+
+ BCM2835SystemTimerState systmr;
+ BCM2835MphiState mphi;
+ UnimplementedDeviceState txp;
+ UnimplementedDeviceState armtmr;
+ BCM2835PowerMgtState powermgt;
+ BCM2835CprmanState cprman;
+ PL011State uart0;
+ BCM2835AuxState aux;
+ BCM2835FBState fb;
+ BCM2835DMAState dma;
+ BCM2835ICState ic;
+ BCM2835PropertyState property;
+ BCM2835RngState rng;
+ BCM2835MboxState mboxes;
+ SDHCIState sdhci;
+ BCM2835SDHostState sdhost;
+ BCM2835GpioState gpio;
+ Bcm2835ThermalState thermal;
+ UnimplementedDeviceState i2s;
+ UnimplementedDeviceState spi[1];
+ UnimplementedDeviceState i2c[3];
+ UnimplementedDeviceState otp;
+ UnimplementedDeviceState dbus;
+ UnimplementedDeviceState ave0;
+ UnimplementedDeviceState v3d;
+ UnimplementedDeviceState bscsl;
+ UnimplementedDeviceState smi;
+ DWC2State dwc2;
+ UnimplementedDeviceState sdramc;
+};
+
+#endif /* BCM2835_PERIPHERALS_H */
diff --git a/include/hw/arm/bcm2836.h b/include/hw/arm/bcm2836.h
new file mode 100644
index 000000000..6f90cabfa
--- /dev/null
+++ b/include/hw/arm/bcm2836.h
@@ -0,0 +1,47 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * Upstreaming code cleanup [including bcm2835_*] (c) 2013 Jan Petrous
+ *
+ * Rasperry Pi 2 emulation and refactoring Copyright (c) 2015, Microsoft
+ * Written by Andrew Baumann
+ *
+ * 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 BCM2836_H
+#define BCM2836_H
+
+#include "hw/arm/bcm2835_peripherals.h"
+#include "hw/intc/bcm2836_control.h"
+#include "target/arm/cpu.h"
+#include "qom/object.h"
+
+#define TYPE_BCM283X "bcm283x"
+OBJECT_DECLARE_TYPE(BCM283XState, BCM283XClass, BCM283X)
+
+#define BCM283X_NCPUS 4
+
+/* These type names are for specific SoCs; other than instantiating
+ * 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"
+
+struct BCM283XState {
+ /*< private >*/
+ DeviceState parent_obj;
+ /*< public >*/
+
+ uint32_t enabled_cpus;
+
+ struct {
+ ARMCPU core;
+ } cpu[BCM283X_NCPUS];
+ BCM2836ControlState control;
+ BCM2835PeripheralState peripherals;
+};
+
+#endif /* BCM2836_H */
diff --git a/include/hw/arm/boot.h b/include/hw/arm/boot.h
new file mode 100644
index 000000000..ce2b48b88
--- /dev/null
+++ b/include/hw/arm/boot.h
@@ -0,0 +1,171 @@
+/*
+ * ARM kernel loader.
+ *
+ * Copyright (c) 2006 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the LGPL.
+ *
+ */
+
+#ifndef HW_ARM_BOOT_H
+#define HW_ARM_BOOT_H
+
+#include "target/arm/cpu-qom.h"
+#include "qemu/notify.h"
+
+typedef enum {
+ ARM_ENDIANNESS_UNKNOWN = 0,
+ ARM_ENDIANNESS_LE,
+ ARM_ENDIANNESS_BE8,
+ ARM_ENDIANNESS_BE32,
+} arm_endianness;
+
+/**
+ * armv7m_load_kernel:
+ * @cpu: CPU
+ * @kernel_filename: file to load
+ * @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);
+
+/* arm_boot.c */
+struct arm_boot_info {
+ uint64_t ram_size;
+ const char *kernel_filename;
+ const char *kernel_cmdline;
+ const char *initrd_filename;
+ const char *dtb_filename;
+ hwaddr loader_start;
+ hwaddr dtb_start;
+ hwaddr dtb_limit;
+ /* If set to True, arm_load_kernel() will not load DTB.
+ * It allows board to load DTB manually later.
+ * (default: False)
+ */
+ bool skip_dtb_autoload;
+ /* multicore boards that use the default secondary core boot functions
+ * need to put the address of the secondary boot code, the boot reg,
+ * and the GIC address in the next 3 values, respectively. boards that
+ * have their own boot functions can use these values as they want.
+ */
+ 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).
+ */
+ bool secure_boot;
+ int (*atag_board)(const struct arm_boot_info *info, void *p);
+ /* multicore boards that use the default secondary core boot functions
+ * can ignore these two function calls. If the default functions won't
+ * work, then write_secondary_boot() should write a suitable blob of
+ * code mimicking the secondary CPU startup process used by the board's
+ * 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.
+ */
+ void (*write_secondary_boot)(ARMCPU *cpu,
+ const struct arm_boot_info *info);
+ void (*secondary_cpu_reset_hook)(ARMCPU *cpu,
+ const struct arm_boot_info *info);
+ /* if a board is able to create a dtb without a dtb file then it
+ * sets get_dtb. This will only be used if no dtb file is provided
+ * by the user. On success, sets *size to the length of the created
+ * dtb, and returns a pointer to it. (The caller must free this memory
+ * with g_free() when it has finished with it.) On failure, returns NULL.
+ */
+ void *(*get_dtb)(const struct arm_boot_info *info, int *size);
+ /* if a board needs to be able to modify a device tree provided by
+ * the user it should implement this hook.
+ */
+ void (*modify_dtb)(const struct arm_boot_info *info, void *fdt);
+ /* Used internally by arm_boot.c */
+ int is_linux;
+ hwaddr initrd_start;
+ hwaddr initrd_size;
+ hwaddr entry;
+
+ /* Boot firmware has been loaded, typically at address 0, with -bios or
+ * -pflash. It also implies that fw_cfg_find() will succeed.
+ */
+ bool firmware_loaded;
+
+ /* Address at which board specific loader/setup code exists. If enabled,
+ * this code-blob will run before anything else. It must return to the
+ * caller via the link register. There is no stack set up. Enabled by
+ * defining write_board_setup, which is responsible for loading the blob
+ * to the specified address.
+ */
+ hwaddr board_setup_addr;
+ void (*write_board_setup)(ARMCPU *cpu,
+ const struct arm_boot_info *info);
+
+ /*
+ * If set, the board specific loader/setup blob will be run from secure
+ * mode, regardless of secure_boot. The blob becomes responsible for
+ * changing to non-secure state if implementing a non-secure boot,
+ * including setting up EL3/Secure registers such as the NSACR as
+ * required by the Linux booting ABI before the switch to non-secure.
+ */
+ bool secure_board_setup;
+
+ arm_endianness endianness;
+};
+
+/**
+ * arm_load_kernel - Loads memory with everything needed to boot
+ *
+ * @cpu: handle to the first CPU object
+ * @info: handle to the boot info struct
+ * Registers a machine init done notifier that copies to memory
+ * everything needed to boot, depending on machine and user options:
+ * kernel image, boot loaders, initrd, dtb. Also registers the CPU
+ * reset handler.
+ *
+ * In case the machine file supports the platform bus device and its
+ * dynamically instantiable sysbus devices, this function must be called
+ * before sysbus-fdt arm_register_platform_bus_fdt_creator. Indeed the
+ * machine init done notifiers are called in registration reverse order.
+ */
+void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info);
+
+AddressSpace *arm_boot_address_space(ARMCPU *cpu,
+ const struct arm_boot_info *info);
+
+/**
+ * arm_load_dtb() - load a device tree binary image into memory
+ * @addr: the address to load the image at
+ * @binfo: struct describing the boot environment
+ * @addr_limit: upper limit of the available memory area at @addr
+ * @as: address space to load image to
+ *
+ * Load a device tree supplied by the machine or by the user with the
+ * '-dtb' command line option, and put it at offset @addr in target
+ * memory.
+ *
+ * If @addr_limit contains a meaningful value (i.e., it is strictly greater
+ * than @addr), the device tree is only loaded if its size does not exceed
+ * the limit.
+ *
+ * Returns: the size of the device tree image on success,
+ * 0 if the image size exceeds the limit,
+ * -1 on errors.
+ *
+ * Note: Must not be called unless have_dtb(binfo) is true.
+ */
+int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
+ hwaddr addr_limit, AddressSpace *as, MachineState *ms);
+
+/* Write a secure board setup routine with a dummy handler for SMCs */
+void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
+ const struct arm_boot_info *info,
+ hwaddr mvbar_addr);
+
+#endif /* HW_ARM_BOOT_H */
diff --git a/include/hw/arm/digic.h b/include/hw/arm/digic.h
new file mode 100644
index 000000000..8f2735c28
--- /dev/null
+++ b/include/hw/arm/digic.h
@@ -0,0 +1,43 @@
+/*
+ * Misc Canon DIGIC declarations.
+ *
+ * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.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 HW_ARM_DIGIC_H
+#define HW_ARM_DIGIC_H
+
+#include "cpu.h"
+#include "hw/timer/digic-timer.h"
+#include "hw/char/digic-uart.h"
+#include "qom/object.h"
+
+#define TYPE_DIGIC "digic"
+
+OBJECT_DECLARE_SIMPLE_TYPE(DigicState, DIGIC)
+
+#define DIGIC4_NB_TIMERS 3
+
+struct DigicState {
+ /*< private >*/
+ DeviceState parent_obj;
+ /*< public >*/
+
+ ARMCPU cpu;
+
+ DigicTimerState timer[DIGIC4_NB_TIMERS];
+ DigicUartState uart;
+};
+
+#endif /* HW_ARM_DIGIC_H */
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
new file mode 100644
index 000000000..60b9e126f
--- /dev/null
+++ b/include/hw/arm/exynos4210.h
@@ -0,0 +1,141 @@
+/*
+ * Samsung exynos4210 SoC emulation
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ * Maksim Kozlov <m.kozlov@samsung.com>
+ * Evgeny Voevodin <e.voevodin@samsung.com>
+ * Igor Mitsyanko <i.mitsyanko@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 EXYNOS4210_H
+#define EXYNOS4210_H
+
+#include "hw/or-irq.h"
+#include "hw/sysbus.h"
+#include "target/arm/cpu-qom.h"
+#include "qom/object.h"
+
+#define EXYNOS4210_NCPUS 2
+
+#define EXYNOS4210_DRAM0_BASE_ADDR 0x40000000
+#define EXYNOS4210_DRAM1_BASE_ADDR 0xa0000000
+#define EXYNOS4210_DRAM_MAX_SIZE 0x60000000 /* 1.5 GB */
+
+#define EXYNOS4210_IROM_BASE_ADDR 0x00000000
+#define EXYNOS4210_IROM_SIZE 0x00010000 /* 64 KB */
+#define EXYNOS4210_IROM_MIRROR_BASE_ADDR 0x02000000
+#define EXYNOS4210_IROM_MIRROR_SIZE 0x00010000 /* 64 KB */
+
+#define EXYNOS4210_IRAM_BASE_ADDR 0x02020000
+#define EXYNOS4210_IRAM_SIZE 0x00020000 /* 128 KB */
+
+/* Secondary CPU startup code is in IROM memory */
+#define EXYNOS4210_SMP_BOOT_ADDR EXYNOS4210_IROM_BASE_ADDR
+#define EXYNOS4210_SMP_BOOT_SIZE 0x1000
+#define EXYNOS4210_BASE_BOOT_ADDR EXYNOS4210_DRAM0_BASE_ADDR
+/* Secondary CPU polling address to get loader start from */
+#define EXYNOS4210_SECOND_CPU_BOOTREG 0x10020814
+
+#define EXYNOS4210_SMP_PRIVATE_BASE_ADDR 0x10500000
+#define EXYNOS4210_L2X0_BASE_ADDR 0x10502000
+
+/*
+ * exynos4210 IRQ subsystem stub definitions.
+ */
+#define EXYNOS4210_IRQ_GATE_NINPUTS 2 /* Internal and External GIC */
+
+#define EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ 64
+#define EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ 16
+#define EXYNOS4210_MAX_INT_COMBINER_IN_IRQ \
+ (EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ * 8)
+#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;
+
+struct Exynos4210State {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+ ARMCPU *cpu[EXYNOS4210_NCPUS];
+ Exynos4210Irq irqs;
+ qemu_irq *irq_table;
+
+ MemoryRegion chipid_mem;
+ MemoryRegion iram_mem;
+ MemoryRegion irom_mem;
+ MemoryRegion irom_alias_mem;
+ MemoryRegion boot_secondary;
+ MemoryRegion bootreg_mem;
+ I2CBus *i2c_if[EXYNOS4210_I2C_NUMBER];
+ qemu_or_irq pl330_irq_orgate[EXYNOS4210_NUM_DMA];
+};
+
+#define TYPE_EXYNOS4210_SOC "exynos4210"
+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
+ * bit - bit number inside group */
+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,
+ int fifo_size,
+ int channel,
+ Chardev *chr,
+ qemu_irq irq);
+
+#endif /* EXYNOS4210_H */
diff --git a/include/hw/arm/fdt.h b/include/hw/arm/fdt.h
new file mode 100644
index 000000000..c3d501501
--- /dev/null
+++ b/include/hw/arm/fdt.h
@@ -0,0 +1,34 @@
+/*
+ *
+ * Copyright (c) 2015 Linaro Limited
+ *
+ * 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/>.
+ *
+ * Define macros useful when building ARM device tree nodes
+ */
+
+#ifndef QEMU_ARM_FDT_H
+#define QEMU_ARM_FDT_H
+
+#define GIC_FDT_IRQ_TYPE_SPI 0
+#define GIC_FDT_IRQ_TYPE_PPI 1
+
+#define GIC_FDT_IRQ_FLAGS_EDGE_LO_HI 1
+#define GIC_FDT_IRQ_FLAGS_EDGE_HI_LO 2
+#define GIC_FDT_IRQ_FLAGS_LEVEL_HI 4
+#define GIC_FDT_IRQ_FLAGS_LEVEL_LO 8
+
+#define GIC_FDT_IRQ_PPI_CPU_START 8
+#define GIC_FDT_IRQ_PPI_CPU_WIDTH 8
+
+#endif
diff --git a/include/hw/arm/fsl-imx25.h b/include/hw/arm/fsl-imx25.h
new file mode 100644
index 000000000..1b1086e94
--- /dev/null
+++ b/include/hw/arm/fsl-imx25.h
@@ -0,0 +1,279 @@
+/*
+ * Freescale i.MX25 SoC emulation
+ *
+ * Copyright (C) 2015 Jean-Christophe Dubois <jcd@tribudubois.net>
+ *
+ * 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 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"
+#include "hw/timer/imx_gpt.h"
+#include "hw/timer/imx_epit.h"
+#include "hw/net/imx_fec.h"
+#include "hw/misc/imx_rngc.h"
+#include "hw/i2c/imx_i2c.h"
+#include "hw/gpio/imx_gpio.h"
+#include "hw/sd/sdhci.h"
+#include "hw/usb/chipidea.h"
+#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"
+OBJECT_DECLARE_SIMPLE_TYPE(FslIMX25State, FSL_IMX25)
+
+#define FSL_IMX25_NUM_UARTS 5
+#define FSL_IMX25_NUM_GPTS 4
+#define FSL_IMX25_NUM_EPITS 2
+#define FSL_IMX25_NUM_I2CS 3
+#define FSL_IMX25_NUM_GPIOS 4
+#define FSL_IMX25_NUM_ESDHCS 2
+#define FSL_IMX25_NUM_USBS 2
+
+struct FslIMX25State {
+ /*< private >*/
+ DeviceState parent_obj;
+
+ /*< public >*/
+ ARMCPU cpu;
+ IMXAVICState avic;
+ IMX25CCMState ccm;
+ IMXSerialState uart[FSL_IMX25_NUM_UARTS];
+ IMXGPTState gpt[FSL_IMX25_NUM_GPTS];
+ IMXEPITState epit[FSL_IMX25_NUM_EPITS];
+ IMXFECState fec;
+ IMXRNGCState rngc;
+ IMXI2CState i2c[FSL_IMX25_NUM_I2CS];
+ IMXGPIOState gpio[FSL_IMX25_NUM_GPIOS];
+ SDHCIState esdhc[FSL_IMX25_NUM_ESDHCS];
+ ChipideaState usb[FSL_IMX25_NUM_USBS];
+ IMX2WdtState wdt;
+ MemoryRegion rom[2];
+ MemoryRegion iram;
+ MemoryRegion iram_alias;
+ uint32_t phy_num;
+};
+
+/**
+ * i.MX25 memory map
+ ****************************************************************
+ * 0x0000_0000 0x0000_3FFF 16 Kbytes ROM (36 Kbytes)
+ * 0x0000_4000 0x0040_3FFF 4 Mbytes Reserved
+ * 0x0040_4000 0x0040_8FFF 20 Kbytes ROM (36 Kbytes)
+ * 0x0040_9000 0x0FFF_FFFF 252 Mbytes (minus 36 Kbytes) Reserved
+ * 0x1000_0000 0x1FFF_FFFF 256 Mbytes Reserved
+ * 0x2000_0000 0x2FFF_FFFF 256 Mbytes Reserved
+ * 0x3000_0000 0x3FFF_FFFF 256 Mbytes Reserved
+ * 0x4000_0000 0x43EF_FFFF 63 Mbytes Reserved
+ * 0x43F0_0000 0x43F0_3FFF 16 Kbytes AIPS A control registers
+ * 0x43F0_4000 0x43F0_7FFF 16 Kbytes ARM926 platform MAX
+ * 0x43F0_8000 0x43F0_BFFF 16 Kbytes ARM926 platform CLKCTL
+ * 0x43F0_C000 0x43F0_FFFF 16 Kbytes ARM926 platform ETB registers
+ * 0x43F1_0000 0x43F1_3FFF 16 Kbytes ARM926 platform ETB memory
+ * 0x43F1_4000 0x43F1_7FFF 16 Kbytes ARM926 platform AAPE registers
+ * 0x43F1_8000 0x43F7_FFFF 416 Kbytes Reserved
+ * 0x43F8_0000 0x43F8_3FFF 16 Kbytes I2C-1
+ * 0x43F8_4000 0x43F8_7FFF 16 Kbytes I2C-3
+ * 0x43F8_8000 0x43F8_BFFF 16 Kbytes CAN-1
+ * 0x43F8_C000 0x43F8_FFFF 16 Kbytes CAN-2
+ * 0x43F9_0000 0x43F9_3FFF 16 Kbytes UART-1
+ * 0x43F9_4000 0x43F9_7FFF 16 Kbytes UART-2
+ * 0x43F9_8000 0x43F9_BFFF 16 Kbytes I2C-2
+ * 0x43F9_C000 0x43F9_FFFF 16 Kbytes 1-Wire
+ * 0x43FA_0000 0x43FA_3FFF 16 Kbytes ATA (CPU side)
+ * 0x43FA_4000 0x43FA_7FFF 16 Kbytes CSPI-1
+ * 0x43FA_8000 0x43FA_BFFF 16 Kbytes KPP
+ * 0x43FA_C000 0x43FA_FFFF 16 Kbytes IOMUXC
+ * 0x43FB_0000 0x43FB_3FFF 16 Kbytes AUDMUX
+ * 0x43FB_4000 0x43FB_7FFF 16 Kbytes Reserved
+ * 0x43FB_8000 0x43FB_BFFF 16 Kbytes ECT (IP BUS A)
+ * 0x43FB_C000 0x43FB_FFFF 16 Kbytes ECT (IP BUS B)
+ * 0x43FC_0000 0x43FF_FFFF 256 Kbytes Reserved AIPS A off-platform slots
+ * 0x4400_0000 0x4FFF_FFFF 192 Mbytes Reserved
+ * 0x5000_0000 0x5000_3FFF 16 Kbytes SPBA base address
+ * 0x5000_4000 0x5000_7FFF 16 Kbytes CSPI-3
+ * 0x5000_8000 0x5000_BFFF 16 Kbytes UART-4
+ * 0x5000_C000 0x5000_FFFF 16 Kbytes UART-3
+ * 0x5001_0000 0x5001_3FFF 16 Kbytes CSPI-2
+ * 0x5001_4000 0x5001_7FFF 16 Kbytes SSI-2
+ * 0x5001_C000 0x5001_FFFF 16 Kbytes Reserved
+ * 0x5002_0000 0x5002_3FFF 16 Kbytes ATA
+ * 0x5002_4000 0x5002_7FFF 16 Kbytes SIM-1
+ * 0x5002_8000 0x5002_BFFF 16 Kbytes SIM-2
+ * 0x5002_C000 0x5002_FFFF 16 Kbytes UART-5
+ * 0x5003_0000 0x5003_3FFF 16 Kbytes TSC
+ * 0x5003_4000 0x5003_7FFF 16 Kbytes SSI-1
+ * 0x5003_8000 0x5003_BFFF 16 Kbytes FEC
+ * 0x5003_C000 0x5003_FFFF 16 Kbytes SPBA registers
+ * 0x5004_0000 0x51FF_FFFF 32 Mbytes (minus 256 Kbytes)
+ * 0x5200_0000 0x53EF_FFFF 31 Mbytes Reserved
+ * 0x53F0_0000 0x53F0_3FFF 16 Kbytes AIPS B control registers
+ * 0x53F0_4000 0x53F7_FFFF 496 Kbytes Reserved
+ * 0x53F8_0000 0x53F8_3FFF 16 Kbytes CCM
+ * 0x53F8_4000 0x53F8_7FFF 16 Kbytes GPT-4
+ * 0x53F8_8000 0x53F8_BFFF 16 Kbytes GPT-3
+ * 0x53F8_C000 0x53F8_FFFF 16 Kbytes GPT-2
+ * 0x53F9_0000 0x53F9_3FFF 16 Kbytes GPT-1
+ * 0x53F9_4000 0x53F9_7FFF 16 Kbytes EPIT-1
+ * 0x53F9_8000 0x53F9_BFFF 16 Kbytes EPIT-2
+ * 0x53F9_C000 0x53F9_FFFF 16 Kbytes GPIO-4
+ * 0x53FA_0000 0x53FA_3FFF 16 Kbytes PWM-2
+ * 0x53FA_4000 0x53FA_7FFF 16 Kbytes GPIO-3
+ * 0x53FA_8000 0x53FA_BFFF 16 Kbytes PWM-3
+ * 0x53FA_C000 0x53FA_FFFF 16 Kbytes SCC
+ * 0x53FB_0000 0x53FB_3FFF 16 Kbytes RNGB
+ * 0x53FB_4000 0x53FB_7FFF 16 Kbytes eSDHC-1
+ * 0x53FB_8000 0x53FB_BFFF 16 Kbytes eSDHC-2
+ * 0x53FB_C000 0x53FB_FFFF 16 Kbytes LCDC
+ * 0x53FC_0000 0x53FC_3FFF 16 Kbytes SLCDC
+ * 0x53FC_4000 0x53FC_7FFF 16 Kbytes Reserved
+ * 0x53FC_8000 0x53FC_BFFF 16 Kbytes PWM-4
+ * 0x53FC_C000 0x53FC_FFFF 16 Kbytes GPIO-1
+ * 0x53FD_0000 0x53FD_3FFF 16 Kbytes GPIO-2
+ * 0x53FD_4000 0x53FD_7FFF 16 Kbytes SDMA
+ * 0x53FD_8000 0x53FD_BFFF 16 Kbytes Reserved
+ * 0x53FD_C000 0x53FD_FFFF 16 Kbytes WDOG
+ * 0x53FE_0000 0x53FE_3FFF 16 Kbytes PWM-1
+ * 0x53FE_4000 0x53FE_7FFF 16 Kbytes Reserved
+ * 0x53FE_8000 0x53FE_BFFF 16 Kbytes Reserved
+ * 0x53FE_C000 0x53FE_FFFF 16 Kbytes RTICv3
+ * 0x53FF_0000 0x53FF_3FFF 16 Kbytes IIM
+ * 0x53FF_4000 0x53FF_7FFF 16 Kbytes USB
+ * 0x53FF_8000 0x53FF_BFFF 16 Kbytes CSI
+ * 0x53FF_C000 0x53FF_FFFF 16 Kbytes DryIce
+ * 0x5400_0000 0x5FFF_FFFF 192 Mbytes Reserved (aliased AIPS B slots)
+ * 0x6000_0000 0x67FF_FFFF 128 Mbytes ARM926 platform ROMPATCH
+ * 0x6800_0000 0x6FFF_FFFF 128 Mbytes ARM926 platform ASIC
+ * 0x7000_0000 0x77FF_FFFF 128 Mbytes Reserved
+ * 0x7800_0000 0x7801_FFFF 128 Kbytes RAM
+ * 0x7802_0000 0x7FFF_FFFF 128 Mbytes (minus 128 Kbytes)
+ * 0x8000_0000 0x8FFF_FFFF 256 Mbytes SDRAM bank 0
+ * 0x9000_0000 0x9FFF_FFFF 256 Mbytes SDRAM bank 1
+ * 0xA000_0000 0xA7FF_FFFF 128 Mbytes WEIM CS0 (flash 128) 1
+ * 0xA800_0000 0xAFFF_FFFF 128 Mbytes WEIM CS1 (flash 64) 1
+ * 0xB000_0000 0xB1FF_FFFF 32 Mbytes WEIM CS2 (SRAM)
+ * 0xB200_0000 0xB3FF_FFFF 32 Mbytes WEIM CS3 (SRAM)
+ * 0xB400_0000 0xB5FF_FFFF 32 Mbytes WEIM CS4
+ * 0xB600_0000 0xB7FF_FFFF 32 Mbytes Reserved
+ * 0xB800_0000 0xB800_0FFF 4 Kbytes Reserved
+ * 0xB800_1000 0xB800_1FFF 4 Kbytes SDRAM control registers
+ * 0xB800_2000 0xB800_2FFF 4 Kbytes WEIM control registers
+ * 0xB800_3000 0xB800_3FFF 4 Kbytes M3IF control registers
+ * 0xB800_4000 0xB800_4FFF 4 Kbytes EMI control registers
+ * 0xB800_5000 0xBAFF_FFFF 32 Mbytes (minus 20 Kbytes)
+ * 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 registers
+ * 0xBB01_2000 0xBFFF_FFFF 96 Mbytes (minus 8 Kbytes) Reserved
+ * 0xC000_0000 0xFFFF_FFFF 1024 Mbytes Reserved
+ */
+
+#define FSL_IMX25_ROM0_ADDR 0x00000000
+#define FSL_IMX25_ROM0_SIZE 0x4000
+#define FSL_IMX25_ROM1_ADDR 0x00404000
+#define FSL_IMX25_ROM1_SIZE 0x4000
+#define FSL_IMX25_I2C1_ADDR 0x43F80000
+#define FSL_IMX25_I2C1_SIZE 0x4000
+#define FSL_IMX25_I2C3_ADDR 0x43F84000
+#define FSL_IMX25_I2C3_SIZE 0x4000
+#define FSL_IMX25_UART1_ADDR 0x43F90000
+#define FSL_IMX25_UART1_SIZE 0x4000
+#define FSL_IMX25_UART2_ADDR 0x43F94000
+#define FSL_IMX25_UART2_SIZE 0x4000
+#define FSL_IMX25_I2C2_ADDR 0x43F98000
+#define FSL_IMX25_I2C2_SIZE 0x4000
+#define FSL_IMX25_UART4_ADDR 0x50008000
+#define FSL_IMX25_UART4_SIZE 0x4000
+#define FSL_IMX25_UART3_ADDR 0x5000C000
+#define FSL_IMX25_UART3_SIZE 0x4000
+#define FSL_IMX25_UART5_ADDR 0x5002C000
+#define FSL_IMX25_UART5_SIZE 0x4000
+#define FSL_IMX25_FEC_ADDR 0x50038000
+#define FSL_IMX25_CCM_ADDR 0x53F80000
+#define FSL_IMX25_CCM_SIZE 0x4000
+#define FSL_IMX25_GPT4_ADDR 0x53F84000
+#define FSL_IMX25_GPT4_SIZE 0x4000
+#define FSL_IMX25_GPT3_ADDR 0x53F88000
+#define FSL_IMX25_GPT3_SIZE 0x4000
+#define FSL_IMX25_GPT2_ADDR 0x53F8C000
+#define FSL_IMX25_GPT2_SIZE 0x4000
+#define FSL_IMX25_GPT1_ADDR 0x53F90000
+#define FSL_IMX25_GPT1_SIZE 0x4000
+#define FSL_IMX25_EPIT1_ADDR 0x53F94000
+#define FSL_IMX25_EPIT1_SIZE 0x4000
+#define FSL_IMX25_EPIT2_ADDR 0x53F98000
+#define FSL_IMX25_EPIT2_SIZE 0x4000
+#define FSL_IMX25_GPIO4_ADDR 0x53F9C000
+#define FSL_IMX25_GPIO4_SIZE 0x4000
+#define FSL_IMX25_GPIO3_ADDR 0x53FA4000
+#define FSL_IMX25_GPIO3_SIZE 0x4000
+#define FSL_IMX25_RNGC_ADDR 0x53FB0000
+#define FSL_IMX25_RNGC_SIZE 0x4000
+#define FSL_IMX25_ESDHC1_ADDR 0x53FB4000
+#define FSL_IMX25_ESDHC1_SIZE 0x4000
+#define FSL_IMX25_ESDHC2_ADDR 0x53FB8000
+#define FSL_IMX25_ESDHC2_SIZE 0x4000
+#define FSL_IMX25_GPIO1_ADDR 0x53FCC000
+#define FSL_IMX25_GPIO1_SIZE 0x4000
+#define FSL_IMX25_GPIO2_ADDR 0x53FD0000
+#define FSL_IMX25_GPIO2_SIZE 0x4000
+#define FSL_IMX25_WDT_ADDR 0x53FDC000
+#define FSL_IMX25_WDT_SIZE 0x4000
+#define FSL_IMX25_USB1_ADDR 0x53FF4000
+#define FSL_IMX25_USB1_SIZE 0x0200
+#define FSL_IMX25_USB2_ADDR 0x53FF4400
+#define FSL_IMX25_USB2_SIZE 0x0200
+#define FSL_IMX25_AVIC_ADDR 0x68000000
+#define FSL_IMX25_AVIC_SIZE 0x4000
+#define FSL_IMX25_IRAM_ADDR 0x78000000
+#define FSL_IMX25_IRAM_SIZE 0x20000
+#define FSL_IMX25_IRAM_ALIAS_ADDR 0x78020000
+#define FSL_IMX25_IRAM_ALIAS_SIZE 0x7FE0000
+#define FSL_IMX25_SDRAM0_ADDR 0x80000000
+#define FSL_IMX25_SDRAM0_SIZE 0x10000000
+#define FSL_IMX25_SDRAM1_ADDR 0x90000000
+#define FSL_IMX25_SDRAM1_SIZE 0x10000000
+
+#define FSL_IMX25_UART1_IRQ 45
+#define FSL_IMX25_UART2_IRQ 32
+#define FSL_IMX25_UART3_IRQ 18
+#define FSL_IMX25_UART4_IRQ 5
+#define FSL_IMX25_UART5_IRQ 40
+#define FSL_IMX25_GPT1_IRQ 54
+#define FSL_IMX25_GPT2_IRQ 53
+#define FSL_IMX25_GPT3_IRQ 29
+#define FSL_IMX25_GPT4_IRQ 1
+#define FSL_IMX25_EPIT1_IRQ 28
+#define FSL_IMX25_EPIT2_IRQ 27
+#define FSL_IMX25_FEC_IRQ 57
+#define FSL_IMX25_RNGC_IRQ 22
+#define FSL_IMX25_I2C1_IRQ 3
+#define FSL_IMX25_I2C2_IRQ 4
+#define FSL_IMX25_I2C3_IRQ 10
+#define FSL_IMX25_GPIO1_IRQ 52
+#define FSL_IMX25_GPIO2_IRQ 51
+#define FSL_IMX25_GPIO3_IRQ 16
+#define FSL_IMX25_GPIO4_IRQ 23
+#define FSL_IMX25_ESDHC1_IRQ 9
+#define FSL_IMX25_ESDHC2_IRQ 8
+#define FSL_IMX25_USB1_IRQ 37
+#define FSL_IMX25_USB2_IRQ 35
+#define FSL_IMX25_WDT_IRQ 55
+
+#endif /* FSL_IMX25_H */
diff --git a/include/hw/arm/fsl-imx31.h b/include/hw/arm/fsl-imx31.h
new file mode 100644
index 000000000..c116a73e0
--- /dev/null
+++ b/include/hw/arm/fsl-imx31.h
@@ -0,0 +1,128 @@
+/*
+ * Freescale i.MX31 SoC emulation
+ *
+ * Copyright (C) 2015 Jean-Christophe Dubois <jcd@tribudubois.net>
+ *
+ * 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 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"
+#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/watchdog/wdt_imx2.h"
+#include "exec/memory.h"
+#include "target/arm/cpu.h"
+#include "qom/object.h"
+
+#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
+
+struct FslIMX31State {
+ /*< private >*/
+ DeviceState parent_obj;
+
+ /*< public >*/
+ ARMCPU cpu;
+ IMXAVICState avic;
+ IMX31CCMState ccm;
+ IMXSerialState uart[FSL_IMX31_NUM_UARTS];
+ IMXGPTState gpt;
+ IMXEPITState epit[FSL_IMX31_NUM_EPITS];
+ IMXI2CState i2c[FSL_IMX31_NUM_I2CS];
+ IMXGPIOState gpio[FSL_IMX31_NUM_GPIOS];
+ IMX2WdtState wdt;
+ MemoryRegion secure_rom;
+ MemoryRegion rom;
+ MemoryRegion iram;
+ MemoryRegion iram_alias;
+};
+
+#define FSL_IMX31_SECURE_ROM_ADDR 0x00000000
+#define FSL_IMX31_SECURE_ROM_SIZE 0x4000
+#define FSL_IMX31_ROM_ADDR 0x00404000
+#define FSL_IMX31_ROM_SIZE 0x4000
+#define FSL_IMX31_IRAM_ALIAS_ADDR 0x10000000
+#define FSL_IMX31_IRAM_ALIAS_SIZE 0xFFC0000
+#define FSL_IMX31_IRAM_ADDR 0x1FFFC000
+#define FSL_IMX31_IRAM_SIZE 0x4000
+#define FSL_IMX31_I2C1_ADDR 0x43F80000
+#define FSL_IMX31_I2C1_SIZE 0x4000
+#define FSL_IMX31_I2C3_ADDR 0x43F84000
+#define FSL_IMX31_I2C3_SIZE 0x4000
+#define FSL_IMX31_UART1_ADDR 0x43F90000
+#define FSL_IMX31_UART1_SIZE 0x4000
+#define FSL_IMX31_UART2_ADDR 0x43F94000
+#define FSL_IMX31_UART2_SIZE 0x4000
+#define FSL_IMX31_I2C2_ADDR 0x43F98000
+#define FSL_IMX31_I2C2_SIZE 0x4000
+#define FSL_IMX31_CCM_ADDR 0x53F80000
+#define FSL_IMX31_CCM_SIZE 0x4000
+#define FSL_IMX31_GPT_ADDR 0x53F90000
+#define FSL_IMX31_GPT_SIZE 0x4000
+#define FSL_IMX31_EPIT1_ADDR 0x53F94000
+#define FSL_IMX31_EPIT1_SIZE 0x4000
+#define FSL_IMX31_EPIT2_ADDR 0x53F98000
+#define FSL_IMX31_EPIT2_SIZE 0x4000
+#define FSL_IMX31_GPIO3_ADDR 0x53FA4000
+#define FSL_IMX31_GPIO3_SIZE 0x4000
+#define FSL_IMX31_GPIO1_ADDR 0x53FCC000
+#define FSL_IMX31_GPIO1_SIZE 0x4000
+#define FSL_IMX31_GPIO2_ADDR 0x53FD0000
+#define FSL_IMX31_GPIO2_SIZE 0x4000
+#define FSL_IMX31_WDT_ADDR 0x53FDC000
+#define FSL_IMX31_WDT_SIZE 0x4000
+#define FSL_IMX31_AVIC_ADDR 0x68000000
+#define FSL_IMX31_AVIC_SIZE 0x100
+#define FSL_IMX31_SDRAM0_ADDR 0x80000000
+#define FSL_IMX31_SDRAM0_SIZE 0x10000000
+#define FSL_IMX31_SDRAM1_ADDR 0x90000000
+#define FSL_IMX31_SDRAM1_SIZE 0x10000000
+#define FSL_IMX31_FLASH0_ADDR 0xA0000000
+#define FSL_IMX31_FLASH0_SIZE 0x8000000
+#define FSL_IMX31_FLASH1_ADDR 0xA8000000
+#define FSL_IMX31_FLASH1_SIZE 0x8000000
+#define FSL_IMX31_CS2_ADDR 0xB0000000
+#define FSL_IMX31_CS2_SIZE 0x2000000
+#define FSL_IMX31_CS3_ADDR 0xB2000000
+#define FSL_IMX31_CS3_SIZE 0x2000000
+#define FSL_IMX31_CS4_ADDR 0xB4000000
+#define FSL_IMX31_CS4_SIZE 0x2000000
+#define FSL_IMX31_CS5_ADDR 0xB6000000
+#define FSL_IMX31_CS5_SIZE 0x2000000
+#define FSL_IMX31_NAND_ADDR 0xB8000000
+#define FSL_IMX31_NAND_SIZE 0x1000
+
+#define FSL_IMX31_EPIT2_IRQ 27
+#define FSL_IMX31_EPIT1_IRQ 28
+#define FSL_IMX31_GPT_IRQ 29
+#define FSL_IMX31_UART2_IRQ 32
+#define FSL_IMX31_UART1_IRQ 45
+#define FSL_IMX31_I2C1_IRQ 10
+#define FSL_IMX31_I2C2_IRQ 4
+#define FSL_IMX31_I2C3_IRQ 3
+#define FSL_IMX31_GPIO1_IRQ 52
+#define FSL_IMX31_GPIO2_IRQ 51
+#define FSL_IMX31_GPIO3_IRQ 56
+
+#endif /* FSL_IMX31_H */
diff --git a/include/hw/arm/fsl-imx6.h b/include/hw/arm/fsl-imx6.h
new file mode 100644
index 000000000..83291457c
--- /dev/null
+++ b/include/hw/arm/fsl-imx6.h
@@ -0,0 +1,464 @@
+/*
+ * Freescale i.MX31 SoC emulation
+ *
+ * Copyright (C) 2015 Jean-Christophe Dubois <jcd@tribudubois.net>
+ *
+ * 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 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/watchdog/wdt_imx2.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/usb/chipidea.h"
+#include "hw/usb/imx-usb-phy.h"
+#include "exec/memory.h"
+#include "cpu.h"
+#include "qom/object.h"
+
+#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
+#define FSL_IMX6_NUM_EPITS 2
+#define FSL_IMX6_NUM_I2CS 3
+#define FSL_IMX6_NUM_GPIOS 7
+#define FSL_IMX6_NUM_ESDHCS 4
+#define FSL_IMX6_NUM_ECSPIS 5
+#define FSL_IMX6_NUM_WDTS 2
+#define FSL_IMX6_NUM_USB_PHYS 2
+#define FSL_IMX6_NUM_USBS 4
+
+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;
+};
+
+
+#define FSL_IMX6_MMDC_ADDR 0x10000000
+#define FSL_IMX6_MMDC_SIZE 0xF0000000
+#define FSL_IMX6_EIM_MEM_ADDR 0x08000000
+#define FSL_IMX6_EIM_MEM_SIZE 0x8000000
+#define FSL_IMX6_IPU_2_ADDR 0x02800000
+#define FSL_IMX6_IPU_2_SIZE 0x400000
+#define FSL_IMX6_IPU_1_ADDR 0x02400000
+#define FSL_IMX6_IPU_1_SIZE 0x400000
+#define FSL_IMX6_MIPI_HSI_ADDR 0x02208000
+#define FSL_IMX6_MIPI_HSI_SIZE 0x4000
+#define FSL_IMX6_OPENVG_ADDR 0x02204000
+#define FSL_IMX6_OPENVG_SIZE 0x4000
+#define FSL_IMX6_SATA_ADDR 0x02200000
+#define FSL_IMX6_SATA_SIZE 0x4000
+#define FSL_IMX6_AIPS_2_ADDR 0x02100000
+#define FSL_IMX6_AIPS_2_SIZE 0x100000
+/* AIPS2 */
+#define FSL_IMX6_UART5_ADDR 0x021F4000
+#define FSL_IMX6_UART5_SIZE 0x4000
+#define FSL_IMX6_UART4_ADDR 0x021F0000
+#define FSL_IMX6_UART4_SIZE 0x4000
+#define FSL_IMX6_UART3_ADDR 0x021EC000
+#define FSL_IMX6_UART3_SIZE 0x4000
+#define FSL_IMX6_UART2_ADDR 0x021E8000
+#define FSL_IMX6_UART2_SIZE 0x4000
+#define FSL_IMX6_VDOA_ADDR 0x021E4000
+#define FSL_IMX6_VDOA_SIZE 0x4000
+#define FSL_IMX6_MIPI_DSI_ADDR 0x021E0000
+#define FSL_IMX6_MIPI_DSI_SIZE 0x4000
+#define FSL_IMX6_MIPI_CSI_ADDR 0x021DC000
+#define FSL_IMX6_MIPI_CSI_SIZE 0x4000
+#define FSL_IMX6_AUDMUX_ADDR 0x021D8000
+#define FSL_IMX6_AUDMUX_SIZE 0x4000
+#define FSL_IMX6_TZASC2_ADDR 0x021D4000
+#define FSL_IMX6_TZASC2_SIZE 0x4000
+#define FSL_IMX6_TZASC1_ADDR 0x021D0000
+#define FSL_IMX6_TZASC1_SIZE 0x4000
+#define FSL_IMX6_CSU_ADDR 0x021C0000
+#define FSL_IMX6_CSU_SIZE 0x4000
+#define FSL_IMX6_OCOTPCTRL_ADDR 0x021BC000
+#define FSL_IMX6_OCOTPCTRL_SIZE 0x4000
+#define FSL_IMX6_EIM_ADDR 0x021B8000
+#define FSL_IMX6_EIM_SIZE 0x4000
+#define FSL_IMX6_MMDC1_ADDR 0x021B4000
+#define FSL_IMX6_MMDC1_SIZE 0x4000
+#define FSL_IMX6_MMDC0_ADDR 0x021B0000
+#define FSL_IMX6_MMDC0_SIZE 0x4000
+#define FSL_IMX6_ROMCP_ADDR 0x021AC000
+#define FSL_IMX6_ROMCP_SIZE 0x4000
+#define FSL_IMX6_I2C3_ADDR 0x021A8000
+#define FSL_IMX6_I2C3_SIZE 0x4000
+#define FSL_IMX6_I2C2_ADDR 0x021A4000
+#define FSL_IMX6_I2C2_SIZE 0x4000
+#define FSL_IMX6_I2C1_ADDR 0x021A0000
+#define FSL_IMX6_I2C1_SIZE 0x4000
+#define FSL_IMX6_uSDHC4_ADDR 0x0219C000
+#define FSL_IMX6_uSDHC4_SIZE 0x4000
+#define FSL_IMX6_uSDHC3_ADDR 0x02198000
+#define FSL_IMX6_uSDHC3_SIZE 0x4000
+#define FSL_IMX6_uSDHC2_ADDR 0x02194000
+#define FSL_IMX6_uSDHC2_SIZE 0x4000
+#define FSL_IMX6_uSDHC1_ADDR 0x02190000
+#define FSL_IMX6_uSDHC1_SIZE 0x4000
+#define FSL_IMX6_MLB150_ADDR 0x0218C000
+#define FSL_IMX6_MLB150_SIZE 0x4000
+#define FSL_IMX6_ENET_ADDR 0x02188000
+#define FSL_IMX6_ENET_SIZE 0x4000
+#define FSL_IMX6_USBOH3_USB_ADDR 0x02184000
+#define FSL_IMX6_USBOH3_USB_SIZE 0x4000
+#define FSL_IMX6_AIPS2_CFG_ADDR 0x0217C000
+#define FSL_IMX6_AIPS2_CFG_SIZE 0x4000
+/* DAP */
+#define FSL_IMX6_PTF_CTRL_ADDR 0x02160000
+#define FSL_IMX6_PTF_CTRL_SIZE 0x1000
+#define FSL_IMX6_PTM3_ADDR 0x0215F000
+#define FSL_IMX6_PTM3_SIZE 0x1000
+#define FSL_IMX6_PTM2_ADDR 0x0215E000
+#define FSL_IMX6_PTM2_SIZE 0x1000
+#define FSL_IMX6_PTM1_ADDR 0x0215D000
+#define FSL_IMX6_PTM1_SIZE 0x1000
+#define FSL_IMX6_PTM0_ADDR 0x0215C000
+#define FSL_IMX6_PTM0_SIZE 0x1000
+#define FSL_IMX6_CTI3_ADDR 0x0215B000
+#define FSL_IMX6_CTI3_SIZE 0x1000
+#define FSL_IMX6_CTI2_ADDR 0x0215A000
+#define FSL_IMX6_CTI2_SIZE 0x1000
+#define FSL_IMX6_CTI1_ADDR 0x02159000
+#define FSL_IMX6_CTI1_SIZE 0x1000
+#define FSL_IMX6_CTI0_ADDR 0x02158000
+#define FSL_IMX6_CTI0_SIZE 0x1000
+#define FSL_IMX6_CPU3_PMU_ADDR 0x02157000
+#define FSL_IMX6_CPU3_PMU_SIZE 0x1000
+#define FSL_IMX6_CPU3_DEBUG_IF_ADDR 0x02156000
+#define FSL_IMX6_CPU3_DEBUG_IF_SIZE 0x1000
+#define FSL_IMX6_CPU2_PMU_ADDR 0x02155000
+#define FSL_IMX6_CPU2_PMU_SIZE 0x1000
+#define FSL_IMX6_CPU2_DEBUG_IF_ADDR 0x02154000
+#define FSL_IMX6_CPU2_DEBUG_IF_SIZE 0x1000
+#define FSL_IMX6_CPU1_PMU_ADDR 0x02153000
+#define FSL_IMX6_CPU1_PMU_SIZE 0x1000
+#define FSL_IMX6_CPU1_DEBUG_IF_ADDR 0x02152000
+#define FSL_IMX6_CPU1_DEBUG_IF_SIZE 0x1000
+#define FSL_IMX6_CPU0_PMU_ADDR 0x02151000
+#define FSL_IMX6_CPU0_PMU_SIZE 0x1000
+#define FSL_IMX6_CPU0_DEBUG_IF_ADDR 0x02150000
+#define FSL_IMX6_CPU0_DEBUG_IF_SIZE 0x1000
+#define FSL_IMX6_CA9_INTEG_ADDR 0x0214F000
+#define FSL_IMX6_CA9_INTEG_SIZE 0x1000
+#define FSL_IMX6_FUNNEL_ADDR 0x02144000
+#define FSL_IMX6_FUNNEL_SIZE 0x1000
+#define FSL_IMX6_TPIU_ADDR 0x02143000
+#define FSL_IMX6_TPIU_SIZE 0x1000
+#define FSL_IMX6_EXT_CTI_ADDR 0x02142000
+#define FSL_IMX6_EXT_CTI_SIZE 0x1000
+#define FSL_IMX6_ETB_ADDR 0x02141000
+#define FSL_IMX6_ETB_SIZE 0x1000
+#define FSL_IMX6_DAP_ROM_TABLE_ADDR 0x02140000
+#define FSL_IMX6_DAP_ROM_TABLE_SIZE 0x1000
+/* DAP end */
+#define FSL_IMX6_CAAM_ADDR 0x02100000
+#define FSL_IMX6_CAAM_SIZE 0x10000
+/* AIPS2 end */
+#define FSL_IMX6_AIPS_1_ADDR 0x02000000
+#define FSL_IMX6_AIPS_1_SIZE 0x100000
+/* AIPS1 */
+#define FSL_IMX6_SDMA_ADDR 0x020EC000
+#define FSL_IMX6_SDMA_SIZE 0x4000
+#define FSL_IMX6_DCIC2_ADDR 0x020E8000
+#define FSL_IMX6_DCIC2_SIZE 0x4000
+#define FSL_IMX6_DCIC1_ADDR 0x020E4000
+#define FSL_IMX6_DCIC1_SIZE 0x4000
+#define FSL_IMX6_IOMUXC_ADDR 0x020E0000
+#define FSL_IMX6_IOMUXC_SIZE 0x4000
+#define FSL_IMX6_PGCARM_ADDR 0x020DCA00
+#define FSL_IMX6_PGCARM_SIZE 0x20
+#define FSL_IMX6_PGCPU_ADDR 0x020DC260
+#define FSL_IMX6_PGCPU_SIZE 0x20
+#define FSL_IMX6_GPC_ADDR 0x020DC000
+#define FSL_IMX6_GPC_SIZE 0x4000
+#define FSL_IMX6_SRC_ADDR 0x020D8000
+#define FSL_IMX6_SRC_SIZE 0x4000
+#define FSL_IMX6_EPIT2_ADDR 0x020D4000
+#define FSL_IMX6_EPIT2_SIZE 0x4000
+#define FSL_IMX6_EPIT1_ADDR 0x020D0000
+#define FSL_IMX6_EPIT1_SIZE 0x4000
+#define FSL_IMX6_SNVSHP_ADDR 0x020CC000
+#define FSL_IMX6_SNVSHP_SIZE 0x4000
+#define FSL_IMX6_USBPHY2_ADDR 0x020CA000
+#define FSL_IMX6_USBPHY2_SIZE 0x1000
+#define FSL_IMX6_USBPHY1_ADDR 0x020C9000
+#define FSL_IMX6_USBPHY1_SIZE 0x1000
+#define FSL_IMX6_ANALOG_ADDR 0x020C8000
+#define FSL_IMX6_ANALOG_SIZE 0x1000
+#define FSL_IMX6_CCM_ADDR 0x020C4000
+#define FSL_IMX6_CCM_SIZE 0x4000
+#define FSL_IMX6_WDOG2_ADDR 0x020C0000
+#define FSL_IMX6_WDOG2_SIZE 0x4000
+#define FSL_IMX6_WDOG1_ADDR 0x020BC000
+#define FSL_IMX6_WDOG1_SIZE 0x4000
+#define FSL_IMX6_KPP_ADDR 0x020B8000
+#define FSL_IMX6_KPP_SIZE 0x4000
+#define FSL_IMX6_GPIO7_ADDR 0x020B4000
+#define FSL_IMX6_GPIO7_SIZE 0x4000
+#define FSL_IMX6_GPIO6_ADDR 0x020B0000
+#define FSL_IMX6_GPIO6_SIZE 0x4000
+#define FSL_IMX6_GPIO5_ADDR 0x020AC000
+#define FSL_IMX6_GPIO5_SIZE 0x4000
+#define FSL_IMX6_GPIO4_ADDR 0x020A8000
+#define FSL_IMX6_GPIO4_SIZE 0x4000
+#define FSL_IMX6_GPIO3_ADDR 0x020A4000
+#define FSL_IMX6_GPIO3_SIZE 0x4000
+#define FSL_IMX6_GPIO2_ADDR 0x020A0000
+#define FSL_IMX6_GPIO2_SIZE 0x4000
+#define FSL_IMX6_GPIO1_ADDR 0x0209C000
+#define FSL_IMX6_GPIO1_SIZE 0x4000
+#define FSL_IMX6_GPT_ADDR 0x02098000
+#define FSL_IMX6_GPT_SIZE 0x4000
+#define FSL_IMX6_CAN2_ADDR 0x02094000
+#define FSL_IMX6_CAN2_SIZE 0x4000
+#define FSL_IMX6_CAN1_ADDR 0x02090000
+#define FSL_IMX6_CAN1_SIZE 0x4000
+#define FSL_IMX6_PWM4_ADDR 0x0208C000
+#define FSL_IMX6_PWM4_SIZE 0x4000
+#define FSL_IMX6_PWM3_ADDR 0x02088000
+#define FSL_IMX6_PWM3_SIZE 0x4000
+#define FSL_IMX6_PWM2_ADDR 0x02084000
+#define FSL_IMX6_PWM2_SIZE 0x4000
+#define FSL_IMX6_PWM1_ADDR 0x02080000
+#define FSL_IMX6_PWM1_SIZE 0x4000
+#define FSL_IMX6_AIPS1_CFG_ADDR 0x0207C000
+#define FSL_IMX6_AIPS1_CFG_SIZE 0x4000
+#define FSL_IMX6_VPU_ADDR 0x02040000
+#define FSL_IMX6_VPU_SIZE 0x3C000
+#define FSL_IMX6_AIPS1_SPBA_ADDR 0x0203C000
+#define FSL_IMX6_AIPS1_SPBA_SIZE 0x4000
+#define FSL_IMX6_ASRC_ADDR 0x02034000
+#define FSL_IMX6_ASRC_SIZE 0x4000
+#define FSL_IMX6_SSI3_ADDR 0x02030000
+#define FSL_IMX6_SSI3_SIZE 0x4000
+#define FSL_IMX6_SSI2_ADDR 0x0202C000
+#define FSL_IMX6_SSI2_SIZE 0x4000
+#define FSL_IMX6_SSI1_ADDR 0x02028000
+#define FSL_IMX6_SSI1_SIZE 0x4000
+#define FSL_IMX6_ESAI_ADDR 0x02024000
+#define FSL_IMX6_ESAI_SIZE 0x4000
+#define FSL_IMX6_UART1_ADDR 0x02020000
+#define FSL_IMX6_UART1_SIZE 0x4000
+#define FSL_IMX6_eCSPI5_ADDR 0x02018000
+#define FSL_IMX6_eCSPI5_SIZE 0x4000
+#define FSL_IMX6_eCSPI4_ADDR 0x02014000
+#define FSL_IMX6_eCSPI4_SIZE 0x4000
+#define FSL_IMX6_eCSPI3_ADDR 0x02010000
+#define FSL_IMX6_eCSPI3_SIZE 0x4000
+#define FSL_IMX6_eCSPI2_ADDR 0x0200C000
+#define FSL_IMX6_eCSPI2_SIZE 0x4000
+#define FSL_IMX6_eCSPI1_ADDR 0x02008000
+#define FSL_IMX6_eCSPI1_SIZE 0x4000
+#define FSL_IMX6_SPDIF_ADDR 0x02004000
+#define FSL_IMX6_SPDIF_SIZE 0x4000
+/* AIPS1 end */
+#define FSL_IMX6_PCIe_REG_ADDR 0x01FFC000
+#define FSL_IMX6_PCIe_REG_SIZE 0x4000
+#define FSL_IMX6_PCIe_ADDR 0x01000000
+#define FSL_IMX6_PCIe_SIZE 0xFFC000
+#define FSL_IMX6_GPV_1_PL301_CFG_ADDR 0x00C00000
+#define FSL_IMX6_GPV_1_PL301_CFG_SIZE 0x100000
+#define FSL_IMX6_GPV_0_PL301_CFG_ADDR 0x00B00000
+#define FSL_IMX6_GPV_0_PL301_CFG_SIZE 0x100000
+#define FSL_IMX6_PL310_ADDR 0x00A02000
+#define FSL_IMX6_PL310_SIZE 0x1000
+#define FSL_IMX6_A9MPCORE_ADDR 0x00A00000
+#define FSL_IMX6_A9MPCORE_SIZE 0x2000
+#define FSL_IMX6_OCRAM_ALIAS_ADDR 0x00940000
+#define FSL_IMX6_OCRAM_ALIAS_SIZE 0xC0000
+#define FSL_IMX6_OCRAM_ADDR 0x00900000
+#define FSL_IMX6_OCRAM_SIZE 0x40000
+#define FSL_IMX6_GPV_4_PL301_CFG_ADDR 0x00800000
+#define FSL_IMX6_GPV_4_PL301_CFG_SIZE 0x100000
+#define FSL_IMX6_GPV_3_PL301_CFG_ADDR 0x00300000
+#define FSL_IMX6_GPV_3_PL301_CFG_SIZE 0x100000
+#define FSL_IMX6_GPV_2_PL301_CFG_ADDR 0x00200000
+#define FSL_IMX6_GPV_2_PL301_CFG_SIZE 0x100000
+#define FSL_IMX6_DTCP_ADDR 0x00138000
+#define FSL_IMX6_DTCP_SIZE 0x4000
+#define FSL_IMX6_GPU_2D_ADDR 0x00134000
+#define FSL_IMX6_GPU_2D_SIZE 0x4000
+#define FSL_IMX6_GPU_3D_ADDR 0x00130000
+#define FSL_IMX6_GPU_3D_SIZE 0x4000
+#define FSL_IMX6_HDMI_ADDR 0x00120000
+#define FSL_IMX6_HDMI_SIZE 0x9000
+#define FSL_IMX6_BCH_ADDR 0x00114000
+#define FSL_IMX6_BCH_SIZE 0x4000
+#define FSL_IMX6_GPMI_ADDR 0x00112000
+#define FSL_IMX6_GPMI_SIZE 0x2000
+#define FSL_IMX6_APBH_BRIDGE_DMA_ADDR 0x00110000
+#define FSL_IMX6_APBH_BRIDGE_DMA_SIZE 0x2000
+#define FSL_IMX6_CAAM_MEM_ADDR 0x00100000
+#define FSL_IMX6_CAAM_MEM_SIZE 0x4000
+#define FSL_IMX6_ROM_ADDR 0x00000000
+#define FSL_IMX6_ROM_SIZE 0x18000
+
+#define FSL_IMX6_IOMUXC_IRQ 0
+#define FSL_IMX6_DAP_IRQ 1
+#define FSL_IMX6_SDMA_IRQ 2
+#define FSL_IMX6_VPU_JPEG_IRQ 3
+#define FSL_IMX6_SNVS_PMIC_IRQ 4
+#define FSL_IMX6_IPU1_ERROR_IRQ 5
+#define FSL_IMX6_IPU1_SYNC_IRQ 6
+#define FSL_IMX6_IPU2_ERROR_IRQ 7
+#define FSL_IMX6_IPU2_SYNC_IRQ 8
+#define FSL_IMX6_GPU3D_IRQ 9
+#define FSL_IMX6_R2D_IRQ 10
+#define FSL_IMX6_V2D_IRQ 11
+#define FSL_IMX6_VPU_IRQ 12
+#define FSL_IMX6_APBH_BRIDGE_DMA_IRQ 13
+#define FSL_IMX6_EIM_IRQ 14
+#define FSL_IMX6_BCH_IRQ 15
+#define FSL_IMX6_GPMI_IRQ 16
+#define FSL_IMX6_DTCP_IRQ 17
+#define FSL_IMX6_VDOA_IRQ 18
+#define FSL_IMX6_SNVS_CONS_IRQ 19
+#define FSL_IMX6_SNVS_SEC_IRQ 20
+#define FSL_IMX6_CSU_IRQ 21
+#define FSL_IMX6_uSDHC1_IRQ 22
+#define FSL_IMX6_uSDHC2_IRQ 23
+#define FSL_IMX6_uSDHC3_IRQ 24
+#define FSL_IMX6_uSDHC4_IRQ 25
+#define FSL_IMX6_UART1_IRQ 26
+#define FSL_IMX6_UART2_IRQ 27
+#define FSL_IMX6_UART3_IRQ 28
+#define FSL_IMX6_UART4_IRQ 29
+#define FSL_IMX6_UART5_IRQ 30
+#define FSL_IMX6_ECSPI1_IRQ 31
+#define FSL_IMX6_ECSPI2_IRQ 32
+#define FSL_IMX6_ECSPI3_IRQ 33
+#define FSL_IMX6_ECSPI4_IRQ 34
+#define FSL_IMX6_ECSPI5_IRQ 35
+#define FSL_IMX6_I2C1_IRQ 36
+#define FSL_IMX6_I2C2_IRQ 37
+#define FSL_IMX6_I2C3_IRQ 38
+#define FSL_IMX6_SATA_IRQ 39
+#define FSL_IMX6_USB_HOST1_IRQ 40
+#define FSL_IMX6_USB_HOST2_IRQ 41
+#define FSL_IMX6_USB_HOST3_IRQ 42
+#define FSL_IMX6_USB_OTG_IRQ 43
+#define FSL_IMX6_USB_PHY_UTMI0_IRQ 44
+#define FSL_IMX6_USB_PHY_UTMI1_IRQ 45
+#define FSL_IMX6_SSI1_IRQ 46
+#define FSL_IMX6_SSI2_IRQ 47
+#define FSL_IMX6_SSI3_IRQ 48
+#define FSL_IMX6_TEMP_IRQ 49
+#define FSL_IMX6_ASRC_IRQ 50
+#define FSL_IMX6_ESAI_IRQ 51
+#define FSL_IMX6_SPDIF_IRQ 52
+#define FSL_IMX6_MLB150_IRQ 53
+#define FSL_IMX6_PMU1_IRQ 54
+#define FSL_IMX6_GPT_IRQ 55
+#define FSL_IMX6_EPIT1_IRQ 56
+#define FSL_IMX6_EPIT2_IRQ 57
+#define FSL_IMX6_GPIO1_INT7_IRQ 58
+#define FSL_IMX6_GPIO1_INT6_IRQ 59
+#define FSL_IMX6_GPIO1_INT5_IRQ 60
+#define FSL_IMX6_GPIO1_INT4_IRQ 61
+#define FSL_IMX6_GPIO1_INT3_IRQ 62
+#define FSL_IMX6_GPIO1_INT2_IRQ 63
+#define FSL_IMX6_GPIO1_INT1_IRQ 64
+#define FSL_IMX6_GPIO1_INT0_IRQ 65
+#define FSL_IMX6_GPIO1_LOW_IRQ 66
+#define FSL_IMX6_GPIO1_HIGH_IRQ 67
+#define FSL_IMX6_GPIO2_LOW_IRQ 68
+#define FSL_IMX6_GPIO2_HIGH_IRQ 69
+#define FSL_IMX6_GPIO3_LOW_IRQ 70
+#define FSL_IMX6_GPIO3_HIGH_IRQ 71
+#define FSL_IMX6_GPIO4_LOW_IRQ 72
+#define FSL_IMX6_GPIO4_HIGH_IRQ 73
+#define FSL_IMX6_GPIO5_LOW_IRQ 74
+#define FSL_IMX6_GPIO5_HIGH_IRQ 75
+#define FSL_IMX6_GPIO6_LOW_IRQ 76
+#define FSL_IMX6_GPIO6_HIGH_IRQ 77
+#define FSL_IMX6_GPIO7_LOW_IRQ 78
+#define FSL_IMX6_GPIO7_HIGH_IRQ 79
+#define FSL_IMX6_WDOG1_IRQ 80
+#define FSL_IMX6_WDOG2_IRQ 81
+#define FSL_IMX6_KPP_IRQ 82
+#define FSL_IMX6_PWM1_IRQ 83
+#define FSL_IMX6_PWM2_IRQ 84
+#define FSL_IMX6_PWM3_IRQ 85
+#define FSL_IMX6_PWM4_IRQ 86
+#define FSL_IMX6_CCM1_IRQ 87
+#define FSL_IMX6_CCM2_IRQ 88
+#define FSL_IMX6_GPC_IRQ 89
+#define FSL_IMX6_SRC_IRQ 91
+#define FSL_IMX6_CPU_L2_IRQ 92
+#define FSL_IMX6_CPU_PARITY_IRQ 93
+#define FSL_IMX6_CPU_PERF_IRQ 94
+#define FSL_IMX6_CPU_CTI_IRQ 95
+#define FSL_IMX6_SRC_COMB_IRQ 96
+#define FSL_IMX6_MIPI_CSI1_IRQ 100
+#define FSL_IMX6_MIPI_CSI2_IRQ 101
+#define FSL_IMX6_MIPI_DSI_IRQ 102
+#define FSL_IMX6_MIPI_HSI_IRQ 103
+#define FSL_IMX6_SJC_IRQ 104
+#define FSL_IMX6_CAAM0_IRQ 105
+#define FSL_IMX6_CAAM1_IRQ 106
+#define FSL_IMX6_ASC1_IRQ 108
+#define FSL_IMX6_ASC2_IRQ 109
+#define FSL_IMX6_FLEXCAN1_IRQ 110
+#define FSL_IMX6_FLEXCAN2_IRQ 111
+#define FSL_IMX6_HDMI_MASTER_IRQ 115
+#define FSL_IMX6_HDMI_CEC_IRQ 116
+#define FSL_IMX6_MLB150_LOW_IRQ 117
+#define FSL_IMX6_ENET_MAC_IRQ 118
+#define FSL_IMX6_ENET_MAC_1588_IRQ 119
+#define FSL_IMX6_PCIE1_IRQ 120
+#define FSL_IMX6_PCIE2_IRQ 121
+#define FSL_IMX6_PCIE3_IRQ 122
+#define FSL_IMX6_PCIE4_IRQ 123
+#define FSL_IMX6_DCIC1_IRQ 124
+#define FSL_IMX6_DCIC2_IRQ 125
+#define FSL_IMX6_MLB150_HIGH_IRQ 126
+#define FSL_IMX6_PMU2_IRQ 127
+#define FSL_IMX6_MAX_IRQ 128
+
+#endif /* FSL_IMX6_H */
diff --git a/include/hw/arm/fsl-imx6ul.h b/include/hw/arm/fsl-imx6ul.h
new file mode 100644
index 000000000..7812e516a
--- /dev/null
+++ b/include/hw/arm/fsl-imx6ul.h
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2018 Jean-Christophe Dubois <jcd@tribudubois.net>
+ *
+ * i.MX6ul SoC definitions
+ *
+ * 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 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"
+#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/usb/chipidea.h"
+#include "hw/usb/imx-usb-phy.h"
+#include "exec/memory.h"
+#include "cpu.h"
+#include "qom/object.h"
+
+#define TYPE_FSL_IMX6UL "fsl-imx6ul"
+OBJECT_DECLARE_SIMPLE_TYPE(FslIMX6ULState, FSL_IMX6UL)
+
+enum FslIMX6ULConfiguration {
+ FSL_IMX6UL_NUM_CPUS = 1,
+ FSL_IMX6UL_NUM_UARTS = 8,
+ FSL_IMX6UL_NUM_ETHS = 2,
+ FSL_IMX6UL_ETH_NUM_TX_RINGS = 2,
+ FSL_IMX6UL_NUM_USDHCS = 2,
+ FSL_IMX6UL_NUM_WDTS = 3,
+ FSL_IMX6UL_NUM_GPTS = 2,
+ FSL_IMX6UL_NUM_EPITS = 2,
+ FSL_IMX6UL_NUM_IOMUXCS = 2,
+ FSL_IMX6UL_NUM_GPIOS = 5,
+ FSL_IMX6UL_NUM_I2CS = 4,
+ FSL_IMX6UL_NUM_ECSPIS = 4,
+ FSL_IMX6UL_NUM_ADCS = 2,
+ FSL_IMX6UL_NUM_USB_PHYS = 2,
+ FSL_IMX6UL_NUM_USBS = 2,
+};
+
+struct FslIMX6ULState {
+ /*< private >*/
+ DeviceState parent_obj;
+
+ /*< public >*/
+ ARMCPU cpu;
+ A15MPPrivState a7mpcore;
+ IMXGPTState gpt[FSL_IMX6UL_NUM_GPTS];
+ IMXEPITState epit[FSL_IMX6UL_NUM_EPITS];
+ IMXGPIOState gpio[FSL_IMX6UL_NUM_GPIOS];
+ IMX6ULCCMState ccm;
+ 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];
+ IMXFECState eth[FSL_IMX6UL_NUM_ETHS];
+ SDHCIState usdhc[FSL_IMX6UL_NUM_USDHCS];
+ IMX2WdtState wdt[FSL_IMX6UL_NUM_WDTS];
+ IMXUSBPHYState usbphy[FSL_IMX6UL_NUM_USB_PHYS];
+ ChipideaState usb[FSL_IMX6UL_NUM_USBS];
+ MemoryRegion rom;
+ MemoryRegion caam;
+ MemoryRegion ocram;
+ MemoryRegion ocram_alias;
+
+ uint32_t phy_num[FSL_IMX6UL_NUM_ETHS];
+};
+
+enum FslIMX6ULMemoryMap {
+ FSL_IMX6UL_MMDC_ADDR = 0x80000000,
+ FSL_IMX6UL_MMDC_SIZE = 2 * 1024 * 1024 * 1024UL,
+
+ FSL_IMX6UL_QSPI1_MEM_ADDR = 0x60000000,
+ FSL_IMX6UL_EIM_ALIAS_ADDR = 0x58000000,
+ FSL_IMX6UL_EIM_CS_ADDR = 0x50000000,
+ FSL_IMX6UL_AES_ENCRYPT_ADDR = 0x10000000,
+ FSL_IMX6UL_QSPI1_RX_ADDR = 0x0C000000,
+
+ /* AIPS-2 */
+ 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_SYS_CNT_CTRL_ADDR = 0x021DC000,
+ FSL_IMX6UL_SYS_CNT_CMP_ADDR = 0x021D8000,
+ FSL_IMX6UL_SYS_CNT_RD_ADDR = 0x021D4000,
+ FSL_IMX6UL_TZASC_ADDR = 0x021D0000,
+ FSL_IMX6UL_PXP_ADDR = 0x021CC000,
+ FSL_IMX6UL_LCDIF_ADDR = 0x021C8000,
+ FSL_IMX6UL_CSI_ADDR = 0x021C4000,
+ FSL_IMX6UL_CSU_ADDR = 0x021C0000,
+ FSL_IMX6UL_OCOTP_CTRL_ADDR = 0x021BC000,
+ FSL_IMX6UL_EIM_ADDR = 0x021B8000,
+ FSL_IMX6UL_SIM2_ADDR = 0x021B4000,
+ FSL_IMX6UL_MMDC_CFG_ADDR = 0x021B0000,
+ FSL_IMX6UL_ROMCP_ADDR = 0x021AC000,
+ 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_USDHC2_ADDR = 0x02194000,
+ FSL_IMX6UL_USDHC1_ADDR = 0x02190000,
+ FSL_IMX6UL_SIM1_ADDR = 0x0218C000,
+ FSL_IMX6UL_ENET1_ADDR = 0x02188000,
+ FSL_IMX6UL_USBO2_USBMISC_ADDR = 0x02184800,
+ FSL_IMX6UL_USBO2_USB_ADDR = 0x02184000,
+ FSL_IMX6UL_USBO2_PL301_ADDR = 0x02180000,
+ FSL_IMX6UL_AIPS2_CFG_ADDR = 0x0217C000,
+ FSL_IMX6UL_CAAM_ADDR = 0x02140000,
+ FSL_IMX6UL_A7MPCORE_DAP_ADDR = 0x02100000,
+
+ /* AIPS-1 */
+ 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_GPT2_ADDR = 0x020E8000,
+ FSL_IMX6UL_IOMUXC_GPR_ADDR = 0x020E4000,
+ FSL_IMX6UL_IOMUXC_ADDR = 0x020E0000,
+ 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_CCM_ADDR = 0x020C4000,
+ FSL_IMX6UL_WDOG2_ADDR = 0x020C0000,
+ FSL_IMX6UL_WDOG1_ADDR = 0x020BC000,
+ FSL_IMX6UL_KPP_ADDR = 0x020B8000,
+ FSL_IMX6UL_ENET2_ADDR = 0x020B4000,
+ FSL_IMX6UL_SNVS_LP_ADDR = 0x020B0000,
+ 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_PWM4_ADDR = 0x0208C000,
+ FSL_IMX6UL_PWM3_ADDR = 0x02088000,
+ FSL_IMX6UL_PWM2_ADDR = 0x02084000,
+ FSL_IMX6UL_PWM1_ADDR = 0x02080000,
+ FSL_IMX6UL_AIPS1_CFG_ADDR = 0x0207C000,
+ FSL_IMX6UL_BEE_ADDR = 0x02044000,
+ FSL_IMX6UL_TOUCH_CTRL_ADDR = 0x02040000,
+ FSL_IMX6UL_SPBA_ADDR = 0x0203C000,
+ FSL_IMX6UL_ASRC_ADDR = 0x02034000,
+ FSL_IMX6UL_SAI3_ADDR = 0x02030000,
+ FSL_IMX6UL_SAI2_ADDR = 0x0202C000,
+ FSL_IMX6UL_SAI1_ADDR = 0x02028000,
+ 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_APBH_DMA_ADDR = 0x01804000,
+ FSL_IMX6UL_APBH_DMA_SIZE = (32 * 1024),
+
+ FSL_IMX6UL_A7MPCORE_ADDR = 0x00A00000,
+
+ FSL_IMX6UL_OCRAM_ALIAS_ADDR = 0x00920000,
+ FSL_IMX6UL_OCRAM_ALIAS_SIZE = 0x00060000,
+ FSL_IMX6UL_OCRAM_MEM_ADDR = 0x00900000,
+ FSL_IMX6UL_OCRAM_MEM_SIZE = 0x00020000,
+ FSL_IMX6UL_CAAM_MEM_ADDR = 0x00100000,
+ FSL_IMX6UL_CAAM_MEM_SIZE = 0x00008000,
+ FSL_IMX6UL_ROM_ADDR = 0x00000000,
+ FSL_IMX6UL_ROM_SIZE = 0x00018000,
+};
+
+enum FslIMX6ULIRQs {
+ FSL_IMX6UL_IOMUXC_IRQ = 0,
+ FSL_IMX6UL_DAP_IRQ = 1,
+ FSL_IMX6UL_SDMA_IRQ = 2,
+ FSL_IMX6UL_TSC_IRQ = 3,
+ FSL_IMX6UL_SNVS_IRQ = 4,
+ FSL_IMX6UL_LCDIF_IRQ = 5,
+ FSL_IMX6UL_BEE_IRQ = 6,
+ FSL_IMX6UL_CSI_IRQ = 7,
+ FSL_IMX6UL_PXP_IRQ = 8,
+ FSL_IMX6UL_SCTR1_IRQ = 9,
+ FSL_IMX6UL_SCTR2_IRQ = 10,
+ FSL_IMX6UL_WDOG3_IRQ = 11,
+ FSL_IMX6UL_APBH_DMA_IRQ = 13,
+ FSL_IMX6UL_WEIM_IRQ = 14,
+ FSL_IMX6UL_RAWNAND1_IRQ = 15,
+ FSL_IMX6UL_RAWNAND2_IRQ = 16,
+ FSL_IMX6UL_UART6_IRQ = 17,
+ FSL_IMX6UL_SRTC_IRQ = 19,
+ FSL_IMX6UL_SRTC_SEC_IRQ = 20,
+ FSL_IMX6UL_CSU_IRQ = 21,
+ FSL_IMX6UL_USDHC1_IRQ = 22,
+ FSL_IMX6UL_USDHC2_IRQ = 23,
+ FSL_IMX6UL_SAI3_IRQ = 24,
+ FSL_IMX6UL_SAI32_IRQ = 25,
+
+ FSL_IMX6UL_UART1_IRQ = 26,
+ FSL_IMX6UL_UART2_IRQ = 27,
+ FSL_IMX6UL_UART3_IRQ = 28,
+ FSL_IMX6UL_UART4_IRQ = 29,
+ FSL_IMX6UL_UART5_IRQ = 30,
+
+ FSL_IMX6UL_ECSPI1_IRQ = 31,
+ FSL_IMX6UL_ECSPI2_IRQ = 32,
+ FSL_IMX6UL_ECSPI3_IRQ = 33,
+ FSL_IMX6UL_ECSPI4_IRQ = 34,
+
+ FSL_IMX6UL_I2C4_IRQ = 35,
+ FSL_IMX6UL_I2C1_IRQ = 36,
+ FSL_IMX6UL_I2C2_IRQ = 37,
+ FSL_IMX6UL_I2C3_IRQ = 38,
+
+ FSL_IMX6UL_UART7_IRQ = 39,
+ FSL_IMX6UL_UART8_IRQ = 40,
+
+ FSL_IMX6UL_USB1_IRQ = 43,
+ FSL_IMX6UL_USB2_IRQ = 42,
+ FSL_IMX6UL_USB_PHY1_IRQ = 44,
+ FSL_IMX6UL_USB_PHY2_IRQ = 45,
+
+ FSL_IMX6UL_CAAM_JQ2_IRQ = 46,
+ FSL_IMX6UL_CAAM_ERR_IRQ = 47,
+ FSL_IMX6UL_CAAM_RTIC_IRQ = 48,
+ FSL_IMX6UL_TEMP_IRQ = 49,
+ FSL_IMX6UL_ASRC_IRQ = 50,
+ FSL_IMX6UL_SPDIF_IRQ = 52,
+ FSL_IMX6UL_PMU_REG_IRQ = 54,
+ FSL_IMX6UL_GPT1_IRQ = 55,
+
+ FSL_IMX6UL_EPIT1_IRQ = 56,
+ FSL_IMX6UL_EPIT2_IRQ = 57,
+
+ FSL_IMX6UL_GPIO1_INT7_IRQ = 58,
+ FSL_IMX6UL_GPIO1_INT6_IRQ = 59,
+ FSL_IMX6UL_GPIO1_INT5_IRQ = 60,
+ FSL_IMX6UL_GPIO1_INT4_IRQ = 61,
+ FSL_IMX6UL_GPIO1_INT3_IRQ = 62,
+ FSL_IMX6UL_GPIO1_INT2_IRQ = 63,
+ FSL_IMX6UL_GPIO1_INT1_IRQ = 64,
+ FSL_IMX6UL_GPIO1_INT0_IRQ = 65,
+ FSL_IMX6UL_GPIO1_LOW_IRQ = 66,
+ FSL_IMX6UL_GPIO1_HIGH_IRQ = 67,
+ FSL_IMX6UL_GPIO2_LOW_IRQ = 68,
+ FSL_IMX6UL_GPIO2_HIGH_IRQ = 69,
+ FSL_IMX6UL_GPIO3_LOW_IRQ = 70,
+ FSL_IMX6UL_GPIO3_HIGH_IRQ = 71,
+ FSL_IMX6UL_GPIO4_LOW_IRQ = 72,
+ FSL_IMX6UL_GPIO4_HIGH_IRQ = 73,
+ FSL_IMX6UL_GPIO5_LOW_IRQ = 74,
+ FSL_IMX6UL_GPIO5_HIGH_IRQ = 75,
+
+ FSL_IMX6UL_WDOG1_IRQ = 80,
+ FSL_IMX6UL_WDOG2_IRQ = 81,
+
+ FSL_IMX6UL_KPP_IRQ = 82,
+
+ FSL_IMX6UL_PWM1_IRQ = 83,
+ FSL_IMX6UL_PWM2_IRQ = 84,
+ FSL_IMX6UL_PWM3_IRQ = 85,
+ FSL_IMX6UL_PWM4_IRQ = 86,
+
+ FSL_IMX6UL_CCM1_IRQ = 87,
+ FSL_IMX6UL_CCM2_IRQ = 88,
+
+ FSL_IMX6UL_GPC_IRQ = 89,
+
+ FSL_IMX6UL_SRC_IRQ = 91,
+
+ FSL_IMX6UL_CPU_PERF_IRQ = 94,
+ FSL_IMX6UL_CPU_CTI_IRQ = 95,
+
+ FSL_IMX6UL_SRC_WDOG_IRQ = 96,
+
+ FSL_IMX6UL_SAI1_IRQ = 97,
+ FSL_IMX6UL_SAI2_IRQ = 98,
+
+ FSL_IMX6UL_ADC1_IRQ = 100,
+ FSL_IMX6UL_ADC2_IRQ = 101,
+
+ FSL_IMX6UL_SJC_IRQ = 104,
+
+ FSL_IMX6UL_CAAM_RING0_IRQ = 105,
+ FSL_IMX6UL_CAAM_RING1_IRQ = 106,
+
+ FSL_IMX6UL_QSPI_IRQ = 107,
+
+ FSL_IMX6UL_TZASC_IRQ = 108,
+
+ FSL_IMX6UL_GPT2_IRQ = 109,
+
+ FSL_IMX6UL_CAN1_IRQ = 110,
+ FSL_IMX6UL_CAN2_IRQ = 111,
+
+ FSL_IMX6UL_SIM1_IRQ = 112,
+ FSL_IMX6UL_SIM2_IRQ = 113,
+
+ FSL_IMX6UL_PWM5_IRQ = 114,
+ FSL_IMX6UL_PWM6_IRQ = 115,
+ FSL_IMX6UL_PWM7_IRQ = 116,
+ FSL_IMX6UL_PWM8_IRQ = 117,
+
+ FSL_IMX6UL_ENET1_IRQ = 118,
+ FSL_IMX6UL_ENET1_TIMER_IRQ = 119,
+ FSL_IMX6UL_ENET2_IRQ = 120,
+ FSL_IMX6UL_ENET2_TIMER_IRQ = 121,
+
+ FSL_IMX6UL_PMU_CORE_IRQ = 127,
+ FSL_IMX6UL_MAX_IRQ = 128,
+};
+
+#endif /* FSL_IMX6UL_H */
diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h
new file mode 100644
index 000000000..1c5fa6fd6
--- /dev/null
+++ b/include/hw/arm/fsl-imx7.h
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2018, Impinj, Inc.
+ *
+ * i.MX7 SoC definitions
+ *
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.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 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/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"
+
+#define TYPE_FSL_IMX7 "fsl-imx7"
+OBJECT_DECLARE_SIMPLE_TYPE(FslIMX7State, FSL_IMX7)
+
+enum FslIMX7Configuration {
+ FSL_IMX7_NUM_CPUS = 2,
+ FSL_IMX7_NUM_UARTS = 7,
+ FSL_IMX7_NUM_ETHS = 2,
+ FSL_IMX7_ETH_NUM_TX_RINGS = 3,
+ FSL_IMX7_NUM_USDHCS = 3,
+ FSL_IMX7_NUM_WDTS = 4,
+ FSL_IMX7_NUM_GPTS = 4,
+ FSL_IMX7_NUM_IOMUXCS = 2,
+ FSL_IMX7_NUM_GPIOS = 7,
+ FSL_IMX7_NUM_I2CS = 4,
+ FSL_IMX7_NUM_ECSPIS = 4,
+ FSL_IMX7_NUM_USBS = 3,
+ FSL_IMX7_NUM_ADCS = 2,
+};
+
+struct FslIMX7State {
+ /*< private >*/
+ DeviceState parent_obj;
+
+ /*< public >*/
+ ARMCPU cpu[FSL_IMX7_NUM_CPUS];
+ A15MPPrivState a7mpcore;
+ IMXGPTState gpt[FSL_IMX7_NUM_GPTS];
+ IMXGPIOState gpio[FSL_IMX7_NUM_GPIOS];
+ IMX7CCMState ccm;
+ IMX7AnalogState analog;
+ IMX7SNVSState snvs;
+ IMXGPCv2State gpcv2;
+ IMXSPIState spi[FSL_IMX7_NUM_ECSPIS];
+ IMXI2CState i2c[FSL_IMX7_NUM_I2CS];
+ IMXSerialState uart[FSL_IMX7_NUM_UARTS];
+ IMXFECState eth[FSL_IMX7_NUM_ETHS];
+ SDHCIState usdhc[FSL_IMX7_NUM_USDHCS];
+ IMX2WdtState wdt[FSL_IMX7_NUM_WDTS];
+ IMX7GPRState gpr;
+ ChipideaState usb[FSL_IMX7_NUM_USBS];
+ DesignwarePCIEHost pcie;
+ uint32_t phy_num[FSL_IMX7_NUM_ETHS];
+};
+
+enum FslIMX7MemoryMap {
+ FSL_IMX7_MMDC_ADDR = 0x80000000,
+ FSL_IMX7_MMDC_SIZE = 2 * 1024 * 1024 * 1024UL,
+
+ 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_IOMUXC_LPSR_GPR_ADDR = 0x30270000,
+
+ FSL_IMX7_WDOG1_ADDR = 0x30280000,
+ FSL_IMX7_WDOG2_ADDR = 0x30290000,
+ FSL_IMX7_WDOG3_ADDR = 0x302A0000,
+ FSL_IMX7_WDOG4_ADDR = 0x302B0000,
+
+ FSL_IMX7_IOMUXC_LPSR_ADDR = 0x302C0000,
+
+ FSL_IMX7_GPT1_ADDR = 0x302D0000,
+ FSL_IMX7_GPT2_ADDR = 0x302E0000,
+ FSL_IMX7_GPT3_ADDR = 0x302F0000,
+ FSL_IMX7_GPT4_ADDR = 0x30300000,
+
+ FSL_IMX7_IOMUXC_ADDR = 0x30330000,
+ FSL_IMX7_IOMUXC_GPR_ADDR = 0x30340000,
+ FSL_IMX7_IOMUXCn_SIZE = 0x1000,
+
+ FSL_IMX7_OCOTP_ADDR = 0x30350000,
+ FSL_IMX7_OCOTP_SIZE = 0x10000,
+
+ FSL_IMX7_ANALOG_ADDR = 0x30360000,
+ FSL_IMX7_SNVS_ADDR = 0x30370000,
+ FSL_IMX7_CCM_ADDR = 0x30380000,
+
+ FSL_IMX7_SRC_ADDR = 0x30390000,
+ FSL_IMX7_SRC_SIZE = 0x1000,
+
+ FSL_IMX7_ADC1_ADDR = 0x30610000,
+ FSL_IMX7_ADC2_ADDR = 0x30620000,
+ FSL_IMX7_ADCn_SIZE = 0x1000,
+
+ 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_PCIE_PHY_ADDR = 0x306D0000,
+ FSL_IMX7_PCIE_PHY_SIZE = 0x10000,
+
+ FSL_IMX7_GPC_ADDR = 0x303A0000,
+
+ FSL_IMX7_CAAM_ADDR = 0x30900000,
+ FSL_IMX7_CAAM_SIZE = 0x40000,
+
+ FSL_IMX7_CAN1_ADDR = 0x30A00000,
+ FSL_IMX7_CAN2_ADDR = 0x30A10000,
+ FSL_IMX7_CANn_SIZE = 0x10000,
+
+ FSL_IMX7_I2C1_ADDR = 0x30A20000,
+ FSL_IMX7_I2C2_ADDR = 0x30A30000,
+ FSL_IMX7_I2C3_ADDR = 0x30A40000,
+ FSL_IMX7_I2C4_ADDR = 0x30A50000,
+
+ FSL_IMX7_ECSPI1_ADDR = 0x30820000,
+ FSL_IMX7_ECSPI2_ADDR = 0x30830000,
+ FSL_IMX7_ECSPI3_ADDR = 0x30840000,
+ FSL_IMX7_ECSPI4_ADDR = 0x30630000,
+
+ FSL_IMX7_LCDIF_ADDR = 0x30730000,
+ FSL_IMX7_LCDIF_SIZE = 0x1000,
+
+ FSL_IMX7_UART1_ADDR = 0x30860000,
+ /*
+ * 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
+ */
+ 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_SAI1_ADDR = 0x308A0000,
+ FSL_IMX7_SAI2_ADDR = 0x308B0000,
+ FSL_IMX7_SAI3_ADDR = 0x308C0000,
+ FSL_IMX7_SAIn_SIZE = 0x10000,
+
+ FSL_IMX7_ENET1_ADDR = 0x30BE0000,
+ FSL_IMX7_ENET2_ADDR = 0x30BF0000,
+
+ 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,
+
+ FSL_IMX7_USDHC1_ADDR = 0x30B40000,
+ FSL_IMX7_USDHC2_ADDR = 0x30B50000,
+ FSL_IMX7_USDHC3_ADDR = 0x30B60000,
+
+ FSL_IMX7_SDMA_ADDR = 0x30BD0000,
+ FSL_IMX7_SDMA_SIZE = 0x1000,
+
+ FSL_IMX7_A7MPCORE_ADDR = 0x31000000,
+ FSL_IMX7_A7MPCORE_DAP_ADDR = 0x30000000,
+
+ FSL_IMX7_PCIE_REG_ADDR = 0x33800000,
+ FSL_IMX7_PCIE_REG_SIZE = 16 * 1024,
+
+ FSL_IMX7_GPR_ADDR = 0x30340000,
+
+ FSL_IMX7_DMA_APBH_ADDR = 0x33000000,
+ FSL_IMX7_DMA_APBH_SIZE = 0x2000,
+};
+
+enum FslIMX7IRQs {
+ FSL_IMX7_USDHC1_IRQ = 22,
+ FSL_IMX7_USDHC2_IRQ = 23,
+ FSL_IMX7_USDHC3_IRQ = 24,
+
+ FSL_IMX7_UART1_IRQ = 26,
+ FSL_IMX7_UART2_IRQ = 27,
+ FSL_IMX7_UART3_IRQ = 28,
+ FSL_IMX7_UART4_IRQ = 29,
+ FSL_IMX7_UART5_IRQ = 30,
+ FSL_IMX7_UART6_IRQ = 16,
+
+ FSL_IMX7_ECSPI1_IRQ = 31,
+ FSL_IMX7_ECSPI2_IRQ = 32,
+ FSL_IMX7_ECSPI3_IRQ = 33,
+ FSL_IMX7_ECSPI4_IRQ = 34,
+
+ FSL_IMX7_I2C1_IRQ = 35,
+ FSL_IMX7_I2C2_IRQ = 36,
+ FSL_IMX7_I2C3_IRQ = 37,
+ FSL_IMX7_I2C4_IRQ = 38,
+
+ FSL_IMX7_USB1_IRQ = 43,
+ FSL_IMX7_USB2_IRQ = 42,
+ FSL_IMX7_USB3_IRQ = 40,
+
+ FSL_IMX7_WDOG1_IRQ = 78,
+ FSL_IMX7_WDOG2_IRQ = 79,
+ FSL_IMX7_WDOG3_IRQ = 10,
+ FSL_IMX7_WDOG4_IRQ = 109,
+
+ FSL_IMX7_PCI_INTA_IRQ = 125,
+ FSL_IMX7_PCI_INTB_IRQ = 124,
+ FSL_IMX7_PCI_INTC_IRQ = 123,
+ FSL_IMX7_PCI_INTD_IRQ = 122,
+
+ FSL_IMX7_UART7_IRQ = 126,
+
+#define FSL_IMX7_ENET_IRQ(i, n) ((n) + ((i) ? 100 : 118))
+
+ FSL_IMX7_MAX_IRQ = 128,
+};
+
+#endif /* FSL_IMX7_H */
diff --git a/include/hw/arm/linux-boot-if.h b/include/hw/arm/linux-boot-if.h
new file mode 100644
index 000000000..c85f33b2c
--- /dev/null
+++ b/include/hw/arm/linux-boot-if.h
@@ -0,0 +1,39 @@
+/*
+ * hw/arm/linux-boot-if.h : interface for devices which need to behave
+ * specially for direct boot of an ARM Linux kernel
+ */
+
+#ifndef HW_ARM_LINUX_BOOT_IF_H
+#define HW_ARM_LINUX_BOOT_IF_H
+
+#include "qom/object.h"
+
+#define TYPE_ARM_LINUX_BOOT_IF "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;
+
+struct ARMLinuxBootIfClass {
+ /*< private >*/
+ InterfaceClass parent_class;
+
+ /*< public >*/
+ /** arm_linux_init: configure the device for a direct boot
+ * of an ARM Linux kernel (so that device reset puts it into
+ * the state the kernel expects after firmware initialization,
+ * rather than the true hardware reset state). This callback is
+ * called once after machine construction is complete (before the
+ * first system reset).
+ *
+ * @obj: the object implementing this interface
+ * @secure_boot: true if we are booting Secure, false for NonSecure
+ * (or for a CPU which doesn't support TrustZone)
+ */
+ void (*arm_linux_init)(ARMLinuxBootIf *obj, bool secure_boot);
+};
+
+#endif
diff --git a/include/hw/arm/msf2-soc.h b/include/hw/arm/msf2-soc.h
new file mode 100644
index 000000000..ce417a626
--- /dev/null
+++ b/include/hw/arm/msf2-soc.h
@@ -0,0 +1,76 @@
+/*
+ * Microsemi Smartfusion2 SoC
+ *
+ * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@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.
+ */
+
+#ifndef HW_ARM_MSF2_SOC_H
+#define HW_ARM_MSF2_SOC_H
+
+#include "hw/arm/armv7m.h"
+#include "hw/timer/mss-timer.h"
+#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"
+OBJECT_DECLARE_SIMPLE_TYPE(MSF2State, MSF2_SOC)
+
+#define MSF2_NUM_SPIS 2
+#define MSF2_NUM_UARTS 2
+
+/*
+ * System timer consists of two programmable 32-bit
+ * decrementing counters that generate individual interrupts to
+ * the Cortex-M3 processor
+ */
+#define MSF2_NUM_TIMERS 2
+
+struct MSF2State {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ ARMv7MState armv7m;
+
+ char *cpu_type;
+ char *part_name;
+ uint64_t envm_size;
+ uint64_t esram_size;
+
+ Clock *m3clk;
+ Clock *refclk;
+ uint8_t apb0div;
+ uint8_t apb1div;
+
+ MSF2SysregState sysreg;
+ MSSTimerState timer;
+ MSSSpiState spi[MSF2_NUM_SPIS];
+ MSF2EmacState emac;
+
+ 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 000000000..ce593235d
--- /dev/null
+++ b/include/hw/arm/npcm7xx.h
@@ -0,0 +1,141 @@
+/*
+ * 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/nvram/npcm7xx_otp.h"
+#include "hw/timer/npcm7xx_timer.h"
+#include "hw/ssi/npcm7xx_fiu.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
+
+typedef 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];
+} NPCM7xxMachine;
+
+#define TYPE_NPCM7XX_MACHINE MACHINE_TYPE_NAME("npcm7xx")
+#define NPCM7XX_MACHINE(obj) \
+ OBJECT_CHECK(NPCM7xxMachine, (obj), TYPE_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)
+
+typedef 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];
+ NPCM7xxSDHCIState mmc;
+} NPCM7xxState;
+
+#define TYPE_NPCM7XX "npcm7xx"
+#define NPCM7XX(obj) OBJECT_CHECK(NPCM7xxState, (obj), TYPE_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;
+
+#define NPCM7XX_CLASS(klass) \
+ OBJECT_CLASS_CHECK(NPCM7xxClass, (klass), TYPE_NPCM7XX)
+#define NPCM7XX_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(NPCM7xxClass, (obj), TYPE_NPCM7XX)
+
+/**
+ * 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.h b/include/hw/arm/nrf51.h
new file mode 100644
index 000000000..de836beaa
--- /dev/null
+++ b/include/hw/arm/nrf51.h
@@ -0,0 +1,46 @@
+/*
+ * Nordic Semiconductor nRF51 Series SOC Common Defines
+ *
+ * This file hosts generic defines used in various nRF51 peripheral devices.
+ *
+ * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
+ * Product Spec: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.1.pdf
+ *
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
+ *
+ * This code is licensed under the GPL version 2 or later. See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef NRF51_H
+#define NRF51_H
+
+#define NRF51_FLASH_BASE 0x00000000
+#define NRF51_FICR_BASE 0x10000000
+#define NRF51_FICR_SIZE 0x00000100
+#define NRF51_UICR_BASE 0x10001000
+#define NRF51_SRAM_BASE 0x20000000
+
+#define NRF51_IOMEM_BASE 0x40000000
+#define NRF51_IOMEM_SIZE 0x20000000
+
+#define NRF51_PERIPHERAL_SIZE 0x00001000
+#define NRF51_UART_BASE 0x40002000
+#define NRF51_TWI_BASE 0x40003000
+#define NRF51_TIMER_BASE 0x40008000
+#define NRF51_RNG_BASE 0x4000D000
+#define NRF51_NVMC_BASE 0x4001E000
+#define NRF51_GPIO_BASE 0x50000000
+
+#define NRF51_PRIVATE_BASE 0xF0000000
+#define NRF51_PRIVATE_SIZE 0x10000000
+
+#define NRF51_PAGE_SIZE 1024
+
+/* Trigger */
+#define NRF51_TRIGGER_TASK 0x01
+
+/* Events */
+#define NRF51_EVENT_CLEAR 0x00
+
+#endif
diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
new file mode 100644
index 000000000..e52a56e75
--- /dev/null
+++ b/include/hw/arm/nrf51_soc.h
@@ -0,0 +1,57 @@
+/*
+ * Nordic Semiconductor nRF51 SoC
+ *
+ * Copyright 2018 Joel Stanley <joel@jms.id.au>
+ *
+ * This code is licensed under the GPL version 2 or later. See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef NRF51_SOC_H
+#define NRF51_SOC_H
+
+#include "hw/sysbus.h"
+#include "hw/arm/armv7m.h"
+#include "hw/char/nrf51_uart.h"
+#include "hw/misc/nrf51_rng.h"
+#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"
+OBJECT_DECLARE_SIMPLE_TYPE(NRF51State, NRF51_SOC)
+
+#define NRF51_NUM_TIMERS 3
+
+struct NRF51State {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ ARMv7MState cpu;
+
+ NRF51UARTState uart;
+ NRF51RNGState rng;
+ NRF51NVMState nvm;
+ NRF51GPIOState gpio;
+ NRF51TimerState timer[NRF51_NUM_TIMERS];
+
+ MemoryRegion iomem;
+ MemoryRegion sram;
+ MemoryRegion flash;
+ MemoryRegion clock;
+ MemoryRegion twi;
+
+ uint32_t sram_size;
+ uint32_t flash_size;
+
+ MemoryRegion *board_memory;
+
+ MemoryRegion container;
+
+ Clock *sysclk;
+};
+
+#endif
diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h
new file mode 100644
index 000000000..ff6a173f8
--- /dev/null
+++ b/include/hw/arm/omap.h
@@ -0,0 +1,1043 @@
+/*
+ * Texas Instruments OMAP processors.
+ *
+ * Copyright (C) 2006-2008 Andrzej Zaborowski <balrog@zabor.org>
+ *
+ * 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_ARM_OMAP_H
+#define HW_ARM_OMAP_H
+
+#include "exec/memory.h"
+#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
+# define OMAP_CS0_BASE 0x00000000
+# define OMAP_CS1_BASE 0x04000000
+# define OMAP_CS2_BASE 0x08000000
+# define OMAP_CS3_BASE 0x0c000000
+# define OMAP_EMIFF_BASE 0x10000000
+# define OMAP_IMIF_BASE 0x20000000
+# define OMAP_LOCALBUS_BASE 0x30000000
+# define OMAP2_Q1_BASE 0x40000000
+# define OMAP2_L4_BASE 0x48000000
+# define OMAP2_SRAM_BASE 0x40200000
+# define OMAP2_L3_BASE 0x68000000
+# define OMAP2_Q2_BASE 0x80000000
+# define OMAP2_Q3_BASE 0xc0000000
+# define OMAP_MPUI_BASE 0xe1000000
+
+# define OMAP730_SRAM_SIZE 0x00032000
+# define OMAP15XX_SRAM_SIZE 0x00030000
+# define OMAP16XX_SRAM_SIZE 0x00004000
+# define OMAP1611_SRAM_SIZE 0x0003e800
+# define OMAP242X_SRAM_SIZE 0x000a0000
+# define OMAP243X_SRAM_SIZE 0x00010000
+# define OMAP_CS0_SIZE 0x04000000
+# define OMAP_CS1_SIZE 0x04000000
+# define OMAP_CS2_SIZE 0x04000000
+# define OMAP_CS3_SIZE 0x04000000
+
+/* omap_clk.c */
+struct omap_mpu_state_s;
+typedef struct clk *omap_clk;
+omap_clk omap_findclk(struct omap_mpu_state_s *mpu, const char *name);
+void omap_clk_init(struct omap_mpu_state_s *mpu);
+void omap_clk_adduser(struct clk *clk, qemu_irq user);
+void omap_clk_get(omap_clk clk);
+void omap_clk_put(omap_clk clk);
+void omap_clk_onoff(omap_clk clk, int on);
+void omap_clk_canidle(omap_clk clk, int can);
+void omap_clk_setrate(omap_clk clk, int divide, int multiply);
+int64_t omap_clk_getrate(omap_clk clk);
+void omap_clk_reparent(omap_clk clk, omap_clk parent);
+
+/* omap_intc.c */
+#define TYPE_OMAP_INTC "common-omap-intc"
+typedef struct omap_intr_handler_s omap_intr_handler;
+DECLARE_INSTANCE_CHECKER(omap_intr_handler, OMAP_INTC,
+ TYPE_OMAP_INTC)
+
+
+/*
+ * TODO: Ideally we should have a clock framework that
+ * let us wire these clocks up with QOM properties or links.
+ *
+ * qdev should support a generic means of defining a 'port' with
+ * an arbitrary interface for connecting two devices. Then we
+ * could reframe the omap clock API in terms of clock ports,
+ * and get some type safety. For now the best qdev provides is
+ * passing an arbitrary pointer.
+ * (It's not possible to pass in the string which is the clock
+ * name, because this device does not have the necessary information
+ * (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);
+
+/* omap_i2c.c */
+#define TYPE_OMAP_I2C "omap_i2c"
+OBJECT_DECLARE_SIMPLE_TYPE(OMAPI2CState, OMAP_I2C)
+
+
+/* TODO: clock framework (see above) */
+void omap_i2c_set_iclk(OMAPI2CState *i2c, omap_clk clk);
+void omap_i2c_set_fclk(OMAPI2CState *i2c, omap_clk clk);
+
+/* omap_gpio.c */
+#define TYPE_OMAP1_GPIO "omap-gpio"
+DECLARE_INSTANCE_CHECKER(struct omap_gpif_s, OMAP1_GPIO,
+ TYPE_OMAP1_GPIO)
+
+#define TYPE_OMAP2_GPIO "omap2-gpio"
+DECLARE_INSTANCE_CHECKER(struct omap2_gpif_s, OMAP2_GPIO,
+ TYPE_OMAP2_GPIO)
+
+typedef struct omap_gpif_s omap_gpif;
+typedef struct omap2_gpif_s omap2_gpif;
+
+/* TODO: clock framework (see above) */
+void omap_gpio_set_clk(omap_gpif *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);
+
+/* OMAP2 l4 Interconnect */
+struct omap_l4_s;
+struct omap_l4_region_s {
+ hwaddr offset;
+ size_t size;
+ int access;
+};
+struct omap_l4_agent_info_s {
+ int ta;
+ int region;
+ int regions;
+ int ta_region;
+};
+struct omap_target_agent_s {
+ MemoryRegion iomem;
+ struct omap_l4_s *bus;
+ int regions;
+ const struct omap_l4_region_s *start;
+ hwaddr base;
+ uint32_t component;
+ uint32_t control;
+ uint32_t status;
+};
+struct omap_l4_s *omap_l4_init(MemoryRegion *address_space,
+ hwaddr base, int ta_num);
+
+struct omap_target_agent_s;
+struct omap_target_agent_s *omap_l4ta_get(
+ struct omap_l4_s *bus,
+ const struct omap_l4_region_s *regions,
+ const struct omap_l4_agent_info_s *agents,
+ int cs);
+hwaddr omap_l4_attach(struct omap_target_agent_s *ta,
+ int region, MemoryRegion *mr);
+hwaddr omap_l4_region_base(struct omap_target_agent_s *ta,
+ int region);
+hwaddr omap_l4_region_size(struct omap_target_agent_s *ta,
+ int region);
+
+/* OMAP2 SDRAM controller */
+struct omap_sdrc_s;
+struct omap_sdrc_s *omap_sdrc_init(MemoryRegion *sysmem,
+ hwaddr base);
+void omap_sdrc_reset(struct omap_sdrc_s *s);
+
+/* OMAP2 general purpose memory controller */
+struct omap_gpmc_s;
+struct omap_gpmc_s *omap_gpmc_init(struct omap_mpu_state_s *mpu,
+ hwaddr base,
+ qemu_irq irq, qemu_irq drq);
+void omap_gpmc_reset(struct omap_gpmc_s *s);
+void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, MemoryRegion *iomem);
+void omap_gpmc_attach_nand(struct omap_gpmc_s *s, int cs, DeviceState *nand);
+
+/*
+ * Common IRQ numbers for level 1 interrupt handler
+ * See /usr/include/asm-arm/arch-omap/irqs.h in Linux.
+ */
+# define OMAP_INT_CAMERA 1
+# define OMAP_INT_FIQ 3
+# define OMAP_INT_RTDX 6
+# define OMAP_INT_DSP_MMU_ABORT 7
+# define OMAP_INT_HOST 8
+# define OMAP_INT_ABORT 9
+# define OMAP_INT_BRIDGE_PRIV 13
+# define OMAP_INT_GPIO_BANK1 14
+# define OMAP_INT_UART3 15
+# define OMAP_INT_TIMER3 16
+# define OMAP_INT_DMA_CH0_6 19
+# define OMAP_INT_DMA_CH1_7 20
+# define OMAP_INT_DMA_CH2_8 21
+# define OMAP_INT_DMA_CH3 22
+# define OMAP_INT_DMA_CH4 23
+# define OMAP_INT_DMA_CH5 24
+# define OMAP_INT_DMA_LCD 25
+# define OMAP_INT_TIMER1 26
+# define OMAP_INT_WD_TIMER 27
+# define OMAP_INT_BRIDGE_PUB 28
+# define OMAP_INT_TIMER2 30
+# define OMAP_INT_LCD_CTRL 31
+
+/*
+ * Common OMAP-15xx IRQ numbers for level 1 interrupt handler
+ */
+# define OMAP_INT_15XX_IH2_IRQ 0
+# define OMAP_INT_15XX_LB_MMU 17
+# define OMAP_INT_15XX_LOCAL_BUS 29
+
+/*
+ * OMAP-1510 specific IRQ numbers for level 1 interrupt handler
+ */
+# define OMAP_INT_1510_SPI_TX 4
+# define OMAP_INT_1510_SPI_RX 5
+# define OMAP_INT_1510_DSP_MAILBOX1 10
+# define OMAP_INT_1510_DSP_MAILBOX2 11
+
+/*
+ * OMAP-310 specific IRQ numbers for level 1 interrupt handler
+ */
+# define OMAP_INT_310_McBSP2_TX 4
+# define OMAP_INT_310_McBSP2_RX 5
+# define OMAP_INT_310_HSB_MAILBOX1 12
+# define OMAP_INT_310_HSAB_MMU 18
+
+/*
+ * OMAP-1610 specific IRQ numbers for level 1 interrupt handler
+ */
+# define OMAP_INT_1610_IH2_IRQ 0
+# define OMAP_INT_1610_IH2_FIQ 2
+# define OMAP_INT_1610_McBSP2_TX 4
+# define OMAP_INT_1610_McBSP2_RX 5
+# define OMAP_INT_1610_DSP_MAILBOX1 10
+# define OMAP_INT_1610_DSP_MAILBOX2 11
+# define OMAP_INT_1610_LCD_LINE 12
+# define OMAP_INT_1610_GPTIMER1 17
+# define OMAP_INT_1610_GPTIMER2 18
+# define OMAP_INT_1610_SSR_FIFO_0 29
+
+/*
+ * OMAP-730 specific IRQ numbers for level 1 interrupt handler
+ */
+# define OMAP_INT_730_IH2_FIQ 0
+# define OMAP_INT_730_IH2_IRQ 1
+# define OMAP_INT_730_USB_NON_ISO 2
+# define OMAP_INT_730_USB_ISO 3
+# define OMAP_INT_730_ICR 4
+# define OMAP_INT_730_EAC 5
+# define OMAP_INT_730_GPIO_BANK1 6
+# define OMAP_INT_730_GPIO_BANK2 7
+# define OMAP_INT_730_GPIO_BANK3 8
+# define OMAP_INT_730_McBSP2TX 10
+# define OMAP_INT_730_McBSP2RX 11
+# define OMAP_INT_730_McBSP2RX_OVF 12
+# define OMAP_INT_730_LCD_LINE 14
+# define OMAP_INT_730_GSM_PROTECT 15
+# define OMAP_INT_730_TIMER3 16
+# define OMAP_INT_730_GPIO_BANK5 17
+# define OMAP_INT_730_GPIO_BANK6 18
+# define OMAP_INT_730_SPGIO_WR 29
+
+/*
+ * Common IRQ numbers for level 2 interrupt handler
+ */
+# define OMAP_INT_KEYBOARD 1
+# define OMAP_INT_uWireTX 2
+# define OMAP_INT_uWireRX 3
+# define OMAP_INT_I2C 4
+# define OMAP_INT_MPUIO 5
+# define OMAP_INT_USB_HHC_1 6
+# define OMAP_INT_McBSP3TX 10
+# define OMAP_INT_McBSP3RX 11
+# define OMAP_INT_McBSP1TX 12
+# define OMAP_INT_McBSP1RX 13
+# define OMAP_INT_UART1 14
+# define OMAP_INT_UART2 15
+# define OMAP_INT_USB_W2FC 20
+# define OMAP_INT_1WIRE 21
+# define OMAP_INT_OS_TIMER 22
+# define OMAP_INT_OQN 23
+# define OMAP_INT_GAUGE_32K 24
+# define OMAP_INT_RTC_TIMER 25
+# define OMAP_INT_RTC_ALARM 26
+# define OMAP_INT_DSP_MMU 28
+
+/*
+ * OMAP-1510 specific IRQ numbers for level 2 interrupt handler
+ */
+# define OMAP_INT_1510_BT_MCSI1TX 16
+# define OMAP_INT_1510_BT_MCSI1RX 17
+# define OMAP_INT_1510_SoSSI_MATCH 19
+# define OMAP_INT_1510_MEM_STICK 27
+# define OMAP_INT_1510_COM_SPI_RO 31
+
+/*
+ * OMAP-310 specific IRQ numbers for level 2 interrupt handler
+ */
+# define OMAP_INT_310_FAC 0
+# define OMAP_INT_310_USB_HHC_2 7
+# define OMAP_INT_310_MCSI1_FE 16
+# define OMAP_INT_310_MCSI2_FE 17
+# define OMAP_INT_310_USB_W2FC_ISO 29
+# define OMAP_INT_310_USB_W2FC_NON_ISO 30
+# define OMAP_INT_310_McBSP2RX_OF 31
+
+/*
+ * OMAP-1610 specific IRQ numbers for level 2 interrupt handler
+ */
+# define OMAP_INT_1610_FAC 0
+# define OMAP_INT_1610_USB_HHC_2 7
+# define OMAP_INT_1610_USB_OTG 8
+# define OMAP_INT_1610_SoSSI 9
+# define OMAP_INT_1610_BT_MCSI1TX 16
+# define OMAP_INT_1610_BT_MCSI1RX 17
+# define OMAP_INT_1610_SoSSI_MATCH 19
+# define OMAP_INT_1610_MEM_STICK 27
+# define OMAP_INT_1610_McBSP2RX_OF 31
+# define OMAP_INT_1610_STI 32
+# define OMAP_INT_1610_STI_WAKEUP 33
+# define OMAP_INT_1610_GPTIMER3 34
+# define OMAP_INT_1610_GPTIMER4 35
+# define OMAP_INT_1610_GPTIMER5 36
+# define OMAP_INT_1610_GPTIMER6 37
+# define OMAP_INT_1610_GPTIMER7 38
+# define OMAP_INT_1610_GPTIMER8 39
+# define OMAP_INT_1610_GPIO_BANK2 40
+# define OMAP_INT_1610_GPIO_BANK3 41
+# define OMAP_INT_1610_MMC2 42
+# define OMAP_INT_1610_CF 43
+# define OMAP_INT_1610_WAKE_UP_REQ 46
+# define OMAP_INT_1610_GPIO_BANK4 48
+# define OMAP_INT_1610_SPI 49
+# define OMAP_INT_1610_DMA_CH6 53
+# define OMAP_INT_1610_DMA_CH7 54
+# define OMAP_INT_1610_DMA_CH8 55
+# define OMAP_INT_1610_DMA_CH9 56
+# define OMAP_INT_1610_DMA_CH10 57
+# define OMAP_INT_1610_DMA_CH11 58
+# define OMAP_INT_1610_DMA_CH12 59
+# define OMAP_INT_1610_DMA_CH13 60
+# define OMAP_INT_1610_DMA_CH14 61
+# define OMAP_INT_1610_DMA_CH15 62
+# define OMAP_INT_1610_NAND 63
+
+/*
+ * OMAP-730 specific IRQ numbers for level 2 interrupt handler
+ */
+# define OMAP_INT_730_HW_ERRORS 0
+# define OMAP_INT_730_NFIQ_PWR_FAIL 1
+# define OMAP_INT_730_CFCD 2
+# define OMAP_INT_730_CFIREQ 3
+# define OMAP_INT_730_I2C 4
+# define OMAP_INT_730_PCC 5
+# define OMAP_INT_730_MPU_EXT_NIRQ 6
+# define OMAP_INT_730_SPI_100K_1 7
+# define OMAP_INT_730_SYREN_SPI 8
+# define OMAP_INT_730_VLYNQ 9
+# define OMAP_INT_730_GPIO_BANK4 10
+# define OMAP_INT_730_McBSP1TX 11
+# define OMAP_INT_730_McBSP1RX 12
+# define OMAP_INT_730_McBSP1RX_OF 13
+# define OMAP_INT_730_UART_MODEM_IRDA_2 14
+# define OMAP_INT_730_UART_MODEM_1 15
+# define OMAP_INT_730_MCSI 16
+# define OMAP_INT_730_uWireTX 17
+# define OMAP_INT_730_uWireRX 18
+# define OMAP_INT_730_SMC_CD 19
+# define OMAP_INT_730_SMC_IREQ 20
+# define OMAP_INT_730_HDQ_1WIRE 21
+# define OMAP_INT_730_TIMER32K 22
+# define OMAP_INT_730_MMC_SDIO 23
+# define OMAP_INT_730_UPLD 24
+# define OMAP_INT_730_USB_HHC_1 27
+# define OMAP_INT_730_USB_HHC_2 28
+# define OMAP_INT_730_USB_GENI 29
+# define OMAP_INT_730_USB_OTG 30
+# define OMAP_INT_730_CAMERA_IF 31
+# define OMAP_INT_730_RNG 32
+# define OMAP_INT_730_DUAL_MODE_TIMER 33
+# define OMAP_INT_730_DBB_RF_EN 34
+# define OMAP_INT_730_MPUIO_KEYPAD 35
+# define OMAP_INT_730_SHA1_MD5 36
+# define OMAP_INT_730_SPI_100K_2 37
+# define OMAP_INT_730_RNG_IDLE 38
+# define OMAP_INT_730_MPUIO 39
+# define OMAP_INT_730_LLPC_LCD_CTRL_OFF 40
+# define OMAP_INT_730_LLPC_OE_FALLING 41
+# define OMAP_INT_730_LLPC_OE_RISING 42
+# define OMAP_INT_730_LLPC_VSYNC 43
+# define OMAP_INT_730_WAKE_UP_REQ 46
+# define OMAP_INT_730_DMA_CH6 53
+# define OMAP_INT_730_DMA_CH7 54
+# define OMAP_INT_730_DMA_CH8 55
+# define OMAP_INT_730_DMA_CH9 56
+# define OMAP_INT_730_DMA_CH10 57
+# define OMAP_INT_730_DMA_CH11 58
+# define OMAP_INT_730_DMA_CH12 59
+# define OMAP_INT_730_DMA_CH13 60
+# define OMAP_INT_730_DMA_CH14 61
+# define OMAP_INT_730_DMA_CH15 62
+# define OMAP_INT_730_NAND 63
+
+/*
+ * OMAP-24xx common IRQ numbers
+ */
+# define OMAP_INT_24XX_STI 4
+# define OMAP_INT_24XX_SYS_NIRQ 7
+# define OMAP_INT_24XX_L3_IRQ 10
+# define OMAP_INT_24XX_PRCM_MPU_IRQ 11
+# define OMAP_INT_24XX_SDMA_IRQ0 12
+# define OMAP_INT_24XX_SDMA_IRQ1 13
+# define OMAP_INT_24XX_SDMA_IRQ2 14
+# define OMAP_INT_24XX_SDMA_IRQ3 15
+# define OMAP_INT_243X_MCBSP2_IRQ 16
+# define OMAP_INT_243X_MCBSP3_IRQ 17
+# define OMAP_INT_243X_MCBSP4_IRQ 18
+# define OMAP_INT_243X_MCBSP5_IRQ 19
+# define OMAP_INT_24XX_GPMC_IRQ 20
+# define OMAP_INT_24XX_GUFFAW_IRQ 21
+# define OMAP_INT_24XX_IVA_IRQ 22
+# define OMAP_INT_24XX_EAC_IRQ 23
+# define OMAP_INT_24XX_CAM_IRQ 24
+# define OMAP_INT_24XX_DSS_IRQ 25
+# define OMAP_INT_24XX_MAIL_U0_MPU 26
+# define OMAP_INT_24XX_DSP_UMA 27
+# define OMAP_INT_24XX_DSP_MMU 28
+# define OMAP_INT_24XX_GPIO_BANK1 29
+# define OMAP_INT_24XX_GPIO_BANK2 30
+# define OMAP_INT_24XX_GPIO_BANK3 31
+# define OMAP_INT_24XX_GPIO_BANK4 32
+# define OMAP_INT_243X_GPIO_BANK5 33
+# define OMAP_INT_24XX_MAIL_U3_MPU 34
+# define OMAP_INT_24XX_WDT3 35
+# define OMAP_INT_24XX_WDT4 36
+# define OMAP_INT_24XX_GPTIMER1 37
+# define OMAP_INT_24XX_GPTIMER2 38
+# define OMAP_INT_24XX_GPTIMER3 39
+# define OMAP_INT_24XX_GPTIMER4 40
+# define OMAP_INT_24XX_GPTIMER5 41
+# define OMAP_INT_24XX_GPTIMER6 42
+# define OMAP_INT_24XX_GPTIMER7 43
+# define OMAP_INT_24XX_GPTIMER8 44
+# define OMAP_INT_24XX_GPTIMER9 45
+# define OMAP_INT_24XX_GPTIMER10 46
+# define OMAP_INT_24XX_GPTIMER11 47
+# define OMAP_INT_24XX_GPTIMER12 48
+# define OMAP_INT_24XX_PKA_IRQ 50
+# define OMAP_INT_24XX_SHA1MD5_IRQ 51
+# define OMAP_INT_24XX_RNG_IRQ 52
+# define OMAP_INT_24XX_MG_IRQ 53
+# define OMAP_INT_24XX_I2C1_IRQ 56
+# define OMAP_INT_24XX_I2C2_IRQ 57
+# define OMAP_INT_24XX_MCBSP1_IRQ_TX 59
+# define OMAP_INT_24XX_MCBSP1_IRQ_RX 60
+# define OMAP_INT_24XX_MCBSP2_IRQ_TX 62
+# define OMAP_INT_24XX_MCBSP2_IRQ_RX 63
+# define OMAP_INT_243X_MCBSP1_IRQ 64
+# define OMAP_INT_24XX_MCSPI1_IRQ 65
+# define OMAP_INT_24XX_MCSPI2_IRQ 66
+# define OMAP_INT_24XX_SSI1_IRQ0 67
+# define OMAP_INT_24XX_SSI1_IRQ1 68
+# define OMAP_INT_24XX_SSI2_IRQ0 69
+# define OMAP_INT_24XX_SSI2_IRQ1 70
+# define OMAP_INT_24XX_SSI_GDD_IRQ 71
+# define OMAP_INT_24XX_UART1_IRQ 72
+# define OMAP_INT_24XX_UART2_IRQ 73
+# define OMAP_INT_24XX_UART3_IRQ 74
+# define OMAP_INT_24XX_USB_IRQ_GEN 75
+# define OMAP_INT_24XX_USB_IRQ_NISO 76
+# define OMAP_INT_24XX_USB_IRQ_ISO 77
+# define OMAP_INT_24XX_USB_IRQ_HGEN 78
+# define OMAP_INT_24XX_USB_IRQ_HSOF 79
+# define OMAP_INT_24XX_USB_IRQ_OTG 80
+# define OMAP_INT_24XX_VLYNQ_IRQ 81
+# define OMAP_INT_24XX_MMC_IRQ 83
+# define OMAP_INT_24XX_MS_IRQ 84
+# define OMAP_INT_24XX_FAC_IRQ 85
+# define OMAP_INT_24XX_MCSPI3_IRQ 91
+# define OMAP_INT_243X_HS_USB_MC 92
+# define OMAP_INT_243X_HS_USB_DMA 93
+# define OMAP_INT_243X_CARKIT 94
+# define OMAP_INT_34XX_GPTIMER12 95
+
+/* omap_dma.c */
+enum omap_dma_model {
+ omap_dma_3_0,
+ omap_dma_3_1,
+ omap_dma_3_2,
+ omap_dma_4,
+};
+
+struct soc_dma_s;
+struct soc_dma_s *omap_dma_init(hwaddr base, qemu_irq *irqs,
+ MemoryRegion *sysmem,
+ qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk,
+ enum omap_dma_model model);
+struct soc_dma_s *omap_dma4_init(hwaddr base, qemu_irq *irqs,
+ MemoryRegion *sysmem,
+ struct omap_mpu_state_s *mpu, int fifo,
+ int chans, omap_clk iclk, omap_clk fclk);
+void omap_dma_reset(struct soc_dma_s *s);
+
+struct dma_irq_map {
+ int ih;
+ int intr;
+};
+
+/* Only used in OMAP DMA 3.x gigacells */
+enum omap_dma_port {
+ emiff = 0,
+ emifs,
+ imif, /* omap16xx: ocp_t1 */
+ tipb,
+ local, /* omap16xx: ocp_t2 */
+ tipb_mpui,
+ __omap_dma_port_last,
+};
+
+typedef enum {
+ constant = 0,
+ post_incremented,
+ single_index,
+ double_index,
+} omap_dma_addressing_t;
+
+/* Only used in OMAP DMA 3.x gigacells */
+struct omap_dma_lcd_channel_s {
+ enum omap_dma_port src;
+ hwaddr src_f1_top;
+ hwaddr src_f1_bottom;
+ hwaddr src_f2_top;
+ hwaddr src_f2_bottom;
+
+ /* Used in OMAP DMA 3.2 gigacell */
+ unsigned char brust_f1;
+ unsigned char pack_f1;
+ unsigned char data_type_f1;
+ unsigned char brust_f2;
+ unsigned char pack_f2;
+ unsigned char data_type_f2;
+ unsigned char end_prog;
+ unsigned char repeat;
+ unsigned char auto_init;
+ unsigned char priority;
+ unsigned char fs;
+ unsigned char running;
+ unsigned char bs;
+ unsigned char omap_3_1_compatible_disable;
+ unsigned char dst;
+ unsigned char lch_type;
+ int16_t element_index_f1;
+ int16_t element_index_f2;
+ int32_t frame_index_f1;
+ int32_t frame_index_f2;
+ uint16_t elements_f1;
+ uint16_t frames_f1;
+ uint16_t elements_f2;
+ uint16_t frames_f2;
+ omap_dma_addressing_t mode_f1;
+ omap_dma_addressing_t mode_f2;
+
+ /* Destination port is fixed. */
+ int interrupts;
+ int condition;
+ int dual;
+
+ int current_frame;
+ hwaddr phys_framebuffer[2];
+ qemu_irq irq;
+ struct omap_mpu_state_s *mpu;
+} *omap_dma_get_lcdch(struct soc_dma_s *s);
+
+/*
+ * DMA request numbers for OMAP1
+ * See /usr/include/asm-arm/arch-omap/dma.h in Linux.
+ */
+# define OMAP_DMA_NO_DEVICE 0
+# define OMAP_DMA_MCSI1_TX 1
+# define OMAP_DMA_MCSI1_RX 2
+# define OMAP_DMA_I2C_RX 3
+# define OMAP_DMA_I2C_TX 4
+# define OMAP_DMA_EXT_NDMA_REQ0 5
+# define OMAP_DMA_EXT_NDMA_REQ1 6
+# define OMAP_DMA_UWIRE_TX 7
+# define OMAP_DMA_MCBSP1_TX 8
+# define OMAP_DMA_MCBSP1_RX 9
+# define OMAP_DMA_MCBSP3_TX 10
+# define OMAP_DMA_MCBSP3_RX 11
+# define OMAP_DMA_UART1_TX 12
+# define OMAP_DMA_UART1_RX 13
+# define OMAP_DMA_UART2_TX 14
+# define OMAP_DMA_UART2_RX 15
+# define OMAP_DMA_MCBSP2_TX 16
+# define OMAP_DMA_MCBSP2_RX 17
+# define OMAP_DMA_UART3_TX 18
+# define OMAP_DMA_UART3_RX 19
+# define OMAP_DMA_CAMERA_IF_RX 20
+# define OMAP_DMA_MMC_TX 21
+# define OMAP_DMA_MMC_RX 22
+# define OMAP_DMA_NAND 23 /* Not in OMAP310 */
+# define OMAP_DMA_IRQ_LCD_LINE 24 /* Not in OMAP310 */
+# define OMAP_DMA_MEMORY_STICK 25 /* Not in OMAP310 */
+# define OMAP_DMA_USB_W2FC_RX0 26
+# define OMAP_DMA_USB_W2FC_RX1 27
+# define OMAP_DMA_USB_W2FC_RX2 28
+# define OMAP_DMA_USB_W2FC_TX0 29
+# define OMAP_DMA_USB_W2FC_TX1 30
+# define OMAP_DMA_USB_W2FC_TX2 31
+
+/* These are only for 1610 */
+# define OMAP_DMA_CRYPTO_DES_IN 32
+# define OMAP_DMA_SPI_TX 33
+# define OMAP_DMA_SPI_RX 34
+# define OMAP_DMA_CRYPTO_HASH 35
+# define OMAP_DMA_CCP_ATTN 36
+# define OMAP_DMA_CCP_FIFO_NOT_EMPTY 37
+# define OMAP_DMA_CMT_APE_TX_CHAN_0 38
+# define OMAP_DMA_CMT_APE_RV_CHAN_0 39
+# define OMAP_DMA_CMT_APE_TX_CHAN_1 40
+# define OMAP_DMA_CMT_APE_RV_CHAN_1 41
+# define OMAP_DMA_CMT_APE_TX_CHAN_2 42
+# define OMAP_DMA_CMT_APE_RV_CHAN_2 43
+# define OMAP_DMA_CMT_APE_TX_CHAN_3 44
+# define OMAP_DMA_CMT_APE_RV_CHAN_3 45
+# define OMAP_DMA_CMT_APE_TX_CHAN_4 46
+# define OMAP_DMA_CMT_APE_RV_CHAN_4 47
+# define OMAP_DMA_CMT_APE_TX_CHAN_5 48
+# define OMAP_DMA_CMT_APE_RV_CHAN_5 49
+# define OMAP_DMA_CMT_APE_TX_CHAN_6 50
+# define OMAP_DMA_CMT_APE_RV_CHAN_6 51
+# define OMAP_DMA_CMT_APE_TX_CHAN_7 52
+# define OMAP_DMA_CMT_APE_RV_CHAN_7 53
+# define OMAP_DMA_MMC2_TX 54
+# define OMAP_DMA_MMC2_RX 55
+# define OMAP_DMA_CRYPTO_DES_OUT 56
+
+/*
+ * DMA request numbers for the OMAP2
+ */
+# define OMAP24XX_DMA_NO_DEVICE 0
+# define OMAP24XX_DMA_XTI_DMA 1 /* Not in OMAP2420 */
+# define OMAP24XX_DMA_EXT_DMAREQ0 2
+# define OMAP24XX_DMA_EXT_DMAREQ1 3
+# define OMAP24XX_DMA_GPMC 4
+# define OMAP24XX_DMA_GFX 5 /* Not in OMAP2420 */
+# define OMAP24XX_DMA_DSS 6
+# define OMAP24XX_DMA_VLYNQ_TX 7 /* Not in OMAP2420 */
+# define OMAP24XX_DMA_CWT 8 /* Not in OMAP2420 */
+# define OMAP24XX_DMA_AES_TX 9 /* Not in OMAP2420 */
+# define OMAP24XX_DMA_AES_RX 10 /* Not in OMAP2420 */
+# define OMAP24XX_DMA_DES_TX 11 /* Not in OMAP2420 */
+# define OMAP24XX_DMA_DES_RX 12 /* Not in OMAP2420 */
+# define OMAP24XX_DMA_SHA1MD5_RX 13 /* Not in OMAP2420 */
+# define OMAP24XX_DMA_EXT_DMAREQ2 14
+# define OMAP24XX_DMA_EXT_DMAREQ3 15
+# define OMAP24XX_DMA_EXT_DMAREQ4 16
+# define OMAP24XX_DMA_EAC_AC_RD 17
+# define OMAP24XX_DMA_EAC_AC_WR 18
+# define OMAP24XX_DMA_EAC_MD_UL_RD 19
+# define OMAP24XX_DMA_EAC_MD_UL_WR 20
+# define OMAP24XX_DMA_EAC_MD_DL_RD 21
+# define OMAP24XX_DMA_EAC_MD_DL_WR 22
+# define OMAP24XX_DMA_EAC_BT_UL_RD 23
+# define OMAP24XX_DMA_EAC_BT_UL_WR 24
+# define OMAP24XX_DMA_EAC_BT_DL_RD 25
+# define OMAP24XX_DMA_EAC_BT_DL_WR 26
+# define OMAP24XX_DMA_I2C1_TX 27
+# define OMAP24XX_DMA_I2C1_RX 28
+# define OMAP24XX_DMA_I2C2_TX 29
+# define OMAP24XX_DMA_I2C2_RX 30
+# define OMAP24XX_DMA_MCBSP1_TX 31
+# define OMAP24XX_DMA_MCBSP1_RX 32
+# define OMAP24XX_DMA_MCBSP2_TX 33
+# define OMAP24XX_DMA_MCBSP2_RX 34
+# define OMAP24XX_DMA_SPI1_TX0 35
+# define OMAP24XX_DMA_SPI1_RX0 36
+# define OMAP24XX_DMA_SPI1_TX1 37
+# define OMAP24XX_DMA_SPI1_RX1 38
+# define OMAP24XX_DMA_SPI1_TX2 39
+# define OMAP24XX_DMA_SPI1_RX2 40
+# define OMAP24XX_DMA_SPI1_TX3 41
+# define OMAP24XX_DMA_SPI1_RX3 42
+# define OMAP24XX_DMA_SPI2_TX0 43
+# define OMAP24XX_DMA_SPI2_RX0 44
+# define OMAP24XX_DMA_SPI2_TX1 45
+# define OMAP24XX_DMA_SPI2_RX1 46
+
+# define OMAP24XX_DMA_UART1_TX 49
+# define OMAP24XX_DMA_UART1_RX 50
+# define OMAP24XX_DMA_UART2_TX 51
+# define OMAP24XX_DMA_UART2_RX 52
+# define OMAP24XX_DMA_UART3_TX 53
+# define OMAP24XX_DMA_UART3_RX 54
+# define OMAP24XX_DMA_USB_W2FC_TX0 55
+# define OMAP24XX_DMA_USB_W2FC_RX0 56
+# define OMAP24XX_DMA_USB_W2FC_TX1 57
+# define OMAP24XX_DMA_USB_W2FC_RX1 58
+# define OMAP24XX_DMA_USB_W2FC_TX2 59
+# define OMAP24XX_DMA_USB_W2FC_RX2 60
+# define OMAP24XX_DMA_MMC1_TX 61
+# define OMAP24XX_DMA_MMC1_RX 62
+# define OMAP24XX_DMA_MS 63 /* Not in OMAP2420 */
+# define OMAP24XX_DMA_EXT_DMAREQ5 64
+
+/* omap[123].c */
+/* OMAP2 gp timer */
+struct omap_gp_timer_s;
+struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,
+ qemu_irq irq, omap_clk fclk, omap_clk iclk);
+void omap_gp_timer_reset(struct omap_gp_timer_s *s);
+
+/* OMAP2 sysctimer */
+struct omap_synctimer_s;
+struct omap_synctimer_s *omap_synctimer_init(struct omap_target_agent_s *ta,
+ struct omap_mpu_state_s *mpu, omap_clk fclk, omap_clk iclk);
+void omap_synctimer_reset(struct omap_synctimer_s *s);
+
+struct omap_uart_s;
+struct omap_uart_s *omap_uart_init(hwaddr base,
+ qemu_irq irq, omap_clk fclk, omap_clk iclk,
+ qemu_irq txdma, qemu_irq rxdma,
+ const char *label, Chardev *chr);
+struct omap_uart_s *omap2_uart_init(MemoryRegion *sysmem,
+ struct omap_target_agent_s *ta,
+ qemu_irq irq, omap_clk fclk, omap_clk iclk,
+ 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);
+void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler);
+void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down);
+
+struct omap_uwire_s;
+void omap_uwire_attach(struct omap_uwire_s *s,
+ uWireSlave *slave, int chipselect);
+
+/* OMAP2 spi */
+struct omap_mcspi_s;
+struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta, int chnum,
+ qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk);
+void omap_mcspi_attach(struct omap_mcspi_s *s,
+ uint32_t (*txrx)(void *opaque, uint32_t, int), void *opaque,
+ int chipselect);
+void omap_mcspi_reset(struct omap_mcspi_s *s);
+
+struct I2SCodec {
+ void *opaque;
+
+ /* The CPU can call this if it is generating the clock signal on the
+ * i2s port. The CODEC can ignore it if it is set up as a clock
+ * master and generates its own clock. */
+ void (*set_rate)(void *opaque, int in, int out);
+
+ void (*tx_swallow)(void *opaque);
+ qemu_irq rx_swallow;
+ qemu_irq tx_start;
+
+ int tx_rate;
+ int cts;
+ int rx_rate;
+ int rts;
+
+ struct i2s_fifo_s {
+ uint8_t *fifo;
+ int len;
+ int start;
+ int size;
+ } in, out;
+};
+struct omap_mcbsp_s;
+void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, I2SCodec *slave);
+
+void omap_tap_init(struct omap_target_agent_s *ta,
+ struct omap_mpu_state_s *mpu);
+
+/* omap_lcdc.c */
+struct omap_lcd_panel_s;
+void omap_lcdc_reset(struct omap_lcd_panel_s *s);
+struct omap_lcd_panel_s *omap_lcdc_init(MemoryRegion *sysmem,
+ hwaddr base,
+ qemu_irq irq,
+ struct omap_dma_lcd_channel_s *dma,
+ omap_clk clk);
+
+/* omap_dss.c */
+struct rfbi_chip_s {
+ void *opaque;
+ void (*write)(void *opaque, int dc, uint16_t value);
+ void (*block)(void *opaque, int dc, void *buf, size_t len, int pitch);
+ uint16_t (*read)(void *opaque, int dc);
+};
+struct omap_dss_s;
+void omap_dss_reset(struct omap_dss_s *s);
+struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta,
+ MemoryRegion *sysmem,
+ hwaddr l3_base,
+ qemu_irq irq, qemu_irq drq,
+ omap_clk fck1, omap_clk fck2, omap_clk ck54m,
+ omap_clk ick1, omap_clk ick2);
+void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip);
+
+/* omap_mmc.c */
+struct omap_mmc_s;
+struct omap_mmc_s *omap_mmc_init(hwaddr base,
+ MemoryRegion *sysmem,
+ BlockBackend *blk,
+ qemu_irq irq, qemu_irq dma[], omap_clk clk);
+struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta,
+ BlockBackend *blk, qemu_irq irq, qemu_irq dma[],
+ omap_clk fclk, omap_clk iclk);
+void omap_mmc_reset(struct omap_mmc_s *s);
+void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover);
+void omap_mmc_enable(struct omap_mmc_s *s, int enable);
+
+/* omap_i2c.c */
+I2CBus *omap_i2c_bus(DeviceState *omap_i2c);
+
+# define cpu_is_omap310(cpu) (cpu->mpu_model == omap310)
+# define cpu_is_omap1510(cpu) (cpu->mpu_model == omap1510)
+# define cpu_is_omap1610(cpu) (cpu->mpu_model == omap1610)
+# define cpu_is_omap1710(cpu) (cpu->mpu_model == omap1710)
+# define cpu_is_omap2410(cpu) (cpu->mpu_model == omap2410)
+# define cpu_is_omap2420(cpu) (cpu->mpu_model == omap2420)
+# define cpu_is_omap2430(cpu) (cpu->mpu_model == omap2430)
+# define cpu_is_omap3430(cpu) (cpu->mpu_model == omap3430)
+# define cpu_is_omap3630(cpu) (cpu->mpu_model == omap3630)
+
+# define cpu_is_omap15xx(cpu) \
+ (cpu_is_omap310(cpu) || cpu_is_omap1510(cpu))
+# define cpu_is_omap16xx(cpu) \
+ (cpu_is_omap1610(cpu) || cpu_is_omap1710(cpu))
+# define cpu_is_omap24xx(cpu) \
+ (cpu_is_omap2410(cpu) || cpu_is_omap2420(cpu) || cpu_is_omap2430(cpu))
+
+# define cpu_class_omap1(cpu) \
+ (cpu_is_omap15xx(cpu) || cpu_is_omap16xx(cpu))
+# define cpu_class_omap2(cpu) cpu_is_omap24xx(cpu)
+# define cpu_class_omap3(cpu) \
+ (cpu_is_omap3430(cpu) || cpu_is_omap3630(cpu))
+
+struct omap_mpu_state_s {
+ enum omap_mpu_model {
+ omap310,
+ omap1510,
+ omap1610,
+ omap1710,
+ omap2410,
+ omap2420,
+ omap2422,
+ omap2423,
+ omap2430,
+ omap3430,
+ omap3630,
+ } mpu_model;
+
+ ARMCPU *cpu;
+
+ qemu_irq *drq;
+
+ qemu_irq wakeup;
+
+ MemoryRegion ulpd_pm_iomem;
+ MemoryRegion pin_cfg_iomem;
+ MemoryRegion id_iomem;
+ MemoryRegion id_iomem_e18;
+ MemoryRegion id_iomem_ed4;
+ MemoryRegion id_iomem_e20;
+ MemoryRegion mpui_iomem;
+ MemoryRegion tcmi_iomem;
+ MemoryRegion clkm_iomem;
+ MemoryRegion clkdsp_iomem;
+ MemoryRegion mpui_io_iomem;
+ MemoryRegion tap_iomem;
+ MemoryRegion imif_ram;
+ MemoryRegion sram;
+
+ struct omap_dma_port_if_s {
+ uint32_t (*read[3])(struct omap_mpu_state_s *s,
+ hwaddr offset);
+ void (*write[3])(struct omap_mpu_state_s *s,
+ hwaddr offset, uint32_t value);
+ int (*addr_valid)(struct omap_mpu_state_s *s,
+ hwaddr addr);
+ } port[__omap_dma_port_last];
+
+ uint64_t sdram_size;
+ unsigned long sram_size;
+
+ /* MPUI-TIPB peripherals */
+ struct omap_uart_s *uart[3];
+
+ DeviceState *gpio;
+
+ struct omap_mcbsp_s *mcbsp1;
+ struct omap_mcbsp_s *mcbsp3;
+
+ /* MPU public TIPB peripherals */
+ struct omap_32khz_timer_s *os_timer;
+
+ struct omap_mmc_s *mmc;
+
+ struct omap_mpuio_s *mpuio;
+
+ struct omap_uwire_s *microwire;
+
+ struct omap_pwl_s *pwl;
+ struct omap_pwt_s *pwt;
+ DeviceState *i2c[2];
+
+ struct omap_rtc_s *rtc;
+
+ struct omap_mcbsp_s *mcbsp2;
+
+ struct omap_lpg_s *led[2];
+
+ /* MPU private TIPB peripherals */
+ DeviceState *ih[2];
+
+ struct soc_dma_s *dma;
+
+ struct omap_mpu_timer_s *timer[3];
+ struct omap_watchdog_timer_s *wdt;
+
+ struct omap_lcd_panel_s *lcd;
+
+ uint32_t ulpd_pm_regs[21];
+ int64_t ulpd_gauge_start;
+
+ uint32_t func_mux_ctrl[14];
+ uint32_t comp_mode_ctrl[1];
+ uint32_t pull_dwn_ctrl[4];
+ uint32_t gate_inh_ctrl[1];
+ uint32_t voltage_ctrl[1];
+ uint32_t test_dbg_ctrl[1];
+ uint32_t mod_conf_ctrl[1];
+ int compat1509;
+
+ uint32_t mpui_ctrl;
+
+ struct omap_tipb_bridge_s *private_tipb;
+ struct omap_tipb_bridge_s *public_tipb;
+
+ uint32_t tcmi_regs[17];
+
+ struct dpll_ctl_s *dpll[3];
+
+ omap_clk clks;
+ struct {
+ int cold_start;
+ int clocking_scheme;
+ uint16_t arm_ckctl;
+ uint16_t arm_idlect1;
+ uint16_t arm_idlect2;
+ uint16_t arm_ewupct;
+ uint16_t arm_rstct1;
+ uint16_t arm_rstct2;
+ uint16_t arm_ckout1;
+ int dpll1_mode;
+ uint16_t dsp_idlect1;
+ uint16_t dsp_idlect2;
+ uint16_t dsp_rstct2;
+ } clkm;
+
+ /* OMAP2-only peripherals */
+ struct omap_l4_s *l4;
+
+ struct omap_gp_timer_s *gptimer[12];
+ struct omap_synctimer_s *synctimer;
+
+ struct omap_prcm_s *prcm;
+ struct omap_sdrc_s *sdrc;
+ struct omap_gpmc_s *gpmc;
+ struct omap_sysctl_s *sysc;
+
+ struct omap_mcspi_s *mcspi[2];
+
+ struct omap_dss_s *dss;
+
+ struct omap_eac_s *eac;
+};
+
+/* omap1.c */
+struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *sdram,
+ const char *core);
+
+/* omap2.c */
+struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sdram,
+ const char *core);
+
+uint32_t omap_badwidth_read8(void *opaque, hwaddr addr);
+void omap_badwidth_write8(void *opaque, hwaddr addr,
+ uint32_t value);
+uint32_t omap_badwidth_read16(void *opaque, hwaddr addr);
+void omap_badwidth_write16(void *opaque, hwaddr addr,
+ uint32_t value);
+uint32_t omap_badwidth_read32(void *opaque, hwaddr addr);
+void omap_badwidth_write32(void *opaque, hwaddr addr,
+ uint32_t value);
+
+void omap_mpu_wakeup(void *opaque, int irq, int req);
+
+# define OMAP_BAD_REG(paddr) \
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad register %#08"HWADDR_PRIx"\n", \
+ __func__, paddr)
+# define OMAP_RO_REG(paddr) \
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Read-only register %#08" \
+ HWADDR_PRIx "\n", \
+ __func__, paddr)
+
+/* OMAP-specific Linux bootloader tags for the ATAG_BOARD area
+ (Board-specifc tags are not here) */
+#define OMAP_TAG_CLOCK 0x4f01
+#define OMAP_TAG_MMC 0x4f02
+#define OMAP_TAG_SERIAL_CONSOLE 0x4f03
+#define OMAP_TAG_USB 0x4f04
+#define OMAP_TAG_LCD 0x4f05
+#define OMAP_TAG_GPIO_SWITCH 0x4f06
+#define OMAP_TAG_UART 0x4f07
+#define OMAP_TAG_FBMEM 0x4f08
+#define OMAP_TAG_STI_CONSOLE 0x4f09
+#define OMAP_TAG_CAMERA_SENSOR 0x4f0a
+#define OMAP_TAG_PARTITION 0x4f0b
+#define OMAP_TAG_TEA5761 0x4f10
+#define OMAP_TAG_TMP105 0x4f11
+#define OMAP_TAG_BOOT_REASON 0x4f80
+#define OMAP_TAG_FLASH_PART_STR 0x4f81
+#define OMAP_TAG_VERSION_STR 0x4f82
+
+enum {
+ OMAP_GPIOSW_TYPE_COVER = 0 << 4,
+ OMAP_GPIOSW_TYPE_CONNECTION = 1 << 4,
+ OMAP_GPIOSW_TYPE_ACTIVITY = 2 << 4,
+};
+
+#define OMAP_GPIOSW_INVERTED 0x0001
+#define OMAP_GPIOSW_OUTPUT 0x0002
+
+# define OMAP_MPUI_REG_MASK 0x000007ff
+
+#endif
diff --git a/include/hw/arm/primecell.h b/include/hw/arm/primecell.h
new file mode 100644
index 000000000..7337c3b3c
--- /dev/null
+++ b/include/hw/arm/primecell.h
@@ -0,0 +1,12 @@
+#ifndef PRIMECELL_H
+#define PRIMECELL_H
+
+/* Declarations for ARM PrimeCell based periperals. */
+/* Also includes some devices that are currently only used by the
+ ARM boards. */
+
+/* arm_sysctl GPIO lines */
+#define ARM_SYSCTL_GPIO_MMC_WPROT 0
+#define ARM_SYSCTL_GPIO_MMC_CARDIN 1
+
+#endif
diff --git a/include/hw/arm/pxa.h b/include/hw/arm/pxa.h
new file mode 100644
index 000000000..1095504b8
--- /dev/null
+++ b/include/hw/arm/pxa.h
@@ -0,0 +1,200 @@
+/*
+ * Intel XScale PXA255/270 processor support.
+ *
+ * Copyright (c) 2006 Openedhand Ltd.
+ * Written by Andrzej Zaborowski <balrog@zabor.org>
+ *
+ * This code is licensed under the GNU GPL v2.
+ */
+
+#ifndef PXA_H
+#define PXA_H
+
+#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
+# define PXA2XX_PIC_USBH2 2
+# define PXA2XX_PIC_USBH1 3
+# define PXA2XX_PIC_KEYPAD 4
+# define PXA2XX_PIC_PWRI2C 6
+# define PXA25X_PIC_HWUART 7
+# define PXA27X_PIC_OST_4_11 7
+# define PXA2XX_PIC_GPIO_0 8
+# define PXA2XX_PIC_GPIO_1 9
+# define PXA2XX_PIC_GPIO_X 10
+# define PXA2XX_PIC_I2S 13
+# define PXA26X_PIC_ASSP 15
+# define PXA25X_PIC_NSSP 16
+# define PXA27X_PIC_SSP2 16
+# define PXA2XX_PIC_LCD 17
+# define PXA2XX_PIC_I2C 18
+# define PXA2XX_PIC_ICP 19
+# define PXA2XX_PIC_STUART 20
+# define PXA2XX_PIC_BTUART 21
+# define PXA2XX_PIC_FFUART 22
+# define PXA2XX_PIC_MMC 23
+# define PXA2XX_PIC_SSP 24
+# define PXA2XX_PIC_DMA 25
+# define PXA2XX_PIC_OST_0 26
+# define PXA2XX_PIC_RTC1HZ 30
+# define PXA2XX_PIC_RTCALARM 31
+
+/* DMA requests */
+# define PXA2XX_RX_RQ_I2S 2
+# define PXA2XX_TX_RQ_I2S 3
+# define PXA2XX_RX_RQ_BTUART 4
+# define PXA2XX_TX_RQ_BTUART 5
+# define PXA2XX_RX_RQ_FFUART 6
+# define PXA2XX_TX_RQ_FFUART 7
+# define PXA2XX_RX_RQ_SSP1 13
+# define PXA2XX_TX_RQ_SSP1 14
+# define PXA2XX_RX_RQ_SSP2 15
+# define PXA2XX_TX_RQ_SSP2 16
+# define PXA2XX_RX_RQ_ICP 17
+# define PXA2XX_TX_RQ_ICP 18
+# define PXA2XX_RX_RQ_STUART 19
+# define PXA2XX_TX_RQ_STUART 20
+# define PXA2XX_RX_RQ_MMCI 21
+# define PXA2XX_TX_RQ_MMCI 22
+# define PXA2XX_USB_RQ(x) ((x) + 24)
+# define PXA2XX_RX_RQ_SSP3 66
+# define PXA2XX_TX_RQ_SSP3 67
+
+# define PXA2XX_SDRAM_BASE 0xa0000000
+# define PXA2XX_INTERNAL_BASE 0x5c000000
+# define PXA2XX_INTERNAL_SIZE 0x40000
+
+/* pxa2xx_pic.c */
+DeviceState *pxa2xx_pic_init(hwaddr base, ARMCPU *cpu);
+
+/* pxa2xx_gpio.c */
+DeviceState *pxa2xx_gpio_init(hwaddr base,
+ ARMCPU *cpu, DeviceState *pic, int lines);
+void pxa2xx_gpio_read_notifier(DeviceState *dev, qemu_irq handler);
+
+/* pxa2xx_dma.c */
+DeviceState *pxa255_dma_init(hwaddr base, qemu_irq irq);
+DeviceState *pxa27x_dma_init(hwaddr base, qemu_irq irq);
+
+/* pxa2xx_lcd.c */
+typedef struct PXA2xxLCDState PXA2xxLCDState;
+PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
+ hwaddr base, qemu_irq irq);
+void pxa2xx_lcd_vsync_notifier(PXA2xxLCDState *s, qemu_irq handler);
+
+/* pxa2xx_mmci.c */
+#define TYPE_PXA2XX_MMCI "pxa2xx-mmci"
+OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxMMCIState, PXA2XX_MMCI)
+
+PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem,
+ hwaddr base,
+ 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 */
+#define TYPE_PXA2XX_PCMCIA "pxa2xx-pcmcia"
+OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxPCMCIAState, PXA2XX_PCMCIA)
+
+PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
+ hwaddr base);
+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);
+
+/* pxa2xx_keypad.c */
+struct keymap {
+ int8_t column;
+ int8_t row;
+};
+typedef struct PXA2xxKeyPadState PXA2xxKeyPadState;
+PXA2xxKeyPadState *pxa27x_keypad_init(MemoryRegion *sysmem,
+ hwaddr base,
+ qemu_irq irq);
+void pxa27x_register_keypad(PXA2xxKeyPadState *kp,
+ const struct keymap *map, int size);
+
+/* pxa2xx.c */
+typedef struct PXA2xxI2CState PXA2xxI2CState;
+PXA2xxI2CState *pxa2xx_i2c_init(hwaddr base,
+ qemu_irq irq, uint32_t page_size);
+I2CBus *pxa2xx_i2c_bus(PXA2xxI2CState *s);
+
+#define TYPE_PXA2XX_I2C "pxa2xx_i2c"
+typedef struct PXA2xxI2SState PXA2xxI2SState;
+OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxI2CState, PXA2XX_I2C)
+
+#define TYPE_PXA2XX_FIR "pxa2xx-fir"
+OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxFIrState, PXA2XX_FIR)
+
+typedef struct {
+ ARMCPU *cpu;
+ DeviceState *pic;
+ qemu_irq reset;
+ MemoryRegion sdram;
+ MemoryRegion internal;
+ MemoryRegion cm_iomem;
+ MemoryRegion mm_iomem;
+ MemoryRegion pm_iomem;
+ DeviceState *dma;
+ DeviceState *gpio;
+ PXA2xxLCDState *lcd;
+ SSIBus **ssp;
+ PXA2xxI2CState *i2c[2];
+ PXA2xxMMCIState *mmc;
+ PXA2xxPCMCIAState *pcmcia[2];
+ PXA2xxI2SState *i2s;
+ PXA2xxFIrState *fir;
+ PXA2xxKeyPadState *kp;
+
+ /* Power management */
+ hwaddr pm_base;
+ uint32_t pm_regs[0x40];
+
+ /* Clock management */
+ hwaddr cm_base;
+ uint32_t cm_regs[4];
+ uint32_t clkcfg;
+
+ /* Memory management */
+ hwaddr mm_base;
+ uint32_t mm_regs[0x1a];
+
+ /* Performance monitoring */
+ uint32_t pmnc;
+} PXA2xxState;
+
+struct PXA2xxI2SState {
+ MemoryRegion iomem;
+ qemu_irq irq;
+ qemu_irq rx_dma;
+ qemu_irq tx_dma;
+ void (*data_req)(void *, int, int);
+
+ uint32_t control[2];
+ uint32_t status;
+ uint32_t mask;
+ uint32_t clk;
+
+ int enable;
+ int rx_len;
+ int tx_len;
+ void (*codec_out)(void *, uint32_t);
+ uint32_t (*codec_in)(void *);
+ void *opaque;
+
+ int fifo_len;
+ uint32_t fifo[16];
+};
+
+# 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);
+
+#endif /* PXA_H */
diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h
new file mode 100644
index 000000000..e0e6c8ce9
--- /dev/null
+++ b/include/hw/arm/raspi_platform.h
@@ -0,0 +1,174 @@
+/*
+ * bcm2708 aka bcm2835/2836 aka Raspberry Pi/Pi2 SoC platform defines
+ *
+ * These definitions are derived from those in Raspbian Linux at
+ * arch/arm/mach-{bcm2708,bcm2709}/include/mach/platform.h
+ * where they carry the following notice:
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * 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
+
+#define MSYNC_OFFSET 0x0000 /* Multicore Sync Block */
+#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 ARBA_OFFSET 0x9000
+#define BRDG_OFFSET 0xa000
+#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 (SP804) */
+#define ARMCTRL_0_SBM_OFFSET (ARM_OFFSET + 0x800) /* User 0 (ARM) Semaphores
+ * Doorbells & Mailboxes */
+#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 /* 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 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
+#define INTERRUPT_TIMER1 1
+#define INTERRUPT_TIMER2 2
+#define INTERRUPT_TIMER3 3
+#define INTERRUPT_CODEC0 4
+#define INTERRUPT_CODEC1 5
+#define INTERRUPT_CODEC2 6
+#define INTERRUPT_JPEG 7
+#define INTERRUPT_ISP 8
+#define INTERRUPT_USB 9
+#define INTERRUPT_3D 10
+#define INTERRUPT_TRANSPOSER 11
+#define INTERRUPT_MULTICORESYNC0 12
+#define INTERRUPT_MULTICORESYNC1 13
+#define INTERRUPT_MULTICORESYNC2 14
+#define INTERRUPT_MULTICORESYNC3 15
+#define INTERRUPT_DMA0 16
+#define INTERRUPT_DMA1 17
+#define INTERRUPT_DMA2 18
+#define INTERRUPT_DMA3 19
+#define INTERRUPT_DMA4 20
+#define INTERRUPT_DMA5 21
+#define INTERRUPT_DMA6 22
+#define INTERRUPT_DMA7 23
+#define INTERRUPT_DMA8 24
+#define INTERRUPT_DMA9 25
+#define INTERRUPT_DMA10 26
+#define INTERRUPT_DMA11 27
+#define INTERRUPT_DMA12 28
+#define INTERRUPT_AUX 29
+#define INTERRUPT_ARM 30
+#define INTERRUPT_VPUDMA 31
+#define INTERRUPT_HOSTPORT 32
+#define INTERRUPT_VIDEOSCALER 33
+#define INTERRUPT_CCP2TX 34
+#define INTERRUPT_SDC 35
+#define INTERRUPT_DSI0 36
+#define INTERRUPT_AVE 37
+#define INTERRUPT_CAM0 38
+#define INTERRUPT_CAM1 39
+#define INTERRUPT_HDMI0 40
+#define INTERRUPT_HDMI1 41
+#define INTERRUPT_PIXELVALVE1 42
+#define INTERRUPT_I2CSPISLV 43
+#define INTERRUPT_DSI1 44
+#define INTERRUPT_PWA0 45
+#define INTERRUPT_PWA1 46
+#define INTERRUPT_CPR 47
+#define INTERRUPT_SMI 48
+#define INTERRUPT_GPIO0 49
+#define INTERRUPT_GPIO1 50
+#define INTERRUPT_GPIO2 51
+#define INTERRUPT_GPIO3 52
+#define INTERRUPT_I2C 53
+#define INTERRUPT_SPI 54
+#define INTERRUPT_I2SPCM 55
+#define INTERRUPT_SDIO 56
+#define INTERRUPT_UART0 57
+#define INTERRUPT_SLIMBUS 58
+#define INTERRUPT_VEC 59
+#define INTERRUPT_CPG 60
+#define INTERRUPT_RNG 61
+#define INTERRUPT_ARASANSDIO 62
+#define INTERRUPT_AVSPMON 63
+
+/* ARM CPU IRQs use a private number space */
+#define INTERRUPT_ARM_TIMER 0
+#define INTERRUPT_ARM_MAILBOX 1
+#define INTERRUPT_ARM_DOORBELL_0 2
+#define INTERRUPT_ARM_DOORBELL_1 3
+#define INTERRUPT_VPU0_HALTED 4
+#define INTERRUPT_VPU1_HALTED 5
+#define INTERRUPT_ILLEGAL_TYPE0 6
+#define INTERRUPT_ILLEGAL_TYPE1 7
+
+#endif
diff --git a/include/hw/arm/sharpsl.h b/include/hw/arm/sharpsl.h
new file mode 100644
index 000000000..e986b28c5
--- /dev/null
+++ b/include/hw/arm/sharpsl.h
@@ -0,0 +1,17 @@
+/*
+ * Common declarations for the Zaurii.
+ *
+ * This file is licensed under the GNU GPL.
+ */
+
+#ifndef QEMU_SHARPSL_H
+#define QEMU_SHARPSL_H
+
+#include "exec/hwaddr.h"
+
+/* zaurus.c */
+
+#define SL_PXA_PARAM_BASE 0xa0000a00
+void sl_bootparam_write(hwaddr ptr);
+
+#endif
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
new file mode 100644
index 000000000..706be3c6d
--- /dev/null
+++ b/include/hw/arm/smmu-common.h
@@ -0,0 +1,178 @@
+/*
+ * ARM SMMU Support
+ *
+ * Copyright (C) 2015-2016 Broadcom Corporation
+ * Copyright (c) 2017 Red Hat, Inc.
+ * Written by Prem Mallappa, Eric Auger
+ *
+ * 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 HW_ARM_SMMU_COMMON_H
+#define HW_ARM_SMMU_COMMON_H
+
+#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_MAX_VA_BITS 48
+
+/*
+ * Page table walk error types
+ */
+typedef enum {
+ SMMU_PTW_ERR_NONE,
+ SMMU_PTW_ERR_WALK_EABT, /* Translation walk external abort */
+ SMMU_PTW_ERR_TRANSLATION, /* Translation fault */
+ SMMU_PTW_ERR_ADDR_SIZE, /* Address Size fault */
+ SMMU_PTW_ERR_ACCESS, /* Access fault */
+ SMMU_PTW_ERR_PERMISSION, /* Permission fault */
+} SMMUPTWEventType;
+
+typedef struct SMMUPTWEventInfo {
+ SMMUPTWEventType type;
+ dma_addr_t addr; /* fetched address that induced an abort, if any */
+} SMMUPTWEventInfo;
+
+typedef struct SMMUTransTableInfo {
+ bool disabled; /* is the translation table disabled? */
+ 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;
+
+/*
+ * Generic structure populated by derived SMMU devices
+ * after decoding the configuration information and used as
+ * input to the page table walk
+ */
+typedef struct SMMUTransCfg {
+ 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 */
+ 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 */
+} SMMUTransCfg;
+
+typedef struct SMMUDevice {
+ void *smmu;
+ PCIBus *bus;
+ int devfn;
+ IOMMUMemoryRegion iommu;
+ AddressSpace as;
+ uint32_t cfg_cache_hits;
+ uint32_t cfg_cache_misses;
+ QLIST_ENTRY(SMMUDevice) next;
+} SMMUDevice;
+
+typedef struct SMMUPciBus {
+ PCIBus *bus;
+ SMMUDevice *pbdev[]; /* Parent array is sparse, so dynamically alloc */
+} SMMUPciBus;
+
+typedef struct SMMUIOTLBKey {
+ uint64_t iova;
+ uint16_t asid;
+ uint8_t tg;
+ uint8_t level;
+} SMMUIOTLBKey;
+
+struct SMMUState {
+ /* <private> */
+ SysBusDevice dev;
+ const char *mrtypename;
+ MemoryRegion iomem;
+
+ GHashTable *smmu_pcibus_by_busptr;
+ GHashTable *configs; /* cache for configuration data */
+ GHashTable *iotlb;
+ SMMUPciBus *smmu_pcibus_by_bus_num[SMMU_PCI_BUS_MAX];
+ PCIBus *pci_bus;
+ QLIST_HEAD(, SMMUDevice) devices_with_notifiers;
+ uint8_t bus_num;
+ PCIBus *primary_bus;
+};
+
+struct SMMUBaseClass {
+ /* <private> */
+ SysBusDeviceClass parent_class;
+
+ /*< public >*/
+
+ DeviceRealize parent_realize;
+
+};
+
+#define TYPE_ARM_SMMU "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);
+
+/* Return the stream ID of an SMMU device */
+static inline uint16_t smmu_get_sid(SMMUDevice *sdev)
+{
+ return PCI_BUILD_BDF(pci_bus_num(sdev->bus), sdev->devfn);
+}
+
+/**
+ * smmu_ptw - Perform the page table walk for a given iova / access flags
+ * pair, according to @cfg translation config
+ */
+int smmu_ptw(SMMUTransCfg *cfg, dma_addr_t iova, IOMMUAccessFlags perm,
+ SMMUTLBEntry *tlbe, SMMUPTWEventInfo *info);
+
+/**
+ * select_tt - compute which translation table shall be used according to
+ * the input iova and translation config and return the TT specific info
+ */
+SMMUTransTableInfo *select_tt(SMMUTransCfg *cfg, dma_addr_t iova);
+
+/* Return the iommu mr associated to @sid, or NULL if none */
+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, 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, int asid, 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
new file mode 100644
index 000000000..c641e6073
--- /dev/null
+++ b/include/hw/arm/smmuv3.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2014-2016 Broadcom Corporation
+ * Copyright (c) 2017 Red Hat, Inc.
+ * Written by Prem Mallappa, Eric Auger
+ *
+ * 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.
+ *
+ * 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_SMMUV3_H
+#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"
+
+typedef struct SMMUQueue {
+ uint64_t base; /* base register */
+ uint32_t prod;
+ uint32_t cons;
+ uint8_t entry_size;
+ uint8_t log2size;
+} SMMUQueue;
+
+struct SMMUv3State {
+ SMMUState smmu_state;
+
+ uint32_t features;
+ uint8_t sid_size;
+ uint8_t sid_split;
+
+ uint32_t idr[6];
+ uint32_t iidr;
+ uint32_t aidr;
+ uint32_t cr[3];
+ uint32_t cr0ack;
+ uint32_t statusr;
+ uint32_t irq_ctrl;
+ uint32_t gerror;
+ uint32_t gerrorn;
+ uint64_t gerror_irq_cfg0;
+ uint32_t gerror_irq_cfg1;
+ uint32_t gerror_irq_cfg2;
+ uint64_t strtab_base;
+ uint32_t strtab_base_cfg;
+ uint64_t eventq_irq_cfg0;
+ uint32_t eventq_irq_cfg1;
+ uint32_t eventq_irq_cfg2;
+
+ SMMUQueue eventq, cmdq;
+
+ qemu_irq irq[4];
+ QemuMutex mutex;
+};
+
+typedef enum {
+ SMMU_IRQ_EVTQ,
+ SMMU_IRQ_PRIQ,
+ SMMU_IRQ_CMD_SYNC,
+ SMMU_IRQ_GERROR,
+} SMMUIrq;
+
+struct SMMUv3Class {
+ /*< private >*/
+ SMMUBaseClass smmu_base_class;
+ /*< public >*/
+
+ DeviceRealize parent_realize;
+ DeviceReset parent_reset;
+};
+
+#define TYPE_ARM_SMMUV3 "arm-smmuv3"
+OBJECT_DECLARE_TYPE(SMMUv3State, SMMUv3Class, ARM_SMMUV3)
+
+#endif
diff --git a/include/hw/arm/soc_dma.h b/include/hw/arm/soc_dma.h
new file mode 100644
index 000000000..e93a7499a
--- /dev/null
+++ b/include/hw/arm/soc_dma.h
@@ -0,0 +1,114 @@
+/*
+ * On-chip DMA controller framework.
+ *
+ * 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_SOC_DMA_H
+#define HW_SOC_DMA_H
+
+#include "exec/hwaddr.h"
+
+struct soc_dma_s;
+struct soc_dma_ch_s;
+typedef void (*soc_dma_io_t)(void *opaque, uint8_t *buf, int len);
+typedef void (*soc_dma_transfer_t)(struct soc_dma_ch_s *ch);
+
+enum soc_dma_port_type {
+ soc_dma_port_mem,
+ soc_dma_port_fifo,
+ soc_dma_port_other,
+};
+
+enum soc_dma_access_type {
+ soc_dma_access_const,
+ soc_dma_access_linear,
+ soc_dma_access_other,
+};
+
+struct soc_dma_ch_s {
+ /* Private */
+ struct soc_dma_s *dma;
+ int num;
+ QEMUTimer *timer;
+
+ /* Set by soc_dma.c */
+ int enable;
+ int update;
+
+ /* This should be set by dma->setup_fn(). */
+ int bytes;
+ /* Initialised by the DMA module, call soc_dma_ch_update after writing. */
+ enum soc_dma_access_type type[2];
+ hwaddr vaddr[2]; /* Updated by .transfer_fn(). */
+ /* Private */
+ void *paddr[2];
+ soc_dma_io_t io_fn[2];
+ void *io_opaque[2];
+
+ int running;
+ soc_dma_transfer_t transfer_fn;
+
+ /* Set and used by the DMA module. */
+ void *opaque;
+};
+
+struct soc_dma_s {
+ /* Following fields are set by the SoC DMA module and can be used
+ * by anybody. */
+ uint64_t drqbmp; /* Is zeroed by soc_dma_reset() */
+ qemu_irq *drq;
+ void *opaque;
+ int64_t freq;
+ soc_dma_transfer_t transfer_fn;
+ soc_dma_transfer_t setup_fn;
+ /* Set by soc_dma_init() for use by the DMA module. */
+ struct soc_dma_ch_s *ch;
+};
+
+/* Call to activate or stop a DMA channel. */
+void soc_dma_set_request(struct soc_dma_ch_s *ch, int level);
+/* Call after every write to one of the following fields and before
+ * calling soc_dma_set_request(ch, 1):
+ * ch->type[0...1],
+ * ch->vaddr[0...1],
+ * ch->paddr[0...1],
+ * or after a soc_dma_port_add_fifo() or soc_dma_port_add_mem(). */
+void soc_dma_ch_update(struct soc_dma_ch_s *ch);
+
+/* The SoC should call this when the DMA module is being reset. */
+void soc_dma_reset(struct soc_dma_s *s);
+struct soc_dma_s *soc_dma_init(int n);
+
+void soc_dma_port_add_fifo(struct soc_dma_s *dma, hwaddr virt_base,
+ soc_dma_io_t fn, void *opaque, int out);
+void soc_dma_port_add_mem(struct soc_dma_s *dma, uint8_t *phys_base,
+ hwaddr virt_base, size_t size);
+
+static inline void soc_dma_port_add_fifo_in(struct soc_dma_s *dma,
+ hwaddr virt_base, soc_dma_io_t fn, void *opaque)
+{
+ return soc_dma_port_add_fifo(dma, virt_base, fn, opaque, 0);
+}
+
+static inline void soc_dma_port_add_fifo_out(struct soc_dma_s *dma,
+ hwaddr virt_base, soc_dma_io_t fn, void *opaque)
+{
+ return soc_dma_port_add_fifo(dma, virt_base, fn, opaque, 1);
+}
+
+#endif
diff --git a/include/hw/arm/stm32f100_soc.h b/include/hw/arm/stm32f100_soc.h
new file mode 100644
index 000000000..40cd415b2
--- /dev/null
+++ b/include/hw/arm/stm32f100_soc.h
@@ -0,0 +1,65 @@
+/*
+ * 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 {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ char *cpu_type;
+
+ 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
new file mode 100644
index 000000000..849d3ed88
--- /dev/null
+++ b/include/hw/arm/stm32f205_soc.h
@@ -0,0 +1,76 @@
+/*
+ * STM32F205 SoC
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * 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_STM32F205_SOC_H
+#define HW_ARM_STM32F205_SOC_H
+
+#include "hw/misc/stm32f2xx_syscfg.h"
+#include "hw/timer/stm32f2xx_timer.h"
+#include "hw/char/stm32f2xx_usart.h"
+#include "hw/adc/stm32f2xx_adc.h"
+#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"
+OBJECT_DECLARE_SIMPLE_TYPE(STM32F205State, STM32F205_SOC)
+
+#define STM_NUM_USARTS 6
+#define STM_NUM_TIMERS 4
+#define STM_NUM_ADCS 3
+#define STM_NUM_SPIS 3
+
+#define FLASH_BASE_ADDRESS 0x08000000
+#define FLASH_SIZE (1024 * 1024)
+#define SRAM_BASE_ADDRESS 0x20000000
+#define SRAM_SIZE (128 * 1024)
+
+struct STM32F205State {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ char *cpu_type;
+
+ ARMv7MState armv7m;
+
+ STM32F2XXSyscfgState syscfg;
+ STM32F2XXUsartState usart[STM_NUM_USARTS];
+ STM32F2XXTimerState timer[STM_NUM_TIMERS];
+ STM32F2XXADCState adc[STM_NUM_ADCS];
+ STM32F2XXSPIState spi[STM_NUM_SPIS];
+
+ qemu_or_irq *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
new file mode 100644
index 000000000..5bb0c8d56
--- /dev/null
+++ b/include/hw/arm/stm32f405_soc.h
@@ -0,0 +1,76 @@
+/*
+ * STM32F405 SoC
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * 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_STM32F405_SOC_H
+#define HW_ARM_STM32F405_SOC_H
+
+#include "hw/misc/stm32f4xx_syscfg.h"
+#include "hw/timer/stm32f2xx_timer.h"
+#include "hw/char/stm32f2xx_usart.h"
+#include "hw/adc/stm32f2xx_adc.h"
+#include "hw/misc/stm32f4xx_exti.h"
+#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"
+OBJECT_DECLARE_SIMPLE_TYPE(STM32F405State, STM32F405_SOC)
+
+#define STM_NUM_USARTS 7
+#define STM_NUM_TIMERS 4
+#define STM_NUM_ADCS 6
+#define STM_NUM_SPIS 6
+
+#define FLASH_BASE_ADDRESS 0x08000000
+#define FLASH_SIZE (1024 * 1024)
+#define SRAM_BASE_ADDRESS 0x20000000
+#define SRAM_SIZE (192 * 1024)
+
+struct STM32F405State {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ char *cpu_type;
+
+ ARMv7MState armv7m;
+
+ STM32F4xxSyscfgState syscfg;
+ STM32F4xxExtiState exti;
+ STM32F2XXUsartState usart[STM_NUM_USARTS];
+ STM32F2XXTimerState timer[STM_NUM_TIMERS];
+ qemu_or_irq adc_irqs;
+ STM32F2XXADCState adc[STM_NUM_ADCS];
+ STM32F2XXSPIState spi[STM_NUM_SPIS];
+
+ MemoryRegion sram;
+ MemoryRegion flash;
+ MemoryRegion flash_alias;
+
+ Clock *sysclk;
+ Clock *refclk;
+};
+
+#endif
diff --git a/include/hw/arm/sysbus-fdt.h b/include/hw/arm/sysbus-fdt.h
new file mode 100644
index 000000000..340c382cd
--- /dev/null
+++ b/include/hw/arm/sysbus-fdt.h
@@ -0,0 +1,37 @@
+/*
+ * Dynamic sysbus device tree node generation API
+ *
+ * Copyright Linaro Limited, 2014
+ *
+ * Authors:
+ * Alex Graf <agraf@suse.de>
+ * Eric Auger <eric.auger@linaro.org>
+ *
+ * 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_ARM_SYSBUS_FDT_H
+#define HW_ARM_SYSBUS_FDT_H
+
+#include "exec/hwaddr.h"
+
+/**
+ * platform_bus_add_all_fdt_nodes - create all the platform bus nodes
+ *
+ * builds the parent platform bus node and all the nodes of dynamic
+ * sysbus devices attached to it.
+ */
+void platform_bus_add_all_fdt_nodes(void *fdt, const char *intc, hwaddr addr,
+ hwaddr bus_size, int irq_start);
+#endif
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
new file mode 100644
index 000000000..dc6b66ffc
--- /dev/null
+++ b/include/hw/arm/virt.h
@@ -0,0 +1,195 @@
+/*
+ *
+ * Copyright (c) 2015 Linaro Limited
+ *
+ * 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/>.
+ *
+ * Emulate a virtual board which works by passing Linux all the information
+ * it needs about what devices are present via the device tree.
+ * There are some restrictions about what we can do here:
+ * + we can only present devices whose Linux drivers will work based
+ * purely on the device tree with no platform data at all
+ * + we want to present a very stripped-down minimalist platform,
+ * both because this reduces the security attack surface from the guest
+ * and also because it reduces our exposure to being broken when
+ * the kernel updates its device tree bindings and requires further
+ * information in a device binding that we aren't providing.
+ * This is essentially the same approach kvmtool uses.
+ */
+
+#ifndef QEMU_ARM_VIRT_H
+#define QEMU_ARM_VIRT_H
+
+#include "exec/hwaddr.h"
+#include "qemu/notify.h"
+#include "hw/boards.h"
+#include "hw/arm/boot.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,
+ VIRT_MEM,
+ VIRT_CPUPERIPHS,
+ VIRT_GIC_DIST,
+ VIRT_GIC_CPU,
+ VIRT_GIC_V2M,
+ VIRT_GIC_HYP,
+ VIRT_GIC_VCPU,
+ VIRT_GIC_ITS,
+ VIRT_GIC_REDIST,
+ VIRT_SMMU,
+ VIRT_UART,
+ VIRT_MMIO,
+ VIRT_RTC,
+ VIRT_FW_CFG,
+ VIRT_PCIE,
+ VIRT_PCIE_MMIO,
+ VIRT_PCIE_PIO,
+ VIRT_PCIE_ECAM,
+ VIRT_PLATFORM_BUS,
+ 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,
+};
+
+/* indices of IO regions located after the RAM */
+enum {
+ VIRT_HIGH_GIC_REDIST2 = VIRT_LOWMEMMAP_LAST,
+ VIRT_HIGH_PCIE_ECAM,
+ VIRT_HIGH_PCIE_MMIO,
+};
+
+typedef enum VirtIOMMUType {
+ VIRT_IOMMU_NONE,
+ VIRT_IOMMU_SMMUV3,
+ VIRT_IOMMU_VIRTIO,
+} VirtIOMMUType;
+
+typedef enum VirtMSIControllerType {
+ VIRT_MSI_CTRL_NONE,
+ VIRT_MSI_CTRL_GICV2M,
+ VIRT_MSI_CTRL_ITS,
+} VirtMSIControllerType;
+
+typedef enum VirtGICType {
+ VIRT_GIC_VERSION_MAX,
+ VIRT_GIC_VERSION_HOST,
+ VIRT_GIC_VERSION_2,
+ VIRT_GIC_VERSION_3,
+ VIRT_GIC_VERSION_NOSEL,
+} VirtGICType;
+
+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_ecam;
+ 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;
+ bool no_secure_gpio;
+ /* Machines < 6.2 have no support for describing cpu topology to guest */
+ bool no_cpu_topology;
+};
+
+struct VirtMachineState {
+ MachineState parent;
+ Notifier machine_done;
+ DeviceState *platform_bus_dev;
+ FWCfgState *fw_cfg;
+ PFlashCFI01 *flash[2];
+ bool secure;
+ bool highmem;
+ bool highmem_ecam;
+ bool its;
+ bool tcg_its;
+ bool virt;
+ bool ras;
+ bool mte;
+ 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 fdt_size;
+ uint32_t clock_phandle;
+ uint32_t gic_phandle;
+ uint32_t msi_phandle;
+ uint32_t iommu_phandle;
+ int psci_conduit;
+ hwaddr highest_gpa;
+ DeviceState *gic;
+ DeviceState *acpi_dev;
+ Notifier powerdown_notifier;
+ PCIBus *bus;
+ char *oem_id;
+ char *oem_table_id;
+};
+
+#define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM)
+
+#define TYPE_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
+OBJECT_DECLARE_TYPE(VirtMachineState, VirtMachineClass, VIRT_MACHINE)
+
+void virt_acpi_setup(VirtMachineState *vms);
+bool virt_is_acpi_enabled(VirtMachineState *vms);
+
+/* 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;
+
+ assert(vms->gic_version == VIRT_GIC_VERSION_3);
+
+ return MACHINE(vms)->smp.cpus > redist0_capacity ? 2 : 1;
+}
+
+#endif /* QEMU_ARM_VIRT_H */
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
new file mode 100644
index 000000000..895ba12c6
--- /dev/null
+++ b/include/hw/arm/xlnx-versal.h
@@ -0,0 +1,194 @@
+/*
+ * Model of the Xilinx Versal
+ *
+ * Copyright (c) 2018 Xilinx Inc.
+ * Written by Edgar E. Iglesias
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or
+ * (at your option) any later version.
+ */
+
+#ifndef XLNX_VERSAL_H
+#define XLNX_VERSAL_H
+
+#include "hw/sysbus.h"
+#include "hw/arm/boot.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"
+
+#define TYPE_XLNX_VERSAL "xlnx-versal"
+OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
+
+#define XLNX_VERSAL_NR_ACPUS 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
+
+struct Versal {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ struct {
+ struct {
+ MemoryRegion mr;
+ ARMCPU cpu[XLNX_VERSAL_NR_ACPUS];
+ GICv3State gic;
+ } apu;
+ } fpd;
+
+ MemoryRegion mr_ps;
+
+ struct {
+ /* 4 ranges to access DDR. */
+ MemoryRegion mr_ddr_ranges[4];
+ } noc;
+
+ struct {
+ MemoryRegion mr_ocm;
+
+ struct {
+ PL011State uart[XLNX_VERSAL_NR_UARTS];
+ CadenceGEMState gem[XLNX_VERSAL_NR_GEMS];
+ XlnxZDMA adma[XLNX_VERSAL_NR_ADMAS];
+ VersalUsb2 usb;
+ } iou;
+
+ struct {
+ qemu_or_irq irq_orgate;
+ XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM];
+ } xram;
+ } lpd;
+
+ /* The Platform Management Controller subsystem. */
+ struct {
+ struct {
+ SDHCIState sd[XLNX_VERSAL_NR_SDS];
+ } iou;
+
+ XlnxZynqMPRTC rtc;
+ XlnxBBRam bbram;
+ XlnxEFuse efuse;
+ XlnxVersalEFuseCtrl efuse_ctrl;
+ XlnxVersalEFuseCache efuse_cache;
+ } pmc;
+
+ struct {
+ MemoryRegion *mr_ddr;
+ uint32_t psci_conduit;
+ } cfg;
+};
+
+/* Memory-map and IRQ definitions. Copied a subset from
+ * auto-generated files. */
+
+#define VERSAL_GIC_MAINT_IRQ 9
+#define VERSAL_TIMER_VIRT_IRQ 11
+#define VERSAL_TIMER_S_EL1_IRQ 13
+#define VERSAL_TIMER_NS_EL1_IRQ 14
+#define VERSAL_TIMER_NS_EL2_IRQ 10
+
+#define VERSAL_UART0_IRQ_0 18
+#define VERSAL_UART1_IRQ_0 19
+#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_XRAM_IRQ_0 79
+#define VERSAL_BBRAM_APB_IRQ_0 121
+#define VERSAL_RTC_APB_ERR_IRQ 121
+#define VERSAL_SD0_IRQ_0 126
+#define VERSAL_EFUSE_IRQ 139
+#define VERSAL_RTC_ALARM_IRQ 142
+#define VERSAL_RTC_SECONDS_IRQ 143
+
+/* Architecturally reserved IRQs suitable for virtualization. */
+#define VERSAL_RSVD_IRQ_FIRST 111
+#define VERSAL_RSVD_IRQ_LAST 118
+
+#define MM_TOP_RSVD 0xa0000000U
+#define MM_TOP_RSVD_SIZE 0x4000000
+#define MM_GIC_APU_DIST_MAIN 0xf9000000U
+#define MM_GIC_APU_DIST_MAIN_SIZE 0x10000
+#define MM_GIC_APU_REDIST_0 0xf9080000U
+#define MM_GIC_APU_REDIST_0_SIZE 0x80000
+
+#define MM_UART0 0xff000000U
+#define MM_UART0_SIZE 0x10000
+#define MM_UART1 0xff010000U
+#define MM_UART1_SIZE 0x10000
+
+#define MM_GEM0 0xff0c0000U
+#define MM_GEM0_SIZE 0x10000
+#define MM_GEM1 0xff0d0000U
+#define MM_GEM1_SIZE 0x10000
+
+#define MM_ADMA_CH0 0xffa80000U
+#define MM_ADMA_CH0_SIZE 0x10000
+
+#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
+#define MM_TOP_DDR_2_SIZE 0x800000000ULL
+#define MM_TOP_DDR_3 0xc000000000ULL
+#define MM_TOP_DDR_3_SIZE 0x4000000000ULL
+#define MM_TOP_DDR_4 0x10000000000ULL
+#define MM_TOP_DDR_4_SIZE 0xb780000000ULL
+
+#define MM_PSM_START 0xffc80000U
+#define MM_PSM_END 0xffcf0000U
+
+#define MM_CRL 0xff5e0000U
+#define MM_CRL_SIZE 0x300000
+#define MM_IOU_SCNTR 0xff130000U
+#define MM_IOU_SCNTR_SIZE 0x10000
+#define MM_IOU_SCNTRS 0xff140000U
+#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_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_CRP 0xf1260000U
+#define MM_PMC_CRP_SIZE 0x10000
+#define MM_PMC_RTC 0xf12a0000
+#define MM_PMC_RTC_SIZE 0x10000
+#endif
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
new file mode 100644
index 000000000..062e637fe
--- /dev/null
+++ b/include/hw/arm/xlnx-zynqmp.h
@@ -0,0 +1,138 @@
+/*
+ * Xilinx Zynq MPSoC emulation
+ *
+ * Copyright (C) 2015 Xilinx Inc
+ * Written by Peter Crosthwaite <peter.crosthwaite@xilinx.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 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/net/xlnx-zynqmp-can.h"
+#include "hw/ide/ahci.h"
+#include "hw/sd/sdhci.h"
+#include "hw/ssi/xilinx_spips.h"
+#include "hw/dma/xlnx_dpdma.h"
+#include "hw/dma/xlnx-zdma.h"
+#include "hw/display/xlnx_dp.h"
+#include "hw/intc/xlnx-zynqmp-ipi.h"
+#include "hw/rtc/xlnx-zynqmp-rtc.h"
+#include "hw/cpu/cluster.h"
+#include "target/arm/cpu.h"
+#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"
+
+#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_QSPI_BUS 2
+#define XLNX_ZYNQMP_NUM_QSPI_BUS_CS 2
+#define XLNX_ZYNQMP_NUM_QSPI_FLASH 4
+
+#define XLNX_ZYNQMP_NUM_OCM_BANKS 4
+#define XLNX_ZYNQMP_OCM_RAM_0_ADDRESS 0xFFFC0000
+#define XLNX_ZYNQMP_OCM_RAM_SIZE 0x10000
+
+#define XLNX_ZYNQMP_GIC_REGIONS 6
+
+/*
+ * 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.
+ */
+
+#define XLNX_ZYNQMP_GIC_REGION_SIZE 0x1000
+#define XLNX_ZYNQMP_GIC_ALIASES (0x10000 / XLNX_ZYNQMP_GIC_REGION_SIZE)
+
+#define XLNX_ZYNQMP_MAX_LOW_RAM_SIZE 0x80000000ull
+
+#define XLNX_ZYNQMP_MAX_HIGH_RAM_SIZE 0x800000000ull
+#define XLNX_ZYNQMP_HIGH_RAM_START 0x800000000ull
+
+#define XLNX_ZYNQMP_MAX_RAM_SIZE (XLNX_ZYNQMP_MAX_LOW_RAM_SIZE + \
+ XLNX_ZYNQMP_MAX_HIGH_RAM_SIZE)
+
+/*
+ * Unimplemented mmio regions needed to boot some images.
+ */
+#define XLNX_ZYNQMP_NUM_UNIMP_AREAS 1
+
+struct XlnxZynqMPState {
+ /*< private >*/
+ DeviceState parent_obj;
+
+ /*< public >*/
+ CPUClusterState apu_cluster;
+ CPUClusterState rpu_cluster;
+ ARMCPU apu_cpu[XLNX_ZYNQMP_NUM_APU_CPUS];
+ ARMCPU rpu_cpu[XLNX_ZYNQMP_NUM_RPU_CPUS];
+ GICState gic;
+ MemoryRegion gic_mr[XLNX_ZYNQMP_GIC_REGIONS][XLNX_ZYNQMP_GIC_ALIASES];
+
+ MemoryRegion ocm_ram[XLNX_ZYNQMP_NUM_OCM_BANKS];
+
+ 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];
+ XlnxZynqMPQSPIPS qspi;
+ XlnxDPState dp;
+ XlnxDPDMAState dpdma;
+ XlnxZynqMPIPI ipi;
+ XlnxZynqMPRTC rtc;
+ XlnxZDMA gdma[XLNX_ZYNQMP_NUM_GDMA_CH];
+ XlnxZDMA adma[XLNX_ZYNQMP_NUM_ADMA_CH];
+ XlnxCSUDMA qspi_dma;
+
+ char *boot_cpu;
+ ARMCPU *boot_cpu_ptr;
+
+ /* Has the ARM Security extensions? */
+ bool secure;
+ /* Has the ARM Virtualization extensions? */
+ bool virt;
+
+ /* CAN bus. */
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
+};
+
+#endif
diff --git a/include/hw/audio/pcspk.h b/include/hw/audio/pcspk.h
new file mode 100644
index 000000000..950617958
--- /dev/null
+++ b/include/hw/audio/pcspk.h
@@ -0,0 +1,40 @@
+/*
+ * QEMU PC speaker emulation
+ *
+ * Copyright (c) 2006 Joachim Henke
+ *
+ * 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_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
new file mode 100644
index 000000000..f09a29785
--- /dev/null
+++ b/include/hw/audio/soundhw.h
@@ -0,0 +1,15 @@
+#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));
+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);
+
+#endif
diff --git a/include/hw/audio/wm8750.h b/include/hw/audio/wm8750.h
new file mode 100644
index 000000000..f7bafd5e3
--- /dev/null
+++ b/include/hw/audio/wm8750.h
@@ -0,0 +1,30 @@
+/*
+ * 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_DAC_WM8750_H
+#define HW_DAC_WM8750_H
+
+
+#define TYPE_WM8750 "wm8750"
+#define TYPE_MV88W8618_AUDIO "mv88w8618_audio"
+
+typedef void data_req_cb(void *opaque, int free_out, int free_in);
+
+void wm8750_data_req_set(DeviceState *dev, data_req_cb *data_req, void *opaque);
+void wm8750_dac_dat(void *opaque, uint32_t sample);
+uint32_t wm8750_adc_dat(void *opaque);
+void *wm8750_dac_buffer(void *opaque, int samples);
+void wm8750_dac_commit(void *opaque);
+void wm8750_set_bclk_in(void *opaque, int new_hz);
+
+#endif
diff --git a/include/hw/block/block.h b/include/hw/block/block.h
new file mode 100644
index 000000000..5902c0440
--- /dev/null
+++ b/include/hw/block/block.h
@@ -0,0 +1,105 @@
+/*
+ * Common code for block device models
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * 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_BLOCK_H
+#define HW_BLOCK_H
+
+#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;
+ uint32_t opt_io_size;
+ int32_t bootindex;
+ uint32_t discard_granularity;
+ /* geometry, not all devices use this */
+ uint32_t cyls, heads, secs;
+ uint32_t lcyls, lheads, lsecs;
+ OnOffAuto wce;
+ bool share_rw;
+ BlockdevOnError rerror;
+ BlockdevOnError werror;
+} BlockConf;
+
+static inline unsigned int get_physical_block_exp(BlockConf *conf)
+{
+ unsigned int exp = 0, size;
+
+ for (size = conf->physical_block_size;
+ size > conf->logical_block_size;
+ size >>= 1) {
+ exp++;
+ }
+
+ return exp;
+}
+
+#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, \
+ _conf.physical_block_size), \
+ DEFINE_PROP_SIZE32("min_io_size", _state, _conf.min_io_size, 0), \
+ DEFINE_PROP_SIZE32("opt_io_size", _state, _conf.opt_io_size, 0), \
+ DEFINE_PROP_SIZE32("discard_granularity", _state, \
+ _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 DEFINE_BLOCK_PROPERTIES(_state, _conf) \
+ DEFINE_PROP_DRIVE("drive", _state, _conf.blk), \
+ DEFINE_BLOCK_PROPERTIES_BASE(_state, _conf)
+
+#define DEFINE_BLOCK_CHS_PROPERTIES(_state, _conf) \
+ DEFINE_PROP_UINT32("cyls", _state, _conf.cyls, 0), \
+ DEFINE_PROP_UINT32("heads", _state, _conf.heads, 0), \
+ DEFINE_PROP_UINT32("secs", _state, _conf.secs, 0), \
+ DEFINE_PROP_UINT32("lcyls", _state, _conf.lcyls, 0), \
+ DEFINE_PROP_UINT32("lheads", _state, _conf.lheads, 0), \
+ DEFINE_PROP_UINT32("lsecs", _state, _conf.lsecs, 0)
+
+#define DEFINE_BLOCK_ERROR_PROPERTIES(_state, _conf) \
+ DEFINE_PROP_BLOCKDEV_ON_ERROR("rerror", _state, _conf.rerror, \
+ BLOCKDEV_ON_ERROR_AUTO), \
+ DEFINE_PROP_BLOCKDEV_ON_ERROR("werror", _state, _conf.werror, \
+ BLOCKDEV_ON_ERROR_AUTO)
+
+/* Backend access helpers */
+
+bool blk_check_size_and_read_all(BlockBackend *blk, void *buf, hwaddr size,
+ Error **errp);
+
+/* Configuration helpers */
+
+bool blkconf_geometry(BlockConf *conf, int *trans,
+ unsigned cyls_max, unsigned heads_max, unsigned secs_max,
+ Error **errp);
+bool blkconf_blocksizes(BlockConf *conf, Error **errp);
+bool blkconf_apply_backend_options(BlockConf *conf, bool readonly,
+ bool resizable, Error **errp);
+
+/* Hard disk geometry */
+
+void hd_geometry_guess(BlockBackend *blk,
+ uint32_t *pcyls, uint32_t *pheads, uint32_t *psecs,
+ int *ptrans);
+int hd_bios_chs_auto_trans(uint32_t cyls, uint32_t heads, uint32_t secs);
+
+#endif
diff --git a/include/hw/block/fdc.h b/include/hw/block/fdc.h
new file mode 100644
index 000000000..1ecca7cac
--- /dev/null
+++ b/include/hw/block/fdc.h
@@ -0,0 +1,21 @@
+#ifndef HW_FDC_H
+#define HW_FDC_H
+
+#include "exec/hwaddr.h"
+#include "qapi/qapi-types-block.h"
+
+/* fdc.c */
+#define MAX_FD 2
+
+#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 sun4m_fdctrl_init(qemu_irq irq, hwaddr io_base,
+ DriveInfo **fds, qemu_irq *fdc_tc);
+
+FloppyDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i);
+int cmos_get_fd_drive_type(FloppyDriveType fd0);
+
+#endif
diff --git a/include/hw/block/flash.h b/include/hw/block/flash.h
new file mode 100644
index 000000000..86d8363bb
--- /dev/null
+++ b/include/hw/block/flash.h
@@ -0,0 +1,79 @@
+#ifndef HW_FLASH_H
+#define HW_FLASH_H
+
+/* NOR flash devices */
+
+#include "exec/hwaddr.h"
+#include "qom/object.h"
+
+/* pflash_cfi01.c */
+
+#define TYPE_PFLASH_CFI01 "cfi.pflash01"
+OBJECT_DECLARE_SIMPLE_TYPE(PFlashCFI01, PFLASH_CFI01)
+
+
+PFlashCFI01 *pflash_cfi01_register(hwaddr base,
+ const char *name,
+ hwaddr size,
+ BlockBackend *blk,
+ uint32_t sector_len,
+ int width,
+ uint16_t id0, uint16_t id1,
+ uint16_t id2, uint16_t id3,
+ int be);
+BlockBackend *pflash_cfi01_get_blk(PFlashCFI01 *fl);
+MemoryRegion *pflash_cfi01_get_memory(PFlashCFI01 *fl);
+void pflash_cfi01_legacy_drive(PFlashCFI01 *dev, DriveInfo *dinfo);
+
+/* pflash_cfi02.c */
+
+#define TYPE_PFLASH_CFI02 "cfi.pflash02"
+OBJECT_DECLARE_SIMPLE_TYPE(PFlashCFI02, PFLASH_CFI02)
+
+
+PFlashCFI02 *pflash_cfi02_register(hwaddr base,
+ const char *name,
+ hwaddr size,
+ BlockBackend *blk,
+ uint32_t sector_len,
+ int nb_mappings,
+ int width,
+ uint16_t id0, uint16_t id1,
+ uint16_t id2, uint16_t id3,
+ uint16_t unlock_addr0,
+ uint16_t unlock_addr1,
+ int be);
+
+/* nand.c */
+DeviceState *nand_init(BlockBackend *blk, int manf_id, int chip_id);
+void nand_setpins(DeviceState *dev, uint8_t cle, uint8_t ale,
+ uint8_t ce, uint8_t wp, uint8_t gnd);
+void nand_getpins(DeviceState *dev, int *rb);
+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
+
+/* onenand.c */
+void *onenand_raw_otp(DeviceState *onenand_device);
+
+/* ecc.c */
+typedef struct {
+ 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 const VMStateDescription vmstate_ecc_state;
+
+#endif
diff --git a/include/hw/block/swim.h b/include/hw/block/swim.h
new file mode 100644
index 000000000..c1bd5f655
--- /dev/null
+++ b/include/hw/block/swim.h
@@ -0,0 +1,74 @@
+/*
+ * QEMU Macintosh floppy disk controller emulator (SWIM)
+ *
+ * Copyright (c) 2014-2018 Laurent Vivier <laurent@vivier.eu>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef SWIM_H
+#define SWIM_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define SWIM_MAX_FD 2
+
+typedef struct SWIMCtrl SWIMCtrl;
+
+#define TYPE_SWIM_DRIVE "swim-drive"
+OBJECT_DECLARE_SIMPLE_TYPE(SWIMDrive, SWIM_DRIVE)
+
+struct SWIMDrive {
+ DeviceState qdev;
+ int32_t unit;
+ BlockConf conf;
+};
+
+#define TYPE_SWIM_BUS "swim-bus"
+OBJECT_DECLARE_SIMPLE_TYPE(SWIMBus, SWIM_BUS)
+
+struct SWIMBus {
+ BusState bus;
+ struct SWIMCtrl *ctrl;
+};
+
+typedef struct FDrive {
+ SWIMCtrl *swimctrl;
+ BlockBackend *blk;
+ BlockConf *conf;
+} FDrive;
+
+struct SWIMCtrl {
+ MemoryRegion iomem;
+ 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;
+ /* SWIM mode */
+ uint8_t swim_phase;
+ uint8_t swim_mode;
+ SWIMBus bus;
+};
+
+#define TYPE_SWIM "swim"
+OBJECT_DECLARE_SIMPLE_TYPE(Swim, SWIM)
+
+struct Swim {
+ SysBusDevice parent_obj;
+ SWIMCtrl ctrl;
+};
+#endif
diff --git a/include/hw/boards.h b/include/hw/boards.h
new file mode 100644
index 000000000..9c1c19010
--- /dev/null
+++ b/include/hw/boards.h
@@ -0,0 +1,444 @@
+/* Declarations for use by board files for creating devices. */
+
+#ifndef HW_BOARDS_H
+#define HW_BOARDS_H
+
+#include "exec/memory.h"
+#include "sysemu/hostmem.h"
+#include "sysemu/blockdev.h"
+#include "qemu/accel.h"
+#include "qapi/qapi-types-machine.h"
+#include "qemu/module.h"
+#include "qom/object.h"
+#include "hw/core/cpu.h"
+
+#define TYPE_MACHINE_SUFFIX "-machine"
+
+/* Machine class name that needs to be used for class-name-based machine
+ * type lookup to work.
+ */
+#define MACHINE_TYPE_NAME(machinename) (machinename TYPE_MACHINE_SUFFIX)
+
+#define TYPE_MACHINE "machine"
+#undef MACHINE /* BSD defines it and QEMU does not use it */
+OBJECT_DECLARE_TYPE(MachineState, MachineClass, MACHINE)
+
+extern MachineState *current_machine;
+
+void machine_run_board_init(MachineState *machine);
+bool machine_usb(MachineState *machine);
+int machine_phandle_start(MachineState *machine);
+bool machine_dump_guest_core(MachineState *machine);
+bool machine_mem_merge(MachineState *machine);
+HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine);
+void machine_set_cpu_numa_node(MachineState *machine,
+ const CpuInstanceProperties *props,
+ Error **errp);
+void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp);
+
+/**
+ * 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.
+ */
+MemoryRegion *machine_consume_memdev(MachineState *machine,
+ HostMemoryBackend *backend);
+
+/**
+ * CPUArchId:
+ * @arch_id - architecture-dependent CPU ID of present or possible CPU
+ * @cpu - pointer to corresponding CPU object if it's present on NULL otherwise
+ * @type - QOM class name of possible @cpu object
+ * @props - CPU object properties, initialized by board
+ * #vcpus_count - number of threads provided by @cpu object
+ */
+typedef struct CPUArchId {
+ uint64_t arch_id;
+ int64_t vcpus_count;
+ CpuInstanceProperties props;
+ Object *cpu;
+ const char *type;
+} CPUArchId;
+
+/**
+ * CPUArchIdList:
+ * @len - number of @CPUArchId items in @cpus array
+ * @cpus - array of present or possible CPUs for current machine configuration
+ */
+typedef struct {
+ int len;
+ CPUArchId cpus[];
+} CPUArchIdList;
+
+/**
+ * SMPCompatProps:
+ * @prefer_sockets - whether sockets are preferred over cores in smp parsing
+ * @dies_supported - whether dies are supported by the machine
+ */
+typedef struct {
+ bool prefer_sockets;
+ bool dies_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.
+ * @max_cpus: maximum number of CPUs supported. Default: 1
+ * @min_cpus: minimum number of CPUs supported. Default: 1
+ * @default_cpus: number of CPUs instantiated if none are specified. Default: 1
+ * @is_default:
+ * If true QEMU will use this machine by default if no '-M' option is given.
+ * @get_hotplug_handler: this function is called during bus-less
+ * device hotplug. If defined it returns pointer to an instance
+ * of HotplugHandler object, which handles hotplug operation
+ * for a given @dev. It may return NULL if @dev doesn't require
+ * any actions to be performed by hotplug handler.
+ * @cpu_index_to_instance_props:
+ * used to provide @cpu_index to socket/core/thread number mapping, allowing
+ * legacy code to perform maping from cpu_index to topology properties
+ * Returns: tuple of socket/core/thread ids given cpu_index belongs to.
+ * used to provide @cpu_index to socket number mapping, allowing
+ * a machine to group CPU threads belonging to the same socket/package
+ * Returns: socket number given cpu_index belongs to.
+ * @hw_version:
+ * Value of QEMU_VERSION when the machine was added to QEMU.
+ * Set only by old machines because they need to keep
+ * compatibility on code that exposed QEMU_VERSION to guests in
+ * the past (and now use qemu_hw_version()).
+ * @possible_cpu_arch_ids:
+ * Returns an array of @CPUArchId architecture-dependent CPU IDs
+ * which includes CPU IDs for present and possible to hotplug CPUs.
+ * Caller is responsible for freeing returned list.
+ * @get_default_cpu_node_id:
+ * returns default board specific node_id value for CPU slot specified by
+ * index @idx in @ms->possible_cpus[]
+ * @has_hotpluggable_cpus:
+ * If true, board supports CPUs creation with -device/device_add.
+ * @default_cpu_type:
+ * specifies default CPU_TYPE, which will be used for parsing target
+ * specific features and for creating CPUs if CPU name wasn't provided
+ * explicitly at CLI
+ * @minimum_page_bits:
+ * If non-zero, the board promises never to create a CPU with a page size
+ * smaller than this, so QEMU can use a more efficient larger page
+ * size than the target architecture's minimum. (Attempting to create
+ * such a CPU will fail.) Note that changing this is a migration
+ * compatibility break for the machine.
+ * @ignore_memory_transaction_failures:
+ * If this is flag is true then the CPU will ignore memory transaction
+ * failures which should cause the CPU to take an exception due to an
+ * access to an unassigned physical address; the transaction will instead
+ * return zero (for a read) or be ignored (for a write). This should be
+ * set only by legacy board models which rely on the old RAZ/WI behaviour
+ * for handling devices that QEMU does not yet model. New board models
+ * should instead use "unimplemented-device" for all memory ranges where
+ * the guest will attempt to probe for a device that QEMU doesn't
+ * implement and a stub device is required.
+ * @kvm_type:
+ * Return the type of KVM corresponding to the kvm-type string option or
+ * computed based on other criteria such as the host kernel capabilities.
+ * kvm-type may be NULL if it is not needed.
+ * @numa_mem_supported:
+ * true if '--numa node.mem' option is supported and false otherwise
+ * @hotplug_allowed:
+ * If the hook is provided, then it'll be called for each device
+ * hotplug to check whether the device hotplug is allowed. Return
+ * true to grant allowance or false to reject the hotplug. When
+ * false is returned, an error must be set to show the reason of
+ * the rejection. If the hook is not provided, all hotplug will be
+ * allowed.
+ * @default_ram_id:
+ * Specifies inital RAM MemoryRegion name to be used for default backend
+ * creation if user explicitly hasn't specified backend with "memory-backend"
+ * property.
+ * It also will be used as a way to optin into "-m" option support.
+ * If it's not set by board, '-m' will be ignored and generic code will
+ * not create default RAM MemoryRegion.
+ * @fixup_ram_size:
+ * Amends user provided ram size (with -m option) using machine
+ * specific algorithm. To be used by old machine types for compat
+ * purposes only.
+ * Applies only to default memory backend, i.e., explicit memory backend
+ * wasn't used.
+ */
+struct MachineClass {
+ /*< private >*/
+ ObjectClass parent_class;
+ /*< public >*/
+
+ const char *family; /* NULL iff @name identifies a standalone machtype */
+ char *name;
+ const char *alias;
+ const char *desc;
+ const char *deprecation_reason;
+
+ void (*init)(MachineState *state);
+ void (*reset)(MachineState *state);
+ void (*wakeup)(MachineState *state);
+ int (*kvm_type)(MachineState *machine, const char *arg);
+
+ BlockInterfaceType block_default_type;
+ int units_per_default_bus;
+ int max_cpus;
+ int min_cpus;
+ int default_cpus;
+ unsigned int no_serial:1,
+ no_parallel:1,
+ no_floppy:1,
+ no_cdrom:1,
+ no_sdcard:1,
+ pci_allow_0_address:1,
+ legacy_fw_cfg_order:1;
+ bool is_default;
+ const char *default_machine_opts;
+ const char *default_boot_order;
+ const char *default_display;
+ GPtrArray *compat_props;
+ const char *hw_version;
+ ram_addr_t default_ram_size;
+ const char *default_cpu_type;
+ bool default_kernel_irqchip_split;
+ bool option_rom_has_mr;
+ bool rom_file_has_mr;
+ int minimum_page_bits;
+ bool has_hotpluggable_cpus;
+ bool ignore_memory_transaction_failures;
+ int numa_mem_align_shift;
+ const char **valid_cpu_types;
+ strList *allowed_dynamic_sysbus_devices;
+ bool auto_enable_numa_with_memhp;
+ bool auto_enable_numa_with_memdev;
+ bool ignore_boot_device_suffixes;
+ bool smbus_no_migration_support;
+ bool nvdimm_supported;
+ bool numa_mem_supported;
+ bool auto_enable_numa;
+ SMPCompatProps smp_props;
+ const char *default_ram_id;
+
+ HotplugHandler *(*get_hotplug_handler)(MachineState *machine,
+ DeviceState *dev);
+ bool (*hotplug_allowed)(MachineState *state, DeviceState *dev,
+ Error **errp);
+ CpuInstanceProperties (*cpu_index_to_instance_props)(MachineState *machine,
+ unsigned cpu_index);
+ const CPUArchIdList *(*possible_cpu_arch_ids)(MachineState *machine);
+ int64_t (*get_default_cpu_node_id)(const MachineState *ms, int idx);
+ ram_addr_t (*fixup_ram_size)(ram_addr_t size);
+};
+
+/**
+ * DeviceMemoryState:
+ * @base: address in guest physical address space where the memory
+ * address space for memory devices starts
+ * @mr: address space container for memory devices
+ */
+typedef struct DeviceMemoryState {
+ hwaddr base;
+ MemoryRegion mr;
+} DeviceMemoryState;
+
+/**
+ * CpuTopology:
+ * @cpus: the number of present logical processors on the machine
+ * @sockets: the number of sockets on the machine
+ * @dies: the number of dies in one socket
+ * @cores: the number of cores in one die
+ * @threads: the number of threads in one core
+ * @max_cpus: the maximum number of logical processors on the machine
+ */
+typedef struct CpuTopology {
+ unsigned int cpus;
+ unsigned int sockets;
+ unsigned int dies;
+ unsigned int cores;
+ unsigned int threads;
+ unsigned int max_cpus;
+} CpuTopology;
+
+/**
+ * MachineState:
+ */
+struct MachineState {
+ /*< private >*/
+ Object parent_obj;
+
+ /*< public >*/
+
+ void *fdt;
+ char *dtb;
+ char *dumpdtb;
+ int phandle_start;
+ char *dt_compatible;
+ bool dump_guest_core;
+ bool mem_merge;
+ bool usb;
+ bool usb_disabled;
+ char *firmware;
+ bool iommu;
+ bool suppress_vmdesc;
+ bool enable_graphics;
+ ConfidentialGuestSupport *cgs;
+ char *ram_memdev_id;
+ /*
+ * convenience alias to ram_memdev_id backend memory region
+ * or to numa container memory region
+ */
+ MemoryRegion *ram;
+ DeviceMemoryState *device_memory;
+
+ ram_addr_t ram_size;
+ ram_addr_t maxram_size;
+ uint64_t ram_slots;
+ const char *boot_order;
+ const char *boot_once;
+ char *kernel_filename;
+ char *kernel_cmdline;
+ char *initrd_filename;
+ const char *cpu_type;
+ AccelState *accelerator;
+ CPUArchIdList *possible_cpus;
+ CpuTopology smp;
+ struct NVDIMMState *nvdimms_state;
+ struct NumaState *numa_state;
+};
+
+#define DEFINE_MACHINE(namestr, machine_initfn) \
+ static void machine_initfn##_class_init(ObjectClass *oc, void *data) \
+ { \
+ MachineClass *mc = MACHINE_CLASS(oc); \
+ machine_initfn(mc); \
+ } \
+ static const TypeInfo machine_initfn##_typeinfo = { \
+ .name = MACHINE_TYPE_NAME(namestr), \
+ .parent = TYPE_MACHINE, \
+ .class_init = machine_initfn##_class_init, \
+ }; \
+ static void machine_initfn##_register_types(void) \
+ { \
+ type_register_static(&machine_initfn##_typeinfo); \
+ } \
+ type_init(machine_initfn##_register_types)
+
+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;
+
+extern GlobalProperty hw_compat_4_2[];
+extern const size_t hw_compat_4_2_len;
+
+extern GlobalProperty hw_compat_4_1[];
+extern const size_t hw_compat_4_1_len;
+
+extern GlobalProperty hw_compat_4_0[];
+extern const size_t hw_compat_4_0_len;
+
+extern GlobalProperty hw_compat_3_1[];
+extern const size_t hw_compat_3_1_len;
+
+extern GlobalProperty hw_compat_3_0[];
+extern const size_t hw_compat_3_0_len;
+
+extern GlobalProperty hw_compat_2_12[];
+extern const size_t hw_compat_2_12_len;
+
+extern GlobalProperty hw_compat_2_11[];
+extern const size_t hw_compat_2_11_len;
+
+extern GlobalProperty hw_compat_2_10[];
+extern const size_t hw_compat_2_10_len;
+
+extern GlobalProperty hw_compat_2_9[];
+extern const size_t hw_compat_2_9_len;
+
+extern GlobalProperty hw_compat_2_8[];
+extern const size_t hw_compat_2_8_len;
+
+extern GlobalProperty hw_compat_2_7[];
+extern const size_t hw_compat_2_7_len;
+
+extern GlobalProperty hw_compat_2_6[];
+extern const size_t hw_compat_2_6_len;
+
+extern GlobalProperty hw_compat_2_5[];
+extern const size_t hw_compat_2_5_len;
+
+extern GlobalProperty hw_compat_2_4[];
+extern const size_t hw_compat_2_4_len;
+
+extern GlobalProperty hw_compat_2_3[];
+extern const size_t hw_compat_2_3_len;
+
+extern GlobalProperty hw_compat_2_2[];
+extern const size_t hw_compat_2_2_len;
+
+extern GlobalProperty hw_compat_2_1[];
+extern const size_t hw_compat_2_1_len;
+
+#endif
diff --git a/include/hw/char/avr_usart.h b/include/hw/char/avr_usart.h
new file mode 100644
index 000000000..62eaa1528
--- /dev/null
+++ b/include/hw/char/avr_usart.h
@@ -0,0 +1,92 @@
+/*
+ * AVR USART
+ *
+ * Copyright (c) 2018 University of Kent
+ * Author: Sarah Harris
+ *
+ * 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/lgpl-2.1.html>
+ */
+
+#ifndef HW_CHAR_AVR_USART_H
+#define HW_CHAR_AVR_USART_H
+
+#include "hw/sysbus.h"
+#include "chardev/char-fe.h"
+#include "qom/object.h"
+
+/* Offsets of registers. */
+#define USART_DR 0x06
+#define USART_CSRA 0x00
+#define USART_CSRB 0x01
+#define USART_CSRC 0x02
+#define USART_BRRH 0x05
+#define USART_BRRL 0x04
+
+/* Relevant bits in regiters. */
+#define USART_CSRA_RXC (1 << 7)
+#define USART_CSRA_TXC (1 << 6)
+#define USART_CSRA_DRE (1 << 5)
+#define USART_CSRA_MPCM (1 << 0)
+
+#define USART_CSRB_RXCIE (1 << 7)
+#define USART_CSRB_TXCIE (1 << 6)
+#define USART_CSRB_DREIE (1 << 5)
+#define USART_CSRB_RXEN (1 << 4)
+#define USART_CSRB_TXEN (1 << 3)
+#define USART_CSRB_CSZ2 (1 << 2)
+#define USART_CSRB_RXB8 (1 << 1)
+#define USART_CSRB_TXB8 (1 << 0)
+
+#define USART_CSRC_MSEL1 (1 << 7)
+#define USART_CSRC_MSEL0 (1 << 6)
+#define USART_CSRC_PM1 (1 << 5)
+#define USART_CSRC_PM0 (1 << 4)
+#define USART_CSRC_CSZ1 (1 << 2)
+#define USART_CSRC_CSZ0 (1 << 1)
+
+#define TYPE_AVR_USART "avr-usart"
+OBJECT_DECLARE_SIMPLE_TYPE(AVRUsartState, AVR_USART)
+
+struct AVRUsartState {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /* <public> */
+ MemoryRegion mmio;
+
+ CharBackend chr;
+
+ bool enabled;
+
+ uint8_t data;
+ bool data_valid;
+ uint8_t char_mask;
+ /* Control and Status Registers */
+ uint8_t csra;
+ uint8_t csrb;
+ uint8_t csrc;
+ /* Baud Rate Registers (low/high byte) */
+ uint8_t brrh;
+ uint8_t brrl;
+
+ /* Receive Complete */
+ qemu_irq rxc_irq;
+ /* Transmit Complete */
+ qemu_irq txc_irq;
+ /* Data Register Empty */
+ qemu_irq dre_irq;
+};
+
+#endif /* HW_CHAR_AVR_USART_H */
diff --git a/include/hw/char/bcm2835_aux.h b/include/hw/char/bcm2835_aux.h
new file mode 100644
index 000000000..9e081793a
--- /dev/null
+++ b/include/hw/char/bcm2835_aux.h
@@ -0,0 +1,35 @@
+/*
+ * Rasperry Pi 2 emulation and refactoring Copyright (c) 2015, Microsoft
+ * Written by Andrew Baumann
+ *
+ * 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_AUX_H
+#define BCM2835_AUX_H
+
+#include "hw/sysbus.h"
+#include "chardev/char-fe.h"
+#include "qom/object.h"
+
+#define TYPE_BCM2835_AUX "bcm2835-aux"
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835AuxState, BCM2835_AUX)
+
+#define BCM2835_AUX_RX_FIFO_LEN 8
+
+struct BCM2835AuxState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ MemoryRegion iomem;
+ CharBackend chr;
+ qemu_irq irq;
+
+ uint8_t read_fifo[BCM2835_AUX_RX_FIFO_LEN];
+ uint8_t read_pos, read_count;
+ uint8_t ier, iir;
+};
+
+#endif
diff --git a/include/hw/char/cadence_uart.h b/include/hw/char/cadence_uart.h
new file mode 100644
index 000000000..e7f7cd846
--- /dev/null
+++ b/include/hw/char/cadence_uart.h
@@ -0,0 +1,56 @@
+/*
+ * Device model for Cadence UART
+ *
+ * Copyright (c) 2010 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 CADENCE_UART_H
+#define CADENCE_UART_H
+
+#include "hw/qdev-properties.h"
+#include "hw/sysbus.h"
+#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
+
+#define CADENCE_UART_R_MAX (0x48/4)
+
+#define TYPE_CADENCE_UART "cadence_uart"
+OBJECT_DECLARE_SIMPLE_TYPE(CadenceUARTState, CADENCE_UART)
+
+struct CadenceUARTState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+ uint32_t r[CADENCE_UART_R_MAX];
+ uint8_t rx_fifo[CADENCE_UART_RX_FIFO_SIZE];
+ uint8_t tx_fifo[CADENCE_UART_TX_FIFO_SIZE];
+ uint32_t rx_wpos;
+ uint32_t rx_count;
+ uint32_t tx_count;
+ uint64_t char_tx_time;
+ CharBackend chr;
+ qemu_irq irq;
+ QEMUTimer *fifo_trigger_handle;
+ Clock *refclk;
+};
+
+#endif
diff --git a/include/hw/char/cmsdk-apb-uart.h b/include/hw/char/cmsdk-apb-uart.h
new file mode 100644
index 000000000..9daff0eee
--- /dev/null
+++ b/include/hw/char/cmsdk-apb-uart.h
@@ -0,0 +1,79 @@
+/*
+ * ARM CMSDK APB UART emulation
+ *
+ * Copyright (c) 2017 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 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"
+OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBUART, CMSDK_APB_UART)
+
+struct CMSDKAPBUART {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+ CharBackend chr;
+ qemu_irq txint;
+ qemu_irq rxint;
+ qemu_irq txovrint;
+ qemu_irq rxovrint;
+ qemu_irq uartint;
+ guint watch_tag;
+ uint32_t pclk_frq;
+
+ uint32_t state;
+ uint32_t ctrl;
+ uint32_t intstatus;
+ uint32_t bauddiv;
+ /* This UART has no FIFO, only a 1-character buffer for each of Tx and Rx */
+ uint8_t txbuf;
+ uint8_t rxbuf;
+};
+
+/**
+ * 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
new file mode 100644
index 000000000..f710a1a09
--- /dev/null
+++ b/include/hw/char/digic-uart.h
@@ -0,0 +1,47 @@
+/*
+ * Canon DIGIC UART block declarations.
+ *
+ * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.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 HW_CHAR_DIGIC_UART_H
+#define HW_CHAR_DIGIC_UART_H
+
+#include "hw/sysbus.h"
+#include "chardev/char-fe.h"
+#include "qom/object.h"
+
+#define TYPE_DIGIC_UART "digic-uart"
+OBJECT_DECLARE_SIMPLE_TYPE(DigicUartState, DIGIC_UART)
+
+enum {
+ R_TX = 0x00,
+ R_RX,
+ R_ST = (0x14 >> 2),
+ R_MAX
+};
+
+struct DigicUartState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ MemoryRegion regs_region;
+ CharBackend chr;
+
+ uint32_t reg_rx;
+ uint32_t reg_st;
+};
+
+#endif /* HW_CHAR_DIGIC_UART_H */
diff --git a/include/hw/char/escc.h b/include/hw/char/escc.h
new file mode 100644
index 000000000..7e9482dee
--- /dev/null
+++ b/include/hw/char/escc.h
@@ -0,0 +1,61 @@
+#ifndef HW_ESCC_H
+#define HW_ESCC_H
+
+#include "chardev/char-fe.h"
+#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
+
+OBJECT_DECLARE_SIMPLE_TYPE(ESCCState, ESCC)
+
+typedef enum {
+ escc_chn_a, escc_chn_b,
+} ESCCChnID;
+
+typedef enum {
+ escc_serial, escc_kbd, escc_mouse,
+} ESCCChnType;
+
+#define ESCC_SERIO_QUEUE_SIZE 256
+
+typedef struct {
+ uint8_t data[ESCC_SERIO_QUEUE_SIZE];
+ int rptr, wptr, count;
+} ESCCSERIOQueue;
+
+#define ESCC_SERIAL_REGS 16
+typedef struct ESCCChannelState {
+ qemu_irq irq;
+ uint32_t rxint, txint, rxint_under_svc, txint_under_svc;
+ struct ESCCChannelState *otherchn;
+ uint32_t reg;
+ uint8_t wregs[ESCC_SERIAL_REGS], rregs[ESCC_SERIAL_REGS];
+ ESCCSERIOQueue queue;
+ CharBackend chr;
+ int e0_mode, led_mode, caps_lock_mode, num_lock_mode;
+ int disabled;
+ int clock;
+ uint32_t vmstate_dummy;
+ ESCCChnID chn; /* this channel, A (base+4) or B (base+0) */
+ ESCCChnType type;
+ uint8_t rx, tx;
+ QemuInputHandlerState *hs;
+} ESCCChannelState;
+
+struct ESCCState {
+ SysBusDevice parent_obj;
+
+ struct ESCCChannelState chn[2];
+ uint32_t it_shift;
+ bool bit_swap;
+ MemoryRegion mmio;
+ uint32_t disabled;
+ uint32_t frequency;
+};
+
+#endif
diff --git a/include/hw/char/goldfish_tty.h b/include/hw/char/goldfish_tty.h
new file mode 100644
index 000000000..7503d2fa1
--- /dev/null
+++ b/include/hw/char/goldfish_tty.h
@@ -0,0 +1,35 @@
+/*
+ * 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"
+
+#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/ibex_uart.h b/include/hw/char/ibex_uart.h
new file mode 100644
index 000000000..a39985516
--- /dev/null
+++ b/include/hw/char/ibex_uart.h
@@ -0,0 +1,74 @@
+/*
+ * QEMU lowRISC Ibex UART device
+ *
+ * Copyright (c) 2020 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_UART_H
+#define HW_IBEX_UART_H
+
+#include "hw/sysbus.h"
+#include "hw/registerfields.h"
+#include "chardev/char-fe.h"
+#include "qemu/timer.h"
+#include "qom/object.h"
+
+#define IBEX_UART_TX_FIFO_SIZE 16
+#define IBEX_UART_CLOCK 50000000 /* 50MHz clock */
+
+#define TYPE_IBEX_UART "ibex-uart"
+OBJECT_DECLARE_SIMPLE_TYPE(IbexUartState, IBEX_UART)
+
+struct IbexUartState {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /* <public> */
+ MemoryRegion mmio;
+
+ 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;
+
+ uint32_t uart_intr_state;
+ uint32_t uart_intr_enable;
+ uint32_t uart_ctrl;
+ uint32_t uart_status;
+ uint32_t uart_rdata;
+ uint32_t uart_fifo_ctrl;
+ uint32_t uart_fifo_status;
+ uint32_t uart_ovrd;
+ uint32_t uart_val;
+ uint32_t uart_timeout_ctrl;
+
+ Clock *f_clk;
+
+ CharBackend chr;
+ qemu_irq tx_watermark;
+ qemu_irq rx_watermark;
+ qemu_irq tx_empty;
+ qemu_irq rx_overflow;
+};
+#endif /* HW_IBEX_UART_H */
diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h
new file mode 100644
index 000000000..91c9894ad
--- /dev/null
+++ b/include/hw/char/imx_serial.h
@@ -0,0 +1,109 @@
+/*
+ * Device model for i.MX UART
+ *
+ * Copyright (c) 2008 OKL
+ * Originally Written by Hans Jiang
+ * Copyright (c) 2011 NICTA Pty Ltd.
+ * Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
+ *
+ * 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 IMX_SERIAL_H
+#define IMX_SERIAL_H
+
+#include "hw/sysbus.h"
+#include "chardev/char-fe.h"
+#include "qom/object.h"
+
+#define TYPE_IMX_SERIAL "imx.serial"
+OBJECT_DECLARE_SIMPLE_TYPE(IMXSerialState, IMX_SERIAL)
+
+#define URXD_CHARRDY (1<<15) /* character read is valid */
+#define URXD_ERR (1<<14) /* Character has error */
+#define URXD_FRMERR (1<<12) /* Character has frame error */
+#define URXD_BRK (1<<11) /* Break received */
+
+#define USR1_PARTYER (1<<15) /* Parity Error */
+#define USR1_RTSS (1<<14) /* RTS pin status */
+#define USR1_TRDY (1<<13) /* Tx ready */
+#define USR1_RTSD (1<<12) /* RTS delta: pin changed state */
+#define USR1_ESCF (1<<11) /* Escape sequence interrupt */
+#define USR1_FRAMERR (1<<10) /* Framing error */
+#define USR1_RRDY (1<<9) /* receiver ready */
+#define USR1_AGTIM (1<<8) /* Aging timer interrupt */
+#define USR1_DTRD (1<<7) /* DTR changed */
+#define USR1_RXDS (1<<6) /* Receiver is idle */
+#define USR1_AIRINT (1<<5) /* Aysnch IR interrupt */
+#define USR1_AWAKE (1<<4) /* Falling edge detected on RXd pin */
+
+#define USR2_ADET (1<<15) /* Autobaud complete */
+#define USR2_TXFE (1<<14) /* Transmit FIFO empty */
+#define USR2_DTRF (1<<13) /* DTR/DSR transition */
+#define USR2_IDLE (1<<12) /* UART has been idle for too long */
+#define USR2_ACST (1<<11) /* Autobaud counter stopped */
+#define USR2_RIDELT (1<<10) /* Ring Indicator delta */
+#define USR2_RIIN (1<<9) /* Ring Indicator Input */
+#define USR2_IRINT (1<<8) /* Serial Infrared Interrupt */
+#define USR2_WAKE (1<<7) /* Start bit detected */
+#define USR2_DCDDELT (1<<6) /* Data Carrier Detect delta */
+#define USR2_DCDIN (1<<5) /* Data Carrier Detect Input */
+#define USR2_RTSF (1<<4) /* RTS transition */
+#define USR2_TXDC (1<<3) /* Transmission complete */
+#define USR2_BRCD (1<<2) /* Break condition detected */
+#define USR2_ORE (1<<1) /* Overrun error */
+#define USR2_RDR (1<<0) /* Receive data ready */
+
+#define UCR1_TRDYEN (1<<13) /* Tx Ready Interrupt Enable */
+#define UCR1_RRDYEN (1<<9) /* Rx Ready Interrupt Enable */
+#define UCR1_TXMPTYEN (1<<6) /* Tx Empty Interrupt Enable */
+#define UCR1_UARTEN (1<<0) /* UART 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_TCEN BIT(3) /* TX complete interrupt enable */
+
+#define UTS1_TXEMPTY (1<<6)
+#define UTS1_RXEMPTY (1<<5)
+#define UTS1_TXFULL (1<<4)
+#define UTS1_RXFULL (1<<3)
+
+struct IMXSerialState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+ int32_t readbuff;
+
+ uint32_t usr1;
+ uint32_t usr2;
+ uint32_t ucr1;
+ uint32_t ucr2;
+ uint32_t uts1;
+
+ /*
+ * The registers below are implemented just so that the
+ * guest OS sees what it has written
+ */
+ uint32_t onems;
+ uint32_t ufcr;
+ uint32_t ubmr;
+ uint32_t ubrc;
+ uint32_t ucr3;
+ uint32_t ucr4;
+
+ qemu_irq irq;
+ CharBackend chr;
+};
+
+#endif
diff --git a/include/hw/char/mchp_pfsoc_mmuart.h b/include/hw/char/mchp_pfsoc_mmuart.h
new file mode 100644
index 000000000..b0e14ca35
--- /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
new file mode 100644
index 000000000..561b6383c
--- /dev/null
+++ b/include/hw/char/nrf51_uart.h
@@ -0,0 +1,78 @@
+/*
+ * nRF51 SoC UART emulation
+ *
+ * Copyright (c) 2018 Julia Suvorova <jusual@mail.ru>
+ *
+ * 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 NRF51_UART_H
+#define NRF51_UART_H
+
+#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"
+OBJECT_DECLARE_SIMPLE_TYPE(NRF51UARTState, NRF51_UART)
+
+REG32(UART_STARTRX, 0x000)
+REG32(UART_STOPRX, 0x004)
+REG32(UART_STARTTX, 0x008)
+REG32(UART_STOPTX, 0x00C)
+REG32(UART_SUSPEND, 0x01C)
+
+REG32(UART_CTS, 0x100)
+REG32(UART_NCTS, 0x104)
+REG32(UART_RXDRDY, 0x108)
+REG32(UART_TXDRDY, 0x11C)
+REG32(UART_ERROR, 0x124)
+REG32(UART_RXTO, 0x144)
+
+REG32(UART_INTEN, 0x300)
+ FIELD(UART_INTEN, CTS, 0, 1)
+ FIELD(UART_INTEN, NCTS, 1, 1)
+ FIELD(UART_INTEN, RXDRDY, 2, 1)
+ FIELD(UART_INTEN, TXDRDY, 7, 1)
+ FIELD(UART_INTEN, ERROR, 9, 1)
+ FIELD(UART_INTEN, RXTO, 17, 1)
+REG32(UART_INTENSET, 0x304)
+REG32(UART_INTENCLR, 0x308)
+REG32(UART_ERRORSRC, 0x480)
+REG32(UART_ENABLE, 0x500)
+REG32(UART_PSELRTS, 0x508)
+REG32(UART_PSELTXD, 0x50C)
+REG32(UART_PSELCTS, 0x510)
+REG32(UART_PSELRXD, 0x514)
+REG32(UART_RXD, 0x518)
+REG32(UART_TXD, 0x51C)
+REG32(UART_BAUDRATE, 0x524)
+REG32(UART_CONFIG, 0x56C)
+
+struct NRF51UARTState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ CharBackend chr;
+ qemu_irq irq;
+ guint watch_tag;
+
+ uint8_t rx_fifo[UART_FIFO_LENGTH];
+ unsigned int rx_fifo_pos;
+ unsigned int rx_fifo_len;
+
+ uint32_t reg[0x56C];
+
+ bool rx_started;
+ bool tx_started;
+ bool pending_tx_byte;
+ bool enabled;
+};
+
+#endif
diff --git a/include/hw/char/parallel.h b/include/hw/char/parallel.h
new file mode 100644
index 000000000..0a23c0f57
--- /dev/null
+++ b/include/hw/char/parallel.h
@@ -0,0 +1,13 @@
+#ifndef HW_PARALLEL_H
+#define HW_PARALLEL_H
+
+#include "hw/isa/isa.h"
+#include "chardev/char.h"
+
+void parallel_hds_isa_init(ISABus *bus, int n);
+
+bool parallel_mm_init(MemoryRegion *address_space,
+ hwaddr base, int it_shift, qemu_irq irq,
+ Chardev *chr);
+
+#endif
diff --git a/include/hw/char/pl011.h b/include/hw/char/pl011.h
new file mode 100644
index 000000000..dc2c90eed
--- /dev/null
+++ b/include/hw/char/pl011.h
@@ -0,0 +1,91 @@
+/*
+ * 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_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"
+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"
+
+struct PL011State {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ uint32_t readbuff;
+ uint32_t flags;
+ uint32_t lcr;
+ uint32_t rsr;
+ uint32_t cr;
+ uint32_t dmacr;
+ uint32_t int_enabled;
+ uint32_t int_level;
+ uint32_t read_fifo[16];
+ uint32_t ilpr;
+ uint32_t ibrd;
+ uint32_t fbrd;
+ uint32_t ifl;
+ int read_pos;
+ int read_count;
+ int read_trigger;
+ CharBackend chr;
+ qemu_irq irq[6];
+ Clock *clk;
+ bool migrate_clk;
+ const unsigned char *id;
+};
+
+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;
+}
+
+#endif
diff --git a/include/hw/char/renesas_sci.h b/include/hw/char/renesas_sci.h
new file mode 100644
index 000000000..a4764e3ee
--- /dev/null
+++ b/include/hw/char/renesas_sci.h
@@ -0,0 +1,54 @@
+/*
+ * Renesas Serial Communication Interface
+ *
+ * Copyright (c) 2018 Yoshinori Sato
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_CHAR_RENESAS_SCI_H
+#define HW_CHAR_RENESAS_SCI_H
+
+#include "chardev/char-fe.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_RENESAS_SCI "renesas-sci"
+typedef struct RSCIState RSCIState;
+DECLARE_INSTANCE_CHECKER(RSCIState, RSCI,
+ TYPE_RENESAS_SCI)
+
+enum {
+ ERI = 0,
+ RXI = 1,
+ TXI = 2,
+ TEI = 3,
+ SCI_NR_IRQ = 4
+};
+
+struct RSCIState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ MemoryRegion memory;
+ QEMUTimer timer;
+ CharBackend chr;
+ qemu_irq irq[SCI_NR_IRQ];
+
+ uint8_t smr;
+ uint8_t brr;
+ uint8_t scr;
+ uint8_t tdr;
+ uint8_t ssr;
+ uint8_t rdr;
+ uint8_t scmr;
+ uint8_t semr;
+
+ uint8_t read_ssr;
+ int64_t trtime;
+ int64_t rx_next;
+ uint64_t input_freq;
+};
+
+#endif
diff --git a/include/hw/char/riscv_htif.h b/include/hw/char/riscv_htif.h
new file mode 100644
index 000000000..fb9452cf5
--- /dev/null
+++ b/include/hw/char/riscv_htif.h
@@ -0,0 +1,59 @@
+/*
+ * QEMU RISCV Host Target Interface (HTIF) Emulation
+ *
+ * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
+ * Copyright (c) 2017-2018 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_RISCV_HTIF_H
+#define HW_RISCV_HTIF_H
+
+#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"
+
+typedef struct HTIFState {
+ int allow_tohost;
+ int fromhost_inprogress;
+
+ 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;
+
+/* 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);
+
+#endif
diff --git a/include/hw/char/serial.h b/include/hw/char/serial.h
new file mode 100644
index 000000000..8ba7eca3d
--- /dev/null
+++ b/include/hw/char/serial.h
@@ -0,0 +1,116 @@
+/*
+ * QEMU 16550A UART emulation
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2008 Citrix Systems, 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 HW_SERIAL_H
+#define HW_SERIAL_H
+
+#include "chardev/char-fe.h"
+#include "exec/memory.h"
+#include "qemu/fifo8.h"
+#include "chardev/char.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define UART_FIFO_LENGTH 16 /* 16550A Fifo Length */
+
+struct SerialState {
+ DeviceState parent;
+
+ uint16_t divider;
+ uint8_t rbr; /* receive register */
+ uint8_t thr; /* transmit holding register */
+ uint8_t tsr; /* transmit shift register */
+ uint8_t ier;
+ uint8_t iir; /* read only */
+ uint8_t lcr;
+ uint8_t mcr;
+ uint8_t lsr; /* read only */
+ uint8_t msr; /* read only */
+ uint8_t scr;
+ uint8_t fcr;
+ uint8_t fcr_vmstate; /* we can't write directly this value
+ it has side effects */
+ /* NOTE: this hidden state is necessary for tx irq generation as
+ it can be reset while reading iir */
+ int thr_ipending;
+ qemu_irq irq;
+ CharBackend chr;
+ int last_break_enable;
+ uint32_t baudbase;
+ uint32_t tsr_retry;
+ guint watch_tag;
+ bool wakeup;
+
+ /* Time when the last byte was successfully sent out of the tsr */
+ uint64_t last_xmit_ts;
+ Fifo8 recv_fifo;
+ Fifo8 xmit_fifo;
+ /* Interrupt trigger level for recv_fifo */
+ uint8_t recv_fifo_itl;
+
+ QEMUTimer *fifo_timeout_timer;
+ int timeout_ipending; /* timeout interrupt pending state */
+
+ uint64_t char_transmit_time; /* time to transmit a char in ticks */
+ int poll_msl;
+
+ QEMUTimer *modem_status_poll;
+ MemoryRegion io;
+};
+typedef struct SerialState SerialState;
+
+struct SerialMM {
+ SysBusDevice parent;
+
+ SerialState serial;
+
+ uint8_t regshift;
+ uint8_t endianness;
+};
+
+extern const VMStateDescription vmstate_serial;
+extern const MemoryRegionOps serial_io_ops;
+
+void serial_set_frequency(SerialState *s, uint32_t frequency);
+
+#define TYPE_SERIAL "serial"
+OBJECT_DECLARE_SIMPLE_TYPE(SerialState, SERIAL)
+
+#define TYPE_SERIAL_MM "serial-mm"
+OBJECT_DECLARE_SIMPLE_TYPE(SerialMM, SERIAL_MM)
+
+SerialMM *serial_mm_init(MemoryRegion *address_space,
+ hwaddr base, int regshift,
+ qemu_irq irq, int baudbase,
+ Chardev *chr, enum device_endian end);
+
+/* serial-isa.c */
+
+#define MAX_ISA_SERIAL_PORTS 4
+
+#define TYPE_ISA_SERIAL "isa-serial"
+void serial_hds_isa_init(ISABus *bus, int from, int to);
+
+#endif
diff --git a/include/hw/char/shakti_uart.h b/include/hw/char/shakti_uart.h
new file mode 100644
index 000000000..526c40823
--- /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/char/sifive_uart.h b/include/hw/char/sifive_uart.h
new file mode 100644
index 000000000..7f6c79f8b
--- /dev/null
+++ b/include/hw/char/sifive_uart.h
@@ -0,0 +1,78 @@
+/*
+ * SiFive UART interface
+ *
+ * Copyright (c) 2016 Stefan O'Rear
+ * 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_UART_H
+#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,
+ SIFIVE_UART_RXFIFO = 4,
+ SIFIVE_UART_TXCTRL = 8,
+ SIFIVE_UART_TXMARK = 10,
+ SIFIVE_UART_RXCTRL = 12,
+ SIFIVE_UART_RXMARK = 14,
+ SIFIVE_UART_IE = 16,
+ SIFIVE_UART_IP = 20,
+ SIFIVE_UART_DIV = 24,
+ SIFIVE_UART_MAX = 32
+};
+
+enum {
+ SIFIVE_UART_IE_TXWM = 1, /* Transmit watermark interrupt enable */
+ SIFIVE_UART_IE_RXWM = 2 /* Receive watermark interrupt enable */
+};
+
+enum {
+ SIFIVE_UART_IP_TXWM = 1, /* Transmit watermark interrupt pending */
+ SIFIVE_UART_IP_RXWM = 2 /* Receive watermark interrupt pending */
+};
+
+#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)
+
+struct SiFiveUARTState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ qemu_irq irq;
+ MemoryRegion mmio;
+ CharBackend chr;
+ 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 *sifive_uart_create(MemoryRegion *address_space, hwaddr base,
+ Chardev *chr, qemu_irq irq);
+
+#endif
diff --git a/include/hw/char/stm32f2xx_usart.h b/include/hw/char/stm32f2xx_usart.h
new file mode 100644
index 000000000..65bcc8547
--- /dev/null
+++ b/include/hw/char/stm32f2xx_usart.h
@@ -0,0 +1,77 @@
+/*
+ * STM32F2XX USART
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * 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_STM32F2XX_USART_H
+#define HW_STM32F2XX_USART_H
+
+#include "hw/sysbus.h"
+#include "chardev/char-fe.h"
+#include "qom/object.h"
+
+#define USART_SR 0x00
+#define USART_DR 0x04
+#define USART_BRR 0x08
+#define USART_CR1 0x0C
+#define USART_CR2 0x10
+#define USART_CR3 0x14
+#define USART_GTPR 0x18
+
+/*
+ * NB: The reset value mentioned in "24.6.1 Status register" seems bogus.
+ * Looking at "Table 98 USART register map and reset values", it seems it
+ * should be 0xc0, and that's how real hardware behaves.
+ */
+#define USART_SR_RESET (USART_SR_TXE | USART_SR_TC)
+
+#define USART_SR_TXE (1 << 7)
+#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 TYPE_STM32F2XX_USART "stm32f2xx-usart"
+OBJECT_DECLARE_SIMPLE_TYPE(STM32F2XXUsartState, STM32F2XX_USART)
+
+struct STM32F2XXUsartState {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /* <public> */
+ MemoryRegion mmio;
+
+ uint32_t usart_sr;
+ uint32_t usart_dr;
+ uint32_t usart_brr;
+ uint32_t usart_cr1;
+ uint32_t usart_cr2;
+ uint32_t usart_cr3;
+ uint32_t usart_gtpr;
+
+ CharBackend chr;
+ qemu_irq irq;
+};
+#endif /* HW_STM32F2XX_USART_H */
diff --git a/include/hw/char/xilinx_uartlite.h b/include/hw/char/xilinx_uartlite.h
new file mode 100644
index 000000000..bb32d0fcb
--- /dev/null
+++ b/include/hw/char/xilinx_uartlite.h
@@ -0,0 +1,38 @@
+/*
+ * 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 XILINX_UARTLITE_H
+#define XILINX_UARTLITE_H
+
+#include "hw/qdev-properties.h"
+#include "hw/sysbus.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;
+}
+
+#endif
diff --git a/include/hw/clock.h b/include/hw/clock.h
new file mode 100644
index 000000000..5c927cee7
--- /dev/null
+++ b/include/hw/clock.h
@@ -0,0 +1,379 @@
+/*
+ * Hardware Clocks
+ *
+ * Copyright GreenSocs 2016-2020
+ *
+ * Authors:
+ * Frederic Konrad
+ * Damien Hedde
+ *
+ * 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_HW_CLOCK_H
+#define QEMU_HW_CLOCK_H
+
+#include "qom/object.h"
+#include "qemu/queue.h"
+#include "qemu/host-utils.h"
+#include "qemu/bitops.h"
+
+#define TYPE_CLOCK "clock"
+OBJECT_DECLARE_SIMPLE_TYPE(Clock, CLOCK)
+
+/*
+ * 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.
+ * It can represent:
+ * + periods from 2^-32ns up to 4seconds
+ * + frequency from ~0.25Hz 2e10Ghz
+ * Resolution of frequency representation decreases with frequency:
+ * + at 100MHz, resolution is ~2mHz
+ * + at 1Ghz, resolution is ~0.2Hz
+ * + at 10Ghz, resolution is ~20Hz
+ */
+#define CLOCK_PERIOD_1SEC (1000000000llu << 32)
+
+/*
+ * macro helpers to convert to hertz / nanosecond
+ */
+#define CLOCK_PERIOD_FROM_NS(ns) ((ns) * (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)
+
+/**
+ * Clock:
+ * @parent_obj: parent class
+ * @period: unsigned integer representing the period of the clock
+ * @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
+ */
+
+
+struct Clock {
+ /*< private >*/
+ Object parent_obj;
+
+ /* all fields are private and should not be modified directly */
+
+ /* fields */
+ uint64_t period;
+ 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;
+ QLIST_HEAD(, Clock) children;
+ QLIST_ENTRY(Clock) sibling;
+};
+
+/*
+ * vmstate description entry to be added in device vmsd.
+ */
+extern const VMStateDescription vmstate_clock;
+#define VMSTATE_CLOCK(field, state) \
+ 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:
+ * @clk: clock
+ *
+ * compute the canonical path of the clock (used by log messages)
+ */
+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, unsigned int events);
+
+/**
+ * clock_clear_callback:
+ * @clk: the clock to delete the callback from
+ *
+ * Unregister the callback registered with clock_set_callback.
+ */
+void clock_clear_callback(Clock *clk);
+
+/**
+ * clock_set_source:
+ * @clk: the clock.
+ * @src: the source clock
+ *
+ * Setup @src as the clock source of @clk. The current @src period
+ * value is also copied to @clk and its subtree but no callback is
+ * called.
+ * Further @src update will be propagated to @clk and its subtree.
+ */
+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.
+ */
+bool clock_set(Clock *clk, uint64_t value);
+
+static inline bool clock_set_hz(Clock *clk, unsigned hz)
+{
+ return clock_set(clk, CLOCK_PERIOD_FROM_HZ(hz));
+}
+
+static inline bool clock_set_ns(Clock *clk, unsigned ns)
+{
+ return clock_set(clk, CLOCK_PERIOD_FROM_NS(ns));
+}
+
+/**
+ * clock_propagate:
+ * @clk: the clock
+ *
+ * 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
+ * or migration.
+ */
+void clock_propagate(Clock *clk);
+
+/**
+ * clock_update:
+ * @clk: the clock to update.
+ * @value: the new clock's value, 0 means unclocked
+ *
+ * Update the @clk to the new @value. All connected clocks will be informed
+ * of this update. This is equivalent to call @clock_set() then
+ * @clock_propagate().
+ */
+static inline void clock_update(Clock *clk, uint64_t value)
+{
+ if (clock_set(clk, value)) {
+ clock_propagate(clk);
+ }
+}
+
+static inline void clock_update_hz(Clock *clk, unsigned hz)
+{
+ clock_update(clk, CLOCK_PERIOD_FROM_HZ(hz));
+}
+
+static inline void clock_update_ns(Clock *clk, unsigned ns)
+{
+ clock_update(clk, CLOCK_PERIOD_FROM_NS(ns));
+}
+
+/**
+ * clock_get:
+ * @clk: the clk to fetch the clock
+ *
+ * @return: the current period.
+ */
+static inline uint64_t clock_get(const Clock *clk)
+{
+ return clk->period;
+}
+
+static inline unsigned clock_get_hz(Clock *clk)
+{
+ return CLOCK_PERIOD_TO_HZ(clock_get(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)
+{
+ /*
+ * 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;
+}
+
+/**
+ * clock_is_enabled:
+ * @clk: a clock
+ *
+ * @return: true if the clock is running.
+ */
+static inline bool clock_is_enabled(const Clock *clk)
+{
+ return clock_get(clk) != 0;
+}
+
+/**
+ * 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
+ *
+ * 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.
+ */
+void 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 000000000..5dbfd7995
--- /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_realizefn)(CPUState *cpu, Error **errp);
+} AccelCPUClass;
+
+#endif /* ACCEL_CPU_H */
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
new file mode 100644
index 000000000..e948e81f1
--- /dev/null
+++ b/include/hw/core/cpu.h
@@ -0,0 +1,1048 @@
+/*
+ * QEMU CPU model
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * 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/gpl-2.0.html>
+ */
+#ifndef QEMU_CPU_H
+#define QEMU_CPU_H
+
+#include "hw/qdev-core.h"
+#include "disas/dis-asm.h"
+#include "exec/hwaddr.h"
+#include "exec/memattrs.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
+ * @short_description: Base class for all CPUs
+ */
+
+#define TYPE_CPU "cpu"
+
+/* Since this macro is used a lot in hot code paths and in conjunction with
+ * FooCPU *foo_env_get_cpu(), we deviate from usual QOM practice by using
+ * an unchecked cast.
+ */
+#define CPU(obj) ((CPUState *)(obj))
+
+typedef struct CPUClass CPUClass;
+DECLARE_CLASS_CHECKERS(CPUClass, CPU,
+ TYPE_CPU)
+
+typedef enum MMUAccessType {
+ MMU_DATA_LOAD = 0,
+ MMU_DATA_STORE = 1,
+ MMU_INST_FETCH = 2
+} MMUAccessType;
+
+typedef struct CPUWatchpoint CPUWatchpoint;
+
+/* see tcg-cpu-ops.h */
+struct TCGCPUOps;
+
+/* 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.
+ * @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.
+ * @memory_rw_debug: Callback for GDB memory access.
+ * @dump_state: Callback for dumping state.
+ * @get_arch_id: Callback for getting architecture-dependent CPU ID.
+ * @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;
+ * for example on Arm it will also set the Thumb mode bit based
+ * on the least significant bit of the new PC value.
+ * 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.
+ * @gdb_read_register: Callback for letting GDB read a register.
+ * @gdb_write_register: Callback for letting GDB write a register.
+ * @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.
+ * @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.
+ * @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.
+ */
+struct CPUClass {
+ /*< private >*/
+ DeviceClass parent_class;
+ /*< public >*/
+
+ ObjectClass *(*class_by_name)(const char *cpu_model);
+ void (*parse_features)(const char *typename, char *str, Error **errp);
+
+ bool (*has_work)(CPUState *cpu);
+ int (*memory_rw_debug)(CPUState *cpu, vaddr addr,
+ uint8_t *buf, int len, bool is_write);
+ void (*dump_state)(CPUState *cpu, FILE *, int flags);
+ int64_t (*get_arch_id)(CPUState *cpu);
+ void (*set_pc)(CPUState *cpu, vaddr value);
+ int (*gdb_read_register)(CPUState *cpu, GByteArray *buf, int reg);
+ int (*gdb_write_register)(CPUState *cpu, uint8_t *buf, int reg);
+ 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 (*disas_set_info)(CPUState *cpu, disassemble_info *info);
+
+ 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 struct 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;
+};
+
+/*
+ * Low 16 bits: number of cycles left, used only in icount mode.
+ * High 16 bits: Set to -1 to force TCG to stop executing linked TBs
+ * for this CPU and return to its top level loop (even in non-icount mode).
+ * This allows a single read-compare-cbranch-write sequence to test
+ * for both decrementer underflow and exceptions.
+ */
+typedef union IcountDecr {
+ uint32_t u32;
+ struct {
+#ifdef HOST_WORDS_BIGENDIAN
+ uint16_t high;
+ uint16_t low;
+#else
+ uint16_t low;
+ uint16_t high;
+#endif
+ } u16;
+} IcountDecr;
+
+typedef struct CPUBreakpoint {
+ vaddr pc;
+ int flags; /* BP_* */
+ QTAILQ_ENTRY(CPUBreakpoint) entry;
+} CPUBreakpoint;
+
+struct CPUWatchpoint {
+ vaddr vaddr;
+ vaddr len;
+ vaddr hitaddr;
+ MemTxAttrs hitattrs;
+ int flags; /* BP_* */
+ 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;
+struct hvf_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
+ * hosts in a single parameter
+ */
+typedef union {
+ int host_int;
+ unsigned long host_ulong;
+ void *host_ptr;
+ vaddr target_ptr;
+} run_on_cpu_data;
+
+#define RUN_ON_CPU_HOST_PTR(p) ((run_on_cpu_data){.host_ptr = (p)})
+#define RUN_ON_CPU_HOST_INT(i) ((run_on_cpu_data){.host_int = (i)})
+#define RUN_ON_CPU_HOST_ULONG(ul) ((run_on_cpu_data){.host_ulong = (ul)})
+#define RUN_ON_CPU_TARGET_PTR(v) ((run_on_cpu_data){.target_ptr = (v)})
+#define RUN_ON_CPU_NULL RUN_ON_CPU_HOST_PTR(NULL)
+
+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:
+ * @cpu_index: CPU index (informative).
+ * @cluster_index: Identifies which cluster this CPU is in.
+ * For boards which don't define clusters or for "loose" CPUs not assigned
+ * 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.
+ * @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.
+ * @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.
+ * @created: Indicates whether the CPU thread has been successfully created.
+ * @interrupt_request: Indicates a pending interrupt request.
+ * @halted: Nonzero if the CPU is in suspended state.
+ * @stop: Indicates a pending stop request.
+ * @stopped: Indicates the CPU has been artificially stopped.
+ * @unplug: Indicates a pending CPU unplug request.
+ * @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.
+ * @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.
+ * @opaque: User data.
+ * @mem_io_pc: Host Program Counter at which the memory was accessed.
+ * @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.
+ * @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.
+ */
+struct CPUState {
+ /*< private >*/
+ DeviceState parent_obj;
+ /*< public >*/
+
+ int nr_cores;
+ int nr_threads;
+
+ struct QemuThread *thread;
+#ifdef _WIN32
+ HANDLE hThread;
+#endif
+ int thread_id;
+ bool running, has_waiter;
+ struct QemuCond *halt_cond;
+ bool thread_kicked;
+ 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;
+ uint32_t cflags_next_tb;
+ /* updates protected by BQL */
+ uint32_t interrupt_request;
+ int singlestep_enabled;
+ int64_t icount_budget;
+ int64_t icount_extra;
+ uint64_t random_seed;
+ sigjmp_buf jmp_env;
+
+ QemuMutex work_mutex;
+ QSIMPLEQ_HEAD(, qemu_work_item) work_list;
+
+ CPUAddressSpace *cpu_ases;
+ int num_ases;
+ AddressSpace *as;
+ MemoryRegion *memory;
+
+ void *env_ptr; /* CPUArchState */
+ IcountDecr *icount_decr_ptr;
+
+ /* Accessed in parallel; all accesses must be atomic */
+ TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE];
+
+ struct GDBRegisterState *gdb_regs;
+ int gdb_num_regs;
+ int gdb_num_g_regs;
+ QTAILQ_ENTRY(CPUState) node;
+
+ /* ice debug support */
+ QTAILQ_HEAD(, CPUBreakpoint) breakpoints;
+
+ QTAILQ_HEAD(, CPUWatchpoint) watchpoints;
+ CPUWatchpoint *watchpoint_hit;
+
+ void *opaque;
+
+ /* In order to avoid passing too many arguments to the MMIO helpers,
+ * we store some rarely used information in the CPU context.
+ */
+ 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;
+
+ /* 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);
+
+#ifdef CONFIG_PLUGIN
+ GArray *plugin_mem_cbs;
+ /* saved iotlb data from io_writex */
+ SavedIOTLB saved_iotlb;
+#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 */
+ bool vcpu_dirty;
+
+ /* Used to keep track of an outstanding cpu throttle thread for migration
+ * autoconverge
+ */
+ bool throttle_thread_scheduled;
+
+ bool ignore_memory_transaction_failures;
+
+ struct hax_vcpu_state *hax_vcpu;
+
+ struct hvf_vcpu_state *hvf;
+
+ /* track IOMMUs whose translations we've cached in the TCG TLB */
+ GArray *iommu_notifiers;
+};
+
+typedef QTAILQ_HEAD(CPUTailQ, CPUState) CPUTailQ;
+extern CPUTailQ cpus;
+
+#define first_cpu QTAILQ_FIRST_RCU(&cpus)
+#define CPU_NEXT(cpu) QTAILQ_NEXT_RCU(cpu, node)
+#define CPU_FOREACH(cpu) QTAILQ_FOREACH_RCU(cpu, &cpus, node)
+#define CPU_FOREACH_SAFE(cpu, next_cpu) \
+ QTAILQ_FOREACH_SAFE_RCU(cpu, &cpus, 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++) {
+ qatomic_set(&cpu->tb_jmp_cache[i], NULL);
+ }
+}
+
+/**
+ * qemu_tcg_mttcg_enabled:
+ * Check whether we are running MultiThread TCG or not.
+ *
+ * Returns: %true if we are in MTTCG mode %false otherwise.
+ */
+extern bool mttcg_enabled;
+#define qemu_tcg_mttcg_enabled() (mttcg_enabled)
+
+/**
+ * cpu_paging_enabled:
+ * @cpu: The CPU whose state is to be inspected.
+ *
+ * Returns: %true if paging is enabled, %false otherwise.
+ */
+bool cpu_paging_enabled(const CPUState *cpu);
+
+/**
+ * cpu_get_memory_mapping:
+ * @cpu: The CPU whose memory mappings are to be obtained.
+ * @list: Where to write the memory mappings to.
+ * @errp: Pointer for reporting an #Error.
+ */
+void cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list,
+ Error **errp);
+
+#if !defined(CONFIG_USER_ONLY)
+
+/**
+ * cpu_write_elf64_note:
+ * @f: pointer to a function that writes memory to a file
+ * @cpu: The CPU whose memory is to be dumped
+ * @cpuid: ID number of the CPU
+ * @opaque: pointer to the CPUState struct
+ */
+int cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu,
+ int cpuid, void *opaque);
+
+/**
+ * cpu_write_elf64_qemunote:
+ * @f: pointer to a function that writes memory to a file
+ * @cpu: The CPU whose memory is to be dumped
+ * @cpuid: ID number of the CPU
+ * @opaque: pointer to the CPUState struct
+ */
+int cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
+ void *opaque);
+
+/**
+ * cpu_write_elf32_note:
+ * @f: pointer to a function that writes memory to a file
+ * @cpu: The CPU whose memory is to be dumped
+ * @cpuid: ID number of the CPU
+ * @opaque: pointer to the CPUState struct
+ */
+int cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cpu,
+ int cpuid, void *opaque);
+
+/**
+ * cpu_write_elf32_qemunote:
+ * @f: pointer to a function that writes memory to a file
+ * @cpu: The CPU whose memory is to be dumped
+ * @cpuid: ID number of the CPU
+ * @opaque: pointer to the CPUState struct
+ */
+int cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
+ void *opaque);
+
+/**
+ * cpu_get_crash_info:
+ * @cpu: The CPU to get crash information for
+ *
+ * Gets the previously saved crash information.
+ * Caller is responsible for freeing the data.
+ */
+GuestPanicInformation *cpu_get_crash_info(CPUState *cpu);
+
+#endif /* !CONFIG_USER_ONLY */
+
+/**
+ * CPUDumpFlags:
+ * @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
+ */
+enum CPUDumpFlags {
+ CPU_DUMP_CODE = 0x00010000,
+ CPU_DUMP_FPU = 0x00020000,
+ CPU_DUMP_CCOP = 0x00040000,
+};
+
+/**
+ * cpu_dump_state:
+ * @cpu: The CPU whose state is to be dumped.
+ * @f: If non-null, dump to this stream, else to current print sink.
+ *
+ * Dumps CPU state.
+ */
+void cpu_dump_state(CPUState *cpu, FILE *f, int flags);
+
+#ifndef CONFIG_USER_ONLY
+/**
+ * cpu_get_phys_page_attrs_debug:
+ * @cpu: The CPU to obtain the physical page address for.
+ * @addr: The virtual address.
+ * @attrs: Updated on return with the memory transaction attributes to use
+ * for this access.
+ *
+ * Obtains the physical page corresponding to a virtual one, together
+ * with the corresponding memory transaction attributes to use for the access.
+ * Use it only for debugging because no protection checks are done.
+ *
+ * Returns: Corresponding physical page address or -1 if no page found.
+ */
+hwaddr cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr,
+ MemTxAttrs *attrs);
+
+/**
+ * cpu_get_phys_page_debug:
+ * @cpu: The CPU to obtain the physical page address for.
+ * @addr: The virtual address.
+ *
+ * Obtains the physical page corresponding to a virtual one.
+ * Use it only for debugging because no protection checks are done.
+ *
+ * Returns: Corresponding physical page address or -1 if no page found.
+ */
+hwaddr cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+
+/** cpu_asidx_from_attrs:
+ * @cpu: CPU
+ * @attrs: memory transaction attributes
+ *
+ * Returns the address space index specifying the CPU AddressSpace
+ * to use for a memory access with the given transaction attributes.
+ */
+int cpu_asidx_from_attrs(CPUState *cpu, MemTxAttrs attrs);
+
+/**
+ * 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 */
+
+/**
+ * cpu_list_add:
+ * @cpu: The CPU to be added to the list of CPUs.
+ */
+void cpu_list_add(CPUState *cpu);
+
+/**
+ * cpu_list_remove:
+ * @cpu: The CPU to be removed from the list of CPUs.
+ */
+void cpu_list_remove(CPUState *cpu);
+
+/**
+ * cpu_reset:
+ * @cpu: The CPU whose state is to be reset.
+ */
+void cpu_reset(CPUState *cpu);
+
+/**
+ * cpu_class_by_name:
+ * @typename: The CPU base type.
+ * @cpu_model: The model string without any parameters.
+ *
+ * Looks up a CPU #ObjectClass matching name @cpu_model.
+ *
+ * Returns: A #CPUClass or %NULL if not matching class is found.
+ */
+ObjectClass *cpu_class_by_name(const char *typename, const char *cpu_model);
+
+/**
+ * cpu_create:
+ * @typename: The CPU type.
+ *
+ * Instantiates a CPU and realizes the CPU.
+ *
+ * Returns: A #CPUState or %NULL if an error occurred.
+ */
+CPUState *cpu_create(const char *typename);
+
+/**
+ * parse_cpu_option:
+ * @cpu_option: The -cpu option including optional parameters.
+ *
+ * processes optional parameters and registers them as global properties
+ *
+ * Returns: type of CPU to create or prints error and terminates process
+ * if an error occurred.
+ */
+const char *parse_cpu_option(const char *cpu_option);
+
+/**
+ * cpu_has_work:
+ * @cpu: The vCPU to check.
+ *
+ * Checks whether the CPU has work to do.
+ *
+ * Returns: %true if the CPU has work, %false otherwise.
+ */
+static inline bool cpu_has_work(CPUState *cpu)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ g_assert(cc->has_work);
+ return cc->has_work(cpu);
+}
+
+/**
+ * qemu_cpu_is_self:
+ * @cpu: The vCPU to check against.
+ *
+ * Checks whether the caller is executing on the vCPU thread.
+ *
+ * Returns: %true if called from @cpu's thread, %false otherwise.
+ */
+bool qemu_cpu_is_self(CPUState *cpu);
+
+/**
+ * qemu_cpu_kick:
+ * @cpu: The vCPU to kick.
+ *
+ * Kicks @cpu's thread.
+ */
+void qemu_cpu_kick(CPUState *cpu);
+
+/**
+ * cpu_is_stopped:
+ * @cpu: The CPU to check.
+ *
+ * Checks whether the CPU is stopped.
+ *
+ * Returns: %true if run state is not running or if artificially stopped;
+ * %false otherwise.
+ */
+bool cpu_is_stopped(CPUState *cpu);
+
+/**
+ * do_run_on_cpu:
+ * @cpu: The vCPU to run on.
+ * @func: The function to be executed.
+ * @data: Data to pass to the function.
+ * @mutex: Mutex to release while waiting for @func to run.
+ *
+ * Used internally in the implementation of run_on_cpu.
+ */
+void do_run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data,
+ QemuMutex *mutex);
+
+/**
+ * run_on_cpu:
+ * @cpu: The vCPU to run on.
+ * @func: The function to be executed.
+ * @data: Data to pass to the function.
+ *
+ * Schedules the function @func for execution on the vCPU @cpu.
+ */
+void run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data);
+
+/**
+ * async_run_on_cpu:
+ * @cpu: The vCPU to run on.
+ * @func: The function to be executed.
+ * @data: Data to pass to the function.
+ *
+ * Schedules the function @func for execution on the vCPU @cpu asynchronously.
+ */
+void async_run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data);
+
+/**
+ * async_safe_run_on_cpu:
+ * @cpu: The vCPU to run on.
+ * @func: The function to be executed.
+ * @data: Data to pass to the function.
+ *
+ * Schedules the function @func for execution on the vCPU @cpu asynchronously,
+ * while all other vCPUs are sleeping.
+ *
+ * Unlike run_on_cpu and async_run_on_cpu, the function is run outside the
+ * BQL.
+ */
+void async_safe_run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data);
+
+/**
+ * cpu_in_exclusive_context()
+ * @cpu: The vCPU to check
+ *
+ * Returns true if @cpu is an exclusive context, for example running
+ * something which has previously been queued via async_safe_run_on_cpu().
+ */
+static inline bool cpu_in_exclusive_context(const CPUState *cpu)
+{
+ return cpu->in_exclusive_context;
+}
+
+/**
+ * qemu_get_cpu:
+ * @index: The CPUState@cpu_index value of the CPU to obtain.
+ *
+ * Gets a CPU matching @index.
+ *
+ * Returns: The CPU or %NULL if there is no matching CPU.
+ */
+CPUState *qemu_get_cpu(int index);
+
+/**
+ * cpu_exists:
+ * @id: Guest-exposed CPU ID to lookup.
+ *
+ * Search for CPU with specified ID.
+ *
+ * Returns: %true - CPU is found, %false - CPU isn't found.
+ */
+bool cpu_exists(int64_t id);
+
+/**
+ * cpu_by_arch_id:
+ * @id: Guest-exposed CPU ID of the CPU to obtain.
+ *
+ * Get a CPU with matching @id.
+ *
+ * Returns: The CPU or %NULL if there is no matching CPU.
+ */
+CPUState *cpu_by_arch_id(int64_t id);
+
+/**
+ * cpu_interrupt:
+ * @cpu: The CPU to set an interrupt on.
+ * @mask: The interrupts to set.
+ *
+ * Invokes the interrupt handler.
+ */
+
+void cpu_interrupt(CPUState *cpu, int mask);
+
+/**
+ * cpu_set_pc:
+ * @cpu: The CPU to set the program counter for.
+ * @addr: Program counter value.
+ *
+ * Sets the program counter for a CPU.
+ */
+static inline void cpu_set_pc(CPUState *cpu, vaddr addr)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ cc->set_pc(cpu, addr);
+}
+
+/**
+ * cpu_reset_interrupt:
+ * @cpu: The CPU to clear the interrupt on.
+ * @mask: The interrupt mask to clear.
+ *
+ * Resets interrupts on the vCPU @cpu.
+ */
+void cpu_reset_interrupt(CPUState *cpu, int mask);
+
+/**
+ * cpu_exit:
+ * @cpu: The CPU to exit.
+ *
+ * Requests the CPU @cpu to exit execution.
+ */
+void cpu_exit(CPUState *cpu);
+
+/**
+ * cpu_resume:
+ * @cpu: The CPU to resume.
+ *
+ * Resumes CPU, i.e. puts CPU into runnable state.
+ */
+void cpu_resume(CPUState *cpu);
+
+/**
+ * cpu_remove_sync:
+ * @cpu: The CPU to remove.
+ *
+ * Requests the CPU to be removed and waits till it is removed.
+ */
+void cpu_remove_sync(CPUState *cpu);
+
+/**
+ * process_queued_cpu_work() - process all items on CPU work queue
+ * @cpu: The CPU which work queue to process.
+ */
+void process_queued_cpu_work(CPUState *cpu);
+
+/**
+ * cpu_exec_start:
+ * @cpu: The CPU for the current thread.
+ *
+ * Record that a CPU has started execution and can be interrupted with
+ * cpu_exit.
+ */
+void cpu_exec_start(CPUState *cpu);
+
+/**
+ * cpu_exec_end:
+ * @cpu: The CPU for the current thread.
+ *
+ * Record that a CPU has stopped execution and exclusive sections
+ * can be executed without interrupting it.
+ */
+void cpu_exec_end(CPUState *cpu);
+
+/**
+ * start_exclusive:
+ *
+ * Wait for a concurrent exclusive section to end, and then start
+ * a section of work that is run while other CPUs are not running
+ * between cpu_exec_start and cpu_exec_end. CPUs that are running
+ * cpu_exec are exited immediately. CPUs that call cpu_exec_start
+ * during the exclusive section go to sleep until this CPU calls
+ * end_exclusive.
+ */
+void start_exclusive(void);
+
+/**
+ * end_exclusive:
+ *
+ * Concludes an exclusive execution section started by start_exclusive.
+ */
+void end_exclusive(void);
+
+/**
+ * qemu_init_vcpu:
+ * @cpu: The vCPU to initialize.
+ *
+ * Initializes a vCPU.
+ */
+void qemu_init_vcpu(CPUState *cpu);
+
+#define SSTEP_ENABLE 0x1 /* Enable simulated HW single stepping */
+#define SSTEP_NOIRQ 0x2 /* Do not use IRQ while single stepping */
+#define SSTEP_NOTIMER 0x4 /* Do not Timers while single stepping */
+
+/**
+ * cpu_single_step:
+ * @cpu: CPU to the flags for.
+ * @enabled: Flags to enable.
+ *
+ * Enables or disables single-stepping for @cpu.
+ */
+void cpu_single_step(CPUState *cpu, int enabled);
+
+/* Breakpoint/watchpoint flags */
+#define BP_MEM_READ 0x01
+#define BP_MEM_WRITE 0x02
+#define BP_MEM_ACCESS (BP_MEM_READ | BP_MEM_WRITE)
+#define BP_STOP_BEFORE_ACCESS 0x04
+/* 0x08 currently unused */
+#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)
+
+int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags,
+ CPUBreakpoint **breakpoint);
+int cpu_breakpoint_remove(CPUState *cpu, vaddr pc, int flags);
+void cpu_breakpoint_remove_by_ref(CPUState *cpu, CPUBreakpoint *breakpoint);
+void cpu_breakpoint_remove_all(CPUState *cpu, int mask);
+
+/* Return true if PC matches an installed breakpoint. */
+static inline bool cpu_breakpoint_test(CPUState *cpu, vaddr pc, int mask)
+{
+ CPUBreakpoint *bp;
+
+ if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) {
+ QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
+ if (bp->pc == pc && (bp->flags & mask)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+#ifdef CONFIG_USER_ONLY
+static inline int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len,
+ int flags, CPUWatchpoint **watchpoint)
+{
+ return -ENOSYS;
+}
+
+static inline int cpu_watchpoint_remove(CPUState *cpu, vaddr addr,
+ vaddr len, int flags)
+{
+ return -ENOSYS;
+}
+
+static inline void cpu_watchpoint_remove_by_ref(CPUState *cpu,
+ CPUWatchpoint *wp)
+{
+}
+
+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);
+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);
+
+/**
+ * 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
+
+/**
+ * cpu_get_address_space:
+ * @cpu: CPU to get address space from
+ * @asidx: index identifying which address space to get
+ *
+ * Return the requested address space of this CPU. @asidx
+ * specifies which address space to read.
+ */
+AddressSpace *cpu_get_address_space(CPUState *cpu, int asidx);
+
+void QEMU_NORETURN cpu_abort(CPUState *cpu, const char *fmt, ...)
+ GCC_FMT_ATTR(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);
+void cpu_exec_unrealizefn(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
+ * 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);
+
+#ifdef NEED_CPU_H
+
+#ifdef CONFIG_SOFTMMU
+
+extern const VMStateDescription vmstate_cpu_common;
+
+#define VMSTATE_CPU() { \
+ .name = "parent_obj", \
+ .size = sizeof(CPUState), \
+ .vmsd = &vmstate_cpu_common, \
+ .flags = VMS_STRUCT, \
+ .offset = 0, \
+}
+#endif /* CONFIG_SOFTMMU */
+
+#endif /* NEED_CPU_H */
+
+#define UNASSIGNED_CPU_INDEX -1
+#define UNASSIGNED_CLUSTER_INDEX -1
+
+#endif
diff --git a/include/hw/core/generic-loader.h b/include/hw/core/generic-loader.h
new file mode 100644
index 000000000..19d87b39c
--- /dev/null
+++ b/include/hw/core/generic-loader.h
@@ -0,0 +1,47 @@
+/*
+ * Generic Loader
+ *
+ * Copyright (C) 2014 Li Guang
+ * Written by Li Guang <lig.fnst@cn.fujitsu.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 GENERIC_LOADER_H
+#define GENERIC_LOADER_H
+
+#include "elf.h"
+#include "hw/qdev-core.h"
+#include "qom/object.h"
+
+struct GenericLoaderState {
+ /* <private> */
+ DeviceState parent_obj;
+
+ /* <public> */
+ CPUState *cpu;
+
+ uint64_t addr;
+ uint64_t data;
+ uint8_t data_len;
+ uint32_t cpu_num;
+
+ char *file;
+
+ bool force_raw;
+ bool data_be;
+ bool set_pc;
+};
+
+#define TYPE_GENERIC_LOADER "loader"
+OBJECT_DECLARE_SIMPLE_TYPE(GenericLoaderState, GENERIC_LOADER)
+
+#endif
diff --git a/include/hw/core/split-irq.h b/include/hw/core/split-irq.h
new file mode 100644
index 000000000..ff8852f40
--- /dev/null
+++ b/include/hw/core/split-irq.h
@@ -0,0 +1,55 @@
+/*
+ * IRQ splitter device.
+ *
+ * Copyright (c) 2018 Linaro Limited.
+ * Written by Peter Maydell
+ *
+ * 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 simple device which has one GPIO input line and multiple
+ * GPIO output lines. Any change on the input line is forwarded to all
+ * of the outputs.
+ *
+ * QEMU interface:
+ * + one unnamed GPIO input: the input line
+ * + N unnamed GPIO outputs: the output lines
+ * + QOM property "num-lines": sets the number of output lines
+ */
+#ifndef HW_SPLIT_IRQ_H
+#define HW_SPLIT_IRQ_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_SPLIT_IRQ "split-irq"
+
+#define MAX_SPLIT_LINES 16
+
+
+OBJECT_DECLARE_SIMPLE_TYPE(SplitIRQ, SPLIT_IRQ)
+
+struct SplitIRQ {
+ DeviceState parent_obj;
+
+ qemu_irq out_irq[MAX_SPLIT_LINES];
+ uint16_t num_lines;
+};
+
+#endif
diff --git a/include/hw/core/sysemu-cpu-ops.h b/include/hw/core/sysemu-cpu-ops.h
new file mode 100644
index 000000000..a9ba39e5f
--- /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.
+ */
+ void (*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, void *opaque);
+ /**
+ * @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, void *opaque);
+ /**
+ * @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,
+ void *opaque);
+ /**
+ * @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,
+ void *opaque);
+ /**
+ * @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 000000000..e13898553
--- /dev/null
+++ b/include/hw/core/tcg-cpu-ops.h
@@ -0,0 +1,166 @@
+/*
+ * 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: Initalize 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);
+ /** @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
+#if defined(CONFIG_USER_ONLY) && defined(TARGET_I386)
+ /**
+ * @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);
+#else
+ /**
+ * @do_interrupt: Callback for interrupt handling.
+ */
+ void (*do_interrupt)(CPUState *cpu);
+#endif /* !CONFIG_USER_ONLY || !TARGET_I386 */
+#ifdef CONFIG_SOFTMMU
+ /** @cpu_exec_interrupt: Callback for processing interrupts in cpu_exec */
+ bool (*cpu_exec_interrupt)(CPUState *cpu, int interrupt_request);
+ /**
+ * @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.
+ */
+ void (*do_unaligned_access)(CPUState *cpu, vaddr addr,
+ MMUAccessType access_type,
+ int mmu_idx, uintptr_t retaddr) QEMU_NORETURN;
+
+ /**
+ * @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
+ */
+ 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);
+#else
+ /**
+ * 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);
+#endif /* CONFIG_SOFTMMU */
+#endif /* NEED_CPU_H */
+
+};
+
+#endif /* TCG_CPU_OPS_H */
diff --git a/include/hw/cpu/a15mpcore.h b/include/hw/cpu/a15mpcore.h
new file mode 100644
index 000000000..75d39e545
--- /dev/null
+++ b/include/hw/cpu/a15mpcore.h
@@ -0,0 +1,44 @@
+/*
+ * Cortex-A15MPCore internal peripheral emulation.
+ *
+ * Copyright (c) 2012 Linaro Limited.
+ * Written by Peter Maydell.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef HW_CPU_A15MPCORE_H
+#define HW_CPU_A15MPCORE_H
+
+#include "hw/sysbus.h"
+#include "hw/intc/arm_gic.h"
+#include "qom/object.h"
+
+/* A15MP private memory region. */
+
+#define TYPE_A15MPCORE_PRIV "a15mpcore_priv"
+OBJECT_DECLARE_SIMPLE_TYPE(A15MPPrivState, A15MPCORE_PRIV)
+
+struct A15MPPrivState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ uint32_t num_cpu;
+ uint32_t num_irq;
+ MemoryRegion container;
+
+ GICState gic;
+};
+
+#endif
diff --git a/include/hw/cpu/a9mpcore.h b/include/hw/cpu/a9mpcore.h
new file mode 100644
index 000000000..e0396ab6a
--- /dev/null
+++ b/include/hw/cpu/a9mpcore.h
@@ -0,0 +1,39 @@
+/*
+ * Cortex-A9MPCore internal peripheral emulation.
+ *
+ * Copyright (c) 2009 CodeSourcery.
+ * Copyright (c) 2011 Linaro Limited.
+ * Written by Paul Brook, Peter Maydell.
+ *
+ * This code is licensed under the GPL.
+ */
+#ifndef HW_CPU_A9MPCORE_H
+#define HW_CPU_A9MPCORE_H
+
+#include "hw/sysbus.h"
+#include "hw/intc/arm_gic.h"
+#include "hw/misc/a9scu.h"
+#include "hw/timer/arm_mptimer.h"
+#include "hw/timer/a9gtimer.h"
+#include "qom/object.h"
+
+#define TYPE_A9MPCORE_PRIV "a9mpcore_priv"
+OBJECT_DECLARE_SIMPLE_TYPE(A9MPPrivState, A9MPCORE_PRIV)
+
+struct A9MPPrivState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ uint32_t num_cpu;
+ MemoryRegion container;
+ uint32_t num_irq;
+
+ A9SCUState scu;
+ GICState gic;
+ A9GTimerState gtimer;
+ ARMMPTimerState mptimer;
+ ARMMPTimerState wdt;
+};
+
+#endif
diff --git a/include/hw/cpu/arm11mpcore.h b/include/hw/cpu/arm11mpcore.h
new file mode 100644
index 000000000..2cac8c123
--- /dev/null
+++ b/include/hw/cpu/arm11mpcore.h
@@ -0,0 +1,35 @@
+/*
+ * ARM11MPCore internal peripheral emulation.
+ *
+ * Copyright (c) 2006-2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the GPL.
+ */
+
+#ifndef HW_CPU_ARM11MPCORE_H
+#define HW_CPU_ARM11MPCORE_H
+
+#include "hw/sysbus.h"
+#include "hw/misc/arm11scu.h"
+#include "hw/intc/arm_gic.h"
+#include "hw/timer/arm_mptimer.h"
+#include "qom/object.h"
+
+#define TYPE_ARM11MPCORE_PRIV "arm11mpcore_priv"
+OBJECT_DECLARE_SIMPLE_TYPE(ARM11MPCorePriveState, ARM11MPCORE_PRIV)
+
+struct ARM11MPCorePriveState {
+ SysBusDevice parent_obj;
+
+ uint32_t num_cpu;
+ MemoryRegion container;
+ uint32_t num_irq;
+
+ ARM11SCUState scu;
+ GICState gic;
+ ARMMPTimerState mptimer;
+ ARMMPTimerState wdtimer;
+};
+
+#endif
diff --git a/include/hw/cpu/cluster.h b/include/hw/cpu/cluster.h
new file mode 100644
index 000000000..53fbf36af
--- /dev/null
+++ b/include/hw/cpu/cluster.h
@@ -0,0 +1,81 @@
+/*
+ * QEMU CPU cluster
+ *
+ * Copyright (c) 2018 GreenSocs SAS
+ *
+ * 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/gpl-2.0.html>
+ */
+#ifndef HW_CPU_CLUSTER_H
+#define HW_CPU_CLUSTER_H
+
+#include "hw/qdev-core.h"
+#include "qom/object.h"
+
+/*
+ * CPU Cluster type
+ *
+ * A cluster is a group of CPUs which are all identical and have the same view
+ * of the rest of the system. It is mainly an internal QEMU representation and
+ * does not necessarily match with the notion of clusters on the real hardware.
+ *
+ * If CPUs are not identical (for example, Cortex-A53 and Cortex-A57 CPUs in an
+ * Arm big.LITTLE system) they should be in different clusters. If the CPUs do
+ * not have the same view of memory (for example the main CPU and a management
+ * controller processor) they should be in different clusters.
+ *
+ * A cluster is created by creating an object of TYPE_CPU_CLUSTER, and then
+ * adding the CPUs to it as QOM child objects (e.g. using the
+ * object_initialize_child() or object_property_add_child() functions).
+ * The CPUs may be either direct children of the cluster object, or indirect
+ * children (e.g. children of children of the cluster object).
+ *
+ * All CPUs must be added as children before the cluster is realized.
+ * (Regrettably QOM provides no way to prevent adding children to a realized
+ * object and no way for the parent to be notified when a new child is added
+ * to it, so this restriction is not checked for, but the system will not
+ * behave correctly if it is not adhered to. The cluster will assert that
+ * it contains at least one CPU, which should catch most inadvertent
+ * violations of this constraint.)
+ *
+ * A CPU which is not put into any cluster will be considered implicitly
+ * to be in a cluster with all the other "loose" CPUs, so all CPUs that are
+ * not assigned to clusters must be identical.
+ */
+
+#define TYPE_CPU_CLUSTER "cpu-cluster"
+OBJECT_DECLARE_SIMPLE_TYPE(CPUClusterState, CPU_CLUSTER)
+
+/*
+ * This limit is imposed by TCG, which puts the cluster ID into an
+ * 8 bit field (and uses all-1s for the default "not in any cluster").
+ */
+#define MAX_CLUSTERS 255
+
+/**
+ * CPUClusterState:
+ * @cluster_id: The cluster ID. This value is for internal use only and should
+ * not be exposed directly to the user or to the guest.
+ *
+ * State of a CPU cluster.
+ */
+struct CPUClusterState {
+ /*< private >*/
+ DeviceState parent_obj;
+
+ /*< public >*/
+ uint32_t cluster_id;
+};
+
+#endif
diff --git a/include/hw/cpu/core.h b/include/hw/cpu/core.h
new file mode 100644
index 000000000..98ab91647
--- /dev/null
+++ b/include/hw/cpu/core.h
@@ -0,0 +1,33 @@
+/*
+ * CPU core abstract device
+ *
+ * Copyright (C) 2016 Bharata B Rao <bharata@linux.vnet.ibm.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_CPU_CORE_H
+#define HW_CPU_CORE_H
+
+#include "hw/qdev-core.h"
+#include "qom/object.h"
+
+#define TYPE_CPU_CORE "cpu-core"
+
+OBJECT_DECLARE_SIMPLE_TYPE(CPUCore, CPU_CORE)
+
+struct CPUCore {
+ /*< private >*/
+ DeviceState parent_obj;
+
+ /*< public >*/
+ int core_id;
+ int nr_threads;
+};
+
+/* Note: topology field names need to be kept in sync with
+ * 'CpuInstanceProperties' */
+
+#define CPU_CORE_PROP_CORE_ID "core-id"
+
+#endif
diff --git a/include/hw/cris/etraxfs.h b/include/hw/cris/etraxfs.h
new file mode 100644
index 000000000..8b01ed67d
--- /dev/null
+++ b/include/hw/cris/etraxfs.h
@@ -0,0 +1,53 @@
+/*
+ * QEMU ETRAX System Emulator
+ *
+ * Copyright (c) 2008 Edgar E. Iglesias, Axis Communications AB.
+ *
+ * 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_ETRAXFS_H
+#define HW_ETRAXFS_H
+
+#include "net/net.h"
+#include "hw/cris/etraxfs_dma.h"
+#include "hw/qdev-properties.h"
+#include "hw/sysbus.h"
+
+DeviceState *etraxfs_eth_init(NICInfo *nd, hwaddr base, int phyaddr,
+ struct etraxfs_dma_client *dma_out,
+ struct etraxfs_dma_client *dma_in);
+
+static inline DeviceState *etraxfs_ser_create(hwaddr addr,
+ qemu_irq irq,
+ Chardev *chr)
+{
+ DeviceState *dev;
+ SysBusDevice *s;
+
+ dev = qdev_new("etraxfs-serial");
+ 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/cris/etraxfs_dma.h b/include/hw/cris/etraxfs_dma.h
new file mode 100644
index 000000000..095d76b95
--- /dev/null
+++ b/include/hw/cris/etraxfs_dma.h
@@ -0,0 +1,36 @@
+#ifndef HW_ETRAXFS_DMA_H
+#define HW_ETRAXFS_DMA_H
+
+#include "exec/hwaddr.h"
+
+struct dma_context_metadata {
+ /* data descriptor md */
+ uint16_t metadata;
+};
+
+struct etraxfs_dma_client
+{
+ /* DMA controller. */
+ int channel;
+ void *ctrl;
+
+ /* client. */
+ struct {
+ int (*push)(void *opaque, unsigned char *buf,
+ int len, bool eop);
+ void (*pull)(void *opaque);
+ void (*metadata_push)(void *opaque,
+ const struct dma_context_metadata *md);
+ void *opaque;
+ } client;
+};
+
+void *etraxfs_dmac_init(hwaddr base, int nr_channels);
+void etraxfs_dmac_connect(void *opaque, int channel, qemu_irq *line,
+ int input);
+void etraxfs_dmac_connect_client(void *opaque, int c,
+ struct etraxfs_dma_client *cl);
+int etraxfs_dmac_input(struct etraxfs_dma_client *client,
+ void *buf, int len, int eop);
+
+#endif
diff --git a/include/hw/display/bcm2835_fb.h b/include/hw/display/bcm2835_fb.h
new file mode 100644
index 000000000..38671afff
--- /dev/null
+++ b/include/hw/display/bcm2835_fb.h
@@ -0,0 +1,89 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * Upstreaming code cleanup [including bcm2835_*] (c) 2013 Jan Petrous
+ *
+ * Rasperry Pi 2 emulation and refactoring Copyright (c) 2015, Microsoft
+ * Written by Andrew Baumann
+ *
+ * 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_FB_H
+#define BCM2835_FB_H
+
+#include "hw/sysbus.h"
+#include "ui/console.h"
+#include "qom/object.h"
+
+#define TYPE_BCM2835_FB "bcm2835-fb"
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835FBState, BCM2835_FB)
+
+/*
+ * Configuration information about the fb which the guest can program
+ * via the mailbox property interface.
+ */
+typedef struct {
+ uint32_t xres, yres;
+ uint32_t xres_virtual, yres_virtual;
+ uint32_t xoffset, yoffset;
+ uint32_t bpp;
+ uint32_t base;
+ uint32_t pixo;
+ uint32_t alpha;
+} BCM2835FBConfig;
+
+struct BCM2835FBState {
+ /*< private >*/
+ SysBusDevice busdev;
+ /*< public >*/
+
+ uint32_t vcram_base, vcram_size;
+ MemoryRegion *dma_mr;
+ AddressSpace dma_as;
+ MemoryRegion iomem;
+ MemoryRegionSection fbsection;
+ QemuConsole *con;
+ qemu_irq mbox_irq;
+
+ bool lock, invalidate, pending;
+
+ BCM2835FBConfig config;
+ BCM2835FBConfig initial_config;
+};
+
+void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig);
+
+/**
+ * bcm2835_fb_get_pitch: return number of bytes per line of the framebuffer
+ * @config: configuration info for the framebuffer
+ *
+ * Return the number of bytes per line of the framebuffer, ie the number
+ * that must be added to a pixel address to get the address of the pixel
+ * directly below it on screen.
+ */
+static inline uint32_t bcm2835_fb_get_pitch(BCM2835FBConfig *config)
+{
+ uint32_t xres = MAX(config->xres, config->xres_virtual);
+ return xres * (config->bpp >> 3);
+}
+
+/**
+ * bcm2835_fb_get_size: return total size of framebuffer in bytes
+ * @config: configuration info for the framebuffer
+ */
+static inline uint32_t bcm2835_fb_get_size(BCM2835FBConfig *config)
+{
+ uint32_t yres = MAX(config->yres, config->yres_virtual);
+ return yres * bcm2835_fb_get_pitch(config);
+}
+
+/**
+ * bcm2835_fb_validate_config: check provided config
+ *
+ * Validates the configuration information provided by the guest and
+ * adjusts it if necessary.
+ */
+void bcm2835_fb_validate_config(BCM2835FBConfig *config);
+
+#endif
diff --git a/include/hw/display/blizzard.h b/include/hw/display/blizzard.h
new file mode 100644
index 000000000..5b3301883
--- /dev/null
+++ b/include/hw/display/blizzard.h
@@ -0,0 +1,21 @@
+/*
+ * Epson S1D13744/S1D13745 (Blizzard/Hailstorm/Tornado) LCD/TV controller.
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Written by Andrzej Zaborowski
+ *
+ * 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_DISPLAY_BLIZZARD_H
+#define HW_DISPLAY_BLIZZARD_H
+
+
+void *s1d13745_init(qemu_irq gpio_int);
+void s1d13745_write(void *opaque, int dc, uint16_t value);
+void s1d13745_write_block(void *opaque, int dc,
+ void *buf, size_t len, int pitch);
+uint16_t s1d13745_read(void *opaque, int dc);
+
+#endif
diff --git a/include/hw/display/bochs-vbe.h b/include/hw/display/bochs-vbe.h
new file mode 100644
index 000000000..bc2f046ee
--- /dev/null
+++ b/include/hw/display/bochs-vbe.h
@@ -0,0 +1,69 @@
+#ifndef HW_DISPLAY_BOCHS_VBE_H
+#define HW_DISPLAY_BOCHS_VBE_H
+
+/*
+ * bochs vesa bios extension interface
+ */
+
+#define VBE_DISPI_MAX_XRES 16000
+#define VBE_DISPI_MAX_YRES 12000
+#define VBE_DISPI_MAX_BPP 32
+
+#define VBE_DISPI_INDEX_ID 0x0
+#define VBE_DISPI_INDEX_XRES 0x1
+#define VBE_DISPI_INDEX_YRES 0x2
+#define VBE_DISPI_INDEX_BPP 0x3
+#define VBE_DISPI_INDEX_ENABLE 0x4
+#define VBE_DISPI_INDEX_BANK 0x5
+#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
+#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
+#define VBE_DISPI_INDEX_X_OFFSET 0x8
+#define VBE_DISPI_INDEX_Y_OFFSET 0x9
+#define VBE_DISPI_INDEX_NB 0xa /* size of vbe_regs[] */
+#define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa /* read-only, not in vbe_regs */
+
+/* VBE_DISPI_INDEX_ID */
+#define VBE_DISPI_ID0 0xB0C0
+#define VBE_DISPI_ID1 0xB0C1
+#define VBE_DISPI_ID2 0xB0C2
+#define VBE_DISPI_ID3 0xB0C3
+#define VBE_DISPI_ID4 0xB0C4
+#define VBE_DISPI_ID5 0xB0C5
+
+/* VBE_DISPI_INDEX_ENABLE */
+#define VBE_DISPI_DISABLED 0x00
+#define VBE_DISPI_ENABLED 0x01
+#define VBE_DISPI_GETCAPS 0x02
+#define VBE_DISPI_8BIT_DAC 0x20
+#define VBE_DISPI_LFB_ENABLED 0x40
+#define VBE_DISPI_NOCLEARMEM 0x80
+
+/* only used by isa-vga, pci vga devices use a memory bar */
+#define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000
+
+
+/*
+ * qemu extension: mmio bar (region 2)
+ */
+
+#define PCI_VGA_MMIO_SIZE 0x1000
+
+/* vga register region */
+#define PCI_VGA_IOPORT_OFFSET 0x400
+#define PCI_VGA_IOPORT_SIZE (0x3e0 - 0x3c0)
+
+/* bochs vbe register region */
+#define PCI_VGA_BOCHS_OFFSET 0x500
+#define PCI_VGA_BOCHS_SIZE (0x0b * 2)
+
+/* qemu extension register region */
+#define PCI_VGA_QEXT_OFFSET 0x600
+#define PCI_VGA_QEXT_SIZE (2 * 4)
+
+/* qemu extension registers */
+#define PCI_VGA_QEXT_REG_SIZE (0 * 4)
+#define PCI_VGA_QEXT_REG_BYTEORDER (1 * 4)
+#define PCI_VGA_QEXT_LITTLE_ENDIAN 0x1e1e1e1e
+#define PCI_VGA_QEXT_BIG_ENDIAN 0xbebebebe
+
+#endif /* HW_DISPLAY_BOCHS_VBE_H */
diff --git a/include/hw/display/dpcd.h b/include/hw/display/dpcd.h
new file mode 100644
index 000000000..a4e37abf6
--- /dev/null
+++ b/include/hw/display/dpcd.h
@@ -0,0 +1,105 @@
+/*
+ * dpcd.h
+ *
+ * Copyright (C)2015 : GreenSocs Ltd
+ * http://www.greensocs.com/ , email: info@greensocs.com
+ *
+ * Developed by :
+ * Frederic Konrad <fred.konrad@greensocs.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 DPCD_H
+#define DPCD_H
+#include "qom/object.h"
+
+
+#define TYPE_DPCD "dpcd"
+OBJECT_DECLARE_SIMPLE_TYPE(DPCDState, DPCD)
+
+/* DCPD Revision. */
+#define DPCD_REVISION 0x00
+#define DPCD_REV_1_0 0x10
+#define DPCD_REV_1_1 0x11
+
+/* DCPD Max Link Rate. */
+#define DPCD_MAX_LINK_RATE 0x01
+#define DPCD_1_62GBPS 0x06
+#define DPCD_2_7GBPS 0x0A
+#define DPCD_5_4GBPS 0x14
+
+#define DPCD_MAX_LANE_COUNT 0x02
+#define DPCD_ONE_LANE 0x01
+#define DPCD_TWO_LANES 0x02
+#define DPCD_FOUR_LANES 0x04
+
+/* DCPD Max down spread. */
+#define DPCD_UP_TO_0_5 0x01
+#define DPCD_NO_AUX_HANDSHAKE_LINK_TRAINING 0x40
+
+/* DCPD Downstream port type. */
+#define DPCD_DISPLAY_PORT 0x00
+#define DPCD_ANALOG 0x02
+#define DPCD_DVI_HDMI 0x04
+#define DPCD_OTHER 0x06
+
+/* DPCD Format conversion. */
+#define DPCD_FORMAT_CONVERSION 0x08
+
+/* Main link channel coding. */
+#define DPCD_ANSI_8B_10B 0x01
+
+/* Down stream port count. */
+#define DPCD_OUI_SUPPORTED 0x80
+
+/* Receiver port capability. */
+#define DPCD_RECEIVE_PORT0_CAP_0 0x08
+#define DPCD_RECEIVE_PORT0_CAP_1 0x09
+#define DPCD_EDID_PRESENT 0x02
+#define DPCD_ASSOCIATED_TO_PRECEDING_PORT 0x04
+
+/* Down stream port capability. */
+#define DPCD_CAP_DISPLAY_PORT 0x000
+#define DPCD_CAP_ANALOG_VGA 0x001
+#define DPCD_CAP_DVI 0x002
+#define DPCD_CAP_HDMI 0x003
+#define DPCD_CAP_OTHER 0x100
+
+#define DPCD_LANE0_1_STATUS 0x202
+#define DPCD_LANE0_CR_DONE (1 << 0)
+#define DPCD_LANE0_CHANNEL_EQ_DONE (1 << 1)
+#define DPCD_LANE0_SYMBOL_LOCKED (1 << 2)
+#define DPCD_LANE1_CR_DONE (1 << 4)
+#define DPCD_LANE1_CHANNEL_EQ_DONE (1 << 5)
+#define DPCD_LANE1_SYMBOL_LOCKED (1 << 6)
+
+#define DPCD_LANE2_3_STATUS 0x203
+#define DPCD_LANE2_CR_DONE (1 << 0)
+#define DPCD_LANE2_CHANNEL_EQ_DONE (1 << 1)
+#define DPCD_LANE2_SYMBOL_LOCKED (1 << 2)
+#define DPCD_LANE3_CR_DONE (1 << 4)
+#define DPCD_LANE3_CHANNEL_EQ_DONE (1 << 5)
+#define DPCD_LANE3_SYMBOL_LOCKED (1 << 6)
+
+#define DPCD_LANE_ALIGN_STATUS_UPDATED 0x204
+#define DPCD_INTERLANE_ALIGN_DONE 0x01
+#define DPCD_DOWNSTREAM_PORT_STATUS_CHANGED 0x40
+#define DPCD_LINK_STATUS_UPDATED 0x80
+
+#define DPCD_SINK_STATUS 0x205
+#define DPCD_RECEIVE_PORT_0_STATUS 0x01
+
+#endif /* DPCD_H */
diff --git a/include/hw/display/edid.h b/include/hw/display/edid.h
new file mode 100644
index 000000000..520f8ec20
--- /dev/null
+++ b/include/hw/display/edid.h
@@ -0,0 +1,32 @@
+#ifndef EDID_H
+#define EDID_H
+
+typedef struct qemu_edid_info {
+ const char *vendor; /* http://www.uefi.org/pnp_id_list */
+ const char *name;
+ const char *serial;
+ 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,
+ qemu_edid_info *info);
+size_t qemu_edid_size(uint8_t *edid);
+void qemu_edid_region_io(MemoryRegion *region, Object *owner,
+ uint8_t *edid, size_t size);
+
+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
new file mode 100644
index 000000000..94b588058
--- /dev/null
+++ b/include/hw/display/i2c-ddc.h
@@ -0,0 +1,41 @@
+/* A simple I2C slave for returning monitor EDID data via DDC.
+ *
+ * Copyright (c) 2011 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 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.
+ *
+ * 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 I2C_DDC_H
+#define I2C_DDC_H
+
+#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 {
+ /*< private >*/
+ I2CSlave i2c;
+ /*< public >*/
+ bool firstbyte;
+ uint8_t reg;
+ qemu_edid_info edid_info;
+ uint8_t edid_blob[128];
+};
+
+
+#define TYPE_I2CDDC "i2c-ddc"
+OBJECT_DECLARE_SIMPLE_TYPE(I2CDDCState, I2CDDC)
+
+#endif /* I2C_DDC_H */
diff --git a/include/hw/display/macfb.h b/include/hw/display/macfb.h
new file mode 100644
index 000000000..e52775aa2
--- /dev/null
+++ b/include/hw/display/macfb.h
@@ -0,0 +1,101 @@
+/*
+ * QEMU Motorola 680x0 Macintosh Video Card Emulation
+ * Copyright (c) 2012-2018 Laurent Vivier
+ *
+ * some parts from QEMU G364 framebuffer Emulator.
+ * Copyright (c) 2007-2011 Herve Poussineau
+ *
+ * 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 MACFB_H
+#define MACFB_H
+
+#include "exec/memory.h"
+#include "hw/irq.h"
+#include "ui/console.h"
+#include "qemu/timer.h"
+#include "qom/object.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_NUM_REGS 8
+
+typedef struct MacfbState {
+ MemoryRegion mem_vram;
+ MemoryRegion mem_ctrl;
+ QemuConsole *con;
+
+ uint8_t *vram;
+ uint32_t vram_bit_mask;
+ uint32_t palette_current;
+ 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;
+
+ uint32_t irq_state;
+ uint32_t irq_mask;
+ QEMUTimer *vbl_timer;
+ qemu_irq irq;
+} MacfbState;
+
+#define TYPE_MACFB "sysbus-macfb"
+OBJECT_DECLARE_SIMPLE_TYPE(MacfbSysBusState, MACFB)
+
+struct MacfbSysBusState {
+ SysBusDevice busdev;
+
+ MacfbState macfb;
+};
+
+#define TYPE_NUBUS_MACFB "nubus-macfb"
+OBJECT_DECLARE_TYPE(MacfbNubusState, MacfbNubusDeviceClass, NUBUS_MACFB)
+
+struct MacfbNubusDeviceClass {
+ DeviceClass parent_class;
+
+ DeviceRealize parent_realize;
+ DeviceUnrealize parent_unrealize;
+};
+
+
+struct MacfbNubusState {
+ NubusDevice busdev;
+
+ MacfbState macfb;
+};
+
+#endif
diff --git a/include/hw/display/ramfb.h b/include/hw/display/ramfb.h
new file mode 100644
index 000000000..b33a2c467
--- /dev/null
+++ b/include/hw/display/ramfb.h
@@ -0,0 +1,12 @@
+#ifndef RAMFB_H
+#define RAMFB_H
+
+/* ramfb.c */
+typedef struct RAMFBState RAMFBState;
+void ramfb_display_update(QemuConsole *con, RAMFBState *s);
+RAMFBState *ramfb_setup(Error **errp);
+
+/* ramfb-standalone.c */
+#define TYPE_RAMFB_DEVICE "ramfb"
+
+#endif /* RAMFB_H */
diff --git a/include/hw/display/tc6393xb.h b/include/hw/display/tc6393xb.h
new file mode 100644
index 000000000..f9263bf98
--- /dev/null
+++ b/include/hw/display/tc6393xb.h
@@ -0,0 +1,21 @@
+/*
+ * Toshiba TC6393XB I/O Controller.
+ * Found in Sharp Zaurus SL-6000 (tosa) or some
+ * Toshiba e-Series PDAs.
+ *
+ * Copyright (c) 2007 Hervé Poussineau
+ *
+ * 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_DISPLAY_TC6393XB_H
+#define HW_DISPLAY_TC6393XB_H
+
+typedef struct TC6393xbState TC6393xbState;
+
+TC6393xbState *tc6393xb_init(struct MemoryRegion *sysmem,
+ uint32_t base, qemu_irq irq);
+qemu_irq tc6393xb_l3v_get(TC6393xbState *s);
+
+#endif
diff --git a/include/hw/display/vga.h b/include/hw/display/vga.h
new file mode 100644
index 000000000..5f7825e0e
--- /dev/null
+++ b/include/hw/display/vga.h
@@ -0,0 +1,31 @@
+/*
+ * QEMU VGA Emulator.
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * 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_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,
+ VGA_RETRACE_PRECISE
+};
+
+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);
+
+#endif
diff --git a/include/hw/display/xlnx_dp.h b/include/hw/display/xlnx_dp.h
new file mode 100644
index 000000000..8ab4733bb
--- /dev/null
+++ b/include/hw/display/xlnx_dp.h
@@ -0,0 +1,110 @@
+/*
+ * xlnx_dp.h
+ *
+ * Copyright (C) 2015 : GreenSocs Ltd
+ * http://www.greensocs.com/ , email: info@greensocs.com
+ *
+ * Developed by :
+ * Frederic Konrad <fred.konrad@greensocs.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 XLNX_DP_H
+#define XLNX_DP_H
+
+#include "hw/sysbus.h"
+#include "ui/console.h"
+#include "hw/misc/auxbus.h"
+#include "hw/i2c/i2c.h"
+#include "hw/display/dpcd.h"
+#include "hw/display/i2c-ddc.h"
+#include "qemu/fifo8.h"
+#include "qemu/units.h"
+#include "hw/dma/xlnx_dpdma.h"
+#include "audio/audio.h"
+#include "qom/object.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_AVBUF_REG_ARRAY_SIZE (0x238 >> 2)
+#define DP_VBLEND_REG_ARRAY_SIZE (0x1DF >> 2)
+#define DP_AUDIO_REG_ARRAY_SIZE (0x50 >> 2)
+
+struct PixmanPlane {
+ pixman_format_code_t format;
+ DisplaySurface *surface;
+};
+
+struct XlnxDPState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /* < public >*/
+ MemoryRegion container;
+
+ uint32_t core_registers[DP_CORE_REG_ARRAY_SIZE];
+ MemoryRegion core_iomem;
+
+ uint32_t avbufm_registers[DP_AVBUF_REG_ARRAY_SIZE];
+ MemoryRegion avbufm_iomem;
+
+ uint32_t vblend_registers[DP_VBLEND_REG_ARRAY_SIZE];
+ MemoryRegion vblend_iomem;
+
+ uint32_t audio_registers[DP_AUDIO_REG_ARRAY_SIZE];
+ MemoryRegion audio_iomem;
+
+ QemuConsole *console;
+
+ /*
+ * This is the planes used to display in console. When the blending is
+ * enabled bout_plane is displayed in console else it's g_plane.
+ */
+ struct PixmanPlane g_plane;
+ struct PixmanPlane v_plane;
+ struct PixmanPlane bout_plane;
+
+ QEMUSoundCard aud_card;
+ SWVoiceOut *amixer_output_stream;
+ int16_t audio_buffer_0[AUD_CHBUF_MAX_DEPTH];
+ int16_t audio_buffer_1[AUD_CHBUF_MAX_DEPTH];
+ size_t audio_data_available[2];
+ int64_t temp_buffer[AUD_CHBUF_MAX_DEPTH];
+ int16_t out_buffer[AUD_CHBUF_MAX_DEPTH];
+ size_t byte_left; /* byte available in out_buffer. */
+ size_t data_ptr; /* next byte to be sent to QEMU. */
+
+ /* Associated DPDMA controller. */
+ XlnxDPDMAState *dpdma;
+
+ qemu_irq irq;
+
+ AUXBus *aux_bus;
+ Fifo8 rx_fifo;
+ Fifo8 tx_fifo;
+
+ /*
+ * XXX: This should be in an other module.
+ */
+ DPCDState *dpcd;
+ I2CDDCState *edid;
+};
+
+#define TYPE_XLNX_DP "xlnx.v-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
new file mode 100644
index 000000000..1d26b1d8d
--- /dev/null
+++ b/include/hw/dma/bcm2835_dma.h
@@ -0,0 +1,47 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ *
+ * 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_DMA_H
+#define BCM2835_DMA_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+typedef struct {
+ uint32_t cs;
+ uint32_t conblk_ad;
+ uint32_t ti;
+ uint32_t source_ad;
+ uint32_t dest_ad;
+ uint32_t txfr_len;
+ uint32_t stride;
+ uint32_t nextconbk;
+ uint32_t debug;
+
+ qemu_irq irq;
+} BCM2835DMAChan;
+
+#define TYPE_BCM2835_DMA "bcm2835-dma"
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835DMAState, BCM2835_DMA)
+
+#define BCM2835_DMA_NCHANS 16
+
+struct BCM2835DMAState {
+ /*< private >*/
+ SysBusDevice busdev;
+ /*< public >*/
+
+ MemoryRegion iomem0, iomem15;
+ MemoryRegion *dma_mr;
+ AddressSpace dma_as;
+
+ BCM2835DMAChan chan[BCM2835_DMA_NCHANS];
+ uint32_t int_status;
+ uint32_t enable;
+};
+
+#endif
diff --git a/include/hw/dma/i8257.h b/include/hw/dma/i8257.h
new file mode 100644
index 000000000..f652345d6
--- /dev/null
+++ b/include/hw/dma/i8257.h
@@ -0,0 +1,50 @@
+#ifndef HW_I8257_H
+#define HW_I8257_H
+
+#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];
+ uint16_t base[2];
+ uint8_t mode;
+ uint8_t page;
+ uint8_t pageh;
+ uint8_t dack;
+ uint8_t eop;
+ IsaDmaTransferHandler transfer_handler;
+ void *opaque;
+} I8257Regs;
+
+struct I8257State {
+ /* <private> */
+ ISADevice parent_obj;
+
+ /* <public> */
+ int32_t base;
+ int32_t page_base;
+ int32_t pageh_base;
+ int32_t dshift;
+
+ uint8_t status;
+ uint8_t command;
+ uint8_t mask;
+ uint8_t flip_flop;
+ I8257Regs regs[4];
+ MemoryRegion channel_io;
+ MemoryRegion cont_io;
+
+ QEMUBH *dma_bh;
+ bool dma_bh_scheduled;
+ int running;
+ PortioList portio_page;
+ PortioList portio_pageh;
+};
+
+void i8257_dma_init(ISABus *bus, bool high_page_enable);
+
+#endif
diff --git a/include/hw/dma/pl080.h b/include/hw/dma/pl080.h
new file mode 100644
index 000000000..3c9659e43
--- /dev/null
+++ b/include/hw/dma/pl080.h
@@ -0,0 +1,73 @@
+/*
+ * ARM PrimeCell PL080/PL081 DMA controller
+ *
+ * Copyright (c) 2006 CodeSourcery.
+ * Copyright (c) 2018 Linaro Limited
+ * Written by Paul Brook, Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or
+ * (at your option) any later version.
+ */
+
+/*
+ * This is a model of the Arm PrimeCell PL080/PL081 DMA controller:
+ * The PL080 TRM is:
+ * https://developer.arm.com/documentation/ddi0196/latest
+ * and the PL081 TRM is:
+ * https://developer.arm.com/documentation/ddi0218/latest
+ *
+ * QEMU interface:
+ * + sysbus IRQ 0: DMACINTR combined interrupt line
+ * + sysbus IRQ 1: DMACINTERR error interrupt request
+ * + sysbus IRQ 2: DMACINTTC count interrupt request
+ * + sysbus MMIO region 0: MemoryRegion for the device's registers
+ * + QOM property "downstream": MemoryRegion defining where DMA
+ * bus master transactions are made
+ */
+
+#ifndef HW_DMA_PL080_H
+#define HW_DMA_PL080_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define PL080_MAX_CHANNELS 8
+
+typedef struct {
+ uint32_t src;
+ uint32_t dest;
+ uint32_t lli;
+ uint32_t ctrl;
+ uint32_t conf;
+} pl080_channel;
+
+#define TYPE_PL080 "pl080"
+#define TYPE_PL081 "pl081"
+OBJECT_DECLARE_SIMPLE_TYPE(PL080State, PL080)
+
+struct PL080State {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ uint8_t tc_int;
+ uint8_t tc_mask;
+ uint8_t err_int;
+ uint8_t err_mask;
+ uint32_t conf;
+ uint32_t sync;
+ uint32_t req_single;
+ uint32_t req_burst;
+ pl080_channel chan[PL080_MAX_CHANNELS];
+ int nchannels;
+ /* Flag to avoid recursive DMA invocations. */
+ int running;
+ qemu_irq irq;
+ qemu_irq interr;
+ qemu_irq inttc;
+
+ MemoryRegion *downstream;
+ AddressSpace downstream_as;
+};
+
+#endif
diff --git a/include/hw/dma/sifive_pdma.h b/include/hw/dma/sifive_pdma.h
new file mode 100644
index 000000000..e319bbd6c
--- /dev/null
+++ b/include/hw/dma/sifive_pdma.h
@@ -0,0 +1,57 @@
+/*
+ * 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
+
+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
new file mode 100644
index 000000000..efc75217d
--- /dev/null
+++ b/include/hw/dma/xlnx-zdma.h
@@ -0,0 +1,84 @@
+/*
+ * QEMU model of the ZynqMP generic DMA
+ *
+ * Copyright (c) 2014 Xilinx Inc.
+ * Copyright (c) 2018 FEIMTECH AB
+ *
+ * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>,
+ * Francisco Iglesias <francisco.iglesias@feimtech.se>
+ *
+ * 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_ZDMA_H
+#define XLNX_ZDMA_H
+
+#include "hw/sysbus.h"
+#include "hw/register.h"
+#include "sysemu/dma.h"
+#include "qom/object.h"
+
+#define ZDMA_R_MAX (0x204 / 4)
+
+typedef enum {
+ DISABLED = 0,
+ ENABLED = 1,
+ PAUSED = 2,
+} XlnxZDMAState;
+
+typedef union {
+ struct {
+ uint64_t addr;
+ uint32_t size;
+ uint32_t attr;
+ };
+ uint32_t words[4];
+} XlnxZDMADescr;
+
+struct XlnxZDMA {
+ SysBusDevice parent_obj;
+ MemoryRegion iomem;
+ MemTxAttrs attr;
+ MemoryRegion *dma_mr;
+ AddressSpace dma_as;
+ qemu_irq irq_zdma_ch_imr;
+
+ struct {
+ uint32_t bus_width;
+ } cfg;
+
+ XlnxZDMAState state;
+ bool error;
+
+ XlnxZDMADescr dsc_src;
+ XlnxZDMADescr dsc_dst;
+
+ uint32_t regs[ZDMA_R_MAX];
+ RegisterInfo regs_info[ZDMA_R_MAX];
+
+ /* We don't model the common bufs. Must be at least 16 bytes
+ to model write only mode. */
+ uint8_t buf[2048];
+};
+
+#define TYPE_XLNX_ZDMA "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
new file mode 100644
index 000000000..e4cf085d7
--- /dev/null
+++ b/include/hw/dma/xlnx-zynq-devcfg.h
@@ -0,0 +1,62 @@
+/*
+ * QEMU model of the Xilinx Devcfg Interface
+ *
+ * (C) 2011 PetaLogix Pty Ltd
+ * (C) 2014 Xilinx Inc.
+ * Written by Peter Crosthwaite <peter.crosthwaite@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_ZYNQ_DEVCFG_H
+#define XLNX_ZYNQ_DEVCFG_H
+
+#include "hw/register.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_XLNX_ZYNQ_DEVCFG "xlnx.ps7-dev-cfg"
+
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqDevcfg, XLNX_ZYNQ_DEVCFG)
+
+#define XLNX_ZYNQ_DEVCFG_R_MAX (0x100 / 4)
+
+#define XLNX_ZYNQ_DEVCFG_DMA_CMD_FIFO_LEN 10
+
+typedef struct XlnxZynqDevcfgDMACmd {
+ uint32_t src_addr;
+ uint32_t dest_addr;
+ uint32_t src_len;
+ uint32_t dest_len;
+} XlnxZynqDevcfgDMACmd;
+
+struct XlnxZynqDevcfg {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ qemu_irq irq;
+
+ XlnxZynqDevcfgDMACmd dma_cmd_fifo[XLNX_ZYNQ_DEVCFG_DMA_CMD_FIFO_LEN];
+ uint8_t dma_cmd_fifo_num;
+
+ uint32_t regs[XLNX_ZYNQ_DEVCFG_R_MAX];
+ RegisterInfo regs_info[XLNX_ZYNQ_DEVCFG_R_MAX];
+};
+
+#endif
diff --git a/include/hw/dma/xlnx_csu_dma.h b/include/hw/dma/xlnx_csu_dma.h
new file mode 100644
index 000000000..9e9dc551e
--- /dev/null
+++ b/include/hw/dma/xlnx_csu_dma.h
@@ -0,0 +1,52 @@
+/*
+ * 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
+
+#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;
+
+#define XLNX_CSU_DMA(obj) \
+ OBJECT_CHECK(XlnxCSUDMA, (obj), TYPE_XLNX_CSU_DMA)
+
+#endif
diff --git a/include/hw/dma/xlnx_dpdma.h b/include/hw/dma/xlnx_dpdma.h
new file mode 100644
index 000000000..40537a848
--- /dev/null
+++ b/include/hw/dma/xlnx_dpdma.h
@@ -0,0 +1,86 @@
+/*
+ * xlnx_dpdma.h
+ *
+ * Copyright (C) 2015 : GreenSocs Ltd
+ * http://www.greensocs.com/ , email: info@greensocs.com
+ *
+ * Developed by :
+ * Frederic Konrad <fred.konrad@greensocs.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 XLNX_DPDMA_H
+#define XLNX_DPDMA_H
+
+#include "hw/sysbus.h"
+#include "ui/console.h"
+#include "sysemu/dma.h"
+#include "qom/object.h"
+
+#define XLNX_DPDMA_REG_ARRAY_SIZE (0x1000 >> 2)
+
+struct XlnxDPDMAState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+ MemoryRegion iomem;
+ uint32_t registers[XLNX_DPDMA_REG_ARRAY_SIZE];
+ uint8_t *data[6];
+ bool operation_finished[6];
+ qemu_irq irq;
+};
+
+
+#define TYPE_XLNX_DPDMA "xlnx.dpdma"
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxDPDMAState, XLNX_DPDMA)
+
+/*
+ * xlnx_dpdma_start_operation: Start the operation on the specified channel. The
+ * DPDMA gets the current descriptor and retrieves
+ * data to the buffer specified by
+ * dpdma_set_host_data_location().
+ *
+ * Returns The number of bytes transferred by the DPDMA
+ * or 0 if an error occurred.
+ *
+ * @s The DPDMA state.
+ * @channel The channel to start.
+ */
+size_t xlnx_dpdma_start_operation(XlnxDPDMAState *s, uint8_t channel,
+ bool one_desc);
+
+/*
+ * xlnx_dpdma_set_host_data_location: Set the location in the host memory where
+ * to store the data out from the dma
+ * channel.
+ *
+ * @s The DPDMA state.
+ * @channel The channel associated to the pointer.
+ * @p The buffer where to store the data.
+ */
+/* XXX: add a maximum size arg and send an interrupt in case of overflow. */
+void xlnx_dpdma_set_host_data_location(XlnxDPDMAState *s, uint8_t channel,
+ void *p);
+
+/*
+ * xlnx_dpdma_trigger_vsync_irq: Trigger a VSYNC IRQ when the display is
+ * updated.
+ *
+ * @s The DPDMA state.
+ */
+void xlnx_dpdma_trigger_vsync_irq(XlnxDPDMAState *s);
+
+#endif /* XLNX_DPDMA_H */
diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
new file mode 100644
index 000000000..995de8495
--- /dev/null
+++ b/include/hw/elf_ops.h
@@ -0,0 +1,611 @@
+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 */
+}
+
+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 */
+}
+
+static void glue(bswap_shdr, SZ)(struct elf_shdr *shdr)
+{
+ bswap32s(&shdr->sh_name);
+ bswap32s(&shdr->sh_type);
+ bswapSZs(&shdr->sh_flags);
+ bswapSZs(&shdr->sh_addr);
+ bswapSZs(&shdr->sh_offset);
+ bswapSZs(&shdr->sh_size);
+ bswap32s(&shdr->sh_link);
+ bswap32s(&shdr->sh_info);
+ bswapSZs(&shdr->sh_addralign);
+ bswapSZs(&shdr->sh_entsize);
+}
+
+static void glue(bswap_sym, SZ)(struct elf_sym *sym)
+{
+ bswap32s(&sym->st_name);
+ bswapSZs(&sym->st_value);
+ bswapSZs(&sym->st_size);
+ bswap16s(&sym->st_shndx);
+}
+
+static void glue(bswap_rela, SZ)(struct elf_rela *rela)
+{
+ bswapSZs(&rela->r_offset);
+ bswapSZs(&rela->r_info);
+ bswapSZs((elf_word *)&rela->r_addend);
+}
+
+static struct elf_shdr *glue(find_section, SZ)(struct elf_shdr *shdr_table,
+ int n, int type)
+{
+ int i;
+ for(i=0;i<n;i++) {
+ if (shdr_table[i].sh_type == type)
+ return shdr_table + i;
+ }
+ return NULL;
+}
+
+static int glue(symfind, SZ)(const void *s0, const void *s1)
+{
+ hwaddr addr = *(hwaddr *)s0;
+ struct elf_sym *sym = (struct elf_sym *)s1;
+ int result = 0;
+ if (addr < sym->st_value) {
+ result = -1;
+ } else if (addr >= sym->st_value + sym->st_size) {
+ result = 1;
+ }
+ return result;
+}
+
+static const char *glue(lookup_symbol, SZ)(struct syminfo *s,
+ hwaddr orig_addr)
+{
+ struct elf_sym *syms = glue(s->disas_symtab.elf, SZ);
+ struct elf_sym *sym;
+
+ sym = bsearch(&orig_addr, syms, s->disas_num_syms, sizeof(*syms),
+ glue(symfind, SZ));
+ if (sym != NULL) {
+ return s->disas_strtab + sym->st_name;
+ }
+
+ return "";
+}
+
+static int glue(symcmp, SZ)(const void *s0, const void *s1)
+{
+ struct elf_sym *sym0 = (struct elf_sym *)s0;
+ struct elf_sym *sym1 = (struct elf_sym *)s1;
+ return (sym0->st_value < sym1->st_value)
+ ? -1
+ : ((sym0->st_value > sym1->st_value) ? 1 : 0);
+}
+
+static void glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
+ int clear_lsb, symbol_fn_t sym_cb)
+{
+ struct elf_shdr *symtab, *strtab;
+ g_autofree struct elf_shdr *shdr_table = NULL;
+ g_autofree struct elf_sym *syms = NULL;
+ g_autofree char *str = NULL;
+ struct syminfo *s;
+ int nsyms, i;
+
+ shdr_table = load_at(fd, ehdr->e_shoff,
+ sizeof(struct elf_shdr) * ehdr->e_shnum);
+ if (!shdr_table) {
+ return ;
+ }
+
+ if (must_swab) {
+ for (i = 0; i < ehdr->e_shnum; i++) {
+ glue(bswap_shdr, SZ)(shdr_table + i);
+ }
+ }
+
+ symtab = glue(find_section, SZ)(shdr_table, ehdr->e_shnum, SHT_SYMTAB);
+ if (!symtab) {
+ return;
+ }
+ syms = load_at(fd, symtab->sh_offset, symtab->sh_size);
+ if (!syms) {
+ return;
+ }
+
+ nsyms = symtab->sh_size / sizeof(struct elf_sym);
+
+ /* String table */
+ if (symtab->sh_link >= ehdr->e_shnum) {
+ return;
+ }
+ strtab = &shdr_table[symtab->sh_link];
+
+ str = load_at(fd, strtab->sh_offset, strtab->sh_size);
+ if (!str) {
+ return;
+ }
+
+ i = 0;
+ while (i < nsyms) {
+ if (must_swab) {
+ glue(bswap_sym, SZ)(&syms[i]);
+ }
+ if (sym_cb) {
+ sym_cb(str + syms[i].st_name, syms[i].st_info,
+ syms[i].st_value, syms[i].st_size);
+ }
+ /* We are only interested in function symbols.
+ Throw everything else away. */
+ if (syms[i].st_shndx == SHN_UNDEF ||
+ syms[i].st_shndx >= SHN_LORESERVE ||
+ ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
+ nsyms--;
+ if (i < nsyms) {
+ syms[i] = syms[nsyms];
+ }
+ continue;
+ }
+ if (clear_lsb) {
+ /* The bottom address bit marks a Thumb or MIPS16 symbol. */
+ syms[i].st_value &= ~(glue(glue(Elf, SZ), _Addr))1;
+ }
+ i++;
+ }
+
+ /* check we have symbols left */
+ if (nsyms == 0) {
+ return;
+ }
+
+ syms = g_realloc(syms, nsyms * sizeof(*syms));
+ qsort(syms, nsyms, sizeof(*syms), glue(symcmp, SZ));
+ for (i = 0; i < nsyms - 1; i++) {
+ if (syms[i].st_size == 0) {
+ syms[i].st_size = syms[i + 1].st_value - syms[i].st_value;
+ }
+ }
+
+ /* Commit */
+ s = g_malloc0(sizeof(*s));
+ s->lookup_symbol = glue(lookup_symbol, SZ);
+ glue(s->disas_symtab.elf, SZ) = g_steal_pointer(&syms);
+ s->disas_num_syms = nsyms;
+ s->disas_strtab = g_steal_pointer(&str);
+ s->next = syminfos;
+ syminfos = s;
+}
+
+static int glue(elf_reloc, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
+ uint64_t (*translate_fn)(void *, uint64_t),
+ void *translate_opaque, uint8_t *data,
+ struct elf_phdr *ph, int elf_machine)
+{
+ struct elf_shdr *reltab, *shdr_table = NULL;
+ struct elf_rela *rels = NULL;
+ int nrels, i, ret = -1;
+ elf_word wordval;
+ void *addr;
+
+ shdr_table = load_at(fd, ehdr->e_shoff,
+ sizeof(struct elf_shdr) * ehdr->e_shnum);
+ if (!shdr_table) {
+ return -1;
+ }
+ if (must_swab) {
+ for (i = 0; i < ehdr->e_shnum; i++) {
+ glue(bswap_shdr, SZ)(&shdr_table[i]);
+ }
+ }
+
+ reltab = glue(find_section, SZ)(shdr_table, ehdr->e_shnum, SHT_RELA);
+ if (!reltab) {
+ goto fail;
+ }
+ rels = load_at(fd, reltab->sh_offset, reltab->sh_size);
+ if (!rels) {
+ goto fail;
+ }
+ nrels = reltab->sh_size / sizeof(struct elf_rela);
+
+ for (i = 0; i < nrels; i++) {
+ if (must_swab) {
+ glue(bswap_rela, SZ)(&rels[i]);
+ }
+ if (rels[i].r_offset < ph->p_vaddr ||
+ rels[i].r_offset >= ph->p_vaddr + ph->p_filesz) {
+ continue;
+ }
+ addr = &data[rels[i].r_offset - ph->p_vaddr];
+ switch (elf_machine) {
+ case EM_S390:
+ switch (rels[i].r_info) {
+ case R_390_RELATIVE:
+ wordval = *(elf_word *)addr;
+ if (must_swab) {
+ bswapSZs(&wordval);
+ }
+ wordval = translate_fn(translate_opaque, wordval);
+ if (must_swab) {
+ bswapSZs(&wordval);
+ }
+ *(elf_word *)addr = wordval;
+ break;
+ default:
+ fprintf(stderr, "Unsupported relocation type %i!\n",
+ (int)rels[i].r_info);
+ }
+ }
+ }
+
+ ret = 0;
+fail:
+ g_free(rels);
+ g_free(shdr_table);
+ return ret;
+}
+
+/*
+ * Given 'nhdr', a pointer to a range of ELF Notes, search through them
+ * for a note matching type 'elf_note_type' and return a pointer to
+ * the matching ELF note.
+ */
+static struct elf_note *glue(get_elf_note_type, SZ)(struct elf_note *nhdr,
+ elf_word note_size,
+ elf_word phdr_align,
+ elf_word elf_note_type)
+{
+ elf_word nhdr_size = sizeof(struct elf_note);
+ elf_word elf_note_entry_offset = 0;
+ elf_word note_type;
+ elf_word nhdr_namesz;
+ elf_word nhdr_descsz;
+
+ if (nhdr == NULL) {
+ return NULL;
+ }
+
+ note_type = nhdr->n_type;
+ while (note_type != elf_note_type) {
+ nhdr_namesz = nhdr->n_namesz;
+ nhdr_descsz = nhdr->n_descsz;
+
+ elf_note_entry_offset = nhdr_size +
+ QEMU_ALIGN_UP(nhdr_namesz, phdr_align) +
+ QEMU_ALIGN_UP(nhdr_descsz, phdr_align);
+
+ /*
+ * If the offset calculated in this iteration exceeds the
+ * supplied size, we are done and no matching note was found.
+ */
+ if (elf_note_entry_offset > note_size) {
+ return NULL;
+ }
+
+ /* skip to the next ELF Note entry */
+ nhdr = (void *)nhdr + elf_note_entry_offset;
+ note_type = nhdr->n_type;
+ }
+
+ return nhdr;
+}
+
+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;
+ 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;
+ ssize_t ret = ELF_LOAD_FAILED;
+
+ if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
+ goto fail;
+ if (must_swab) {
+ glue(bswap_ehdr, SZ)(&ehdr);
+ }
+
+ if (elf_machine <= EM_NONE) {
+ /* The caller didn't specify an ARCH, we can figure it out */
+ elf_machine = ehdr.e_machine;
+ }
+
+ switch (elf_machine) {
+ case EM_PPC64:
+ if (ehdr.e_machine != EM_PPC64) {
+ if (ehdr.e_machine != EM_PPC) {
+ ret = ELF_LOAD_WRONG_ARCH;
+ goto fail;
+ }
+ }
+ break;
+ case EM_X86_64:
+ if (ehdr.e_machine != EM_X86_64) {
+ if (ehdr.e_machine != EM_386) {
+ ret = ELF_LOAD_WRONG_ARCH;
+ goto fail;
+ }
+ }
+ break;
+ case EM_MICROBLAZE:
+ if (ehdr.e_machine != EM_MICROBLAZE) {
+ if (ehdr.e_machine != EM_MICROBLAZE_OLD) {
+ ret = ELF_LOAD_WRONG_ARCH;
+ goto fail;
+ }
+ }
+ break;
+ case EM_MIPS:
+ case EM_NANOMIPS:
+ if ((ehdr.e_machine != EM_MIPS) &&
+ (ehdr.e_machine != EM_NANOMIPS)) {
+ ret = ELF_LOAD_WRONG_ARCH;
+ goto fail;
+ }
+ break;
+ default:
+ if (elf_machine != ehdr.e_machine) {
+ ret = ELF_LOAD_WRONG_ARCH;
+ goto fail;
+ }
+ }
+
+ if (pflags) {
+ *pflags = (elf_word)ehdr.e_flags;
+ }
+ if (pentry)
+ *pentry = (uint64_t)(elf_sword)ehdr.e_entry;
+
+ glue(load_symbols, SZ)(&ehdr, fd, must_swab, clear_lsb, sym_cb);
+
+ size = ehdr.e_phnum * sizeof(phdr[0]);
+ if (lseek(fd, ehdr.e_phoff, SEEK_SET) != ehdr.e_phoff) {
+ goto fail;
+ }
+ phdr = g_malloc0(size);
+ if (!phdr)
+ goto fail;
+ if (read(fd, phdr, size) != size)
+ goto fail;
+ if (must_swab) {
+ for(i = 0; i < ehdr.e_phnum; i++) {
+ ph = &phdr[i];
+ glue(bswap_phdr, SZ)(ph);
+ }
+ }
+
+ /*
+ * Since we want to be able to modify the mapped buffer, we set the
+ * '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);
+ if (!mapped_file) {
+ goto fail;
+ }
+
+ total_size = 0;
+ for(i = 0; i < ehdr.e_phnum; i++) {
+ ph = &phdr[i];
+ if (ph->p_type == PT_LOAD) {
+ mem_size = ph->p_memsz; /* Size of the ROM */
+ file_size = ph->p_filesz; /* Size of the allocated data */
+ data_offset = ph->p_offset; /* Offset where the data is located */
+
+ if (file_size > 0) {
+ if (g_mapped_file_get_length(mapped_file) <
+ file_size + data_offset) {
+ goto fail;
+ }
+
+ data = (uint8_t *)g_mapped_file_get_contents(mapped_file);
+ data += data_offset;
+ }
+
+ /* The ELF spec is somewhat vague about the purpose of the
+ * physical address field. One common use in the embedded world
+ * is that physical address field specifies the load address
+ * and the virtual address field specifies the execution address.
+ * Segments are packed into ROM or flash, and the relocation
+ * and zero-initialization of data is done at runtime. This
+ * means that the memsz header represents the runtime size of the
+ * segment, but the filesz represents the loadtime size. If
+ * we try to honour the memsz value for an ELF file like this
+ * we will end up with overlapping segments (which the
+ * loader.c code will later reject).
+ * We support ELF files using this scheme by by checking whether
+ * paddr + memsz for this segment would overlap with any other
+ * segment. If so, then we assume it's using this scheme and
+ * truncate the loaded segment to the filesz size.
+ * If the segment considered as being memsz size doesn't overlap
+ * then we use memsz for the segment length, to handle ELF files
+ * which assume that the loader will do the zero-initialization.
+ */
+ if (mem_size > file_size) {
+ /* If this segment's zero-init portion overlaps another
+ * segment's data or zero-init portion, then truncate this one.
+ * Invalid ELF files where the segments overlap even when
+ * only file_size bytes are loaded will be rejected by
+ * the ROM overlap check in loader.c, so we don't try to
+ * explicitly detect those here.
+ */
+ int j;
+ elf_word zero_start = ph->p_paddr + file_size;
+ elf_word zero_end = ph->p_paddr + mem_size;
+
+ for (j = 0; j < ehdr.e_phnum; j++) {
+ struct elf_phdr *jph = &phdr[j];
+
+ if (i != j && jph->p_type == PT_LOAD) {
+ elf_word other_start = jph->p_paddr;
+ elf_word other_end = jph->p_paddr + jph->p_memsz;
+
+ if (!(other_start >= zero_end ||
+ zero_start >= other_end)) {
+ mem_size = file_size;
+ break;
+ }
+ }
+ }
+ }
+
+ if (mem_size > SSIZE_MAX - total_size) {
+ ret = ELF_LOAD_TOO_BIG;
+ goto fail;
+ }
+
+ /* address_offset is hack for kernel images that are
+ linked at the wrong physical address. */
+ if (translate_fn) {
+ addr = translate_fn(translate_opaque, ph->p_paddr);
+ glue(elf_reloc, SZ)(&ehdr, fd, must_swab, translate_fn,
+ translate_opaque, data, ph, elf_machine);
+ } else {
+ addr = ph->p_paddr;
+ }
+
+ if (data_swab) {
+ int j;
+ for (j = 0; j < file_size; j += (1 << data_swab)) {
+ uint8_t *dp = data + j;
+ switch (data_swab) {
+ case (1):
+ *(uint16_t *)dp = bswap16(*(uint16_t *)dp);
+ break;
+ case (2):
+ *(uint32_t *)dp = bswap32(*(uint32_t *)dp);
+ break;
+ case (3):
+ *(uint64_t *)dp = bswap64(*(uint64_t *)dp);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ }
+ }
+
+ /* the entry pointer in the ELF header is a virtual
+ * address, if the text segments paddr and vaddr differ
+ * we need to adjust the entry */
+ if (pentry && !translate_fn &&
+ ph->p_vaddr != ph->p_paddr &&
+ ehdr.e_entry >= ph->p_vaddr &&
+ ehdr.e_entry < ph->p_vaddr + ph->p_filesz &&
+ ph->p_flags & PF_X) {
+ *pentry = ehdr.e_entry - ph->p_vaddr + ph->p_paddr;
+ }
+
+ /* Some ELF files really do have segments of zero size;
+ * just ignore them rather than trying to create empty
+ * ROM blobs, because the zero-length blob can falsely
+ * trigger the overlapping-ROM-blobs check.
+ */
+ if (mem_size != 0) {
+ if (load_rom) {
+ g_autofree char *label =
+ g_strdup_printf("%s ELF program header segment %d",
+ name, i);
+
+ /*
+ * rom_add_elf_program() takes its own reference to
+ * 'mapped_file'.
+ */
+ rom_add_elf_program(label, mapped_file, data, file_size,
+ mem_size, addr, as);
+ } else {
+ MemTxResult res;
+
+ res = address_space_write(as ? as : &address_space_memory,
+ addr, MEMTXATTRS_UNSPECIFIED,
+ data, file_size);
+ if (res != MEMTX_OK) {
+ goto fail;
+ }
+ }
+ }
+
+ total_size += mem_size;
+ if (addr < low)
+ low = addr;
+ if ((addr + mem_size) > high)
+ high = addr + mem_size;
+
+ data = NULL;
+
+ } else if (ph->p_type == PT_NOTE && elf_note_fn) {
+ struct elf_note *nhdr = NULL;
+
+ file_size = ph->p_filesz; /* Size of the range of ELF notes */
+ data_offset = ph->p_offset; /* Offset where the notes are located */
+
+ if (file_size > 0) {
+ if (g_mapped_file_get_length(mapped_file) <
+ file_size + data_offset) {
+ goto fail;
+ }
+
+ data = (uint8_t *)g_mapped_file_get_contents(mapped_file);
+ data += data_offset;
+ }
+
+ /*
+ * Search the ELF notes to find one with a type matching the
+ * value passed in via 'translate_opaque'
+ */
+ nhdr = (struct elf_note *)data;
+ assert(translate_opaque != NULL);
+ nhdr = glue(get_elf_note_type, SZ)(nhdr, file_size, ph->p_align,
+ *(uint64_t *)translate_opaque);
+ if (nhdr != NULL) {
+ 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;
+ ret = total_size;
+ fail:
+ if (mapped_file) {
+ g_mapped_file_unref(mapped_file);
+ }
+ g_free(phdr);
+ return ret;
+}
diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h
new file mode 100644
index 000000000..5a0dd0c8c
--- /dev/null
+++ b/include/hw/firmware/smbios.h
@@ -0,0 +1,289 @@
+#ifndef QEMU_SMBIOS_H
+#define QEMU_SMBIOS_H
+
+/*
+ * SMBIOS Support
+ *
+ * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
+ *
+ * Authors:
+ * Alex Williamson <alex.williamson@hp.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+
+#define SMBIOS_MAX_TYPE 127
+
+/* memory area description, used by type 19 table */
+struct smbios_phys_mem_area {
+ uint64_t address;
+ 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
+ * address between 0xf0000 and 0xfffff. Note that either entry point type
+ * can be used in a 64-bit target system, except that SMBIOS 2.1 entry point
+ * only allows the SMBIOS struct table to reside below 4GB address space.
+ */
+
+/* SMBIOS 2.1 (32-bit) Entry Point
+ * - introduced since SMBIOS 2.1
+ * - supports structure table below 4GB only
+ */
+struct smbios_21_entry_point {
+ uint8_t anchor_string[4];
+ uint8_t checksum;
+ uint8_t length;
+ uint8_t smbios_major_version;
+ uint8_t smbios_minor_version;
+ uint16_t max_structure_size;
+ uint8_t entry_point_revision;
+ uint8_t formatted_area[5];
+ uint8_t intermediate_anchor_string[5];
+ uint8_t intermediate_checksum;
+ uint16_t structure_table_length;
+ uint32_t structure_table_address;
+ uint16_t number_of_structures;
+ uint8_t smbios_bcd_revision;
+} QEMU_PACKED;
+
+/* SMBIOS 3.0 (64-bit) Entry Point
+ * - introduced since SMBIOS 3.0
+ * - supports structure table at 64-bit address space
+ */
+struct smbios_30_entry_point {
+ uint8_t anchor_string[5];
+ uint8_t checksum;
+ uint8_t length;
+ uint8_t smbios_major_version;
+ uint8_t smbios_minor_version;
+ uint8_t smbios_doc_rev;
+ uint8_t entry_point_revision;
+ uint8_t reserved;
+ uint32_t structure_table_max_size;
+ uint64_t structure_table_address;
+} QEMU_PACKED;
+
+typedef union {
+ struct smbios_21_entry_point ep21;
+ struct smbios_30_entry_point ep30;
+} QEMU_PACKED SmbiosEntryPoint;
+
+/* This goes at the beginning of every SMBIOS structure. */
+struct smbios_structure_header {
+ uint8_t type;
+ uint8_t length;
+ uint16_t handle;
+} QEMU_PACKED;
+
+/* SMBIOS type 0 - BIOS Information */
+struct smbios_type_0 {
+ struct smbios_structure_header header;
+ uint8_t vendor_str;
+ uint8_t bios_version_str;
+ uint16_t bios_starting_address_segment;
+ uint8_t bios_release_date_str;
+ uint8_t bios_rom_size;
+ uint64_t bios_characteristics;
+ uint8_t bios_characteristics_extension_bytes[2];
+ uint8_t system_bios_major_release;
+ uint8_t system_bios_minor_release;
+ uint8_t embedded_controller_major_release;
+ uint8_t embedded_controller_minor_release;
+} QEMU_PACKED;
+
+/* UUID encoding. The time_* fields are little-endian, as specified by SMBIOS
+ * version 2.6.
+ */
+struct smbios_uuid {
+ uint32_t time_low;
+ uint16_t time_mid;
+ uint16_t time_hi_and_version;
+ uint8_t clock_seq_hi_and_reserved;
+ uint8_t clock_seq_low;
+ uint8_t node[6];
+} QEMU_PACKED;
+
+/* SMBIOS type 1 - System Information */
+struct smbios_type_1 {
+ struct smbios_structure_header header;
+ uint8_t manufacturer_str;
+ uint8_t product_name_str;
+ uint8_t version_str;
+ uint8_t serial_number_str;
+ struct smbios_uuid uuid;
+ uint8_t wake_up_type;
+ uint8_t sku_number_str;
+ uint8_t family_str;
+} QEMU_PACKED;
+
+/* SMBIOS type 2 - Base Board */
+struct smbios_type_2 {
+ struct smbios_structure_header header;
+ uint8_t manufacturer_str;
+ uint8_t product_str;
+ uint8_t version_str;
+ uint8_t serial_number_str;
+ uint8_t asset_tag_number_str;
+ uint8_t feature_flags;
+ uint8_t location_str;
+ uint16_t chassis_handle;
+ uint8_t board_type;
+ uint8_t contained_element_count;
+ /* contained elements follow */
+} QEMU_PACKED;
+
+/* SMBIOS type 3 - System Enclosure (v2.7) */
+struct smbios_type_3 {
+ struct smbios_structure_header header;
+ uint8_t manufacturer_str;
+ uint8_t type;
+ uint8_t version_str;
+ uint8_t serial_number_str;
+ uint8_t asset_tag_number_str;
+ uint8_t boot_up_state;
+ uint8_t power_supply_state;
+ uint8_t thermal_state;
+ uint8_t security_status;
+ uint32_t oem_defined;
+ uint8_t height;
+ uint8_t number_of_power_cords;
+ uint8_t contained_element_count;
+ uint8_t contained_element_record_length;
+ uint8_t sku_number_str;
+ /* contained elements follow */
+} QEMU_PACKED;
+
+/* SMBIOS type 4 - Processor Information (v2.6) */
+struct smbios_type_4 {
+ struct smbios_structure_header header;
+ uint8_t socket_designation_str;
+ uint8_t processor_type;
+ uint8_t processor_family;
+ uint8_t processor_manufacturer_str;
+ uint32_t processor_id[2];
+ uint8_t processor_version_str;
+ uint8_t voltage;
+ uint16_t external_clock;
+ uint16_t max_speed;
+ uint16_t current_speed;
+ uint8_t status;
+ uint8_t processor_upgrade;
+ uint16_t l1_cache_handle;
+ uint16_t l2_cache_handle;
+ uint16_t l3_cache_handle;
+ uint8_t serial_number_str;
+ uint8_t asset_tag_number_str;
+ uint8_t part_number_str;
+ uint8_t core_count;
+ uint8_t core_enabled;
+ uint8_t thread_count;
+ uint16_t processor_characteristics;
+ uint16_t processor_family2;
+} QEMU_PACKED;
+
+/* SMBIOS type 11 - OEM strings */
+struct smbios_type_11 {
+ struct smbios_structure_header header;
+ uint8_t count;
+} QEMU_PACKED;
+
+/* SMBIOS type 16 - Physical Memory Array (v2.7) */
+struct smbios_type_16 {
+ struct smbios_structure_header header;
+ uint8_t location;
+ uint8_t use;
+ uint8_t error_correction;
+ uint32_t maximum_capacity;
+ uint16_t memory_error_information_handle;
+ uint16_t number_of_memory_devices;
+ uint64_t extended_maximum_capacity;
+} QEMU_PACKED;
+
+/* SMBIOS type 17 - Memory Device (v2.8) */
+struct smbios_type_17 {
+ struct smbios_structure_header header;
+ uint16_t physical_memory_array_handle;
+ uint16_t memory_error_information_handle;
+ uint16_t total_width;
+ uint16_t data_width;
+ uint16_t size;
+ uint8_t form_factor;
+ uint8_t device_set;
+ uint8_t device_locator_str;
+ uint8_t bank_locator_str;
+ uint8_t memory_type;
+ uint16_t type_detail;
+ uint16_t speed;
+ uint8_t manufacturer_str;
+ uint8_t serial_number_str;
+ uint8_t asset_tag_number_str;
+ uint8_t part_number_str;
+ uint8_t attributes;
+ uint32_t extended_size;
+ uint16_t configured_clock_speed;
+ uint16_t minimum_voltage;
+ uint16_t maximum_voltage;
+ uint16_t configured_voltage;
+} QEMU_PACKED;
+
+/* SMBIOS type 19 - Memory Array Mapped Address (v2.7) */
+struct smbios_type_19 {
+ struct smbios_structure_header header;
+ uint32_t starting_address;
+ uint32_t ending_address;
+ uint16_t memory_array_handle;
+ uint8_t partition_width;
+ uint64_t extended_starting_address;
+ uint64_t extended_ending_address;
+} QEMU_PACKED;
+
+/* SMBIOS type 32 - System Boot Information */
+struct smbios_type_32 {
+ struct smbios_structure_header header;
+ uint8_t reserved[6];
+ 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;
+
+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);
+void smbios_get_tables(MachineState *ms,
+ 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,
+ Error **errp);
+#endif /* QEMU_SMBIOS_H */
diff --git a/include/hw/fw-path-provider.h b/include/hw/fw-path-provider.h
new file mode 100644
index 000000000..8e1d45651
--- /dev/null
+++ b/include/hw/fw-path-provider.h
@@ -0,0 +1,44 @@
+/*
+ * Firmware patch provider class and helpers definitions.
+ *
+ * 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 FW_PATH_PROVIDER_H
+#define FW_PATH_PROVIDER_H
+
+#include "qom/object.h"
+
+#define TYPE_FW_PATH_PROVIDER "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;
+
+struct FWPathProviderClass {
+ InterfaceClass parent_class;
+
+ char *(*get_dev_path)(FWPathProvider *p, BusState *bus, DeviceState *dev);
+};
+
+char *fw_path_provider_get_dev_path(FWPathProvider *p, BusState *bus,
+ DeviceState *dev);
+char *fw_path_provider_try_get_dev_path(Object *o, BusState *bus,
+ DeviceState *dev);
+
+#endif /* FW_PATH_PROVIDER_H */
diff --git a/include/hw/gpio/aspeed_gpio.h b/include/hw/gpio/aspeed_gpio.h
new file mode 100644
index 000000000..801846bef
--- /dev/null
+++ b/include/hw/gpio/aspeed_gpio.h
@@ -0,0 +1,96 @@
+/*
+ * ASPEED GPIO 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_GPIO_H
+#define ASPEED_GPIO_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_ASPEED_GPIO "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_GROUPS_PER_SET 4
+#define ASPEED_GPIO_NR_DEBOUNCE_REGS 3
+#define ASPEED_CHARS_PER_GROUP_LABEL 4
+
+typedef struct GPIOSets GPIOSets;
+
+typedef struct GPIOSetProperties {
+ uint32_t input;
+ uint32_t output;
+ char group_label[ASPEED_GROUPS_PER_SET][ASPEED_CHARS_PER_GROUP_LABEL];
+} GPIOSetProperties;
+
+enum GPIORegType {
+ gpio_not_a_reg,
+ gpio_reg_data_value,
+ gpio_reg_direction,
+ gpio_reg_int_enable,
+ gpio_reg_int_sens_0,
+ gpio_reg_int_sens_1,
+ gpio_reg_int_sens_2,
+ gpio_reg_int_status,
+ gpio_reg_reset_tolerant,
+ gpio_reg_debounce_1,
+ gpio_reg_debounce_2,
+ gpio_reg_cmd_source_0,
+ gpio_reg_cmd_source_1,
+ gpio_reg_data_read,
+ gpio_reg_input_mask,
+};
+
+typedef struct AspeedGPIOReg {
+ uint16_t set_idx;
+ enum GPIORegType type;
+ } AspeedGPIOReg;
+
+struct AspeedGPIOClass {
+ SysBusDevice parent_obj;
+ const GPIOSetProperties *props;
+ uint32_t nr_gpio_pins;
+ uint32_t nr_gpio_sets;
+ const AspeedGPIOReg *reg_table;
+};
+
+struct AspeedGPIOState {
+ /* <private> */
+ SysBusDevice parent;
+
+ /*< public >*/
+ MemoryRegion iomem;
+ int pending;
+ qemu_irq irq;
+ qemu_irq gpios[ASPEED_GPIO_MAX_NR_SETS][ASPEED_GPIOS_PER_SET];
+
+/* Parallel GPIO Registers */
+ uint32_t debounce_regs[ASPEED_GPIO_NR_DEBOUNCE_REGS];
+ struct GPIOSets {
+ uint32_t data_value; /* Reflects pin values */
+ uint32_t data_read; /* Contains last value written to data value */
+ uint32_t direction;
+ uint32_t int_enable;
+ uint32_t int_sens_0;
+ uint32_t int_sens_1;
+ uint32_t int_sens_2;
+ uint32_t int_status;
+ uint32_t reset_tol;
+ uint32_t cmd_source_0;
+ uint32_t cmd_source_1;
+ uint32_t debounce_1;
+ uint32_t debounce_2;
+ uint32_t input_mask;
+ } sets[ASPEED_GPIO_MAX_NR_SETS];
+};
+
+#endif /* _ASPEED_GPIO_H_ */
diff --git a/include/hw/gpio/bcm2835_gpio.h b/include/hw/gpio/bcm2835_gpio.h
new file mode 100644
index 000000000..1c53a0509
--- /dev/null
+++ b/include/hw/gpio/bcm2835_gpio.h
@@ -0,0 +1,40 @@
+/*
+ * Raspberry Pi (BCM2835) GPIO Controller
+ *
+ * Copyright (c) 2017 Antfield SAS
+ *
+ * Authors:
+ * Clement Deschamps <clement.deschamps@antfield.fr>
+ * Luc Michel <luc.michel@antfield.fr>
+ *
+ * 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_GPIO_H
+#define BCM2835_GPIO_H
+
+#include "hw/sd/sd.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+struct BCM2835GpioState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+
+ /* SDBus selector */
+ SDBus sdbus;
+ SDBus *sdbus_sdhci;
+ SDBus *sdbus_sdhost;
+
+ uint8_t fsel[54];
+ uint32_t lev0, lev1;
+ uint8_t sd_fsel;
+ qemu_irq out[54];
+};
+
+#define TYPE_BCM2835_GPIO "bcm2835_gpio"
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835GpioState, BCM2835_GPIO)
+
+#endif
diff --git a/include/hw/gpio/imx_gpio.h b/include/hw/gpio/imx_gpio.h
new file mode 100644
index 000000000..227860b9f
--- /dev/null
+++ b/include/hw/gpio/imx_gpio.h
@@ -0,0 +1,64 @@
+/*
+ * i.MX processors GPIO registers definition.
+ *
+ * Copyright (C) 2015 Jean-Christophe Dubois <jcd@tribudubois.net>
+ *
+ * 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 IMX_GPIO_H
+#define IMX_GPIO_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_IMX_GPIO "imx.gpio"
+OBJECT_DECLARE_SIMPLE_TYPE(IMXGPIOState, IMX_GPIO)
+
+#define IMX_GPIO_MEM_SIZE 0x20
+
+/* i.MX GPIO memory map */
+#define DR_ADDR 0x00 /* DATA REGISTER */
+#define GDIR_ADDR 0x04 /* DIRECTION REGISTER */
+#define PSR_ADDR 0x08 /* PAD STATUS REGISTER */
+#define ICR1_ADDR 0x0c /* INTERRUPT CONFIGURATION REGISTER 1 */
+#define ICR2_ADDR 0x10 /* INTERRUPT CONFIGURATION REGISTER 2 */
+#define IMR_ADDR 0x14 /* INTERRUPT MASK REGISTER */
+#define ISR_ADDR 0x18 /* INTERRUPT STATUS REGISTER */
+#define EDGE_SEL_ADDR 0x1c /* EDGE SEL REGISTER */
+
+#define IMX_GPIO_PIN_COUNT 32
+
+struct IMXGPIOState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+
+ uint32_t dr;
+ uint32_t gdir;
+ uint32_t psr;
+ uint64_t icr;
+ uint32_t imr;
+ uint32_t isr;
+ bool has_edge_sel;
+ uint32_t edge_sel;
+ bool has_upper_pin_irq;
+
+ qemu_irq irq[2];
+ qemu_irq output[IMX_GPIO_PIN_COUNT];
+};
+
+#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 000000000..b1d771bd7
--- /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
new file mode 100644
index 000000000..8f9c2f86d
--- /dev/null
+++ b/include/hw/gpio/nrf51_gpio.h
@@ -0,0 +1,70 @@
+/*
+ * nRF51 System-on-Chip general purpose input/output register definition
+ *
+ * QEMU interface:
+ * + sysbus MMIO regions 0: GPIO registers
+ * + Unnamed GPIO inputs 0-31: Set tri-state input level for GPIO pin.
+ * Level -1: Externally Disconnected/Floating; Pull-up/down will be regarded
+ * Level 0: Input externally driven LOW
+ * Level 1: Input externally driven HIGH
+ * + Unnamed GPIO outputs 0-31:
+ * Level -1: Disconnected/Floating
+ * Level 0: Driven LOW
+ * Level 1: Driven HIGH
+ *
+ * Accuracy of the peripheral model:
+ * + The nRF51 GPIO output driver supports two modes, standard and high-current
+ * mode. These different drive modes are not modeled and handled the same.
+ * + Pin SENSEing is not modeled/implemented.
+ *
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
+ *
+ * This code is licensed under the GPL version 2 or later. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+#ifndef NRF51_GPIO_H
+#define NRF51_GPIO_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+#define TYPE_NRF51_GPIO "nrf51_soc.gpio"
+OBJECT_DECLARE_SIMPLE_TYPE(NRF51GPIOState, NRF51_GPIO)
+
+#define NRF51_GPIO_PINS 32
+
+#define NRF51_GPIO_SIZE 0x1000
+
+#define NRF51_GPIO_REG_OUT 0x504
+#define NRF51_GPIO_REG_OUTSET 0x508
+#define NRF51_GPIO_REG_OUTCLR 0x50C
+#define NRF51_GPIO_REG_IN 0x510
+#define NRF51_GPIO_REG_DIR 0x514
+#define NRF51_GPIO_REG_DIRSET 0x518
+#define NRF51_GPIO_REG_DIRCLR 0x51C
+#define NRF51_GPIO_REG_CNF_START 0x700
+#define NRF51_GPIO_REG_CNF_END 0x77C
+
+#define NRF51_GPIO_PULLDOWN 1
+#define NRF51_GPIO_PULLUP 3
+
+struct NRF51GPIOState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion mmio;
+ qemu_irq irq;
+
+ uint32_t out;
+ uint32_t in;
+ uint32_t in_mask;
+ uint32_t dir;
+ uint32_t cnf[NRF51_GPIO_PINS];
+
+ uint32_t old_out;
+ uint32_t old_out_connected;
+
+ qemu_irq output[NRF51_GPIO_PINS];
+};
+
+
+#endif
diff --git a/include/hw/gpio/sifive_gpio.h b/include/hw/gpio/sifive_gpio.h
new file mode 100644
index 000000000..fc53785c9
--- /dev/null
+++ b/include/hw/gpio/sifive_gpio.h
@@ -0,0 +1,79 @@
+/*
+ * SiFive System-on-Chip general purpose input/output register definition
+ *
+ * Copyright 2019 AdaCore
+ *
+ * Base on nrf51_gpio.c:
+ *
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
+ *
+ * This code is licensed under the GPL version 2 or later. See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef SIFIVE_GPIO_H
+#define SIFIVE_GPIO_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_SIFIVE_GPIO "sifive_soc.gpio"
+typedef struct SIFIVEGPIOState SIFIVEGPIOState;
+DECLARE_INSTANCE_CHECKER(SIFIVEGPIOState, SIFIVE_GPIO,
+ TYPE_SIFIVE_GPIO)
+
+#define SIFIVE_GPIO_PINS 32
+
+#define SIFIVE_GPIO_SIZE 0x100
+
+#define SIFIVE_GPIO_REG_VALUE 0x000
+#define SIFIVE_GPIO_REG_INPUT_EN 0x004
+#define SIFIVE_GPIO_REG_OUTPUT_EN 0x008
+#define SIFIVE_GPIO_REG_PORT 0x00C
+#define SIFIVE_GPIO_REG_PUE 0x010
+#define SIFIVE_GPIO_REG_DS 0x014
+#define SIFIVE_GPIO_REG_RISE_IE 0x018
+#define SIFIVE_GPIO_REG_RISE_IP 0x01C
+#define SIFIVE_GPIO_REG_FALL_IE 0x020
+#define SIFIVE_GPIO_REG_FALL_IP 0x024
+#define SIFIVE_GPIO_REG_HIGH_IE 0x028
+#define SIFIVE_GPIO_REG_HIGH_IP 0x02C
+#define SIFIVE_GPIO_REG_LOW_IE 0x030
+#define SIFIVE_GPIO_REG_LOW_IP 0x034
+#define SIFIVE_GPIO_REG_IOF_EN 0x038
+#define SIFIVE_GPIO_REG_IOF_SEL 0x03C
+#define SIFIVE_GPIO_REG_OUT_XOR 0x040
+
+struct SIFIVEGPIOState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion mmio;
+
+ qemu_irq irq[SIFIVE_GPIO_PINS];
+ qemu_irq output[SIFIVE_GPIO_PINS];
+
+ uint32_t value; /* Actual value of the pin */
+ uint32_t input_en;
+ uint32_t output_en;
+ uint32_t port; /* Pin value requested by the user */
+ uint32_t pue;
+ uint32_t ds;
+ uint32_t rise_ie;
+ uint32_t rise_ip;
+ uint32_t fall_ie;
+ uint32_t fall_ip;
+ uint32_t high_ie;
+ uint32_t high_ip;
+ uint32_t low_ie;
+ uint32_t low_ip;
+ uint32_t iof_en;
+ uint32_t iof_sel;
+ uint32_t out_xor;
+ uint32_t in;
+ uint32_t in_mask;
+
+ /* config */
+ uint32_t ngpio;
+};
+
+#endif /* SIFIVE_GPIO_H */
diff --git a/include/hw/hotplug.h b/include/hw/hotplug.h
new file mode 100644
index 000000000..e15f59c8b
--- /dev/null
+++ b/include/hw/hotplug.h
@@ -0,0 +1,97 @@
+/*
+ * Hotplug handler interface.
+ *
+ * Copyright (c) 2014 Red Hat Inc.
+ *
+ * Authors:
+ * Igor Mammedov <imammedo@redhat.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 HOTPLUG_H
+#define HOTPLUG_H
+
+#include "qom/object.h"
+
+#define TYPE_HOTPLUG_HANDLER "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)
+
+typedef struct HotplugHandler HotplugHandler;
+
+/**
+ * hotplug_fn:
+ * @plug_handler: a device performing plug/uplug action
+ * @plugged_dev: a device that has been (un)plugged
+ * @errp: returns an error if this function fails
+ */
+typedef void (*hotplug_fn)(HotplugHandler *plug_handler,
+ DeviceState *plugged_dev, Error **errp);
+
+/**
+ * HotplugDeviceClass:
+ *
+ * Interface to be implemented by a device performing
+ * hardware (un)plug functions.
+ *
+ * @parent: Opaque parent interface.
+ * @pre_plug: pre plug callback called at start of device.realize(true)
+ * @plug: plug callback called at end of device.realize(true).
+ * @unplug_request: unplug request callback.
+ * Used as a means to initiate device unplug for devices that
+ * require asynchronous unplug handling.
+ * @unplug: unplug callback.
+ * Used for device removal with devices that implement
+ * asynchronous and synchronous (surprise) removal.
+ */
+struct HotplugHandlerClass {
+ /* <private> */
+ InterfaceClass parent;
+
+ /* <public> */
+ hotplug_fn pre_plug;
+ hotplug_fn plug;
+ hotplug_fn unplug_request;
+ hotplug_fn unplug;
+};
+
+/**
+ * hotplug_handler_plug:
+ *
+ * Call #HotplugHandlerClass.plug callback of @plug_handler.
+ */
+void hotplug_handler_plug(HotplugHandler *plug_handler,
+ DeviceState *plugged_dev,
+ Error **errp);
+
+/**
+ * hotplug_handler_pre_plug:
+ *
+ * Call #HotplugHandlerClass.pre_plug callback of @plug_handler.
+ */
+void hotplug_handler_pre_plug(HotplugHandler *plug_handler,
+ DeviceState *plugged_dev,
+ Error **errp);
+
+/**
+ * hotplug_handler_unplug_request:
+ *
+ * Calls #HotplugHandlerClass.unplug_request callback of @plug_handler.
+ */
+void hotplug_handler_unplug_request(HotplugHandler *plug_handler,
+ DeviceState *plugged_dev,
+ Error **errp);
+/**
+ * hotplug_handler_unplug:
+ *
+ * Calls #HotplugHandlerClass.unplug callback of @plug_handler.
+ */
+void hotplug_handler_unplug(HotplugHandler *plug_handler,
+ DeviceState *plugged_dev,
+ Error **errp);
+#endif
diff --git a/include/hw/hw.h b/include/hw/hw.h
new file mode 100644
index 000000000..fc5301f29
--- /dev/null
+++ b/include/hw/hw.h
@@ -0,0 +1,10 @@
+#ifndef QEMU_HW_H
+#define QEMU_HW_H
+
+#ifdef CONFIG_USER_ONLY
+#error Cannot include hw/hw.h from user emulation
+#endif
+
+void QEMU_NORETURN hw_error(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
+
+#endif
diff --git a/include/hw/hyperv/hyperv-proto.h b/include/hw/hyperv/hyperv-proto.h
new file mode 100644
index 000000000..21dc28aee
--- /dev/null
+++ b/include/hw/hyperv/hyperv-proto.h
@@ -0,0 +1,130 @@
+/*
+ * Definitions for Hyper-V guest/hypervisor interaction
+ *
+ * Copyright (c) 2017-2018 Virtuozzo International 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 HW_HYPERV_HYPERV_PROTO_H
+#define HW_HYPERV_HYPERV_PROTO_H
+
+#include "qemu/bitmap.h"
+
+/*
+ * Hypercall status code
+ */
+#define HV_STATUS_SUCCESS 0
+#define HV_STATUS_INVALID_HYPERCALL_CODE 2
+#define HV_STATUS_INVALID_HYPERCALL_INPUT 3
+#define HV_STATUS_INVALID_ALIGNMENT 4
+#define HV_STATUS_INVALID_PARAMETER 5
+#define HV_STATUS_INSUFFICIENT_MEMORY 11
+#define HV_STATUS_INVALID_PORT_ID 17
+#define HV_STATUS_INVALID_CONNECTION_ID 18
+#define HV_STATUS_INSUFFICIENT_BUFFERS 19
+
+/*
+ * Hypercall numbers
+ */
+#define HV_POST_MESSAGE 0x005c
+#define HV_SIGNAL_EVENT 0x005d
+#define HV_HYPERCALL_FAST (1u << 16)
+
+/*
+ * Message size
+ */
+#define HV_MESSAGE_PAYLOAD_SIZE 240
+
+/*
+ * Message types
+ */
+#define HV_MESSAGE_NONE 0x00000000
+#define HV_MESSAGE_VMBUS 0x00000001
+#define HV_MESSAGE_UNMAPPED_GPA 0x80000000
+#define HV_MESSAGE_GPA_INTERCEPT 0x80000001
+#define HV_MESSAGE_TIMER_EXPIRED 0x80000010
+#define HV_MESSAGE_INVALID_VP_REGISTER_VALUE 0x80000020
+#define HV_MESSAGE_UNRECOVERABLE_EXCEPTION 0x80000021
+#define HV_MESSAGE_UNSUPPORTED_FEATURE 0x80000022
+#define HV_MESSAGE_EVENTLOG_BUFFERCOMPLETE 0x80000040
+#define HV_MESSAGE_X64_IOPORT_INTERCEPT 0x80010000
+#define HV_MESSAGE_X64_MSR_INTERCEPT 0x80010001
+#define HV_MESSAGE_X64_CPUID_INTERCEPT 0x80010002
+#define HV_MESSAGE_X64_EXCEPTION_INTERCEPT 0x80010003
+#define HV_MESSAGE_X64_APIC_EOI 0x80010004
+#define HV_MESSAGE_X64_LEGACY_FP_ERROR 0x80010005
+
+/*
+ * Message flags
+ */
+#define HV_MESSAGE_FLAG_PENDING 0x1
+
+/*
+ * Number of synthetic interrupts
+ */
+#define HV_SINT_COUNT 16
+
+/*
+ * Event flags number per SINT
+ */
+#define HV_EVENT_FLAGS_COUNT (256 * 8)
+
+/*
+ * Connection id valid bits
+ */
+#define HV_CONNECTION_ID_MASK 0x00ffffff
+
+/*
+ * Input structure for POST_MESSAGE hypercall
+ */
+struct hyperv_post_message_input {
+ uint32_t connection_id;
+ uint32_t _reserved;
+ uint32_t message_type;
+ uint32_t payload_size;
+ uint8_t payload[HV_MESSAGE_PAYLOAD_SIZE];
+};
+
+/*
+ * Input structure for SIGNAL_EVENT hypercall
+ */
+struct hyperv_signal_event_input {
+ uint32_t connection_id;
+ uint16_t flag_number;
+ uint16_t _reserved_zero;
+};
+
+/*
+ * SynIC message structures
+ */
+struct hyperv_message_header {
+ uint32_t message_type;
+ uint8_t payload_size;
+ uint8_t message_flags; /* HV_MESSAGE_FLAG_XX */
+ uint8_t _reserved[2];
+ uint64_t sender;
+};
+
+struct hyperv_message {
+ struct hyperv_message_header header;
+ uint8_t payload[HV_MESSAGE_PAYLOAD_SIZE];
+};
+
+struct hyperv_message_page {
+ struct hyperv_message slot[HV_SINT_COUNT];
+};
+
+/*
+ * SynIC event flags structures
+ */
+struct hyperv_event_flags {
+ DECLARE_BITMAP(flags, HV_EVENT_FLAGS_COUNT);
+};
+
+struct hyperv_event_flags_page {
+ struct hyperv_event_flags slot[HV_SINT_COUNT];
+};
+
+#endif
diff --git a/include/hw/hyperv/hyperv.h b/include/hw/hyperv/hyperv.h
new file mode 100644
index 000000000..a63ee0003
--- /dev/null
+++ b/include/hw/hyperv/hyperv.h
@@ -0,0 +1,84 @@
+/*
+ * Hyper-V guest/hypervisor interaction
+ *
+ * Copyright (c) 2015-2018 Virtuozzo International 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 HW_HYPERV_HYPERV_H
+#define HW_HYPERV_HYPERV_H
+
+#include "cpu-qom.h"
+#include "hw/hyperv/hyperv-proto.h"
+
+typedef struct HvSintRoute HvSintRoute;
+
+/*
+ * Callback executed in a bottom-half when the status of posting the message
+ * becomes known, before unblocking the connection for further messages
+ */
+typedef void (*HvSintMsgCb)(void *data, int status);
+
+HvSintRoute *hyperv_sint_route_new(uint32_t vp_index, uint32_t sint,
+ HvSintMsgCb cb, void *cb_data);
+void hyperv_sint_route_ref(HvSintRoute *sint_route);
+void hyperv_sint_route_unref(HvSintRoute *sint_route);
+
+int hyperv_sint_route_set_sint(HvSintRoute *sint_route);
+
+/*
+ * Submit a message to be posted in vcpu context. If the submission succeeds,
+ * the status of posting the message is reported via the callback associated
+ * with the @sint_route; until then no more messages are accepted.
+ */
+int hyperv_post_msg(HvSintRoute *sint_route, struct hyperv_message *msg);
+/*
+ * Set event flag @eventno, and signal the SINT if the flag has changed.
+ */
+int hyperv_set_event_flag(HvSintRoute *sint_route, unsigned eventno);
+
+/*
+ * Handler for messages arriving from the guest via HV_POST_MESSAGE hypercall.
+ * Executed in vcpu context.
+ */
+typedef uint16_t (*HvMsgHandler)(const struct hyperv_post_message_input *msg,
+ void *data);
+/*
+ * Associate @handler with the message connection @conn_id, such that @handler
+ * is called with @data when the guest executes HV_POST_MESSAGE hypercall on
+ * @conn_id. If @handler is NULL clear the association.
+ */
+int hyperv_set_msg_handler(uint32_t conn_id, HvMsgHandler handler, void *data);
+/*
+ * Associate @notifier with the event connection @conn_id, such that @notifier
+ * is signaled when the guest executes HV_SIGNAL_EVENT hypercall on @conn_id.
+ * If @notifier is NULL clear the association.
+ */
+int hyperv_set_event_flag_handler(uint32_t conn_id, EventNotifier *notifier);
+
+/*
+ * Process HV_POST_MESSAGE hypercall: parse the data in the guest memory as
+ * specified in @param, and call the HvMsgHandler associated with the
+ * connection on the message contained therein.
+ */
+uint16_t hyperv_hcall_post_message(uint64_t param, bool fast);
+/*
+ * Process HV_SIGNAL_EVENT hypercall: signal the EventNotifier associated with
+ * the connection as specified in @param.
+ */
+uint16_t hyperv_hcall_signal_event(uint64_t param, bool fast);
+
+static inline uint32_t hyperv_vp_index(CPUState *cs)
+{
+ return cs->cpu_index;
+}
+
+void hyperv_synic_add(CPUState *cs);
+void hyperv_synic_reset(CPUState *cs);
+void hyperv_synic_update(CPUState *cs, bool enable,
+ hwaddr msg_page_addr, hwaddr event_page_addr);
+bool hyperv_is_synic_enabled(void);
+
+#endif
diff --git a/include/hw/hyperv/vmbus-bridge.h b/include/hw/hyperv/vmbus-bridge.h
new file mode 100644
index 000000000..1e5419574
--- /dev/null
+++ b/include/hw/hyperv/vmbus-bridge.h
@@ -0,0 +1,34 @@
+/*
+ * QEMU Hyper-V VMBus root bridge
+ *
+ * Copyright (c) 2017-2018 Virtuozzo International 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 HW_HYPERV_VMBUS_BRIDGE_H
+#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"
+
+struct VMBusBridge {
+ SysBusDevice parent_obj;
+
+ uint8_t irq;
+
+ VMBus *bus;
+};
+
+OBJECT_DECLARE_SIMPLE_TYPE(VMBusBridge, VMBUS_BRIDGE)
+
+static inline VMBusBridge *vmbus_bridge_find(void)
+{
+ return VMBUS_BRIDGE(object_resolve_path_type("", TYPE_VMBUS_BRIDGE, NULL));
+}
+
+#endif
diff --git a/include/hw/hyperv/vmbus-proto.h b/include/hw/hyperv/vmbus-proto.h
new file mode 100644
index 000000000..4628d3b32
--- /dev/null
+++ b/include/hw/hyperv/vmbus-proto.h
@@ -0,0 +1,222 @@
+/*
+ * QEMU Hyper-V VMBus support
+ *
+ * Copyright (c) 2017-2018 Virtuozzo International 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 HW_HYPERV_VMBUS_PROTO_H
+#define HW_HYPERV_VMBUS_PROTO_H
+
+#define VMBUS_VERSION_WS2008 ((0 << 16) | (13))
+#define VMBUS_VERSION_WIN7 ((1 << 16) | (1))
+#define VMBUS_VERSION_WIN8 ((2 << 16) | (4))
+#define VMBUS_VERSION_WIN8_1 ((3 << 16) | (0))
+#define VMBUS_VERSION_WIN10 ((4 << 16) | (0))
+#define VMBUS_VERSION_INVAL -1
+#define VMBUS_VERSION_CURRENT VMBUS_VERSION_WIN10
+
+#define VMBUS_MESSAGE_CONNECTION_ID 1
+#define VMBUS_EVENT_CONNECTION_ID 2
+#define VMBUS_MONITOR_CONNECTION_ID 3
+#define VMBUS_SINT 2
+
+#define VMBUS_MSG_INVALID 0
+#define VMBUS_MSG_OFFERCHANNEL 1
+#define VMBUS_MSG_RESCIND_CHANNELOFFER 2
+#define VMBUS_MSG_REQUESTOFFERS 3
+#define VMBUS_MSG_ALLOFFERS_DELIVERED 4
+#define VMBUS_MSG_OPENCHANNEL 5
+#define VMBUS_MSG_OPENCHANNEL_RESULT 6
+#define VMBUS_MSG_CLOSECHANNEL 7
+#define VMBUS_MSG_GPADL_HEADER 8
+#define VMBUS_MSG_GPADL_BODY 9
+#define VMBUS_MSG_GPADL_CREATED 10
+#define VMBUS_MSG_GPADL_TEARDOWN 11
+#define VMBUS_MSG_GPADL_TORNDOWN 12
+#define VMBUS_MSG_RELID_RELEASED 13
+#define VMBUS_MSG_INITIATE_CONTACT 14
+#define VMBUS_MSG_VERSION_RESPONSE 15
+#define VMBUS_MSG_UNLOAD 16
+#define VMBUS_MSG_UNLOAD_RESPONSE 17
+#define VMBUS_MSG_COUNT 18
+
+#define VMBUS_MESSAGE_SIZE_ALIGN sizeof(uint64_t)
+
+#define VMBUS_PACKET_INVALID 0x0
+#define VMBUS_PACKET_SYNCH 0x1
+#define VMBUS_PACKET_ADD_XFER_PAGESET 0x2
+#define VMBUS_PACKET_RM_XFER_PAGESET 0x3
+#define VMBUS_PACKET_ESTABLISH_GPADL 0x4
+#define VMBUS_PACKET_TEARDOWN_GPADL 0x5
+#define VMBUS_PACKET_DATA_INBAND 0x6
+#define VMBUS_PACKET_DATA_USING_XFER_PAGES 0x7
+#define VMBUS_PACKET_DATA_USING_GPADL 0x8
+#define VMBUS_PACKET_DATA_USING_GPA_DIRECT 0x9
+#define VMBUS_PACKET_CANCEL_REQUEST 0xa
+#define VMBUS_PACKET_COMP 0xb
+#define VMBUS_PACKET_DATA_USING_ADDITIONAL_PKT 0xc
+#define VMBUS_PACKET_ADDITIONAL_DATA 0xd
+
+#define VMBUS_CHANNEL_USER_DATA_SIZE 120
+
+#define VMBUS_OFFER_MONITOR_ALLOCATED 0x1
+#define VMBUS_OFFER_INTERRUPT_DEDICATED 0x1
+
+#define VMBUS_RING_BUFFER_FEAT_PENDING_SZ (1ul << 0)
+
+#define VMBUS_CHANNEL_ENUMERATE_DEVICE_INTERFACE 0x1
+#define VMBUS_CHANNEL_SERVER_SUPPORTS_TRANSFER_PAGES 0x2
+#define VMBUS_CHANNEL_SERVER_SUPPORTS_GPADLS 0x4
+#define VMBUS_CHANNEL_NAMED_PIPE_MODE 0x10
+#define VMBUS_CHANNEL_LOOPBACK_OFFER 0x100
+#define VMBUS_CHANNEL_PARENT_OFFER 0x200
+#define VMBUS_CHANNEL_REQUEST_MONITORED_NOTIFICATION 0x400
+#define VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER 0x2000
+
+#define VMBUS_PACKET_FLAG_REQUEST_COMPLETION 1
+
+typedef struct vmbus_message_header {
+ uint32_t message_type;
+ uint32_t _padding;
+} vmbus_message_header;
+
+typedef struct vmbus_message_initiate_contact {
+ vmbus_message_header header;
+ uint32_t version_requested;
+ uint32_t target_vcpu;
+ uint64_t interrupt_page;
+ uint64_t monitor_page1;
+ uint64_t monitor_page2;
+} vmbus_message_initiate_contact;
+
+typedef struct vmbus_message_version_response {
+ vmbus_message_header header;
+ uint8_t version_supported;
+ uint8_t status;
+} vmbus_message_version_response;
+
+typedef struct vmbus_message_offer_channel {
+ vmbus_message_header header;
+ uint8_t type_uuid[16];
+ uint8_t instance_uuid[16];
+ uint64_t _reserved1;
+ uint64_t _reserved2;
+ uint16_t channel_flags;
+ uint16_t mmio_size_mb;
+ uint8_t user_data[VMBUS_CHANNEL_USER_DATA_SIZE];
+ uint16_t sub_channel_index;
+ uint16_t _reserved3;
+ uint32_t child_relid;
+ uint8_t monitor_id;
+ uint8_t monitor_flags;
+ uint16_t interrupt_flags;
+ uint32_t connection_id;
+} vmbus_message_offer_channel;
+
+typedef struct vmbus_message_rescind_channel_offer {
+ vmbus_message_header header;
+ uint32_t child_relid;
+} vmbus_message_rescind_channel_offer;
+
+typedef struct vmbus_gpa_range {
+ uint32_t byte_count;
+ uint32_t byte_offset;
+ uint64_t pfn_array[];
+} vmbus_gpa_range;
+
+typedef struct vmbus_message_gpadl_header {
+ vmbus_message_header header;
+ uint32_t child_relid;
+ uint32_t gpadl_id;
+ uint16_t range_buflen;
+ uint16_t rangecount;
+ vmbus_gpa_range range[];
+} QEMU_PACKED vmbus_message_gpadl_header;
+
+typedef struct vmbus_message_gpadl_body {
+ vmbus_message_header header;
+ uint32_t message_number;
+ uint32_t gpadl_id;
+ uint64_t pfn_array[];
+} vmbus_message_gpadl_body;
+
+typedef struct vmbus_message_gpadl_created {
+ vmbus_message_header header;
+ uint32_t child_relid;
+ uint32_t gpadl_id;
+ uint32_t status;
+} vmbus_message_gpadl_created;
+
+typedef struct vmbus_message_gpadl_teardown {
+ vmbus_message_header header;
+ uint32_t child_relid;
+ uint32_t gpadl_id;
+} vmbus_message_gpadl_teardown;
+
+typedef struct vmbus_message_gpadl_torndown {
+ vmbus_message_header header;
+ uint32_t gpadl_id;
+} vmbus_message_gpadl_torndown;
+
+typedef struct vmbus_message_open_channel {
+ vmbus_message_header header;
+ uint32_t child_relid;
+ uint32_t open_id;
+ uint32_t ring_buffer_gpadl_id;
+ uint32_t target_vp;
+ uint32_t ring_buffer_offset;
+ uint8_t user_data[VMBUS_CHANNEL_USER_DATA_SIZE];
+} vmbus_message_open_channel;
+
+typedef struct vmbus_message_open_result {
+ vmbus_message_header header;
+ uint32_t child_relid;
+ uint32_t open_id;
+ uint32_t status;
+} vmbus_message_open_result;
+
+typedef struct vmbus_message_close_channel {
+ vmbus_message_header header;
+ uint32_t child_relid;
+} vmbus_message_close_channel;
+
+typedef struct vmbus_ring_buffer {
+ uint32_t write_index;
+ uint32_t read_index;
+ uint32_t interrupt_mask;
+ uint32_t pending_send_sz;
+ uint32_t _reserved1[12];
+ uint32_t feature_bits;
+} vmbus_ring_buffer;
+
+typedef struct vmbus_packet_hdr {
+ uint16_t type;
+ uint16_t offset_qwords;
+ uint16_t len_qwords;
+ uint16_t flags;
+ uint64_t transaction_id;
+} vmbus_packet_hdr;
+
+typedef struct vmbus_pkt_gpa_direct {
+ uint32_t _reserved;
+ uint32_t rangecount;
+ vmbus_gpa_range range[];
+} vmbus_pkt_gpa_direct;
+
+typedef struct vmbus_xferpg_range {
+ uint32_t byte_count;
+ uint32_t byte_offset;
+} vmbus_xferpg_range;
+
+typedef struct vmbus_pkt_xferpg {
+ uint16_t buffer_id;
+ uint8_t sender_owns_set;
+ uint8_t _reserved;
+ uint32_t rangecount;
+ vmbus_xferpg_range range[];
+} vmbus_pkt_xferpg;
+
+#endif
diff --git a/include/hw/hyperv/vmbus.h b/include/hw/hyperv/vmbus.h
new file mode 100644
index 000000000..f98bea388
--- /dev/null
+++ b/include/hw/hyperv/vmbus.h
@@ -0,0 +1,229 @@
+/*
+ * QEMU Hyper-V VMBus
+ *
+ * Copyright (c) 2017-2018 Virtuozzo International 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 HW_HYPERV_VMBUS_H
+#define HW_HYPERV_VMBUS_H
+
+#include "sysemu/sysemu.h"
+#include "sysemu/dma.h"
+#include "hw/qdev-core.h"
+#include "migration/vmstate.h"
+#include "hw/hyperv/vmbus-proto.h"
+#include "qemu/uuid.h"
+#include "qom/object.h"
+
+#define TYPE_VMBUS_DEVICE "vmbus-dev"
+
+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
+ * pages, to be used for various buffers shared between the host and the guest.
+ */
+typedef struct VMBusGpadl VMBusGpadl;
+/*
+ * VMBus channel -- a pair of ring buffers for either direction, placed within
+ * one GPADL, and the associated notification means.
+ */
+typedef struct VMBusChannel VMBusChannel;
+/*
+ * Base class for VMBus devices. Includes one or more channels. Identified by
+ * class GUID and instance GUID.
+ */
+
+typedef void(*VMBusChannelNotifyCb)(struct VMBusChannel *chan);
+
+struct VMBusDeviceClass {
+ DeviceClass parent;
+
+ QemuUUID classid;
+ QemuUUID instanceid; /* Fixed UUID for singleton devices */
+ uint16_t channel_flags;
+ uint16_t mmio_size_mb;
+
+ /* Extentions to standard device callbacks */
+ void (*vmdev_realize)(VMBusDevice *vdev, Error **errp);
+ void (*vmdev_unrealize)(VMBusDevice *vdev);
+ void (*vmdev_reset)(VMBusDevice *vdev);
+ /*
+ * Calculate the number of channels based on the device properties. Called
+ * at realize time.
+ **/
+ uint16_t (*num_channels)(VMBusDevice *vdev);
+ /*
+ * Device-specific actions to complete the otherwise successful process of
+ * opening a channel.
+ * Return 0 on success, -errno on failure.
+ */
+ int (*open_channel)(VMBusChannel *chan);
+ /*
+ * Device-specific actions to perform before closing a channel.
+ */
+ void (*close_channel)(VMBusChannel *chan);
+ /*
+ * Main device worker; invoked in response to notifications from either
+ * side, when there's work to do with the data in the channel ring buffers.
+ */
+ VMBusChannelNotifyCb chan_notify_cb;
+};
+
+struct VMBusDevice {
+ DeviceState parent;
+ QemuUUID instanceid;
+ uint16_t num_channels;
+ VMBusChannel *channels;
+ AddressSpace *dma_as;
+};
+
+extern const VMStateDescription vmstate_vmbus_dev;
+
+/*
+ * A unit of work parsed out of a message in the receive (i.e. guest->host)
+ * ring buffer of a channel. It's supposed to be subclassed (through
+ * embedding) by the specific devices.
+ */
+typedef struct VMBusChanReq {
+ VMBusChannel *chan;
+ uint16_t pkt_type;
+ uint32_t msglen;
+ void *msg;
+ uint64_t transaction_id;
+ bool need_comp;
+ QEMUSGList sgl;
+} VMBusChanReq;
+
+VMBusDevice *vmbus_channel_device(VMBusChannel *chan);
+VMBusChannel *vmbus_device_channel(VMBusDevice *dev, uint32_t chan_idx);
+uint32_t vmbus_channel_idx(VMBusChannel *chan);
+bool vmbus_channel_is_open(VMBusChannel *chan);
+
+/*
+ * Notify (on guest's behalf) the host side of the channel that there's data in
+ * the ringbuffer to process.
+ */
+void vmbus_channel_notify_host(VMBusChannel *chan);
+
+/*
+ * Reserve space for a packet in the send (i.e. host->guest) ringbuffer. If
+ * there isn't enough room, indicate that to the guest, to be notified when it
+ * becomes available.
+ * Return 0 on success, negative errno on failure.
+ * The ringbuffer indices are NOT updated, the requested space indicator may.
+ */
+int vmbus_channel_reserve(VMBusChannel *chan,
+ uint32_t desclen, uint32_t msglen);
+
+/*
+ * Send a packet to the guest. The space for the packet MUST be reserved
+ * first.
+ * Return total number of bytes placed in the send ringbuffer on success,
+ * negative errno on failure.
+ * The ringbuffer indices are updated on success, and the guest is signaled if
+ * needed.
+ */
+ssize_t vmbus_channel_send(VMBusChannel *chan, uint16_t pkt_type,
+ void *desc, uint32_t desclen,
+ void *msg, uint32_t msglen,
+ bool need_comp, uint64_t transaction_id);
+
+/*
+ * Prepare to fetch a batch of packets from the receive ring buffer.
+ * Return 0 on success, negative errno on failure.
+ */
+int vmbus_channel_recv_start(VMBusChannel *chan);
+
+/*
+ * Shortcut for a common case of sending a simple completion packet with no
+ * auxiliary descriptors.
+ */
+ssize_t vmbus_channel_send_completion(VMBusChanReq *req,
+ void *msg, uint32_t msglen);
+
+/*
+ * Peek at the receive (i.e. guest->host) ring buffer and extract a unit of
+ * work (a device-specific subclass of VMBusChanReq) from a packet if there's
+ * one.
+ * Return an allocated buffer, containing the request of @size with filled
+ * VMBusChanReq at the beginning, followed by the message payload, or NULL on
+ * failure.
+ * The ringbuffer indices are NOT updated, nor is the private copy of the read
+ * index.
+ */
+void *vmbus_channel_recv_peek(VMBusChannel *chan, uint32_t size);
+
+/*
+ * Update the private copy of the read index once the preceding peek is deemed
+ * successful.
+ * The ringbuffer indices are NOT updated.
+ */
+void vmbus_channel_recv_pop(VMBusChannel *chan);
+
+/*
+ * Propagate the private copy of the read index into the receive ring buffer,
+ * and thus complete the reception of a series of packets. Notify guest if
+ * needed.
+ * Return the number of bytes popped off the receive ring buffer by the
+ * preceding recv_peek/recv_pop calls on success, negative errno on failure.
+ */
+ssize_t vmbus_channel_recv_done(VMBusChannel *chan);
+
+/*
+ * Free the request allocated by vmbus_channel_recv_peek, together with its
+ * fields.
+ */
+void vmbus_free_req(void *req);
+
+/*
+ * Find and reference a GPADL by @gpadl_id.
+ * If not found return NULL.
+ */
+VMBusGpadl *vmbus_get_gpadl(VMBusChannel *chan, uint32_t gpadl_id);
+
+/*
+ * Unreference @gpadl. If the reference count drops to zero, free it.
+ * @gpadl may be NULL, in which case nothing is done.
+ */
+void vmbus_put_gpadl(VMBusGpadl *gpadl);
+
+/*
+ * Calculate total length in bytes of @gpadl.
+ * @gpadl must be valid.
+ */
+uint32_t vmbus_gpadl_len(VMBusGpadl *gpadl);
+
+/*
+ * Copy data from @iov to @gpadl at offset @off.
+ * Return the number of bytes copied, or a negative status on failure.
+ */
+ssize_t vmbus_iov_to_gpadl(VMBusChannel *chan, VMBusGpadl *gpadl, uint32_t off,
+ const struct iovec *iov, size_t iov_cnt);
+
+/*
+ * Map SGList contained in the request @req, at offset @off and no more than
+ * @len bytes, for io in direction @dir, and populate @iov with the mapped
+ * iovecs.
+ * Return the number of iovecs mapped, or negative status on failure.
+ */
+int vmbus_map_sgl(VMBusChanReq *req, DMADirection dir, struct iovec *iov,
+ unsigned iov_cnt, size_t len, size_t off);
+
+/*
+ * Unmap *iov mapped with vmbus_map_sgl, marking the number of bytes @accessed.
+ */
+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/arm_sbcon_i2c.h b/include/hw/i2c/arm_sbcon_i2c.h
new file mode 100644
index 000000000..ad96781e7
--- /dev/null
+++ b/include/hw/i2c/arm_sbcon_i2c.h
@@ -0,0 +1,37 @@
+/*
+ * ARM SBCon two-wire serial bus interface (I2C bitbang)
+ * a.k.a.
+ * ARM Versatile I2C controller
+ *
+ * Copyright (c) 2006-2007 CodeSourcery.
+ * Copyright (c) 2012 Oskar Andero <oskar.andero@gmail.com>
+ * Copyright (C) 2020 Philippe Mathieu-Daudé <f4bug@amsat.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef HW_I2C_ARM_SBCON_H
+#define HW_I2C_ARM_SBCON_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
+
+typedef struct ArmSbconI2CState ArmSbconI2CState;
+DECLARE_INSTANCE_CHECKER(ArmSbconI2CState, ARM_SBCON_I2C,
+ TYPE_ARM_SBCON_I2C)
+
+struct ArmSbconI2CState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ MemoryRegion iomem;
+ bitbang_i2c_interface bitbang;
+ int out;
+ int in;
+};
+
+#endif /* HW_I2C_ARM_SBCON_H */
diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h
new file mode 100644
index 000000000..4b9be0927
--- /dev/null
+++ b/include/hw/i2c/aspeed_i2c.h
@@ -0,0 +1,98 @@
+/*
+ * ASPEED AST2400 I2C Controller
+ *
+ * Copyright (C) 2016 IBM Corp.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef ASPEED_I2C_H
+#define ASPEED_I2C_H
+
+#include "hw/i2c/i2c.h"
+#include "hw/sysbus.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"
+OBJECT_DECLARE_TYPE(AspeedI2CState, AspeedI2CClass, ASPEED_I2C)
+
+#define ASPEED_I2C_NR_BUSSES 16
+#define ASPEED_I2C_MAX_POOL_SIZE 0x800
+
+struct AspeedI2CState;
+
+#define TYPE_ASPEED_I2C_BUS "aspeed.i2c.bus"
+OBJECT_DECLARE_SIMPLE_TYPE(AspeedI2CBus, ASPEED_I2C_BUS)
+struct AspeedI2CBus {
+ SysBusDevice parent_obj;
+
+ struct AspeedI2CState *controller;
+
+ 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;
+};
+
+struct AspeedI2CState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ qemu_irq irq;
+
+ uint32_t intr_status;
+ uint32_t ctrl_global;
+ MemoryRegion pool_iomem;
+ uint8_t pool[ASPEED_I2C_MAX_POOL_SIZE];
+
+ AspeedI2CBus busses[ASPEED_I2C_NR_BUSSES];
+ MemoryRegion *dram_mr;
+ AddressSpace dram_as;
+};
+
+
+struct AspeedI2CClass {
+ SysBusDeviceClass parent_class;
+
+ uint8_t num_busses;
+ uint8_t reg_size;
+ uint8_t gap;
+ qemu_irq (*bus_get_irq)(AspeedI2CBus *);
+
+ uint64_t pool_size;
+ hwaddr pool_base;
+ uint8_t *(*bus_pool_base)(AspeedI2CBus *);
+ bool check_sram;
+ bool has_dma;
+
+};
+
+I2CBus *aspeed_i2c_get_bus(AspeedI2CState *s, int busnr);
+
+#endif /* ASPEED_I2C_H */
diff --git a/include/hw/i2c/bitbang_i2c.h b/include/hw/i2c/bitbang_i2c.h
new file mode 100644
index 000000000..92334e901
--- /dev/null
+++ b/include/hw/i2c/bitbang_i2c.h
@@ -0,0 +1,50 @@
+#ifndef BITBANG_I2C_H
+#define BITBANG_I2C_H
+
+#include "hw/i2c/i2c.h"
+
+typedef struct bitbang_i2c_interface bitbang_i2c_interface;
+
+#define BITBANG_I2C_SDA 0
+#define BITBANG_I2C_SCL 1
+
+typedef enum bitbang_i2c_state {
+ STOPPED = 0,
+ SENDING_BIT7,
+ SENDING_BIT6,
+ SENDING_BIT5,
+ SENDING_BIT4,
+ SENDING_BIT3,
+ SENDING_BIT2,
+ SENDING_BIT1,
+ SENDING_BIT0,
+ WAITING_FOR_ACK,
+ RECEIVING_BIT7,
+ RECEIVING_BIT6,
+ RECEIVING_BIT5,
+ RECEIVING_BIT4,
+ RECEIVING_BIT3,
+ RECEIVING_BIT2,
+ RECEIVING_BIT1,
+ RECEIVING_BIT0,
+ SENDING_ACK,
+ SENT_NACK
+} bitbang_i2c_state;
+
+struct bitbang_i2c_interface {
+ I2CBus *bus;
+ bitbang_i2c_state state;
+ int last_data;
+ int last_clock;
+ int device_out;
+ uint8_t buffer;
+ int current_addr;
+};
+
+/**
+ * bitbang_i2c_init: in-place initialize the bitbang_i2c_interface struct
+ */
+void bitbang_i2c_init(bitbang_i2c_interface *s, I2CBus *bus);
+int bitbang_i2c_set(bitbang_i2c_interface *i2c, int line, int level);
+
+#endif
diff --git a/include/hw/i2c/i2c.h b/include/hw/i2c/i2c.h
new file mode 100644
index 000000000..5ca3b708c
--- /dev/null
+++ b/include/hw/i2c/i2c.h
@@ -0,0 +1,194 @@
+#ifndef QEMU_I2C_H
+#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
+ defer their response (eg. CPU slave interfaces where the data is supplied
+ by the device driver in response to an interrupt). */
+
+enum i2c_event {
+ I2C_START_RECV,
+ I2C_START_SEND,
+ I2C_FINISH,
+ I2C_NACK /* Masker NACKed a receive byte. */
+};
+
+typedef struct I2CNodeList I2CNodeList;
+
+#define TYPE_I2C_SLAVE "i2c-slave"
+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);
+
+ /*
+ * Slave to master. This cannot fail, the device should always
+ * return something here.
+ */
+ uint8_t (*recv)(I2CSlave *s);
+
+ /*
+ * Notify the slave of a bus state change. For start event,
+ * returns non-zero to NAK an operation. For other events the
+ * return code is not used and should be zero.
+ */
+ int (*event)(I2CSlave *s, enum i2c_event event);
+
+ /*
+ * 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;
+
+ /* Remaining fields for internal use by the I2C code. */
+ uint8_t address;
+};
+
+#define TYPE_I2C_BUS "i2c-bus"
+OBJECT_DECLARE_SIMPLE_TYPE(I2CBus, I2C_BUS)
+
+typedef struct I2CNode I2CNode;
+
+struct I2CNode {
+ I2CSlave *elt;
+ QLIST_ENTRY(I2CNode) next;
+};
+
+typedef QLIST_HEAD(I2CNodeList, I2CNode) I2CNodeList;
+
+struct I2CBus {
+ BusState qbus;
+ I2CNodeList current_devs;
+ uint8_t saved_address;
+ bool broadcast;
+};
+
+I2CBus *i2c_init_bus(DeviceState *parent, const char *name);
+int i2c_bus_busy(I2CBus *bus);
+
+/**
+ * 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);
+
+void i2c_end_transfer(I2CBus *bus);
+void i2c_nack(I2CBus *bus);
+int i2c_send(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.
+ * @name: a device type name
+ * @addr: I2C address of the slave when put on a bus
+ *
+ * This only initializes the device state structure and allows
+ * properties to be set. Type @name must exist. The device still
+ * needs to be realized. See qdev-core.h.
+ */
+I2CSlave *i2c_slave_new(const char *name, uint8_t addr);
+
+/**
+ * Create and realize an I2C slave device on the heap.
+ * @bus: I2C bus to put it on
+ * @name: I2C slave device type name
+ * @addr: I2C address of the slave when put on a bus
+ *
+ * Create the device state structure, initialize it, put it on the
+ * specified @bus, and drop the reference to it (the device is realized).
+ */
+I2CSlave *i2c_slave_create_simple(I2CBus *bus, const char *name, uint8_t addr);
+
+/**
+ * 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
+ * @errp: pointer to NULL initialized error object
+ *
+ * Returns: %true on success, %false on failure.
+ *
+ * Call 'realize' on @dev, put it on the specified @bus, and drop the
+ * reference to it.
+ *
+ * This function is useful if you have created @dev via qdev_new(),
+ * i2c_slave_new() or i2c_slave_try_new() (which take 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
+ * i2c_slave_create_simple() is probably better (as it does the create,
+ * init and realize in one step).
+ *
+ * If you are embedding the I2C slave 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
+ * via the child<> property, and so the reference-count-drop done here
+ * would be incorrect. (Instead you would want i2c_slave_realize(),
+ * which doesn't currently exist but would be trivial to create if we
+ * had any code that wanted it.)
+ */
+bool i2c_slave_realize_and_unref(I2CSlave *dev, I2CBus *bus, Error **errp);
+
+/**
+ * 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;
+
+#define VMSTATE_I2C_SLAVE(_field, _state) { \
+ .name = (stringify(_field)), \
+ .size = sizeof(I2CSlave), \
+ .vmsd = &vmstate_i2c_slave, \
+ .flags = VMS_STRUCT, \
+ .offset = vmstate_offset_value(_state, _field, I2CSlave), \
+}
+
+#endif
diff --git a/include/hw/i2c/i2c_mux_pca954x.h b/include/hw/i2c/i2c_mux_pca954x.h
new file mode 100644
index 000000000..8aaf9bbc3
--- /dev/null
+++ b/include/hw/i2c/i2c_mux_pca954x.h
@@ -0,0 +1,19 @@
+#ifndef QEMU_I2C_MUX_PCA954X
+#define QEMU_I2C_MUX_PCA954X
+
+#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
new file mode 100644
index 000000000..e4f91339f
--- /dev/null
+++ b/include/hw/i2c/imx_i2c.h
@@ -0,0 +1,88 @@
+/*
+ * i.MX I2C Bus Serial Interface registers definition
+ *
+ * Copyright (C) 2013 Jean-Christophe Dubois. <jcd@tribudubois.net>
+ *
+ * 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 IMX_I2C_H
+#define IMX_I2C_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_IMX_I2C "imx.i2c"
+OBJECT_DECLARE_SIMPLE_TYPE(IMXI2CState, IMX_I2C)
+
+#define IMX_I2C_MEM_SIZE 0x14
+
+/* i.MX I2C memory map */
+#define IADR_ADDR 0x00 /* address register */
+#define IFDR_ADDR 0x04 /* frequency divider register */
+#define I2CR_ADDR 0x08 /* control register */
+#define I2SR_ADDR 0x0c /* status register */
+#define I2DR_ADDR 0x10 /* data register */
+
+#define IADR_MASK 0xFE
+#define IADR_RESET 0
+
+#define IFDR_MASK 0x3F
+#define IFDR_RESET 0
+
+#define I2CR_IEN (1 << 7)
+#define I2CR_IIEN (1 << 6)
+#define I2CR_MSTA (1 << 5)
+#define I2CR_MTX (1 << 4)
+#define I2CR_TXAK (1 << 3)
+#define I2CR_RSTA (1 << 2)
+#define I2CR_MASK 0xFC
+#define I2CR_RESET 0
+
+#define I2SR_ICF (1 << 7)
+#define I2SR_IAAF (1 << 6)
+#define I2SR_IBB (1 << 5)
+#define I2SR_IAL (1 << 4)
+#define I2SR_SRW (1 << 2)
+#define I2SR_IIF (1 << 1)
+#define I2SR_RXAK (1 << 0)
+#define I2SR_MASK 0xE9
+#define I2SR_RESET 0x81
+
+#define I2DR_MASK 0xFF
+#define I2DR_RESET 0
+
+#define ADDR_RESET 0xFF00
+
+struct IMXI2CState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+ I2CBus *bus;
+ qemu_irq irq;
+
+ uint16_t address;
+
+ uint16_t iadr;
+ uint16_t ifdr;
+ uint16_t i2cr;
+ uint16_t i2sr;
+ uint16_t i2dr_read;
+ uint16_t i2dr_write;
+};
+
+#endif /* IMX_I2C_H */
diff --git a/include/hw/i2c/microbit_i2c.h b/include/hw/i2c/microbit_i2c.h
new file mode 100644
index 000000000..3c29e09bf
--- /dev/null
+++ b/include/hw/i2c/microbit_i2c.h
@@ -0,0 +1,42 @@
+/*
+ * Microbit stub for Nordic Semiconductor nRF51 SoC Two-Wire Interface
+ * http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.1.pdf
+ *
+ * Copyright 2019 Red Hat, Inc.
+ *
+ * This code is licensed under the GPL version 2 or later. See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef MICROBIT_I2C_H
+#define MICROBIT_I2C_H
+
+#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
+#define NRF51_TWI_TASK_STOP 0x014
+#define NRF51_TWI_EVENT_STOPPED 0x104
+#define NRF51_TWI_EVENT_RXDREADY 0x108
+#define NRF51_TWI_EVENT_TXDSENT 0x11c
+#define NRF51_TWI_REG_ENABLE 0x500
+#define NRF51_TWI_REG_RXD 0x518
+#define NRF51_TWI_REG_TXD 0x51c
+#define NRF51_TWI_REG_ADDRESS 0x588
+
+#define TYPE_MICROBIT_I2C "microbit.i2c"
+OBJECT_DECLARE_SIMPLE_TYPE(MicrobitI2CState, MICROBIT_I2C)
+
+#define MICROBIT_I2C_NREGS (NRF51_PERIPHERAL_SIZE / sizeof(uint32_t))
+
+struct MicrobitI2CState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ uint32_t regs[MICROBIT_I2C_NREGS];
+ uint32_t read_idx;
+};
+
+#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 000000000..7d59ee917
--- /dev/null
+++ b/include/hw/i2c/npcm7xx_smbus.h
@@ -0,0 +1,113 @@
+/*
+ * 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 preriod 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.
+ */
+typedef 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;
+} NPCM7xxSMBusState;
+
+#define TYPE_NPCM7XX_SMBUS "npcm7xx-smbus"
+#define NPCM7XX_SMBUS(obj) OBJECT_CHECK(NPCM7xxSMBusState, (obj), \
+ TYPE_NPCM7XX_SMBUS)
+
+#endif /* NPCM7XX_SMBUS_H */
diff --git a/include/hw/i2c/pm_smbus.h b/include/hw/i2c/pm_smbus.h
new file mode 100644
index 000000000..0d74207ef
--- /dev/null
+++ b/include/hw/i2c/pm_smbus.h
@@ -0,0 +1,56 @@
+#ifndef PM_SMBUS_H
+#define PM_SMBUS_H
+
+#include "exec/memory.h"
+#include "hw/i2c/smbus_master.h"
+
+#define PM_SMBUS_MAX_MSG_SIZE 32
+
+typedef struct PMSMBus {
+ I2CBus *smbus;
+ MemoryRegion io;
+
+ uint8_t smb_stat;
+ uint8_t smb_ctl;
+ uint8_t smb_cmd;
+ uint8_t smb_addr;
+ uint8_t smb_data0;
+ uint8_t smb_data1;
+ uint8_t smb_data[PM_SMBUS_MAX_MSG_SIZE];
+ uint8_t smb_blkdata;
+ uint8_t smb_auxctl;
+ uint32_t smb_index;
+
+ /* Set by pm_smbus.c */
+ void (*reset)(struct PMSMBus *s);
+
+ /* Set by the user. */
+ bool i2c_enable;
+ void (*set_irq)(struct PMSMBus *s, bool enabled);
+ void *opaque;
+
+ /* Internally used by pm_smbus. */
+
+ /* Set on block transfers after the last byte has been read, so the
+ INTR bit can be set at the right time. */
+ bool op_done;
+
+ /* Set during an I2C block read, so we know how to handle data. */
+ bool in_i2c_block_read;
+
+ /* Used to work around a bug in AMIBIOS, see smb_transaction_start() */
+ bool start_transaction_on_status_read;
+} PMSMBus;
+
+void pm_smbus_init(DeviceState *parent, PMSMBus *smb, bool force_aux_blk);
+
+/*
+ * For backwards compatibility on migration, older versions don't have
+ * working migration for pm_smbus, this lets us ignore the migrations
+ * for older machine versions.
+ */
+bool pm_smbus_vmstate_needed(void);
+
+extern const VMStateDescription pmsmb_vmstate;
+
+#endif /* PM_SMBUS_H */
diff --git a/include/hw/i2c/pmbus_device.h b/include/hw/i2c/pmbus_device.h
new file mode 100644
index 000000000..62bd38c83
--- /dev/null
+++ b/include/hw/i2c/pmbus_device.h
@@ -0,0 +1,517 @@
+/*
+ * 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_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 */
+};
+
+/* 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 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_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_MFR_INFO BIT_ULL(50)
+
+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 */
+ 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;
+
+/**
+ * Convert sensor values to direct mode format
+ *
+ * Y = (m * x - b) * 10^R
+ *
+ * @return uint32_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);
+
+/**
+ * @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 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);
+
+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/ppc4xx_i2c.h b/include/hw/i2c/ppc4xx_i2c.h
new file mode 100644
index 000000000..4e882fa3c
--- /dev/null
+++ b/include/hw/i2c/ppc4xx_i2c.h
@@ -0,0 +1,63 @@
+/*
+ * PPC4xx I2C controller emulation
+ *
+ * Copyright (c) 2007 Jocelyn Mayer
+ * Copyright (c) 2012 François Revol
+ * Copyright (c) 2016-2018 BALATON Zoltan
+ *
+ * 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 PPC4XX_I2C_H
+#define PPC4XX_I2C_H
+
+#include "hw/sysbus.h"
+#include "hw/i2c/bitbang_i2c.h"
+#include "qom/object.h"
+
+#define TYPE_PPC4xx_I2C "ppc4xx-i2c"
+OBJECT_DECLARE_SIMPLE_TYPE(PPC4xxI2CState, PPC4xx_I2C)
+
+struct PPC4xxI2CState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ I2CBus *bus;
+ qemu_irq irq;
+ MemoryRegion iomem;
+ bitbang_i2c_interface bitbang;
+ int mdidx;
+ uint8_t mdata[4];
+ uint8_t lmadr;
+ uint8_t hmadr;
+ uint8_t cntl;
+ uint8_t mdcntl;
+ uint8_t sts;
+ uint8_t extsts;
+ uint8_t lsadr;
+ uint8_t hsadr;
+ uint8_t clkdiv;
+ uint8_t intrmsk;
+ uint8_t xfrcnt;
+ uint8_t xtcntlss;
+ uint8_t directcntl;
+};
+
+#endif /* PPC4XX_I2C_H */
diff --git a/include/hw/i2c/smbus_eeprom.h b/include/hw/i2c/smbus_eeprom.h
new file mode 100644
index 000000000..68b0063ab
--- /dev/null
+++ b/include/hw/i2c/smbus_eeprom.h
@@ -0,0 +1,36 @@
+/*
+ * QEMU SMBus EEPROM API
+ *
+ * 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_SMBUS_EEPROM_H
+#define HW_SMBUS_EEPROM_H
+
+#include "exec/cpu-common.h"
+#include "hw/i2c/i2c.h"
+
+void smbus_eeprom_init_one(I2CBus *bus, uint8_t address, uint8_t *eeprom_buf);
+void smbus_eeprom_init(I2CBus *bus, int nb_eeprom,
+ const uint8_t *eeprom_spd, int size);
+
+enum sdram_type { SDR = 0x4, DDR = 0x7, DDR2 = 0x8 };
+uint8_t *spd_data_generate(enum sdram_type type, ram_addr_t size);
+
+#endif
diff --git a/include/hw/i2c/smbus_master.h b/include/hw/i2c/smbus_master.h
new file mode 100644
index 000000000..bb13bc423
--- /dev/null
+++ b/include/hw/i2c/smbus_master.h
@@ -0,0 +1,55 @@
+/*
+ * QEMU SMBus host (master) API
+ *
+ * Copyright (c) 2007 Arastra, 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 HW_SMBUS_MASTER_H
+#define HW_SMBUS_MASTER_H
+
+#include "hw/i2c/i2c.h"
+
+/* Master device commands. */
+int smbus_quick_command(I2CBus *bus, uint8_t addr, int read);
+int smbus_receive_byte(I2CBus *bus, uint8_t addr);
+int smbus_send_byte(I2CBus *bus, uint8_t addr, uint8_t data);
+int smbus_read_byte(I2CBus *bus, uint8_t addr, uint8_t command);
+int smbus_write_byte(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t data);
+int smbus_read_word(I2CBus *bus, uint8_t addr, uint8_t command);
+int smbus_write_word(I2CBus *bus, uint8_t addr, uint8_t command, uint16_t data);
+
+/*
+ * Do a block transfer from an I2C device. If recv_len is set, then the
+ * first received byte is a length field and is used to know how much data
+ * to receive. Otherwise receive "len" bytes. If send_cmd is set, send
+ * the command byte first before receiving the data.
+ */
+int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
+ int len, bool recv_len, bool send_cmd);
+
+/*
+ * Do a block transfer to an I2C device. If send_len is set, send the
+ * "len" value before the data.
+ */
+int smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
+ int len, bool send_len);
+
+#endif
diff --git a/include/hw/i2c/smbus_slave.h b/include/hw/i2c/smbus_slave.h
new file mode 100644
index 000000000..86bfe0a79
--- /dev/null
+++ b/include/hw/i2c/smbus_slave.h
@@ -0,0 +1,95 @@
+/*
+ * QEMU SMBus device (slave) API
+ *
+ * Copyright (c) 2007 Arastra, 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 HW_SMBUS_SLAVE_H
+#define HW_SMBUS_SLAVE_H
+
+#include "hw/i2c/i2c.h"
+#include "qom/object.h"
+
+#define TYPE_SMBUS_DEVICE "smbus-device"
+OBJECT_DECLARE_TYPE(SMBusDevice, SMBusDeviceClass,
+ SMBUS_DEVICE)
+
+
+struct SMBusDeviceClass {
+ I2CSlaveClass parent_class;
+
+ /*
+ * An operation with no data, special in SMBus.
+ * This may be NULL, quick commands are ignore in that case.
+ */
+ void (*quick_cmd)(SMBusDevice *dev, uint8_t read);
+
+ /*
+ * We can't distinguish between a word write and a block write with
+ * length 1, so pass the whole data block including the length byte
+ * (if present). The device is responsible figuring out what type of
+ * command this is.
+ * This may be NULL if no data is written to the device. Writes
+ * will be ignore in that case.
+ */
+ int (*write_data)(SMBusDevice *dev, uint8_t *buf, uint8_t len);
+
+ /*
+ * Likewise we can't distinguish between different reads, or even know
+ * the length of the read until the read is complete, so read data a
+ * byte at a time. The device is responsible for adding the length
+ * byte on block reads. This call cannot fail, it should return
+ * something, preferably 0xff if nothing is available.
+ * This may be NULL if no data is read from the device. Reads will
+ * return 0xff in that case.
+ */
+ uint8_t (*receive_byte)(SMBusDevice *dev);
+};
+
+#define SMBUS_DATA_MAX_LEN 34 /* command + len + 32 bytes of data. */
+
+struct SMBusDevice {
+ /* The SMBus protocol is implemented on top of I2C. */
+ I2CSlave i2c;
+
+ /* Remaining fields for internal use only. */
+ int32_t mode;
+ int32_t data_len;
+ uint8_t data_buf[SMBUS_DATA_MAX_LEN];
+};
+
+extern const VMStateDescription vmstate_smbus_device;
+
+#define VMSTATE_SMBUS_DEVICE(_field, _state) { \
+ .name = (stringify(_field)), \
+ .size = sizeof(SMBusDevice), \
+ .vmsd = &vmstate_smbus_device, \
+ .flags = VMS_STRUCT, \
+ .offset = vmstate_offset_value(_state, _field, SMBusDevice), \
+}
+
+/*
+ * Users should call this in their .needed functions to know if the
+ * SMBus slave data needs to be transferred.
+ */
+bool smbus_vmstate_needed(SMBusDevice *dev);
+
+#endif
diff --git a/include/hw/i386/apic-msidef.h b/include/hw/i386/apic-msidef.h
new file mode 100644
index 000000000..420b41167
--- /dev/null
+++ b/include/hw/i386/apic-msidef.h
@@ -0,0 +1,31 @@
+#ifndef HW_APIC_MSIDEF_H
+#define HW_APIC_MSIDEF_H
+
+/*
+ * Intel APIC constants: from include/asm/msidef.h
+ */
+
+/*
+ * Shifts for MSI data
+ */
+
+#define MSI_DATA_VECTOR_SHIFT 0
+#define MSI_DATA_VECTOR_MASK 0x000000ff
+
+#define MSI_DATA_DELIVERY_MODE_SHIFT 8
+#define MSI_DATA_LEVEL_SHIFT 14
+#define MSI_DATA_TRIGGER_SHIFT 15
+
+/*
+ * Shift/mask fields for msi address
+ */
+
+#define MSI_ADDR_DEST_MODE_SHIFT 2
+
+#define MSI_ADDR_REDIRECTION_SHIFT 3
+
+#define MSI_ADDR_DEST_ID_SHIFT 12
+#define MSI_ADDR_DEST_IDX_SHIFT 4
+#define MSI_ADDR_DEST_ID_MASK 0x000ff000
+
+#endif /* HW_APIC_MSIDEF_H */
diff --git a/include/hw/i386/apic.h b/include/hw/i386/apic.h
new file mode 100644
index 000000000..da1d2fe15
--- /dev/null
+++ b/include/hw/i386/apic.h
@@ -0,0 +1,27 @@
+#ifndef APIC_H
+#define APIC_H
+
+
+/* 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);
+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);
+uint64_t cpu_get_apic_base(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);
+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);
+
+/* pc.c */
+DeviceState *cpu_get_current_apic(void);
+
+#endif
diff --git a/include/hw/i386/apic_internal.h b/include/hw/i386/apic_internal.h
new file mode 100644
index 000000000..c175e7e71
--- /dev/null
+++ b/include/hw/i386/apic_internal.h
@@ -0,0 +1,231 @@
+/*
+ * APIC support - internal interfaces
+ *
+ * Copyright (c) 2004-2005 Fabrice Bellard
+ * 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.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 QEMU_APIC_INTERNAL_H
+#define QEMU_APIC_INTERNAL_H
+
+#include "cpu.h"
+#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
+#define APIC_LVT_THERMAL 1
+#define APIC_LVT_PERFORM 2
+#define APIC_LVT_LINT0 3
+#define APIC_LVT_LINT1 4
+#define APIC_LVT_ERROR 5
+#define APIC_LVT_NB 6
+
+/* APIC delivery modes */
+#define APIC_DM_FIXED 0
+#define APIC_DM_LOWPRI 1
+#define APIC_DM_SMI 2
+#define APIC_DM_NMI 4
+#define APIC_DM_INIT 5
+#define APIC_DM_SIPI 6
+#define APIC_DM_EXTINT 7
+
+/* APIC destination mode */
+#define APIC_DESTMODE_FLAT 0xf
+#define APIC_DESTMODE_CLUSTER 1
+
+#define APIC_TRIGGER_EDGE 0
+#define APIC_TRIGGER_LEVEL 1
+
+#define APIC_VECTOR_MASK 0xff
+#define APIC_DCR_MASK 0xf
+
+#define APIC_LVT_TIMER_SHIFT 17
+#define APIC_LVT_MASKED_SHIFT 16
+#define APIC_LVT_LEVEL_TRIGGER_SHIFT 15
+#define APIC_LVT_REMOTE_IRR_SHIFT 14
+#define APIC_LVT_INT_POLARITY_SHIFT 13
+#define APIC_LVT_DELIV_STS_SHIFT 12
+#define APIC_LVT_DELIV_MOD_SHIFT 8
+
+#define APIC_LVT_TIMER_TSCDEADLINE (2 << APIC_LVT_TIMER_SHIFT)
+#define APIC_LVT_TIMER_PERIODIC (1 << APIC_LVT_TIMER_SHIFT)
+#define APIC_LVT_MASKED (1 << APIC_LVT_MASKED_SHIFT)
+#define APIC_LVT_LEVEL_TRIGGER (1 << APIC_LVT_LEVEL_TRIGGER_SHIFT)
+#define APIC_LVT_REMOTE_IRR (1 << APIC_LVT_REMOTE_IRR_SHIFT)
+#define APIC_LVT_INT_POLARITY (1 << APIC_LVT_INT_POLARITY_SHIFT)
+#define APIC_LVT_DELIV_STS (1 << APIC_LVT_DELIV_STS_SHIFT)
+#define APIC_LVT_DELIV_MOD (7 << APIC_LVT_DELIV_MOD_SHIFT)
+
+#define APIC_ESR_ILL_ADDRESS_SHIFT 7
+#define APIC_ESR_RECV_ILL_VECT_SHIFT 6
+#define APIC_ESR_SEND_ILL_VECT_SHIFT 5
+#define APIC_ESR_RECV_ACCEPT_SHIFT 3
+#define APIC_ESR_SEND_ACCEPT_SHIFT 2
+#define APIC_ESR_RECV_CHECK_SUM_SHIFT 1
+
+#define APIC_ESR_ILLEGAL_ADDRESS (1 << APIC_ESR_ILL_ADDRESS_SHIFT)
+#define APIC_ESR_RECV_ILLEGAL_VECT (1 << APIC_ESR_RECV_ILL_VECT_SHIFT)
+#define APIC_ESR_SEND_ILLEGAL_VECT (1 << APIC_ESR_SEND_ILL_VECT_SHIFT)
+#define APIC_ESR_RECV_ACCEPT (1 << APIC_ESR_RECV_ACCEPT_SHIFT)
+#define APIC_ESR_SEND_ACCEPT (1 << APIC_ESR_SEND_ACCEPT_SHIFT)
+#define APIC_ESR_RECV_CHECK_SUM (1 << APIC_ESR_RECV_CHECK_SUM_SHIFT)
+#define APIC_ESR_SEND_CHECK_SUM 1
+
+#define APIC_ICR_DEST_SHIFT 24
+#define APIC_ICR_DEST_SHORT_SHIFT 18
+#define APIC_ICR_TRIGGER_MOD_SHIFT 15
+#define APIC_ICR_LEVEL_SHIFT 14
+#define APIC_ICR_DELIV_STS_SHIFT 12
+#define APIC_ICR_DEST_MOD_SHIFT 11
+#define APIC_ICR_DELIV_MOD_SHIFT 8
+
+#define APIC_ICR_DEST_SHORT (3 << APIC_ICR_DEST_SHORT_SHIFT)
+#define APIC_ICR_TRIGGER_MOD (1 << APIC_ICR_TRIGGER_MOD_SHIFT)
+#define APIC_ICR_LEVEL (1 << APIC_ICR_LEVEL_SHIFT)
+#define APIC_ICR_DELIV_STS (1 << APIC_ICR_DELIV_STS_SHIFT)
+#define APIC_ICR_DEST_MOD (1 << APIC_ICR_DEST_MOD_SHIFT)
+#define APIC_ICR_DELIV_MOD (7 << APIC_ICR_DELIV_MOD_SHIFT)
+
+#define APIC_PR_CLASS_SHIFT 4
+#define APIC_PR_SUB_CLASS 0xf
+
+#define APIC_LOGDEST_XAPIC_SHIFT 4
+#define APIC_LOGDEST_XAPIC_ID 0xf
+
+#define APIC_LOGDEST_X2APIC_SHIFT 16
+#define APIC_LOGDEST_X2APIC_ID 0xffff
+
+#define APIC_SPURIO_FOCUS_SHIFT 9
+#define APIC_SPURIO_ENABLED_SHIFT 8
+
+#define APIC_SPURIO_FOCUS (1 << APIC_SPURIO_FOCUS_SHIFT)
+#define APIC_SPURIO_ENABLED (1 << APIC_SPURIO_ENABLED_SHIFT)
+
+#define APIC_SV_DIRECTED_IO (1 << 12)
+#define APIC_SV_ENABLE (1 << 8)
+
+#define VAPIC_ENABLE_BIT 0
+#define VAPIC_ENABLE_MASK (1 << VAPIC_ENABLE_BIT)
+
+typedef struct APICCommonState APICCommonState;
+
+#define TYPE_APIC_COMMON "apic-common"
+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);
+ void (*set_tpr)(APICCommonState *s, uint8_t val);
+ uint8_t (*get_tpr)(APICCommonState *s);
+ void (*enable_tpr_reporting)(APICCommonState *s, bool enable);
+ void (*vapic_base_update)(APICCommonState *s);
+ void (*external_nmi)(APICCommonState *s);
+ void (*pre_save)(APICCommonState *s);
+ void (*post_load)(APICCommonState *s);
+ void (*reset)(APICCommonState *s);
+ /* send_msi emulates an APIC bus and its proper place would be in a new
+ * device, but it's convenient to have it here for now.
+ */
+ void (*send_msi)(MSIMessage *msi);
+};
+
+struct APICCommonState {
+ /*< private >*/
+ DeviceState parent_obj;
+ /*< public >*/
+
+ MemoryRegion io_memory;
+ X86CPU *cpu;
+ uint32_t apicbase;
+ uint8_t id; /* legacy APIC ID */
+ uint32_t initial_apic_id;
+ uint8_t version;
+ uint8_t arb_id;
+ uint8_t tpr;
+ uint32_t spurious_vec;
+ uint8_t log_dest;
+ uint8_t dest_mode;
+ uint32_t isr[8]; /* in service register */
+ uint32_t tmr[8]; /* trigger mode register */
+ uint32_t irr[8]; /* interrupt request register */
+ uint32_t lvt[APIC_LVT_NB];
+ uint32_t esr; /* error register */
+ uint32_t icr[2];
+
+ uint32_t divide_conf;
+ int count_shift;
+ uint32_t initial_count;
+ int64_t initial_count_load_time;
+ int64_t next_time;
+ QEMUTimer *timer;
+ int64_t timer_expiry;
+ int sipi_vector;
+ int wait_for_sipi;
+
+ uint32_t vapic_control;
+ DeviceState *vapic;
+ hwaddr vapic_paddr; /* note: persistence via kvmvapic */
+ bool legacy_instance_id;
+};
+
+typedef struct VAPICState {
+ uint8_t tpr;
+ uint8_t isr;
+ uint8_t zero;
+ uint8_t irr;
+ uint8_t enabled;
+} QEMU_PACKED 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);
+
+void vapic_report_tpr_access(DeviceState *dev, CPUState *cpu, target_ulong ip,
+ TPRAccess access);
+
+int apic_get_ppr(APICCommonState *s);
+uint32_t apic_get_current_count(APICCommonState *s);
+
+static inline void apic_set_bit(uint32_t *tab, int index)
+{
+ int i, mask;
+ i = index >> 5;
+ mask = 1 << (index & 0x1f);
+ tab[i] |= mask;
+}
+
+static inline int apic_get_bit(uint32_t *tab, int index)
+{
+ int i, mask;
+ i = index >> 5;
+ mask = 1 << (index & 0x1f);
+ return !!(tab[i] & mask);
+}
+
+APICCommonClass *apic_get_class(void);
+
+#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 000000000..846c72608
--- /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/ich9.h b/include/hw/i386/ich9.h
new file mode 100644
index 000000000..23ee8e371
--- /dev/null
+++ b/include/hw/i386/ich9.h
@@ -0,0 +1,256 @@
+#ifndef HW_ICH9_H
+#define HW_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"
+#include "qom/object.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);
+
+void ich9_generate_smi(void);
+
+#define ICH9_CC_SIZE (16 * 1024) /* 16KB. Chipset configuration registers */
+
+#define TYPE_ICH9_LPC_DEVICE "ICH9-LPC"
+OBJECT_DECLARE_SIMPLE_TYPE(ICH9LPCState, ICH9_LPC_DEVICE)
+
+struct ICH9LPCState {
+ /* ICH9 LPC PCI to ISA bridge */
+ PCIDevice d;
+
+ /* (pci device, intx) -> pirq
+ * In real chipset case, the unused slots are never used
+ * as ICH9 supports only D25-D31 irq routing.
+ * On the other hand in qemu case, any slot/function can be populated
+ * via command line option.
+ * So fallback interrupt routing for any devices in any slots is necessary.
+ */
+ uint8_t irr[PCI_SLOT_MAX][PCI_NUM_PINS];
+
+ APMState apm;
+ ICH9LPCPMRegs pm;
+ uint32_t sci_level; /* track sci level */
+ uint8_t sci_gsi;
+
+ /* 2.24 Pin Straps */
+ struct {
+ bool spkr_hi;
+ } pin_strap;
+
+ /* 10.1 Chipset Configuration registers(Memory Space)
+ which is pointed by RCBA */
+ uint8_t chip_config[ICH9_CC_SIZE];
+
+ /*
+ * 13.7.5 RST_CNT---Reset Control Register (LPC I/F---D31:F0)
+ *
+ * register contents and IO memory region
+ */
+ uint8_t rst_cnt;
+ MemoryRegion rst_cnt_mem;
+
+ /* SMI feature negotiation via fw_cfg */
+ uint64_t smi_host_features; /* guest-invisible, host endian */
+ uint8_t smi_host_features_le[8]; /* guest-visible, read-only, little
+ * endian uint64_t */
+ uint8_t smi_guest_features_le[8]; /* guest-visible, read-write, little
+ * endian uint64_t */
+ uint8_t smi_features_ok; /* guest-visible, read-only; selecting it
+ * 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];
+};
+
+#define Q35_MASK(bit, ms_bit, ls_bit) \
+((uint##bit##_t)(((1ULL << ((ms_bit) + 1)) - 1) & ~((1ULL << ls_bit) - 1)))
+
+/* ICH9: Chipset Configuration Registers */
+#define ICH9_CC_ADDR_MASK (ICH9_CC_SIZE - 1)
+
+#define ICH9_CC
+#define ICH9_CC_D28IP 0x310C
+#define ICH9_CC_D28IP_SHIFT 4
+#define ICH9_CC_D28IP_MASK 0xf
+#define ICH9_CC_D28IP_DEFAULT 0x00214321
+#define ICH9_CC_D31IR 0x3140
+#define ICH9_CC_D30IR 0x3142
+#define ICH9_CC_D29IR 0x3144
+#define ICH9_CC_D28IR 0x3146
+#define ICH9_CC_D27IR 0x3148
+#define ICH9_CC_D26IR 0x314C
+#define ICH9_CC_D25IR 0x3150
+#define ICH9_CC_DIR_DEFAULT 0x3210
+#define ICH9_CC_D30IR_DEFAULT 0x0
+#define ICH9_CC_DIR_SHIFT 4
+#define ICH9_CC_DIR_MASK 0x7
+#define ICH9_CC_OIC 0x31FF
+#define ICH9_CC_OIC_AEN 0x1
+#define ICH9_CC_GCS 0x3410
+#define ICH9_CC_GCS_DEFAULT 0x00000020
+#define ICH9_CC_GCS_NO_REBOOT (1 << 5)
+
+/* D28:F[0-5] */
+#define ICH9_PCIE_DEV 28
+#define ICH9_PCIE_FUNC_MAX 6
+
+
+/* D29:F0 USB UHCI Controller #1 */
+#define ICH9_USB_UHCI1_DEV 29
+#define ICH9_USB_UHCI1_FUNC 0
+
+/* D30:F0 DMI-to-PCI bridge */
+#define ICH9_D2P_BRIDGE "ICH9 D2P BRIDGE"
+#define ICH9_D2P_BRIDGE_SAVEVM_VERSION 0
+
+#define ICH9_D2P_BRIDGE_DEV 30
+#define ICH9_D2P_BRIDGE_FUNC 0
+
+#define ICH9_D2P_SECONDARY_DEFAULT (256 - 8)
+
+#define ICH9_D2P_A2_REVISION 0x92
+
+/* D31:F0 LPC Processor Interface */
+#define ICH9_RST_CNT_IOPORT 0xCF9
+
+/* D31:F1 LPC controller */
+#define ICH9_A2_LPC "ICH9 A2 LPC"
+#define ICH9_A2_LPC_SAVEVM_VERSION 0
+
+#define ICH9_LPC_DEV 31
+#define ICH9_LPC_FUNC 0
+
+#define ICH9_A2_LPC_REVISION 0x2
+#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_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_9 0x0
+#define ICH9_LPC_ACPI_CTRL_10 0x1
+#define ICH9_LPC_ACPI_CTRL_11 0x2
+#define ICH9_LPC_ACPI_CTRL_20 0x4
+#define ICH9_LPC_ACPI_CTRL_21 0x5
+#define ICH9_LPC_ACPI_CTRL_DEFAULT 0x0
+
+#define ICH9_LPC_PIRQA_ROUT 0x60
+#define ICH9_LPC_PIRQB_ROUT 0x61
+#define ICH9_LPC_PIRQC_ROUT 0x62
+#define ICH9_LPC_PIRQD_ROUT 0x63
+
+#define ICH9_LPC_PIRQE_ROUT 0x68
+#define ICH9_LPC_PIRQF_ROUT 0x69
+#define ICH9_LPC_PIRQG_ROUT 0x6a
+#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_DEFAULT 0x80
+
+#define ICH9_LPC_GEN_PMCON_1 0xa0
+#define ICH9_LPC_GEN_PMCON_1_SMI_LOCK (1 << 4)
+#define ICH9_LPC_GEN_PMCON_2 0xa2
+#define ICH9_LPC_GEN_PMCON_3 0xa4
+#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_EN 0x1
+#define ICH9_LPC_RCBA_DEFAULT 0x0
+
+#define ICH9_LPC_PIC_NUM_PINS 16
+#define ICH9_LPC_IOAPIC_NUM_PINS 24
+
+#define ICH9_GPIO_GSI "gsi"
+
+/* D31:F2 SATA Controller #1 */
+#define ICH9_SATA1_DEV 31
+#define ICH9_SATA1_FUNC 2
+
+/* D31:F0 power management I/O registers
+ offset from the address ICH9_LPC_PMBASE */
+
+/* ICH9 LPC PM I/O registers are 128 ports and 128-aligned */
+#define ICH9_PMIO_SIZE 128
+#define ICH9_PMIO_MASK (ICH9_PMIO_SIZE - 1)
+
+#define ICH9_PMIO_PM1_STS 0x00
+#define ICH9_PMIO_PM1_EN 0x02
+#define ICH9_PMIO_PM1_CNT 0x04
+#define ICH9_PMIO_PM1_TMR 0x08
+#define ICH9_PMIO_GPE0_STS 0x20
+#define ICH9_PMIO_GPE0_EN 0x28
+#define ICH9_PMIO_GPE0_LEN 16
+#define ICH9_PMIO_SMI_EN 0x30
+#define ICH9_PMIO_SMI_EN_APMC_EN (1 << 5)
+#define ICH9_PMIO_SMI_EN_TCO_EN (1 << 13)
+#define ICH9_PMIO_SMI_STS 0x34
+#define ICH9_PMIO_TCO_RLD 0x60
+#define ICH9_PMIO_TCO_LEN 32
+
+/* FADT ACPI_ENABLE/ACPI_DISABLE */
+#define ICH9_APM_ACPI_ENABLE 0x2
+#define ICH9_APM_ACPI_DISABLE 0x3
+
+
+/* D31:F3 SMBus controller */
+#define TYPE_ICH9_SMB_DEVICE "ICH9-SMB"
+
+#define ICH9_A2_SMB_REVISION 0x02
+#define ICH9_SMB_PI 0x00
+
+#define ICH9_SMB_SMBMBAR0 0x10
+#define ICH9_SMB_SMBMBAR1 0x14
+#define ICH9_SMB_SMBM_BAR 0
+#define ICH9_SMB_SMBM_SIZE (1 << 8)
+#define ICH9_SMB_SMB_BASE 0x20
+#define ICH9_SMB_SMB_BASE_BAR 4
+#define ICH9_SMB_SMB_BASE_SIZE (1 << 5)
+#define ICH9_SMB_HOSTC 0x40
+#define ICH9_SMB_HOSTC_SSRESET ((uint8_t)(1 << 3))
+#define ICH9_SMB_HOSTC_I2C_EN ((uint8_t)(1 << 2))
+#define ICH9_SMB_HOSTC_SMB_SMI_EN ((uint8_t)(1 << 1))
+#define ICH9_SMB_HOSTC_HST_EN ((uint8_t)(1 << 0))
+
+/* D31:F3 SMBus I/O and memory mapped I/O registers */
+#define ICH9_SMB_DEV 31
+#define ICH9_SMB_FUNC 3
+
+#define ICH9_SMB_HST_STS 0x00
+#define ICH9_SMB_HST_CNT 0x02
+#define ICH9_SMB_HST_CMD 0x03
+#define ICH9_SMB_XMIT_SLVA 0x04
+#define ICH9_SMB_HST_D0 0x05
+#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 */
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
new file mode 100644
index 000000000..41783ee46
--- /dev/null
+++ b/include/hw/i386/intel_iommu.h
@@ -0,0 +1,282 @@
+/*
+ * QEMU emulation of an Intel IOMMU (VT-d)
+ * (DMA Remapping device)
+ *
+ * Copyright (C) 2013 Knut Omang, Oracle <knut.omang@oracle.com>
+ * Copyright (C) 2014 Le Tan, <tamlokveer@gmail.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 INTEL_IOMMU_H
+#define INTEL_IOMMU_H
+
+#include "hw/i386/x86-iommu.h"
+#include "qemu/iova-tree.h"
+#include "qom/object.h"
+
+#define TYPE_INTEL_IOMMU_DEVICE "intel-iommu"
+OBJECT_DECLARE_SIMPLE_TYPE(IntelIOMMUState, INTEL_IOMMU_DEVICE)
+
+#define TYPE_INTEL_IOMMU_MEMORY_REGION "intel-iommu-iommu-memory-region"
+
+/* DMAR Hardware Unit Definition address (IOMMU unit) */
+#define Q35_HOST_BRIDGE_IOMMU_ADDR 0xfed90000ULL
+
+#define VTD_PCI_BUS_MAX 256
+#define VTD_PCI_SLOT_MAX 32
+#define VTD_PCI_FUNC_MAX 8
+#define VTD_PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
+#define VTD_PCI_FUNC(devfn) ((devfn) & 0x07)
+#define VTD_SID_TO_BUS(sid) (((sid) >> 8) & 0xff)
+#define VTD_SID_TO_DEVFN(sid) ((sid) & 0xff)
+
+#define DMAR_REG_SIZE 0x230
+#define VTD_HOST_AW_39BIT 39
+#define VTD_HOST_AW_48BIT 48
+#define VTD_HOST_ADDRESS_WIDTH VTD_HOST_AW_39BIT
+#define VTD_HAW_MASK(aw) ((1ULL << (aw)) - 1)
+
+#define DMAR_REPORT_F_INTR (1)
+
+#define VTD_MSI_ADDR_HI_MASK (0xffffffff00000000ULL)
+#define VTD_MSI_ADDR_HI_SHIFT (32)
+#define VTD_MSI_ADDR_LO_MASK (0x00000000ffffffffULL)
+
+typedef struct VTDContextEntry VTDContextEntry;
+typedef struct VTDContextCacheEntry VTDContextCacheEntry;
+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;
+typedef struct VTDPASIDEntry VTDPASIDEntry;
+
+/* Context-Entry */
+struct VTDContextEntry {
+ union {
+ struct {
+ uint64_t lo;
+ uint64_t hi;
+ };
+ struct {
+ uint64_t val[4];
+ };
+ };
+};
+
+struct VTDContextCacheEntry {
+ /* The cache entry is obsolete if
+ * context_cache_gen!=IntelIOMMUState.context_cache_gen
+ */
+ uint32_t context_cache_gen;
+ struct VTDContextEntry context_entry;
+};
+
+/* PASID Directory Entry */
+struct VTDPASIDDirEntry {
+ uint64_t val;
+};
+
+/* PASID Table Entry */
+struct VTDPASIDEntry {
+ uint64_t val[8];
+};
+
+struct VTDAddressSpace {
+ PCIBus *bus;
+ uint8_t devfn;
+ 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 */
+ 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[];
+};
+
+struct VTDIOTLBEntry {
+ uint64_t gfn;
+ uint16_t domain_id;
+ uint64_t slpte;
+ uint64_t mask;
+ uint8_t access_flags;
+};
+
+/* VT-d Source-ID Qualifier types */
+enum {
+ VTD_SQ_FULL = 0x00, /* Full SID verification */
+ VTD_SQ_IGN_3 = 0x01, /* Ignore bit 3 */
+ VTD_SQ_IGN_2_3 = 0x02, /* Ignore bits 2 & 3 */
+ VTD_SQ_IGN_1_3 = 0x03, /* Ignore bits 1-3 */
+ VTD_SQ_MAX,
+};
+
+/* VT-d Source Validation Types */
+enum {
+ VTD_SVT_NONE = 0x00, /* No validation */
+ VTD_SVT_ALL = 0x01, /* Do full validation */
+ VTD_SVT_BUS = 0x02, /* Validate bus range */
+ VTD_SVT_MAX,
+};
+
+/* 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 */
+#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 */
+#endif
+ uint32_t dest_id; /* Destination ID */
+ uint16_t source_id; /* Source-ID */
+#ifdef HOST_WORDS_BIGENDIAN
+ uint64_t __reserved_2:44; /* Reserved 2 */
+ uint64_t sid_vtype:2; /* Source-ID Validation Type */
+ uint64_t sid_q:2; /* Source-ID Qualifier */
+#else
+ uint64_t sid_q:2; /* Source-ID Qualifier */
+ uint64_t sid_vtype:2; /* Source-ID Validation Type */
+ uint64_t __reserved_2:44; /* Reserved 2 */
+#endif
+ } QEMU_PACKED irte;
+ uint64_t data[2];
+};
+
+#define VTD_IR_INT_FORMAT_COMPAT (0) /* Compatible Interrupt */
+#define VTD_IR_INT_FORMAT_REMAP (1) /* Remappable Interrupt */
+
+/* Programming format for MSI/MSI-X addresses */
+union VTD_IR_MSIAddress {
+ struct {
+#ifdef HOST_WORDS_BIGENDIAN
+ 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 */
+ uint32_t sub_valid:1; /* SHV: Sub-Handle Valid bit */
+ uint32_t index_h:1; /* Interrupt index bit 15 */
+ uint32_t __not_care:2;
+#else
+ uint32_t __not_care:2;
+ uint32_t index_h:1; /* Interrupt index bit 15 */
+ uint32_t sub_valid:1; /* SHV: Sub-Handle Valid bit */
+ uint32_t int_mode:1; /* Interrupt format */
+ uint32_t index_l:15; /* Interrupt index bit 14-0 */
+ uint32_t __head:12; /* Should always be: 0x0fee */
+#endif
+ } QEMU_PACKED addr;
+ uint32_t data;
+};
+
+/* When IR is enabled, all MSI/MSI-X data bits should be zero */
+#define VTD_IR_MSI_DATA (0)
+
+/* The iommu (DMAR) device state struct */
+struct IntelIOMMUState {
+ X86IOMMUState x86_iommu;
+ MemoryRegion csrmem;
+ MemoryRegion mr_nodmar;
+ MemoryRegion mr_ir;
+ MemoryRegion mr_sys_alias;
+ uint8_t csr[DMAR_REG_SIZE]; /* register values */
+ uint8_t wmask[DMAR_REG_SIZE]; /* R/W bytes */
+ uint8_t w1cmask[DMAR_REG_SIZE]; /* RW1C(Write 1 to Clear) bytes */
+ uint8_t womask[DMAR_REG_SIZE]; /* WO (write only - read returns 0) */
+ uint32_t version;
+
+ bool caching_mode; /* RO - is cap CM enabled? */
+ bool scalable_mode; /* RO - is Scalable Mode supported? */
+
+ dma_addr_t root; /* Current root table pointer */
+ bool root_scalable; /* Type of root table (scalable or not) */
+ bool dmar_enabled; /* Set if DMA remapping is enabled */
+
+ uint16_t iq_head; /* Current invalidation queue head */
+ uint16_t iq_tail; /* Current invalidation queue tail */
+ dma_addr_t iq; /* Current invalidation queue pointer */
+ uint16_t iq_size; /* IQ Size in number of entries */
+ bool iq_dw; /* IQ descriptor width 256bit or not */
+ bool qi_enabled; /* Set if the QI is enabled */
+ uint8_t iq_last_desc_type; /* The type of last completed descriptor */
+
+ /* The index of the Fault Recording Register to be used next.
+ * Wraps around from N-1 to 0, where N is the number of FRCD_REG.
+ */
+ uint16_t next_frcd_reg;
+
+ uint64_t cap; /* The value of capability reg */
+ uint64_t ecap; /* The value of extended capability reg */
+
+ 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 */
+ /* list of registered notifiers */
+ QLIST_HEAD(, VTDAddressSpace) vtd_as_with_notifiers;
+
+ /* interrupt remapping */
+ bool intr_enabled; /* Whether guest enabled IR */
+ dma_addr_t intr_root; /* Interrupt remapping table pointer */
+ uint32_t intr_size; /* Number of IR table entries */
+ bool intr_eime; /* Extended interrupt mode enabled */
+ OnOffAuto intr_eim; /* Toggle for EIM cabability */
+ 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 */
+
+ /*
+ * Protects IOMMU states in general. Currently it protects the
+ * per-IOMMU IOTLB cache, and context entry cache in VTDAddressSpace.
+ */
+ QemuMutex iommu_lock;
+};
+
+/* 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);
+
+#endif
diff --git a/include/hw/i386/ioapic.h b/include/hw/i386/ioapic.h
new file mode 100644
index 000000000..ef37b8a9f
--- /dev/null
+++ b/include/hw/i386/ioapic.h
@@ -0,0 +1,33 @@
+/*
+ * ioapic.c IOAPIC emulation logic
+ *
+ * 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.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 HW_IOAPIC_H
+#define HW_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 */
diff --git a/include/hw/i386/ioapic_internal.h b/include/hw/i386/ioapic_internal.h
new file mode 100644
index 000000000..021e715f1
--- /dev/null
+++ b/include/hw/i386/ioapic_internal.h
@@ -0,0 +1,118 @@
+/*
+ * 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.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 QEMU_IOAPIC_INTERNAL_H
+#define QEMU_IOAPIC_INTERNAL_H
+
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+#include "qemu/notify.h"
+#include "qom/object.h"
+
+#define MAX_IOAPICS 2
+
+#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
+
+
+#define TYPE_IOAPIC_COMMON "ioapic-common"
+OBJECT_DECLARE_TYPE(IOAPICCommonState, IOAPICCommonClass, IOAPIC_COMMON)
+
+struct IOAPICCommonClass {
+ SysBusDeviceClass parent_class;
+
+ DeviceRealize realize;
+ DeviceUnrealize unrealize;
+ void (*pre_save)(IOAPICCommonState *s);
+ void (*post_load)(IOAPICCommonState *s);
+};
+
+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
new file mode 100644
index 000000000..4d9c732d4
--- /dev/null
+++ b/include/hw/i386/microvm.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ * Copyright (c) 2019 Red Hat, 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_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_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"
+
+struct MicrovmMachineClass {
+ X86MachineClass parent;
+ HotplugHandler *(*orig_hotplug_handler)(MachineState *machine,
+ DeviceState *dev);
+};
+
+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;
+ 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")
+OBJECT_DECLARE_TYPE(MicrovmMachineState, MicrovmMachineClass, MICROVM_MACHINE)
+
+#endif
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
new file mode 100644
index 000000000..9ab39e428
--- /dev/null
+++ b/include/hw/i386/pc.h
@@ -0,0 +1,307 @@
+#ifndef HW_PC_H
+#define HW_PC_H
+
+#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"
+
+#define HPET_INTCAP "hpet-intcap"
+
+/**
+ * PCMachineState:
+ * @acpi_dev: link to ACPI PM device that performs ACPI hotplug handling
+ * @boot_cpus: number of present VCPUs
+ */
+typedef struct PCMachineState {
+ /*< private >*/
+ X86MachineState parent_obj;
+
+ /* <public> */
+
+ /* State for other subsystems/APIs: */
+ Notifier machine_done;
+
+ /* Pointers to devices and objects: */
+ PCIBus *bus;
+ I2CBus *smbus;
+ PFlashCFI01 *flash[2];
+ ISADevice *pcspk;
+ DeviceState *iommu;
+
+ /* Configuration options: */
+ uint64_t max_ram_below_4g;
+ OnOffAuto vmport;
+
+ bool acpi_build_enabled;
+ bool smbus_enabled;
+ bool sata_enabled;
+ bool pit_enabled;
+ bool hpet_enabled;
+ bool default_bus_bypass_iommu;
+ uint64_t max_fw_size;
+
+ /* ACPI Memory hotplug IO base address */
+ hwaddr memhp_io_base;
+
+ SGXEPCState sgx_epc;
+} 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_MAX_FW_SIZE "max-fw-size"
+/**
+ * PCMachineClass:
+ *
+ * Compat fields:
+ *
+ * @enforce_aligned_dimm: check that DIMM's address/size is aligned by
+ * backend's alignment value if provided
+ * @acpi_data_size: Size of the chunk of memory at the top of RAM
+ * for the BIOS ACPI tables and other BIOS
+ * datastructures.
+ * @gigabyte_align: Make sure that guest addresses aligned at
+ * 1Gbyte boundaries get mapped to host
+ * addresses aligned at 1Gbyte boundaries. This
+ * way we can use 1GByte pages in the host.
+ *
+ */
+struct PCMachineClass {
+ /*< private >*/
+ X86MachineClass parent_class;
+
+ /*< public >*/
+
+ /* Device configuration: */
+ bool pci_enabled;
+ bool kvmclock_enabled;
+ const char *default_nic_model;
+
+ /* Compat options: */
+
+ /* Default CPU model version. See x86_cpu_set_default_version(). */
+ int default_cpu_version;
+
+ /* ACPI compat: */
+ bool has_acpi_build;
+ 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;
+
+ /* RAM / address space compat: */
+ bool gigabyte_align;
+ bool has_reserved_memory;
+ bool enforce_aligned_dimm;
+ bool broken_reserved_end;
+
+ /* generate legacy CPU hotplug AML */
+ bool legacy_cpu_hotplug;
+
+ /* use PVH to load kernels that support this feature */
+ bool pvh_enabled;
+
+ /* create kvmclock device even when KVM PV features are not exposed */
+ bool kvmclock_create_always;
+};
+
+#define TYPE_PC_MACHINE "generic-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_guest_info_init(PCMachineState *pcms);
+
+#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"
+#define PCI_HOST_PROP_PCI_HOLE64_END "pci-hole64-end"
+#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"
+
+
+void pc_pci_as_mapping_init(Object *owner, 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 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,
+ 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"
+
+#define TYPE_PORT92 "port92"
+
+/* pc_sysfw.c */
+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);
+
+/* hw/i386/acpi-common.c */
+void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
+ const CPUArchIdList *apic_ids, GArray *entry,
+ bool force_enabled);
+
+/* sgx.c */
+void pc_machine_init_sgx_epc(PCMachineState *pcms);
+
+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;
+
+extern GlobalProperty pc_compat_4_2[];
+extern const size_t pc_compat_4_2_len;
+
+extern GlobalProperty pc_compat_4_1[];
+extern const size_t pc_compat_4_1_len;
+
+extern GlobalProperty pc_compat_4_0[];
+extern const size_t pc_compat_4_0_len;
+
+extern GlobalProperty pc_compat_3_1[];
+extern const size_t pc_compat_3_1_len;
+
+extern GlobalProperty pc_compat_3_0[];
+extern const size_t pc_compat_3_0_len;
+
+extern GlobalProperty pc_compat_2_12[];
+extern const size_t pc_compat_2_12_len;
+
+extern GlobalProperty pc_compat_2_11[];
+extern const size_t pc_compat_2_11_len;
+
+extern GlobalProperty pc_compat_2_10[];
+extern const size_t pc_compat_2_10_len;
+
+extern GlobalProperty pc_compat_2_9[];
+extern const size_t pc_compat_2_9_len;
+
+extern GlobalProperty pc_compat_2_8[];
+extern const size_t pc_compat_2_8_len;
+
+extern GlobalProperty pc_compat_2_7[];
+extern const size_t pc_compat_2_7_len;
+
+extern GlobalProperty pc_compat_2_6[];
+extern const size_t pc_compat_2_6_len;
+
+extern GlobalProperty pc_compat_2_5[];
+extern const size_t pc_compat_2_5_len;
+
+extern GlobalProperty pc_compat_2_4[];
+extern const size_t pc_compat_2_4_len;
+
+extern GlobalProperty pc_compat_2_3[];
+extern const size_t pc_compat_2_3_len;
+
+extern GlobalProperty pc_compat_2_2[];
+extern const size_t pc_compat_2_2_len;
+
+extern GlobalProperty pc_compat_2_1[];
+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) \
+ { \
+ MachineClass *mc = MACHINE_CLASS(oc); \
+ optsfn(mc); \
+ mc->init = initfn; \
+ } \
+ static const TypeInfo pc_machine_type_##suffix = { \
+ .name = namestr TYPE_MACHINE_SUFFIX, \
+ .parent = TYPE_PC_MACHINE, \
+ .class_init = pc_machine_##suffix##_class_init, \
+ }; \
+ static void pc_machine_init_##suffix(void) \
+ { \
+ type_register(&pc_machine_type_##suffix); \
+ } \
+ 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 000000000..a6a65be85
--- /dev/null
+++ b/include/hw/i386/sgx-epc.h
@@ -0,0 +1,67 @@
+/*
+ * 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/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"
+
+/**
+ * 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;
+ 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);
+
+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
new file mode 100644
index 000000000..81573f6cf
--- /dev/null
+++ b/include/hw/i386/topology.h
@@ -0,0 +1,170 @@
+/*
+ * x86 CPU topology data structures and functions
+ *
+ * Copyright (c) 2012 Red Hat 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 HW_I386_TOPOLOGY_H
+#define HW_I386_TOPOLOGY_H
+
+/* 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
+ * as long as:
+ * nr_threads is set to 1;
+ * OFFSET_IDX is assumed to be 0;
+ * CPUID Fn8000_0008_ECX[ApicIdCoreIdSize[3:0]] is set to apicid_core_width().
+ */
+
+
+#include "qemu/bitops.h"
+
+/* 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 die_id;
+ unsigned core_id;
+ unsigned smt_id;
+} X86CPUTopoIDs;
+
+typedef struct X86CPUTopoInfo {
+ unsigned dies_per_pkg;
+ unsigned cores_per_die;
+ unsigned threads_per_core;
+} X86CPUTopoInfo;
+
+/* Return the bit width needed for 'count' IDs
+ */
+static unsigned apicid_bitwidth_for_count(unsigned count)
+{
+ g_assert(count >= 1);
+ count -= 1;
+ return count ? 32 - clz32(count) : 0;
+}
+
+/* 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
+ */
+static inline unsigned apicid_core_width(X86CPUTopoInfo *topo_info)
+{
+ return apicid_bitwidth_for_count(topo_info->cores_per_die);
+}
+
+/* Bit width of the Die_ID field */
+static inline unsigned apicid_die_width(X86CPUTopoInfo *topo_info)
+{
+ return apicid_bitwidth_for_count(topo_info->dies_per_pkg);
+}
+
+/* Bit offset of the Core_ID field
+ */
+static inline unsigned apicid_core_offset(X86CPUTopoInfo *topo_info)
+{
+ return apicid_smt_width(topo_info);
+}
+
+/* Bit offset of the Die_ID field */
+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
+ */
+static inline unsigned apicid_pkg_offset(X86CPUTopoInfo *topo_info)
+{
+ return apicid_die_offset(topo_info) + apicid_die_width(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(X86CPUTopoInfo *topo_info,
+ const X86CPUTopoIDs *topo_ids)
+{
+ return (topo_ids->pkg_id << apicid_pkg_offset(topo_info)) |
+ (topo_ids->die_id << apicid_die_offset(topo_info)) |
+ (topo_ids->core_id << apicid_core_offset(topo_info)) |
+ topo_ids->smt_id;
+}
+
+/* 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,
+ unsigned cpu_index,
+ X86CPUTopoIDs *topo_ids)
+{
+ unsigned nr_dies = topo_info->dies_per_pkg;
+ unsigned nr_cores = topo_info->cores_per_die;
+ unsigned nr_threads = topo_info->threads_per_core;
+
+ topo_ids->pkg_id = cpu_index / (nr_dies * nr_cores * nr_threads);
+ 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(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->pkg_id = apicid >> apicid_pkg_offset(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(X86CPUTopoInfo *topo_info,
+ unsigned cpu_index)
+{
+ X86CPUTopoIDs topo_ids;
+ x86_topo_ids_from_idx(topo_info, cpu_index, &topo_ids);
+ return x86_apicid_from_topo_ids(topo_info, &topo_ids);
+}
+
+#endif /* HW_I386_TOPOLOGY_H */
diff --git a/include/hw/i386/vmport.h b/include/hw/i386/vmport.h
new file mode 100644
index 000000000..8f5e27c6f
--- /dev/null
+++ b/include/hw/i386/vmport.h
@@ -0,0 +1,28 @@
+#ifndef HW_VMPORT_H
+#define HW_VMPORT_H
+
+#include "hw/isa/isa.h"
+
+#define TYPE_VMPORT "vmport"
+typedef uint32_t VMPortReadFunc(void *opaque, uint32_t address);
+
+typedef enum {
+ VMPORT_CMD_GETVERSION = 10,
+ VMPORT_CMD_GETBIOSUUID = 19,
+ VMPORT_CMD_GETRAMSIZE = 20,
+ VMPORT_CMD_VMMOUSE_DATA = 39,
+ VMPORT_CMD_VMMOUSE_STATUS = 40,
+ VMPORT_CMD_VMMOUSE_COMMAND = 41,
+ VMPORT_CMD_GETHZ = 45,
+ VMPORT_CMD_GET_VCPU_INFO = 68,
+ VMPORT_ENTRIES
+} VMPortCommand;
+
+static inline void vmport_init(ISABus *bus)
+{
+ isa_create_simple(bus, TYPE_VMPORT);
+}
+
+void vmport_register(VMPortCommand command, VMPortReadFunc *func, void *opaque);
+
+#endif
diff --git a/include/hw/i386/x86-iommu.h b/include/hw/i386/x86-iommu.h
new file mode 100644
index 000000000..5ba0c056d
--- /dev/null
+++ b/include/hw/i386/x86-iommu.h
@@ -0,0 +1,163 @@
+/*
+ * Common IOMMU interface for X86 platform
+ *
+ * Copyright (C) 2016 Peter Xu, Red Hat <peterx@redhat.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_I386_X86_IOMMU_H
+#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")
+OBJECT_DECLARE_TYPE(X86IOMMUState, X86IOMMUClass, X86_IOMMU_DEVICE)
+
+#define X86_IOMMU_SID_INVALID (0xffff)
+
+typedef struct X86IOMMUIrq X86IOMMUIrq;
+typedef struct X86IOMMU_MSIMessage X86IOMMU_MSIMessage;
+
+struct X86IOMMUClass {
+ SysBusDeviceClass parent;
+ /* Intel/AMD specific realize() hook */
+ DeviceRealize realize;
+ /* MSI-based interrupt remapping */
+ int (*int_remap)(X86IOMMUState *iommu, MSIMessage *src,
+ MSIMessage *dst, uint16_t sid);
+};
+
+/**
+ * iec_notify_fn - IEC (Interrupt Entry Cache) notifier hook,
+ * triggered when IR invalidation happens.
+ * @private: private data
+ * @global: whether this is a global IEC invalidation
+ * @index: IRTE index to invalidate (start from)
+ * @mask: invalidation mask
+ */
+typedef void (*iec_notify_fn)(void *private, bool global,
+ uint32_t index, uint32_t mask);
+
+struct IEC_Notifier {
+ iec_notify_fn iec_notify;
+ void *private;
+ QLIST_ENTRY(IEC_Notifier) list;
+};
+typedef struct IEC_Notifier IEC_Notifier;
+
+struct X86IOMMUState {
+ SysBusDevice busdev;
+ OnOffAuto intr_supported; /* Whether vIOMMU supports IR */
+ bool dt_supported; /* Whether vIOMMU supports DT */
+ bool pt_supported; /* Whether vIOMMU supports pass-through */
+ QLIST_HEAD(, IEC_Notifier) iec_notifiers; /* IEC notify list */
+};
+
+bool x86_iommu_ir_supported(X86IOMMUState *s);
+
+/* Generic IRQ entry information when interrupt remapping is enabled */
+struct X86IOMMUIrq {
+ /* Used by both IOAPIC/MSI interrupt remapping */
+ uint8_t trigger_mode;
+ uint8_t vector;
+ uint8_t delivery_mode;
+ uint32_t dest;
+ uint8_t dest_mode;
+
+ /* only used by MSI interrupt remapping */
+ uint8_t redir_hint;
+ uint8_t msi_addr_last_bits;
+};
+
+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;
+#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 */
+#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;
+#else
+ uint16_t vector:8;
+ uint16_t delivery_mode:3;
+ uint16_t __resved:3;
+ uint16_t level:1;
+ uint16_t trigger_mode:1;
+#endif
+ uint16_t __resved1;
+ } QEMU_PACKED;
+ uint32_t msi_data;
+ };
+};
+
+/**
+ * x86_iommu_get_default - get default IOMMU device
+ * @return: pointer to default IOMMU device
+ */
+X86IOMMUState *x86_iommu_get_default(void);
+
+/**
+ * x86_iommu_iec_register_notifier - register IEC (Interrupt Entry
+ * Cache) notifiers
+ * @iommu: IOMMU device to register
+ * @fn: IEC notifier hook function
+ * @data: notifier private data
+ */
+void x86_iommu_iec_register_notifier(X86IOMMUState *iommu,
+ iec_notify_fn fn, void *data);
+
+/**
+ * x86_iommu_iec_notify_all - Notify IEC invalidations
+ * @iommu: IOMMU device that sends the notification
+ * @global: whether this is a global invalidation. If true, @index
+ * and @mask are undefined.
+ * @index: starting index of interrupt entry to invalidate
+ * @mask: index mask for the invalidation
+ */
+void x86_iommu_iec_notify_all(X86IOMMUState *iommu, bool global,
+ uint32_t index, uint32_t mask);
+
+/**
+ * x86_iommu_irq_to_msi_message - Populate one MSIMessage from X86IOMMUIrq
+ * @X86IOMMUIrq: The IRQ information
+ * @out: Output MSI message
+ */
+void x86_iommu_irq_to_msi_message(X86IOMMUIrq *irq, MSIMessage *out);
+#endif
diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
new file mode 100644
index 000000000..bb1cfb889
--- /dev/null
+++ b/include/hw/i386/x86.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2019 Red Hat, 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_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/isa/isa.h"
+#include "hw/i386/ioapic.h"
+#include "qom/object.h"
+
+struct X86MachineClass {
+ /*< private >*/
+ MachineClass parent;
+
+ /*< public >*/
+
+ /* TSC rate migration: */
+ bool save_tsc_khz;
+ /* Enables contiguous-apic-ID mode */
+ bool compat_apic_id_mode;
+ /* use DMA capable linuxboot option rom */
+ bool fwcfg_dma_enabled;
+};
+
+struct X86MachineState {
+ /*< private >*/
+ MachineState parent;
+
+ /*< public >*/
+
+ /* Pointers to devices and objects: */
+ 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;
+
+ /* CPU and apic information: */
+ bool apic_xrupt_override;
+ unsigned pci_irq_mask;
+ unsigned apic_id_limit;
+ uint16_t boot_cpus;
+ SgxEPCList *sgx_epc_list;
+
+ OnOffAuto smm;
+ OnOffAuto acpi;
+
+ 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;
+
+ /*
+ * 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_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")
+OBJECT_DECLARE_TYPE(X86MachineState, X86MachineClass, X86_MACHINE)
+
+void init_topo_info(X86CPUTopoInfo *topo_info, const X86MachineState *x86ms);
+
+uint32_t x86_cpu_apic_id_from_index(X86MachineState *pcms,
+ unsigned int cpu_index);
+
+void x86_cpu_new(X86MachineState *pcms, int64_t apic_id, Error **errp);
+void x86_cpus_init(X86MachineState *pcms, int default_cpu_version);
+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);
+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 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);
+DeviceState *ioapic_init_secondary(GSIState *gsi_state);
+
+#endif
diff --git a/include/hw/ide.h b/include/hw/ide.h
new file mode 100644
index 000000000..c5ce5da4f
--- /dev/null
+++ b/include/hw/ide.h
@@ -0,0 +1,24 @@
+#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.h b/include/hw/ide/ahci.h
new file mode 100644
index 000000000..210e5e734
--- /dev/null
+++ b/include/hw/ide/ahci.h
@@ -0,0 +1,88 @@
+/*
+ * QEMU AHCI Emulation
+ *
+ * Copyright (c) 2010 qiaochong@loongson.cn
+ * Copyright (c) 2010 Roland Elek <elek.roland@gmail.com>
+ * Copyright (c) 2010 Sebastian Herbszt <herbszt@gmx.de>
+ * Copyright (c) 2010 Alexander Graf <agraf@suse.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.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 HW_IDE_AHCI_H
+#define HW_IDE_AHCI_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+typedef struct AHCIDevice AHCIDevice;
+
+typedef struct AHCIControlRegs {
+ uint32_t cap;
+ uint32_t ghc;
+ uint32_t irqstatus;
+ uint32_t impl;
+ uint32_t version;
+} AHCIControlRegs;
+
+typedef struct AHCIState {
+ DeviceState *container;
+
+ AHCIDevice *dev;
+ AHCIControlRegs control_regs;
+ MemoryRegion mem;
+ 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;
+ qemu_irq irq;
+ AddressSpace *as;
+} AHCIState;
+
+
+#define TYPE_ICH9_AHCI "ich9-ahci"
+OBJECT_DECLARE_SIMPLE_TYPE(AHCIPCIState, 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"
+OBJECT_DECLARE_SIMPLE_TYPE(SysbusAHCIState, SYSBUS_AHCI)
+
+struct SysbusAHCIState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ AHCIState ahci;
+ uint32_t num_ports;
+};
+
+#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 {
+ /*< private >*/
+ SysbusAHCIState parent_obj;
+ /*< public >*/
+
+ MemoryRegion mmio;
+ uint32_t regs[ALLWINNER_AHCI_MMIO_SIZE/4];
+};
+
+#endif /* HW_IDE_AHCI_H */
diff --git a/include/hw/ide/internal.h b/include/hw/ide/internal.h
new file mode 100644
index 000000000..97e7e59dc
--- /dev/null
+++ b/include/hw/ide/internal.h
@@ -0,0 +1,657 @@
+#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
+#include "qom/object.h"
+
+typedef struct IDEDevice IDEDevice;
+typedef struct IDEState IDEState;
+typedef struct IDEDMA IDEDMA;
+typedef struct IDEDMAOps IDEDMAOps;
+
+#define TYPE_IDE_BUS "IDE"
+OBJECT_DECLARE_SIMPLE_TYPE(IDEBus, IDE_BUS)
+
+#define MAX_IDE_DEVS 2
+
+/* Device/Head ("select") Register */
+#define ATA_DEV_SELECT 0x10
+/* ATA1,3: Defined as '1'.
+ * ATA2: Reserved.
+ * ATA3-7: obsolete. */
+#define ATA_DEV_ALWAYS_ON 0xA0
+#define ATA_DEV_LBA 0x40
+#define ATA_DEV_LBA_MSB 0x0F /* LBA 24:27 */
+#define ATA_DEV_HS 0x0F /* HS 3:0 */
+
+
+/* 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
+
+/* Bits of Device Control register */
+#define IDE_CTRL_HOB 0x80
+#define IDE_CTRL_RESET 0x04
+#define IDE_CTRL_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"
+OBJECT_DECLARE_TYPE(IDEDevice, IDEDeviceClass, IDE_DEVICE)
+
+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;
+};
+
+/* 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_CTRL_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_ctrl_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);
+int 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_init(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/pci.h b/include/hw/ide/pci.h
new file mode 100644
index 000000000..d8384e1c4
--- /dev/null
+++ b/include/hw/ide/pci.h
@@ -0,0 +1,72 @@
+#ifndef HW_IDE_PCI_H
+#define HW_IDE_PCI_H
+
+#include "hw/ide/internal.h"
+#include "hw/pci/pci.h"
+#include "qom/object.h"
+
+#define BM_STATUS_DMAING 0x01
+#define BM_STATUS_ERROR 0x02
+#define BM_STATUS_INT 0x04
+
+#define BM_CMD_START 0x01
+#define BM_CMD_READ 0x08
+
+typedef struct BMDMAState {
+ IDEDMA dma;
+ uint8_t cmd;
+ uint8_t status;
+ uint32_t addr;
+
+ IDEBus *bus;
+ /* current transfer state */
+ uint32_t cur_addr;
+ uint32_t cur_prd_last;
+ uint32_t cur_prd_addr;
+ uint32_t cur_prd_len;
+ BlockCompletionFunc *dma_cb;
+ MemoryRegion addr_ioport;
+ MemoryRegion extra_io;
+ qemu_irq irq;
+
+ /* Bit 0-2 and 7: BM status register
+ * Bit 3-6: bus->error_status */
+ uint8_t migration_compat_status;
+ uint8_t migration_retry_unit;
+ int64_t migration_retry_sector_num;
+ uint32_t migration_retry_nsector;
+
+ struct PCIIDEState *pci_dev;
+} BMDMAState;
+
+#define TYPE_PCI_IDE "pci-ide"
+OBJECT_DECLARE_SIMPLE_TYPE(PCIIDEState, PCI_IDE)
+
+struct PCIIDEState {
+ /*< private >*/
+ PCIDevice parent_obj;
+ /*< public >*/
+
+ IDEBus bus[2];
+ BMDMAState bmdma[2];
+ uint32_t secondary; /* used only for cmd646 */
+ MemoryRegion bmdma_bar;
+ MemoryRegion cmd_bar[2];
+ MemoryRegion data_bar[2];
+};
+
+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);
+extern MemoryRegionOps bmdma_addr_ioport_ops;
+void pci_ide_create_devs(PCIDevice *dev);
+
+extern const VMStateDescription vmstate_ide_pci;
+extern const MemoryRegionOps pci_ide_cmd_le_ops;
+extern const MemoryRegionOps pci_ide_data_le_ops;
+#endif
diff --git a/include/hw/input/adb-keys.h b/include/hw/input/adb-keys.h
new file mode 100644
index 000000000..525fba8a6
--- /dev/null
+++ b/include/hw/input/adb-keys.h
@@ -0,0 +1,141 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2016 John Arbuckle
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+/*
+ * adb-keys.h
+ *
+ * Provides an enum of all the Macintosh keycodes.
+ * Additional information: http://www.archive.org/stream/apple-guide-macintosh-family-hardware/Apple_Guide_to_the_Macintosh_Family_Hardware_2e#page/n345/mode/2up
+ * page 308
+ */
+
+#ifndef ADB_KEYS_H
+#define ADB_KEYS_H
+
+enum {
+ ADB_KEY_A = 0x00,
+ ADB_KEY_B = 0x0b,
+ ADB_KEY_C = 0x08,
+ ADB_KEY_D = 0x02,
+ ADB_KEY_E = 0x0e,
+ ADB_KEY_F = 0x03,
+ ADB_KEY_G = 0x05,
+ ADB_KEY_H = 0x04,
+ ADB_KEY_I = 0x22,
+ ADB_KEY_J = 0x26,
+ ADB_KEY_K = 0x28,
+ ADB_KEY_L = 0x25,
+ ADB_KEY_M = 0x2e,
+ ADB_KEY_N = 0x2d,
+ ADB_KEY_O = 0x1f,
+ ADB_KEY_P = 0x23,
+ ADB_KEY_Q = 0x0c,
+ ADB_KEY_R = 0x0f,
+ ADB_KEY_S = 0x01,
+ ADB_KEY_T = 0x11,
+ ADB_KEY_U = 0x20,
+ ADB_KEY_V = 0x09,
+ ADB_KEY_W = 0x0d,
+ ADB_KEY_X = 0x07,
+ ADB_KEY_Y = 0x10,
+ ADB_KEY_Z = 0x06,
+
+ ADB_KEY_0 = 0x1d,
+ ADB_KEY_1 = 0x12,
+ ADB_KEY_2 = 0x13,
+ ADB_KEY_3 = 0x14,
+ ADB_KEY_4 = 0x15,
+ ADB_KEY_5 = 0x17,
+ ADB_KEY_6 = 0x16,
+ ADB_KEY_7 = 0x1a,
+ ADB_KEY_8 = 0x1c,
+ ADB_KEY_9 = 0x19,
+
+ ADB_KEY_GRAVE_ACCENT = 0x32,
+ ADB_KEY_MINUS = 0x1b,
+ ADB_KEY_EQUAL = 0x18,
+ ADB_KEY_DELETE = 0x33,
+ ADB_KEY_CAPS_LOCK = 0x39,
+ ADB_KEY_TAB = 0x30,
+ ADB_KEY_RETURN = 0x24,
+ ADB_KEY_LEFT_BRACKET = 0x21,
+ ADB_KEY_RIGHT_BRACKET = 0x1e,
+ ADB_KEY_BACKSLASH = 0x2a,
+ ADB_KEY_SEMICOLON = 0x29,
+ ADB_KEY_APOSTROPHE = 0x27,
+ ADB_KEY_COMMA = 0x2b,
+ ADB_KEY_PERIOD = 0x2f,
+ ADB_KEY_FORWARD_SLASH = 0x2c,
+ ADB_KEY_LEFT_SHIFT = 0x38,
+ ADB_KEY_RIGHT_SHIFT = 0x7b,
+ ADB_KEY_SPACEBAR = 0x31,
+ ADB_KEY_LEFT_CONTROL = 0x36,
+ ADB_KEY_RIGHT_CONTROL = 0x7d,
+ ADB_KEY_LEFT_OPTION = 0x3a,
+ ADB_KEY_RIGHT_OPTION = 0x7c,
+ ADB_KEY_COMMAND = 0x37,
+
+ ADB_KEY_KP_0 = 0x52,
+ ADB_KEY_KP_1 = 0x53,
+ ADB_KEY_KP_2 = 0x54,
+ ADB_KEY_KP_3 = 0x55,
+ ADB_KEY_KP_4 = 0x56,
+ ADB_KEY_KP_5 = 0x57,
+ ADB_KEY_KP_6 = 0x58,
+ ADB_KEY_KP_7 = 0x59,
+ ADB_KEY_KP_8 = 0x5b,
+ ADB_KEY_KP_9 = 0x5c,
+ ADB_KEY_KP_PERIOD = 0x41,
+ ADB_KEY_KP_ENTER = 0x4c,
+ ADB_KEY_KP_PLUS = 0x45,
+ ADB_KEY_KP_SUBTRACT = 0x4e,
+ ADB_KEY_KP_MULTIPLY = 0x43,
+ ADB_KEY_KP_DIVIDE = 0x4b,
+ ADB_KEY_KP_EQUAL = 0x51,
+ ADB_KEY_KP_CLEAR = 0x47,
+
+ ADB_KEY_UP = 0x3e,
+ ADB_KEY_DOWN = 0x3d,
+ ADB_KEY_LEFT = 0x3b,
+ ADB_KEY_RIGHT = 0x3c,
+
+ ADB_KEY_HELP = 0x72,
+ ADB_KEY_HOME = 0x73,
+ ADB_KEY_PAGE_UP = 0x74,
+ ADB_KEY_PAGE_DOWN = 0x79,
+ ADB_KEY_END = 0x77,
+ ADB_KEY_FORWARD_DELETE = 0x75,
+
+ ADB_KEY_ESC = 0x35,
+ ADB_KEY_F1 = 0x7a,
+ ADB_KEY_F2 = 0x78,
+ ADB_KEY_F3 = 0x63,
+ ADB_KEY_F4 = 0x76,
+ ADB_KEY_F5 = 0x60,
+ ADB_KEY_F6 = 0x61,
+ ADB_KEY_F7 = 0x62,
+ ADB_KEY_F8 = 0x64,
+ ADB_KEY_F9 = 0x65,
+ ADB_KEY_F10 = 0x6d,
+ ADB_KEY_F11 = 0x67,
+ ADB_KEY_F12 = 0x6f,
+ ADB_KEY_F13 = 0x69,
+ ADB_KEY_F14 = 0x6b,
+ ADB_KEY_F15 = 0x71,
+
+ ADB_KEY_VOLUME_UP = 0x48,
+ ADB_KEY_VOLUME_DOWN = 0x49,
+ ADB_KEY_VOLUME_MUTE = 0x4a,
+ ADB_KEY_POWER = 0x7f7f
+};
+
+/* Could not find the value for this key. */
+/* #define ADB_KEY_EJECT */
+
+#endif /* ADB_KEYS_H */
diff --git a/include/hw/input/adb.h b/include/hw/input/adb.h
new file mode 100644
index 000000000..20fced15f
--- /dev/null
+++ b/include/hw/input/adb.h
@@ -0,0 +1,108 @@
+/*
+ * QEMU ADB emulation shared definitions and prototypes
+ *
+ * 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 ADB_H
+#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 ADBDevice ADBDevice;
+
+/* buf = NULL means polling */
+typedef int ADBDeviceRequest(ADBDevice *d, uint8_t *buf_out,
+ const uint8_t *buf, int len);
+
+typedef bool ADBDeviceHasData(ADBDevice *d);
+
+#define TYPE_ADB_DEVICE "adb-device"
+OBJECT_DECLARE_TYPE(ADBDevice, ADBDeviceClass, ADB_DEVICE)
+
+struct ADBDevice {
+ /*< private >*/
+ DeviceState parent_obj;
+ /*< public >*/
+
+ int devaddr;
+ int handler;
+};
+
+
+struct ADBDeviceClass {
+ /*< private >*/
+ DeviceClass parent_class;
+ /*< public >*/
+
+ ADBDeviceRequest *devreq;
+ ADBDeviceHasData *devhasdata;
+};
+
+#define TYPE_ADB_BUS "apple-desktop-bus"
+OBJECT_DECLARE_SIMPLE_TYPE(ADBBusState, ADB_BUS)
+
+#define ADB_STATUS_BUSTIMEOUT 0x1
+#define ADB_STATUS_POLLREPLY 0x2
+
+struct ADBBusState {
+ /*< private >*/
+ BusState parent_obj;
+ /*< public >*/
+
+ ADBDevice *devices[MAX_ADB_DEVICES];
+ uint16_t pending;
+ int nb_devices;
+ int poll_index;
+ uint8_t status;
+
+ QEMUTimer *autopoll_timer;
+ bool autopoll_enabled;
+ bool autopoll_blocked;
+ uint8_t autopoll_rate_ms;
+ uint16_t autopoll_mask;
+ void (*autopoll_cb)(void *opaque);
+ void *autopoll_cb_opaque;
+};
+
+int adb_request(ADBBusState *s, uint8_t *buf_out,
+ const uint8_t *buf, int len);
+int adb_poll(ADBBusState *s, uint8_t *buf_out, uint16_t poll_mask);
+
+void adb_autopoll_block(ADBBusState *s);
+void adb_autopoll_unblock(ADBBusState *s);
+
+void adb_set_autopoll_enabled(ADBBusState *s, bool enabled);
+void adb_set_autopoll_rate_ms(ADBBusState *s, int rate_ms);
+void adb_set_autopoll_mask(ADBBusState *s, uint16_t mask);
+void adb_register_autopoll_callback(ADBBusState *s, void (*cb)(void *opaque),
+ void *opaque);
+
+#define TYPE_ADB_KEYBOARD "adb-keyboard"
+#define TYPE_ADB_MOUSE "adb-mouse"
+
+#endif /* ADB_H */
diff --git a/include/hw/input/gamepad.h b/include/hw/input/gamepad.h
new file mode 100644
index 000000000..6f6aa2406
--- /dev/null
+++ b/include/hw/input/gamepad.h
@@ -0,0 +1,18 @@
+/*
+ * 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/hid.h b/include/hw/input/hid.h
new file mode 100644
index 000000000..6a9d7bf46
--- /dev/null
+++ b/include/hw/input/hid.h
@@ -0,0 +1,83 @@
+#ifndef QEMU_HID_H
+#define QEMU_HID_H
+
+#include "ui/input.h"
+
+#define HID_MOUSE 1
+#define HID_TABLET 2
+#define HID_KEYBOARD 3
+
+typedef struct HIDPointerEvent {
+ int32_t xdx, ydy; /* relative iff it's a mouse, otherwise absolute */
+ int32_t dz, buttons_state;
+} HIDPointerEvent;
+
+#define QUEUE_LENGTH 16 /* should be enough for a triple-click */
+#define QUEUE_MASK (QUEUE_LENGTH-1u)
+#define QUEUE_INCR(v) ((v)++, (v) &= QUEUE_MASK)
+
+typedef struct HIDState HIDState;
+typedef void (*HIDEventFunc)(HIDState *s);
+
+typedef struct HIDMouseState {
+ HIDPointerEvent queue[QUEUE_LENGTH];
+ int mouse_grabbed;
+} HIDMouseState;
+
+typedef struct HIDKeyboardState {
+ uint32_t keycodes[QUEUE_LENGTH];
+ uint16_t modifiers;
+ uint8_t leds;
+ uint8_t key[16];
+ int32_t keys;
+} HIDKeyboardState;
+
+struct HIDState {
+ union {
+ HIDMouseState ptr;
+ HIDKeyboardState kbd;
+ };
+ uint32_t head; /* index into circular queue */
+ uint32_t n;
+ int kind;
+ int32_t protocol;
+ uint8_t idle;
+ bool idle_pending;
+ QEMUTimer *idle_timer;
+ HIDEventFunc event;
+ QemuInputHandlerState *s;
+};
+
+void hid_init(HIDState *hs, int kind, HIDEventFunc event);
+void hid_reset(HIDState *hs);
+void hid_free(HIDState *hs);
+
+bool hid_has_events(HIDState *hs);
+void hid_set_next_idle(HIDState *hs);
+void hid_pointer_activate(HIDState *hs);
+int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len);
+int hid_keyboard_poll(HIDState *hs, uint8_t *buf, int len);
+int hid_keyboard_write(HIDState *hs, uint8_t *buf, int len);
+
+extern const VMStateDescription vmstate_hid_keyboard_device;
+
+#define VMSTATE_HID_KEYBOARD_DEVICE(_field, _state) { \
+ .name = (stringify(_field)), \
+ .size = sizeof(HIDState), \
+ .vmsd = &vmstate_hid_keyboard_device, \
+ .flags = VMS_STRUCT, \
+ .offset = vmstate_offset_value(_state, _field, HIDState), \
+}
+
+extern const VMStateDescription vmstate_hid_ptr_device;
+
+#define VMSTATE_HID_POINTER_DEVICE(_field, _state) { \
+ .name = (stringify(_field)), \
+ .size = sizeof(HIDState), \
+ .vmsd = &vmstate_hid_ptr_device, \
+ .flags = VMS_STRUCT, \
+ .offset = vmstate_offset_value(_state, _field, HIDState), \
+}
+
+
+#endif /* QEMU_HID_H */
diff --git a/include/hw/input/i8042.h b/include/hw/input/i8042.h
new file mode 100644
index 000000000..1d90432da
--- /dev/null
+++ b/include/hw/input/i8042.h
@@ -0,0 +1,26 @@
+/*
+ * QEMU PS/2 Controller
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * SPDX-License-Identifier: MIT
+ */
+#ifndef HW_INPUT_I8042_H
+#define HW_INPUT_I8042_H
+
+#include "hw/isa/isa.h"
+#include "qom/object.h"
+
+#define TYPE_I8042 "i8042"
+OBJECT_DECLARE_SIMPLE_TYPE(ISAKBDState, I8042)
+
+#define I8042_A20_LINE "a20"
+
+
+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);
+
+#endif /* HW_INPUT_I8042_H */
diff --git a/include/hw/input/lasips2.h b/include/hw/input/lasips2.h
new file mode 100644
index 000000000..0cd7b5906
--- /dev/null
+++ b/include/hw/input/lasips2.h
@@ -0,0 +1,16 @@
+/*
+ * QEMU LASI PS/2 emulation
+ *
+ * Copyright (c) 2019 Sven Schnelle
+ *
+ */
+#ifndef HW_INPUT_LASIPS2_H
+#define HW_INPUT_LASIPS2_H
+
+#include "exec/hwaddr.h"
+
+#define TYPE_LASIPS2 "lasips2"
+
+void lasips2_init(MemoryRegion *address_space, hwaddr base, qemu_irq irq);
+
+#endif /* HW_INPUT_LASIPS2_H */
diff --git a/include/hw/input/lm832x.h b/include/hw/input/lm832x.h
new file mode 100644
index 000000000..2a58ccf89
--- /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
+#define HW_INPUT_LM832X
+
+#define TYPE_LM8323 "lm8323"
+
+void lm832x_key_event(DeviceState *dev, int key, int state);
+
+#endif
diff --git a/include/hw/input/ps2.h b/include/hw/input/ps2.h
new file mode 100644
index 000000000..35d983897
--- /dev/null
+++ b/include/hw/input/ps2.h
@@ -0,0 +1,52 @@
+/*
+ * QEMU PS/2 keyboard/mouse emulation
+ *
+ * Copyright (C) 2003 Fabrice Bellard
+ *
+ * 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_PS2_H
+#define HW_PS2_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;
+
+/* 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);
+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);
+int ps2_queue_empty(PS2State *s);
+
+#endif /* HW_PS2_H */
diff --git a/include/hw/input/tsc2xxx.h b/include/hw/input/tsc2xxx.h
new file mode 100644
index 000000000..5b76ebc17
--- /dev/null
+++ b/include/hw/input/tsc2xxx.h
@@ -0,0 +1,41 @@
+/*
+ * TI touchscreen controller
+ *
+ * Copyright (c) 2006 Andrzej Zaborowski
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * 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_TSC2XXX_H
+#define HW_INPUT_TSC2XXX_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);
+ void (*send)(void *opaque, uint16_t data);
+ void *opaque;
+} uWireSlave;
+
+/* tsc210x.c */
+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_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);
+
+#endif
diff --git a/include/hw/intc/allwinner-a10-pic.h b/include/hw/intc/allwinner-a10-pic.h
new file mode 100644
index 000000000..b8364d3ed
--- /dev/null
+++ b/include/hw/intc/allwinner-a10-pic.h
@@ -0,0 +1,43 @@
+#ifndef ALLWINNER_A10_PIC_H
+#define ALLWINNER_A10_PIC_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_AW_A10_PIC "allwinner-a10-pic"
+OBJECT_DECLARE_SIMPLE_TYPE(AwA10PICState, AW_A10_PIC)
+
+#define AW_A10_PIC_VECTOR 0
+#define AW_A10_PIC_BASE_ADDR 4
+#define AW_A10_PIC_PROTECT 8
+#define AW_A10_PIC_NMI 0xc
+#define AW_A10_PIC_IRQ_PENDING 0x10
+#define AW_A10_PIC_FIQ_PENDING 0x20
+#define AW_A10_PIC_SELECT 0x30
+#define AW_A10_PIC_ENABLE 0x40
+#define AW_A10_PIC_MASK 0x50
+
+#define AW_A10_PIC_INT_NR 95
+#define AW_A10_PIC_REG_NUM DIV_ROUND_UP(AW_A10_PIC_INT_NR, 32)
+
+struct AwA10PICState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+ MemoryRegion iomem;
+ qemu_irq parent_fiq;
+ qemu_irq parent_irq;
+
+ uint32_t vector;
+ uint32_t base_addr;
+ uint32_t protect;
+ uint32_t nmi;
+ uint32_t irq_pending[AW_A10_PIC_REG_NUM];
+ uint32_t fiq_pending[AW_A10_PIC_REG_NUM];
+ uint32_t select[AW_A10_PIC_REG_NUM];
+ uint32_t enable[AW_A10_PIC_REG_NUM];
+ uint32_t mask[AW_A10_PIC_REG_NUM];
+ /*priority setting here*/
+};
+
+#endif
diff --git a/include/hw/intc/arm_gic.h b/include/hw/intc/arm_gic.h
new file mode 100644
index 000000000..116ccbb5a
--- /dev/null
+++ b/include/hw/intc/arm_gic.h
@@ -0,0 +1,89 @@
+/*
+ * ARM GIC support
+ *
+ * Copyright (c) 2012 Linaro Limited
+ * Written by Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * QEMU interface:
+ * + QOM property "num-cpu": number of CPUs to support
+ * + QOM property "num-irq": number of IRQs (including both SPIs and PPIs)
+ * + QOM property "revision": GIC version (1 or 2), or 0 for the 11MPCore GIC
+ * + QOM property "has-security-extensions": set true if the GIC should
+ * implement the security extensions
+ * + QOM property "has-virtualization-extensions": set true if the GIC should
+ * implement the virtualization extensions
+ * + unnamed GPIO inputs: (where P is number of SPIs, i.e. num-irq - 32)
+ * [0..P-1] SPIs
+ * [P..P+31] PPIs for CPU 0
+ * [P+32..P+63] PPIs for CPU 1
+ * ...
+ * + sysbus IRQs: (in order; number will vary depending on number of cores)
+ * - IRQ for CPU 0
+ * - IRQ for CPU 1
+ * ...
+ * - FIQ for CPU 0
+ * - FIQ for CPU 1
+ * ...
+ * - VIRQ for CPU 0 (exists even if virt extensions not present)
+ * - VIRQ for CPU 1 (exists even if virt extensions not present)
+ * ...
+ * - VFIQ for CPU 0 (exists even if virt extensions not present)
+ * - VFIQ for CPU 1 (exists even if virt extensions not present)
+ * ...
+ * - maintenance IRQ for CPU i/f 0 (only if virt extensions present)
+ * - maintenance IRQ for CPU i/f 1 (only if virt extensions present)
+ * + sysbus MMIO regions: (in order; numbers will vary depending on
+ * whether virtualization extensions are present and on number of cores)
+ * - distributor registers (GICD*)
+ * - CPU interface for the accessing core (GICC*)
+ * - virtual interface control registers (GICH*) (only if virt extns present)
+ * - virtual CPU interface for the accessing core (GICV*) (only if virt)
+ * - CPU 0 CPU interface registers
+ * - CPU 1 CPU interface registers
+ * ...
+ * - CPU 0 virtual interface control registers (only if virt extns present)
+ * - CPU 1 virtual interface control registers (only if virt extns present)
+ * ...
+ */
+
+#ifndef HW_ARM_GIC_H
+#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
+#define GIC_MAX_PRIORITY_BITS 8
+#define GIC_MIN_PRIORITY_BITS 4
+
+#define TYPE_ARM_GIC "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)
+
+struct ARMGICClass {
+ /*< private >*/
+ ARMGICCommonClass parent_class;
+ /*< public >*/
+
+ DeviceRealize parent_realize;
+};
+
+#endif
diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h
new file mode 100644
index 000000000..708037500
--- /dev/null
+++ b/include/hw/intc/arm_gic_common.h
@@ -0,0 +1,168 @@
+/*
+ * ARM GIC support
+ *
+ * Copyright (c) 2012 Linaro Limited
+ * Written by Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_ARM_GIC_COMMON_H
+#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
+/* First 32 are private to each CPU (SGIs and PPIs). */
+#define GIC_INTERNAL 32
+#define GIC_NR_SGIS 16
+/* Maximum number of possible CPU interfaces, determined by GIC architecture */
+#define GIC_NCPU 8
+/* Maximum number of possible CPU interfaces with their respective vCPU */
+#define GIC_NCPU_VCPU (GIC_NCPU * 2)
+
+#define MAX_NR_GROUP_PRIO 128
+#define GIC_NR_APRS (MAX_NR_GROUP_PRIO / 32)
+
+#define GIC_MIN_BPR 0
+#define GIC_MIN_ABPR (GIC_MIN_BPR + 1)
+
+/* Architectural maximum number of list registers in the virtual interface */
+#define GIC_MAX_LR 64
+
+/* Only 32 priority levels and 32 preemption levels in the vCPU interfaces */
+#define GIC_VIRT_MAX_GROUP_PRIO_BITS 5
+#define GIC_VIRT_MAX_NR_GROUP_PRIO (1 << GIC_VIRT_MAX_GROUP_PRIO_BITS)
+#define GIC_VIRT_NR_APRS (GIC_VIRT_MAX_NR_GROUP_PRIO / 32)
+
+#define GIC_VIRT_MIN_BPR 2
+#define GIC_VIRT_MIN_ABPR (GIC_VIRT_MIN_BPR + 1)
+
+typedef struct gic_irq_state {
+ /* The enable bits are only banked for per-cpu interrupts. */
+ uint8_t enabled;
+ uint8_t pending;
+ uint8_t active;
+ uint8_t level;
+ bool model; /* 0 = N:N, 1 = 1:N */
+ bool edge_trigger; /* true: edge-triggered, false: level-triggered */
+ uint8_t group;
+} gic_irq_state;
+
+struct GICState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ qemu_irq parent_irq[GIC_NCPU];
+ qemu_irq parent_fiq[GIC_NCPU];
+ qemu_irq parent_virq[GIC_NCPU];
+ qemu_irq parent_vfiq[GIC_NCPU];
+ qemu_irq maintenance_irq[GIC_NCPU];
+
+ /* GICD_CTLR; for a GIC with the security extensions the NS banked version
+ * of this register is just an alias of bit 1 of the S banked version.
+ */
+ uint32_t ctlr;
+ /* GICC_CTLR; again, the NS banked version is just aliases of bits of
+ * the S banked register, so our state only needs to store the S version.
+ */
+ uint32_t cpu_ctlr[GIC_NCPU_VCPU];
+
+ gic_irq_state irq_state[GIC_MAXIRQ];
+ uint8_t irq_target[GIC_MAXIRQ];
+ uint8_t priority1[GIC_INTERNAL][GIC_NCPU];
+ uint8_t priority2[GIC_MAXIRQ - GIC_INTERNAL];
+ /* For each SGI on the target CPU, we store 8 bits
+ * indicating which source CPUs have made this SGI
+ * pending on the target CPU. These correspond to
+ * the bytes in the GIC_SPENDSGIR* registers as
+ * read by the target CPU.
+ */
+ uint8_t sgi_pending[GIC_NR_SGIS][GIC_NCPU];
+
+ uint16_t priority_mask[GIC_NCPU_VCPU];
+ uint16_t running_priority[GIC_NCPU_VCPU];
+ uint16_t current_pending[GIC_NCPU_VCPU];
+ uint32_t n_prio_bits;
+
+ /* If we present the GICv2 without security extensions to a guest,
+ * the guest can configure the GICC_CTLR to configure group 1 binary point
+ * in the abpr.
+ * For a GIC with Security Extensions we use use bpr for the
+ * secure copy and abpr as storage for the non-secure copy of the register.
+ */
+ uint8_t bpr[GIC_NCPU_VCPU];
+ uint8_t abpr[GIC_NCPU_VCPU];
+
+ /* The APR is implementation defined, so we choose a layout identical to
+ * the KVM ABI layout for QEMU's implementation of the gic:
+ * If an interrupt for preemption level X is active, then
+ * APRn[X mod 32] == 0b1, where n = X / 32
+ * otherwise the bit is clear.
+ */
+ uint32_t apr[GIC_NR_APRS][GIC_NCPU];
+ uint32_t nsapr[GIC_NR_APRS][GIC_NCPU];
+
+ /* Virtual interface control registers */
+ uint32_t h_hcr[GIC_NCPU];
+ uint32_t h_misr[GIC_NCPU];
+ uint32_t h_lr[GIC_MAX_LR][GIC_NCPU];
+ uint32_t h_apr[GIC_NCPU];
+
+ /* Number of LRs implemented in this GIC instance */
+ uint32_t num_lrs;
+
+ uint32_t num_cpu;
+
+ MemoryRegion iomem; /* Distributor */
+ /* This is just so we can have an opaque pointer which identifies
+ * both this GIC and which CPU interface we should be accessing.
+ */
+ struct GICState *backref[GIC_NCPU];
+ MemoryRegion cpuiomem[GIC_NCPU + 1]; /* CPU interfaces */
+ MemoryRegion vifaceiomem[GIC_NCPU + 1]; /* Virtual interfaces */
+ MemoryRegion vcpuiomem; /* vCPU interface */
+
+ uint32_t num_irq;
+ uint32_t revision;
+ bool security_extn;
+ bool virt_extn;
+ 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;
+};
+typedef struct GICState GICState;
+
+#define TYPE_ARM_GIC_COMMON "arm_gic_common"
+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);
+};
+
+void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
+ const MemoryRegionOps *ops,
+ const MemoryRegionOps *virt_ops);
+
+#endif
diff --git a/include/hw/intc/arm_gicv3.h b/include/hw/intc/arm_gicv3.h
new file mode 100644
index 000000000..a81a6ae7e
--- /dev/null
+++ b/include/hw/intc/arm_gicv3.h
@@ -0,0 +1,32 @@
+/*
+ * ARM Generic Interrupt Controller v3
+ *
+ * Copyright (c) 2015 Huawei.
+ * Copyright (c) 2016 Linaro Limited
+ * Written by Shlomo Pongratz, Peter Maydell
+ *
+ * This code is licensed under the GPL, version 2 or (at your option)
+ * any later version.
+ */
+
+#ifndef HW_ARM_GICV3_H
+#define HW_ARM_GICV3_H
+
+#include "arm_gicv3_common.h"
+#include "qom/object.h"
+
+#define TYPE_ARM_GICV3 "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)
+
+struct ARMGICv3Class {
+ /*< private >*/
+ ARMGICv3CommonClass parent_class;
+ /*< public >*/
+
+ DeviceRealize parent_realize;
+};
+
+#endif
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
new file mode 100644
index 000000000..fc38e4b7d
--- /dev/null
+++ b/include/hw/intc/arm_gicv3_common.h
@@ -0,0 +1,321 @@
+/*
+ * ARM GIC support
+ *
+ * Copyright (c) 2012 Linaro Limited
+ * Copyright (c) 2015 Huawei.
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Written by Peter Maydell
+ * Reworked for GICv3 by Shlomo Pongratz and Pavel Fedin
+ *
+ * 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_GICV3_COMMON_H
+#define HW_ARM_GICV3_COMMON_H
+
+#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.
+ * Note that this does not include LPIs. When implemented, these should be
+ * dealt with separately.
+ */
+#define GICV3_MAXIRQ 1020
+#define GICV3_MAXSPI (GICV3_MAXIRQ - GIC_INTERNAL)
+
+#define GICV3_LPI_INTID_START 8192
+
+#define GICV3_REDIST_SIZE 0x20000
+
+/* Number of SGI target-list bits */
+#define GICV3_TARGETLIST_BITS 16
+
+/* 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
+ * APIs are generally modelled on the generic bitmap.h functions
+ * (which are unsuitable here because they use 'unsigned long' as the
+ * underlying storage type, which is very awkward when you need to
+ * access the data as 32-bit values.)
+ * Each bitmap contains a bit for each interrupt. Although there is
+ * space for the PPIs and SGIs, those bits (the first 32) are never
+ * used as that state lives in the redistributor. The unused bits are
+ * provided purely so that interrupt X's state is always in bit X; this
+ * avoids bugs where we forget to subtract GIC_INTERNAL from an
+ * interrupt number.
+ */
+#define GICV3_BMP_SIZE DIV_ROUND_UP(GICV3_MAXIRQ, 32)
+
+#define GIC_DECLARE_BITMAP(name) \
+ uint32_t name[GICV3_BMP_SIZE]
+
+#define GIC_BIT_MASK(nr) (1U << ((nr) % 32))
+#define GIC_BIT_WORD(nr) ((nr) / 32)
+
+static inline void gic_bmp_set_bit(int nr, uint32_t *addr)
+{
+ uint32_t mask = GIC_BIT_MASK(nr);
+ uint32_t *p = addr + GIC_BIT_WORD(nr);
+
+ *p |= mask;
+}
+
+static inline void gic_bmp_clear_bit(int nr, uint32_t *addr)
+{
+ uint32_t mask = GIC_BIT_MASK(nr);
+ uint32_t *p = addr + GIC_BIT_WORD(nr);
+
+ *p &= ~mask;
+}
+
+static inline int gic_bmp_test_bit(int nr, const uint32_t *addr)
+{
+ return 1U & (addr[GIC_BIT_WORD(nr)] >> (nr & 31));
+}
+
+static inline void gic_bmp_replace_bit(int nr, uint32_t *addr, int val)
+{
+ uint32_t mask = GIC_BIT_MASK(nr);
+ uint32_t *p = addr + GIC_BIT_WORD(nr);
+
+ *p &= ~mask;
+ *p |= (val & 1U) << (nr % 32);
+}
+
+/* Return a pointer to the 32-bit word containing the specified bit. */
+static inline uint32_t *gic_bmp_ptr32(uint32_t *addr, int nr)
+{
+ return addr + GIC_BIT_WORD(nr);
+}
+
+typedef struct GICv3State GICv3State;
+typedef struct GICv3CPUState GICv3CPUState;
+
+/* Some CPU interface registers come in three flavours:
+ * Group0, Group1 (Secure) and Group1 (NonSecure)
+ * (where the latter two are exposed as a single banked system register).
+ * In the state struct they are implemented as a 3-element array which
+ * can be indexed into by the GICV3_G0, GICV3_G1 and GICV3_G1NS constants.
+ * If the CPU doesn't support EL3 then the G1 element is unused.
+ *
+ * These constants are also used to communicate the group to use for
+ * an interrupt or SGI when it is passed between the cpu interface and
+ * the redistributor or distributor. For those purposes the receiving end
+ * must be prepared to cope with a Group 1 Secure interrupt even if it does
+ * not have security support enabled, because security can be disabled
+ * independently in the CPU and in the GIC. In that case the receiver should
+ * treat an incoming Group 1 Secure interrupt as if it were Group 0.
+ * (This architectural requirement is why the _G1 element is the unused one
+ * in a no-EL3 CPU: we would otherwise have to translate back and forth
+ * between (G0, G1NS) from the distributor and (G0, G1) in the CPU i/f.)
+ */
+#define GICV3_G0 0
+#define GICV3_G1 1
+#define GICV3_G1NS 2
+
+/* ICC_CTLR_EL1, GICD_STATUSR and GICR_STATUSR are banked but not
+ * group-related, so those indices are just 0 for S and 1 for NS.
+ * (If the CPU or the GIC, respectively, don't support the Security
+ * extensions then the S element is unused.)
+ */
+#define GICV3_S 0
+#define GICV3_NS 1
+
+typedef struct {
+ int irq;
+ uint8_t prio;
+ int grp;
+} PendingIrq;
+
+struct GICv3CPUState {
+ GICv3State *gic;
+ CPUState *cpu;
+ qemu_irq parent_irq;
+ qemu_irq parent_fiq;
+ qemu_irq parent_virq;
+ qemu_irq parent_vfiq;
+
+ /* Redistributor */
+ uint32_t level; /* Current IRQ level */
+ /* RD_base page registers */
+ uint32_t gicr_ctlr;
+ uint64_t gicr_typer;
+ uint32_t gicr_statusr[2];
+ uint32_t gicr_waker;
+ uint64_t gicr_propbaser;
+ uint64_t gicr_pendbaser;
+ /* SGI_base page registers */
+ uint32_t gicr_igroupr0;
+ uint32_t gicr_ienabler0;
+ uint32_t gicr_ipendr0;
+ uint32_t gicr_iactiver0;
+ uint32_t edge_trigger; /* ICFGR0 and ICFGR1 even bits */
+ uint32_t gicr_igrpmodr0;
+ uint32_t gicr_nsacr;
+ uint8_t gicr_ipriorityr[GIC_INTERNAL];
+
+ /* CPU interface */
+ uint64_t icc_sre_el1;
+ uint64_t icc_ctlr_el1[2];
+ uint64_t icc_pmr_el1;
+ uint64_t icc_bpr[3];
+ uint64_t icc_apr[3][4];
+ uint64_t icc_igrpen[3];
+ uint64_t icc_ctlr_el3;
+
+ /* Virtualization control interface */
+ uint64_t ich_apr[3][4]; /* ich_apr[GICV3_G1][x] never used */
+ uint64_t ich_hcr_el2;
+ uint64_t ich_lr_el2[GICV3_LR_MAX];
+ uint64_t ich_vmcr_el2;
+
+ /* Properties of the CPU interface. These are initialized from
+ * the settings in the CPU proper.
+ * If the number of implemented list registers is 0 then the
+ * virtualization support is not implemented.
+ */
+ int num_list_regs;
+ int vpribits; /* number of virtual priority bits */
+ int vprebits; /* number of virtual 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;
+
+ /* 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 */
+ 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 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
+ * register is just an alias of bit 1 of the S banked version.
+ */
+ uint32_t gicd_ctlr;
+ uint32_t gicd_statusr[2];
+ GIC_DECLARE_BITMAP(group); /* GICD_IGROUPR */
+ GIC_DECLARE_BITMAP(grpmod); /* GICD_IGRPMODR */
+ GIC_DECLARE_BITMAP(enabled); /* GICD_ISENABLER */
+ GIC_DECLARE_BITMAP(pending); /* GICD_ISPENDR */
+ GIC_DECLARE_BITMAP(active); /* GICD_ISACTIVER */
+ GIC_DECLARE_BITMAP(level); /* Current level */
+ GIC_DECLARE_BITMAP(edge_trigger); /* GICD_ICFGR even bits */
+ uint8_t gicd_ipriority[GICV3_MAXIRQ];
+ uint64_t gicd_irouter[GICV3_MAXIRQ];
+ /* Cached information: pointer to the cpu i/f for the CPUs specified
+ * in the IROUTER registers
+ */
+ GICv3CPUState *gicd_irouter_target[GICV3_MAXIRQ];
+ uint32_t gicd_nsacr[DIV_ROUND_UP(GICV3_MAXIRQ, 16)];
+
+ GICv3CPUState *cpu;
+};
+
+#define GICV3_BITMAP_ACCESSORS(BMP) \
+ static inline void gicv3_gicd_##BMP##_set(GICv3State *s, int irq) \
+ { \
+ gic_bmp_set_bit(irq, s->BMP); \
+ } \
+ static inline int gicv3_gicd_##BMP##_test(GICv3State *s, int irq) \
+ { \
+ return gic_bmp_test_bit(irq, s->BMP); \
+ } \
+ static inline void gicv3_gicd_##BMP##_clear(GICv3State *s, int irq) \
+ { \
+ gic_bmp_clear_bit(irq, s->BMP); \
+ } \
+ static inline void gicv3_gicd_##BMP##_replace(GICv3State *s, \
+ int irq, int value) \
+ { \
+ gic_bmp_replace_bit(irq, s->BMP, value); \
+ }
+
+GICV3_BITMAP_ACCESSORS(group)
+GICV3_BITMAP_ACCESSORS(grpmod)
+GICV3_BITMAP_ACCESSORS(enabled)
+GICV3_BITMAP_ACCESSORS(pending)
+GICV3_BITMAP_ACCESSORS(active)
+GICV3_BITMAP_ACCESSORS(level)
+GICV3_BITMAP_ACCESSORS(edge_trigger)
+
+#define TYPE_ARM_GICV3_COMMON "arm-gicv3-common"
+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);
+};
+
+void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
+ const MemoryRegionOps *ops);
+
+#endif
diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h
new file mode 100644
index 000000000..4e79145dd
--- /dev/null
+++ b/include/hw/intc/arm_gicv3_its_common.h
@@ -0,0 +1,113 @@
+/*
+ * ITS support for ARM GICv3
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Written by Pavel Fedin
+ *
+ * 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 QEMU_ARM_GICV3_ITS_COMMON_H
+#define QEMU_ARM_GICV3_ITS_COMMON_H
+
+#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
+#define ITS_SIZE (ITS_CONTROL_SIZE + ITS_TRANS_SIZE)
+
+#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 valid;
+ bool indirect;
+ uint16_t entry_sz;
+ uint32_t page_sz;
+ uint32_t max_entries;
+ union {
+ uint32_t max_devids;
+ uint32_t max_collids;
+ } maxids;
+ uint64_t base_addr;
+} TableDesc;
+
+typedef struct {
+ bool valid;
+ uint32_t max_entries;
+ uint64_t base_addr;
+} CmdQDesc;
+
+struct GICv3ITSState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem_main;
+ MemoryRegion iomem_its_cntrl;
+ MemoryRegion iomem_its_translation;
+
+ GICv3State *gicv3;
+
+ int dev_fd; /* kvm device fd if backed by kvm vgic support */
+ uint64_t gits_translater_gpa;
+ bool translater_gpa_known;
+
+ /* 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;
+ CmdQDesc cq;
+
+ Error *migration_blocker;
+};
+
+typedef struct GICv3ITSState GICv3ITSState;
+
+void gicv3_its_init_mmio(GICv3ITSState *s, const MemoryRegionOps *ops,
+ const MemoryRegionOps *tops);
+
+#define TYPE_ARM_GICV3_ITS_COMMON "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 >*/
+ SysBusDeviceClass parent_class;
+ /*< public >*/
+
+ int (*send_msi)(GICv3ITSState *s, uint32_t data, uint16_t devid);
+ void (*pre_save)(GICv3ITSState *s);
+ void (*post_load)(GICv3ITSState *s);
+};
+
+
+#endif
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
new file mode 100644
index 000000000..0180c7b0c
--- /dev/null
+++ b/include/hw/intc/armv7m_nvic.h
@@ -0,0 +1,89 @@
+/*
+ * ARMv7M NVIC object
+ *
+ * Copyright (c) 2017 Linaro Ltd
+ * Written by Peter Maydell <peter.maydell@linaro.org>
+ *
+ * This code is licensed under the GPL version 2 or later.
+ */
+
+#ifndef HW_ARM_ARMV7M_NVIC_H
+#define HW_ARM_ARMV7M_NVIC_H
+
+#include "target/arm/cpu.h"
+#include "hw/sysbus.h"
+#include "hw/timer/armv7m_systick.h"
+#include "qom/object.h"
+
+#define TYPE_NVIC "armv7m_nvic"
+
+typedef struct NVICState NVICState;
+DECLARE_INSTANCE_CHECKER(NVICState, NVIC,
+ TYPE_NVIC)
+
+/* Highest permitted number of exceptions (architectural limit) */
+#define NVIC_MAX_VECTORS 512
+/* Number of internal exceptions */
+#define NVIC_INTERNAL_VECTORS 16
+
+typedef struct VecInfo {
+ /* Exception priorities can range from -3 to 255; only the unmodifiable
+ * priority values for RESET, NMI and HardFault can be negative.
+ */
+ int16_t prio;
+ uint8_t enabled;
+ uint8_t pending;
+ uint8_t active;
+ uint8_t level; /* exceptions <=15 never set level */
+} VecInfo;
+
+struct NVICState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ ARMCPU *cpu;
+
+ VecInfo vectors[NVIC_MAX_VECTORS];
+ /* If the v8M security extension is implemented, some of the internal
+ * exceptions are banked between security states (ie there exists both
+ * a Secure and a NonSecure version of the exception and its state):
+ * HardFault, MemManage, UsageFault, SVCall, PendSV, SysTick (R_PJHV)
+ * The rest (including all the external exceptions) are not banked, though
+ * they may be configurable to target either Secure or NonSecure state.
+ * We store the secure exception state in sec_vectors[] for the banked
+ * exceptions, and otherwise use only vectors[] (including for exceptions
+ * like SecureFault that unconditionally target Secure state).
+ * Entries in sec_vectors[] for non-banked exception numbers are unused.
+ */
+ VecInfo sec_vectors[NVIC_INTERNAL_VECTORS];
+ /* The PRIGROUP field in AIRCR is banked */
+ uint32_t prigroup[M_REG_NUM_BANKS];
+ uint8_t num_prio_bits;
+
+ /* v8M NVIC_ITNS state (stored as a bool per bit) */
+ bool itns[NVIC_MAX_VECTORS];
+
+ /* The following fields are all cached state that can be recalculated
+ * from the vectors[] and sec_vectors[] arrays and the prigroup field:
+ * - vectpending
+ * - vectpending_is_secure
+ * - exception_prio
+ * - vectpending_prio
+ */
+ unsigned int vectpending; /* highest prio pending enabled exception */
+ /* true if vectpending is a banked secure exception, ie it is in
+ * sec_vectors[] rather than vectors[]
+ */
+ 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 */
+
+ MemoryRegion sysregmem;
+
+ uint32_t num_irq;
+ qemu_irq excpout;
+ qemu_irq sysresetreq;
+};
+
+#endif
diff --git a/include/hw/intc/aspeed_vic.h b/include/hw/intc/aspeed_vic.h
new file mode 100644
index 000000000..68d6ab997
--- /dev/null
+++ b/include/hw/intc/aspeed_vic.h
@@ -0,0 +1,49 @@
+/*
+ * ASPEED Interrupt Controller (New)
+ *
+ * Andrew Jeffery <andrew@aj.id.au>
+ *
+ * Copyright 2016 IBM Corp.
+ *
+ * This code is licensed under the GPL version 2 or later. See
+ * the COPYING file in the top-level directory.
+ *
+ * Need to add SVIC and CVIC support
+ */
+#ifndef ASPEED_VIC_H
+#define ASPEED_VIC_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_ASPEED_VIC "aspeed.vic"
+OBJECT_DECLARE_SIMPLE_TYPE(AspeedVICState, ASPEED_VIC)
+
+#define ASPEED_VIC_NR_IRQS 51
+
+struct AspeedVICState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+ qemu_irq irq;
+ qemu_irq fiq;
+
+ uint64_t level;
+ uint64_t raw;
+ uint64_t select;
+ uint64_t enable;
+ uint64_t trigger;
+
+ /* 0=edge, 1=level */
+ uint64_t sense;
+
+ /* 0=single-edge, 1=dual-edge */
+ uint64_t dual_edge;
+
+ /* 0=low-sensitive/falling-edge, 1=high-sensitive/rising-edge */
+ uint64_t event;
+};
+
+#endif /* ASPEED_VIC_H */
diff --git a/include/hw/intc/bcm2835_ic.h b/include/hw/intc/bcm2835_ic.h
new file mode 100644
index 000000000..588eb76c5
--- /dev/null
+++ b/include/hw/intc/bcm2835_ic.h
@@ -0,0 +1,36 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ *
+ * 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_IC_H
+#define BCM2835_IC_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_BCM2835_IC "bcm2835-ic"
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835ICState, BCM2835_IC)
+
+#define BCM2835_IC_GPU_IRQ "gpu-irq"
+#define BCM2835_IC_ARM_IRQ "arm-irq"
+
+struct BCM2835ICState {
+ /*< private >*/
+ SysBusDevice busdev;
+ /*< public >*/
+
+ MemoryRegion iomem;
+ qemu_irq irq;
+ qemu_irq fiq;
+
+ /* 64 GPU IRQs + 8 ARM IRQs = 72 total (GPU first) */
+ uint64_t gpu_irq_level, gpu_irq_enable;
+ uint8_t arm_irq_level, arm_irq_enable;
+ bool fiq_enable;
+ uint8_t fiq_select;
+};
+
+#endif
diff --git a/include/hw/intc/bcm2836_control.h b/include/hw/intc/bcm2836_control.h
new file mode 100644
index 000000000..a410c817e
--- /dev/null
+++ b/include/hw/intc/bcm2836_control.h
@@ -0,0 +1,61 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * Upstreaming code cleanup [including bcm2835_*] (c) 2013 Jan Petrous
+ *
+ * Rasperry Pi 2 emulation and refactoring Copyright (c) 2015, Microsoft
+ * Written by Andrew Baumann
+ *
+ * ARM Local Timer IRQ Copyright (c) 2019. Zoltán Baldaszti
+ * Added basic IRQ_TIMER interrupt support
+ *
+ * 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 BCM2836_CONTROL_H
+#define BCM2836_CONTROL_H
+
+#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"
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2836ControlState, BCM2836_CONTROL)
+
+struct BCM2836ControlState {
+ /*< private >*/
+ SysBusDevice busdev;
+ /*< public >*/
+ MemoryRegion iomem;
+
+ /* mailbox state */
+ uint32_t mailboxes[BCM2836_NCORES * BCM2836_MBPERCORE];
+
+ /* interrupt routing/control registers */
+ uint8_t route_gpu_irq, route_gpu_fiq;
+ uint32_t timercontrol[BCM2836_NCORES];
+ uint32_t mailboxcontrol[BCM2836_NCORES];
+
+ /* interrupt status regs (derived from input pins; not visible to user) */
+ bool gpu_irq, gpu_fiq;
+ uint8_t timerirqs[BCM2836_NCORES];
+
+ /* local timer */
+ QEMUTimer timer;
+ uint32_t local_timer_control;
+ uint8_t route_localtimer;
+
+ /* interrupt source registers, post-routing (also input-derived; visible) */
+ uint32_t irqsrc[BCM2836_NCORES];
+ uint32_t fiqsrc[BCM2836_NCORES];
+
+ /* outputs to CPU cores */
+ qemu_irq irq[BCM2836_NCORES];
+ qemu_irq fiq[BCM2836_NCORES];
+};
+
+#endif
diff --git a/include/hw/intc/goldfish_pic.h b/include/hw/intc/goldfish_pic.h
new file mode 100644
index 000000000..e9d552f79
--- /dev/null
+++ b/include/hw/intc/goldfish_pic.h
@@ -0,0 +1,33 @@
+/*
+ * 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
+
+#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/intc/heathrow_pic.h b/include/hw/intc/heathrow_pic.h
new file mode 100644
index 000000000..c0a7f6f54
--- /dev/null
+++ b/include/hw/intc/heathrow_pic.h
@@ -0,0 +1,52 @@
+/*
+ * Heathrow PIC support (OldWorld PowerMac)
+ *
+ * Copyright (c) 2005-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 HW_INTC_HEATHROW_PIC_H
+#define HW_INTC_HEATHROW_PIC_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_HEATHROW "heathrow"
+OBJECT_DECLARE_SIMPLE_TYPE(HeathrowState, HEATHROW)
+
+typedef struct HeathrowPICState {
+ uint32_t events;
+ uint32_t mask;
+ uint32_t levels;
+ uint32_t level_triggered;
+} HeathrowPICState;
+
+struct HeathrowState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion mem;
+ HeathrowPICState pics[2];
+ qemu_irq irqs[1];
+};
+
+#define HEATHROW_NUM_IRQS 64
+
+#endif /* HW_INTC_HEATHROW_PIC_H */
diff --git a/include/hw/intc/i8259.h b/include/hw/intc/i8259.h
new file mode 100644
index 000000000..e2b1e8c59
--- /dev/null
+++ b/include/hw/intc/i8259.h
@@ -0,0 +1,12 @@
+#ifndef HW_I8259_H
+#define HW_I8259_H
+
+/* i8259.c */
+
+extern DeviceState *isa_pic;
+qemu_irq *i8259_init(ISABus *bus, qemu_irq parent_irq);
+qemu_irq *kvm_i8259_init(ISABus *bus);
+int pic_get_output(DeviceState *d);
+int pic_read_irq(DeviceState *d);
+
+#endif
diff --git a/include/hw/intc/ibex_plic.h b/include/hw/intc/ibex_plic.h
new file mode 100644
index 000000000..d596436e0
--- /dev/null
+++ b/include/hw/intc/ibex_plic.h
@@ -0,0 +1,67 @@
+/*
+ * 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"
+#include "qom/object.h"
+
+#define TYPE_IBEX_PLIC "ibex-plic"
+OBJECT_DECLARE_SIMPLE_TYPE(IbexPlicState, IBEX_PLIC)
+
+struct IbexPlicState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion mmio;
+
+ uint32_t *pending;
+ uint32_t *hidden_pending;
+ uint32_t *claimed;
+ 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;
+
+ qemu_irq *external_irqs;
+};
+
+#endif /* HW_IBEX_PLIC_H */
diff --git a/include/hw/intc/imx_avic.h b/include/hw/intc/imx_avic.h
new file mode 100644
index 000000000..75fbd1a89
--- /dev/null
+++ b/include/hw/intc/imx_avic.h
@@ -0,0 +1,56 @@
+/*
+ * i.MX31 Vectored Interrupt Controller
+ *
+ * Note this is NOT the PL192 provided by ARM, but
+ * a custom implementation by Freescale.
+ *
+ * Copyright (c) 2008 OKL
+ * Copyright (c) 2011 NICTA Pty Ltd
+ * Originally written by Hans Jiang
+ * Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
+ *
+ * This code is licensed under the GPL version 2 or later. See
+ * the COPYING file in the top-level directory.
+ *
+ * TODO: implement vectors.
+ */
+#ifndef IMX_AVIC_H
+#define IMX_AVIC_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_IMX_AVIC "imx.avic"
+OBJECT_DECLARE_SIMPLE_TYPE(IMXAVICState, IMX_AVIC)
+
+#define IMX_AVIC_NUM_IRQS 64
+
+/* Interrupt Control Bits */
+#define ABFLAG (1<<25)
+#define ABFEN (1<<24)
+#define NIDIS (1<<22) /* Normal Interrupt disable */
+#define FIDIS (1<<21) /* Fast interrupt disable */
+#define NIAD (1<<20) /* Normal Interrupt Arbiter Rise ARM level */
+#define FIAD (1<<19) /* Fast Interrupt Arbiter Rise ARM level */
+#define NM (1<<18) /* Normal interrupt mode */
+
+#define PRIO_PER_WORD (sizeof(uint32_t) * 8 / 4)
+#define PRIO_WORDS (IMX_AVIC_NUM_IRQS/PRIO_PER_WORD)
+
+struct IMXAVICState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+ uint64_t pending;
+ uint64_t enabled;
+ uint64_t is_fiq;
+ uint32_t intcntl;
+ uint32_t intmask;
+ qemu_irq irq;
+ qemu_irq fiq;
+ uint32_t prio[PRIO_WORDS]; /* Priorities are 4-bits each */
+};
+
+#endif /* IMX_AVIC_H */
diff --git a/include/hw/intc/imx_gpcv2.h b/include/hw/intc/imx_gpcv2.h
new file mode 100644
index 000000000..7bdee7e80
--- /dev/null
+++ b/include/hw/intc/imx_gpcv2.h
@@ -0,0 +1,23 @@
+#ifndef IMX_GPCV2_H
+#define IMX_GPCV2_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+enum IMXGPCv2Registers {
+ GPC_NUM = 0xE00 / sizeof(uint32_t),
+};
+
+struct IMXGPCv2State {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+ uint32_t regs[GPC_NUM];
+};
+
+#define TYPE_IMX_GPCV2 "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
new file mode 100644
index 000000000..7018f608c
--- /dev/null
+++ b/include/hw/intc/intc.h
@@ -0,0 +1,28 @@
+#ifndef INTC_H
+#define INTC_H
+
+#include "qom/object.h"
+
+#define TYPE_INTERRUPT_STATS_PROVIDER "intctrl"
+
+typedef struct InterruptStatsProviderClass InterruptStatsProviderClass;
+DECLARE_CLASS_CHECKERS(InterruptStatsProviderClass, INTERRUPT_STATS_PROVIDER,
+ TYPE_INTERRUPT_STATS_PROVIDER)
+#define INTERRUPT_STATS_PROVIDER(obj) \
+ INTERFACE_CHECK(InterruptStatsProvider, (obj), \
+ TYPE_INTERRUPT_STATS_PROVIDER)
+
+typedef struct InterruptStatsProvider InterruptStatsProvider;
+
+struct InterruptStatsProviderClass {
+ InterfaceClass parent;
+
+ /* The returned pointer and statistics must remain valid until
+ * the BQL is next dropped.
+ */
+ bool (*get_statistics)(InterruptStatsProvider *obj, uint64_t **irq_counts,
+ unsigned int *nb_irqs);
+ void (*print_info)(InterruptStatsProvider *obj, Monitor *mon);
+};
+
+#endif
diff --git a/include/hw/intc/loongson_liointc.h b/include/hw/intc/loongson_liointc.h
new file mode 100644
index 000000000..848e65eb3
--- /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 000000000..ef91f2181
--- /dev/null
+++ b/include/hw/intc/m68k_irqc.h
@@ -0,0 +1,41 @@
+/*
+ * 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;
+
+ /* 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
new file mode 100644
index 000000000..eeb136e26
--- /dev/null
+++ b/include/hw/intc/mips_gic.h
@@ -0,0 +1,218 @@
+/*
+ * 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) 2000, 07 MIPS Technologies, Inc.
+ * Copyright (C) 2016 Imagination Technologies
+ *
+ */
+
+#ifndef MIPS_GIC_H
+#define MIPS_GIC_H
+
+#include "qemu/units.h"
+#include "hw/timer/mips_gictimer.h"
+#include "hw/sysbus.h"
+#include "cpu.h"
+#include "qom/object.h"
+/*
+ * GIC Specific definitions
+ */
+
+/* The MIPS default location */
+#define GIC_BASE_ADDR 0x1bdc0000ULL
+#define GIC_ADDRSPACE_SZ (128 * KiB)
+
+/* Constants */
+#define GIC_POL_POS 1
+#define GIC_POL_NEG 0
+#define GIC_TRIG_EDGE 1
+#define GIC_TRIG_LEVEL 0
+
+#define MSK(n) ((1ULL << (n)) - 1)
+
+/* GIC Address Space */
+#define SHARED_SECTION_OFS 0x0000
+#define SHARED_SECTION_SIZE 0x8000
+#define VP_LOCAL_SECTION_OFS 0x8000
+#define VP_LOCAL_SECTION_SIZE 0x4000
+#define VP_OTHER_SECTION_OFS 0xc000
+#define VP_OTHER_SECTION_SIZE 0x4000
+#define USM_VISIBLE_SECTION_OFS 0x10000
+#define USM_VISIBLE_SECTION_SIZE 0x10000
+
+/* Register Map for Shared Section */
+
+#define GIC_SH_CONFIG_OFS 0x0000
+
+/* Shared Global Counter */
+#define GIC_SH_COUNTERLO_OFS 0x0010
+#define GIC_SH_COUNTERHI_OFS 0x0014
+#define GIC_SH_REVISIONID_OFS 0x0020
+
+/* Set/Clear corresponding bit in Edge Detect Register */
+#define GIC_SH_WEDGE_OFS 0x0280
+
+/* Reset Mask - Disables Interrupt */
+#define GIC_SH_RMASK_OFS 0x0300
+#define GIC_SH_RMASK_LAST_OFS 0x031c
+
+/* Set Mask (WO) - Enables Interrupt */
+#define GIC_SH_SMASK_OFS 0x0380
+#define GIC_SH_SMASK_LAST_OFS 0x039c
+
+/* Global Interrupt Mask Register (RO) - Bit Set == Interrupt enabled */
+#define GIC_SH_MASK_OFS 0x0400
+#define GIC_SH_MASK_LAST_OFS 0x041c
+
+/* Pending Global Interrupts (RO) */
+#define GIC_SH_PEND_OFS 0x0480
+#define GIC_SH_PEND_LAST_OFS 0x049c
+
+#define GIC_SH_MAP0_PIN_OFS 0x0500
+#define GIC_SH_MAP255_PIN_OFS 0x08fc
+
+#define GIC_SH_MAP0_VP_OFS 0x2000
+#define GIC_SH_MAP255_VP_LAST_OFS 0x3fe4
+
+/* Register Map for Local Section */
+#define GIC_VP_CTL_OFS 0x0000
+#define GIC_VP_PEND_OFS 0x0004
+#define GIC_VP_MASK_OFS 0x0008
+#define GIC_VP_RMASK_OFS 0x000c
+#define GIC_VP_SMASK_OFS 0x0010
+#define GIC_VP_WD_MAP_OFS 0x0040
+#define GIC_VP_COMPARE_MAP_OFS 0x0044
+#define GIC_VP_TIMER_MAP_OFS 0x0048
+#define GIC_VP_FDC_MAP_OFS 0x004c
+#define GIC_VP_PERFCTR_MAP_OFS 0x0050
+#define GIC_VP_SWINT0_MAP_OFS 0x0054
+#define GIC_VP_SWINT1_MAP_OFS 0x0058
+#define GIC_VP_OTHER_ADDR_OFS 0x0080
+#define GIC_VP_IDENT_OFS 0x0088
+#define GIC_VP_WD_CONFIG0_OFS 0x0090
+#define GIC_VP_WD_COUNT0_OFS 0x0094
+#define GIC_VP_WD_INITIAL0_OFS 0x0098
+#define GIC_VP_COMPARE_LO_OFS 0x00a0
+#define GIC_VP_COMPARE_HI_OFS 0x00a4
+#define GIC_VL_BRK_GROUP 0x3080
+
+/* User-Mode Visible Section Register */
+/* Read-only alias for GIC Shared CounterLo */
+#define GIC_USER_MODE_COUNTERLO 0x0000
+/* Read-only alias for GIC Shared CounterHi */
+#define GIC_USER_MODE_COUNTERHI 0x0004
+
+/* Masks */
+#define GIC_SH_CONFIG_COUNTSTOP_SHF 28
+#define GIC_SH_CONFIG_COUNTSTOP_MSK (MSK(1) << GIC_SH_CONFIG_COUNTSTOP_SHF)
+#define GIC_SH_CONFIG_COUNTBITS_SHF 24
+#define GIC_SH_CONFIG_COUNTBITS_MSK (MSK(4) << GIC_SH_CONFIG_COUNTBITS_SHF)
+#define GIC_SH_CONFIG_NUMINTRS_SHF 16
+#define GIC_SH_CONFIG_NUMINTRS_MSK (MSK(8) << GIC_SH_CONFIG_NUMINTRS_SHF)
+#define GIC_SH_CONFIG_PVPS_SHF 0
+#define GIC_SH_CONFIG_PVPS_MSK (MSK(8) << GIC_SH_CONFIG_NUMVPS_SHF)
+
+#define GIC_SH_WEDGE_RW_SHF 31
+#define GIC_SH_WEDGE_RW_MSK (MSK(1) << GIC_SH_WEDGE_RW_SHF)
+
+#define GIC_MAP_TO_PIN_SHF 31
+#define GIC_MAP_TO_PIN_MSK (MSK(1) << GIC_MAP_TO_PIN_SHF)
+#define GIC_MAP_TO_NMI_SHF 30
+#define GIC_MAP_TO_NMI_MSK (MSK(1) << GIC_MAP_TO_NMI_SHF)
+#define GIC_MAP_TO_YQ_SHF 29
+#define GIC_MAP_TO_YQ_MSK (MSK(1) << GIC_MAP_TO_YQ_SHF)
+#define GIC_MAP_SHF 0
+#define GIC_MAP_MSK (MSK(6) << GIC_MAP_SHF)
+#define GIC_MAP_TO_PIN_REG_MSK \
+ (GIC_MAP_TO_PIN_MSK | GIC_MAP_TO_NMI_MSK | GIC_MAP_TO_YQ_MSK | GIC_MAP_MSK)
+
+/* GIC_VP_CTL Masks */
+#define GIC_VP_CTL_FDC_RTBL_SHF 4
+#define GIC_VP_CTL_FDC_RTBL_MSK (MSK(1) << GIC_VP_CTL_FDC_RTBL_SHF)
+#define GIC_VP_CTL_SWINT_RTBL_SHF 3
+#define GIC_VP_CTL_SWINT_RTBL_MSK (MSK(1) << GIC_VP_CTL_SWINT_RTBL_SHF)
+#define GIC_VP_CTL_PERFCNT_RTBL_SHF 2
+#define GIC_VP_CTL_PERFCNT_RTBL_MSK (MSK(1) << GIC_VP_CTL_PERFCNT_RTBL_SHF)
+#define GIC_VP_CTL_TIMER_RTBL_SHF 1
+#define GIC_VP_CTL_TIMER_RTBL_MSK (MSK(1) << GIC_VP_CTL_TIMER_RTBL_SHF)
+#define GIC_VP_CTL_EIC_MODE_SHF 0
+#define GIC_VP_CTL_EIC_MODE_MSK (MSK(1) << GIC_VP_CTL_EIC_MODE_SHF)
+
+/* GIC_VP_MASK Masks */
+#define GIC_VP_MASK_FDC_SHF 6
+#define GIC_VP_MASK_FDC_MSK (MSK(1) << GIC_VP_MASK_FDC_SHF)
+#define GIC_VP_MASK_SWINT1_SHF 5
+#define GIC_VP_MASK_SWINT1_MSK (MSK(1) << GIC_VP_MASK_SWINT1_SHF)
+#define GIC_VP_MASK_SWINT0_SHF 4
+#define GIC_VP_MASK_SWINT0_MSK (MSK(1) << GIC_VP_MASK_SWINT0_SHF)
+#define GIC_VP_MASK_PERFCNT_SHF 3
+#define GIC_VP_MASK_PERFCNT_MSK (MSK(1) << GIC_VP_MASK_PERFCNT_SHF)
+#define GIC_VP_MASK_TIMER_SHF 2
+#define GIC_VP_MASK_TIMER_MSK (MSK(1) << GIC_VP_MASK_TIMER_SHF)
+#define GIC_VP_MASK_CMP_SHF 1
+#define GIC_VP_MASK_CMP_MSK (MSK(1) << GIC_VP_MASK_CMP_SHF)
+#define GIC_VP_MASK_WD_SHF 0
+#define GIC_VP_MASK_WD_MSK (MSK(1) << GIC_VP_MASK_WD_SHF)
+#define GIC_VP_SET_RESET_MSK (MSK(7) << GIC_VP_MASK_WD_SHF)
+
+#define GIC_CPU_INT_MAX 5 /* Core Interrupt 7 */
+#define GIC_CPU_PIN_OFFSET 2
+
+/* Local GIC interrupts. */
+#define GIC_NUM_LOCAL_INTRS 7
+#define GIC_LOCAL_INT_FDC 6 /* CPU fast debug channel */
+#define GIC_LOCAL_INT_SWINT1 5 /* CPU software interrupt 1 */
+#define GIC_LOCAL_INT_SWINT0 4 /* CPU software interrupt 0 */
+#define GIC_LOCAL_INT_PERFCTR 3 /* CPU performance counter */
+#define GIC_LOCAL_INT_TIMER 2 /* CPU timer interrupt */
+#define GIC_LOCAL_INT_COMPARE 1 /* GIC count and compare timer */
+#define GIC_LOCAL_INT_WD 0 /* GIC watchdog */
+
+#define TYPE_MIPS_GIC "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 MIPSGICIRQState MIPSGICIRQState;
+typedef struct MIPSGICVPState MIPSGICVPState;
+
+struct MIPSGICIRQState {
+ uint8_t enabled;
+ uint8_t pending;
+ uint32_t map_pin;
+ int32_t map_vp;
+ qemu_irq irq;
+};
+
+struct MIPSGICVPState {
+ uint32_t ctl;
+ uint32_t pend;
+ uint32_t mask;
+ uint32_t compare_map;
+ uint32_t other_addr;
+ CPUMIPSState *env;
+};
+
+struct MIPSGICState {
+ SysBusDevice parent_obj;
+ MemoryRegion mr;
+
+ /* Shared Section Registers */
+ uint32_t sh_config;
+ MIPSGICIRQState *irq_state;
+
+ /* VP Local/Other Section Registers */
+ MIPSGICVPState *vps;
+
+ /* GIC VP Timer */
+ MIPSGICTimerState *gic_timer;
+
+ int32_t num_vps;
+ int32_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 000000000..22dd5e5ac
--- /dev/null
+++ b/include/hw/intc/ppc-uic.h
@@ -0,0 +1,80 @@
+/*
+ * "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/sysbus.h"
+#include "qom/object.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 >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ qemu_irq output_int;
+ qemu_irq output_cint;
+
+ /* properties */
+ CPUState *cpu;
+ 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
new file mode 100644
index 000000000..f37339dc0
--- /dev/null
+++ b/include/hw/intc/realview_gic.h
@@ -0,0 +1,28 @@
+/*
+ * ARM RealView Emulation Baseboard Interrupt Controller
+ *
+ * Copyright (c) 2006-2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the GPL.
+ */
+
+#ifndef HW_INTC_REALVIEW_GIC_H
+#define HW_INTC_REALVIEW_GIC_H
+
+#include "hw/sysbus.h"
+#include "hw/intc/arm_gic.h"
+#include "qom/object.h"
+
+#define TYPE_REALVIEW_GIC "realview_gic"
+OBJECT_DECLARE_SIMPLE_TYPE(RealViewGICState, REALVIEW_GIC)
+
+struct RealViewGICState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion container;
+
+ GICState gic;
+};
+
+#endif
diff --git a/include/hw/intc/riscv_aclint.h b/include/hw/intc/riscv_aclint.h
new file mode 100644
index 000000000..229bd08d2
--- /dev/null
+++ b/include/hw/intc/riscv_aclint.h
@@ -0,0 +1,80 @@
+/*
+ * 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;
+
+ /*< 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/rx_icu.h b/include/hw/intc/rx_icu.h
new file mode 100644
index 000000000..7f5889b36
--- /dev/null
+++ b/include/hw/intc/rx_icu.h
@@ -0,0 +1,76 @@
+/*
+ * RX Interrupt Control Unit
+ *
+ * Copyright (c) 2019 Yoshinori Sato
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * 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_INTC_RX_ICU_H
+#define HW_INTC_RX_ICU_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+enum TRG_MODE {
+ TRG_LEVEL = 0,
+ TRG_NEDGE = 1, /* Falling */
+ TRG_PEDGE = 2, /* Raising */
+ TRG_BEDGE = 3, /* Both */
+};
+
+struct IRQSource {
+ enum TRG_MODE sense;
+ int level;
+};
+
+enum {
+ /* Software interrupt request */
+ SWI = 27,
+ NR_IRQS = 256
+};
+
+struct RXICUState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ MemoryRegion memory;
+ struct IRQSource src[NR_IRQS];
+ uint32_t nr_irqs;
+ uint8_t *map;
+ uint32_t nr_sense;
+ uint8_t *init_sense;
+
+ uint8_t ir[NR_IRQS];
+ uint8_t dtcer[NR_IRQS];
+ uint8_t ier[NR_IRQS / 8];
+ uint8_t ipr[142];
+ uint8_t dmasr[4];
+ uint16_t fir;
+ uint8_t nmisr;
+ uint8_t nmier;
+ uint8_t nmiclr;
+ uint8_t nmicr;
+ int16_t req_irq;
+ qemu_irq _irq;
+ qemu_irq _fir;
+ qemu_irq _swi;
+};
+
+#define TYPE_RX_ICU "rx-icu"
+OBJECT_DECLARE_SIMPLE_TYPE(RXICUState, RX_ICU)
+
+#endif /* RX_ICU_H */
diff --git a/include/hw/intc/sifive_plic.h b/include/hw/intc/sifive_plic.h
new file mode 100644
index 000000000..134cf39a9
--- /dev/null
+++ b/include/hw/intc/sifive_plic.h
@@ -0,0 +1,88 @@
+/*
+ * SiFive PLIC (Platform Level Interrupt Controller) interface
+ *
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * This provides a RISC-V PLIC device
+ *
+ * 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_PLIC_H
+#define HW_SIFIVE_PLIC_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_SIFIVE_PLIC "riscv.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;
+
+typedef struct PLICAddr {
+ uint32_t addrid;
+ uint32_t hartid;
+ PLICMode mode;
+} PLICAddr;
+
+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;
+ uint32_t *pending;
+ uint32_t *claimed;
+ uint32_t *enable;
+
+ /* config */
+ char *hart_config;
+ 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;
+
+ qemu_irq *m_external_irqs;
+ qemu_irq *s_external_irqs;
+};
+
+DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
+ 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
new file mode 100644
index 000000000..ccc8bd272
--- /dev/null
+++ b/include/hw/intc/xlnx-pmu-iomod-intc.h
@@ -0,0 +1,57 @@
+/*
+ * QEMU model of Xilinx I/O Module Interrupt Controller
+ *
+ * Copyright (c) 2014 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 HW_INTC_XLNX_PMU_IOMOD_INTC_H
+#define HW_INTC_XLNX_PMU_IOMOD_INTC_H
+
+#include "hw/sysbus.h"
+#include "hw/register.h"
+#include "qom/object.h"
+
+#define TYPE_XLNX_PMU_IO_INTC "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)
+
+struct XlnxPMUIOIntc {
+ SysBusDevice parent_obj;
+ MemoryRegion iomem;
+
+ qemu_irq parent_irq;
+
+ struct {
+ uint32_t intr_size;
+ uint32_t level_edge;
+ uint32_t positive;
+ } cfg;
+
+ uint32_t irq_raw;
+
+ uint32_t regs[XLNXPMUIOINTC_R_MAX];
+ RegisterInfo regs_info[XLNXPMUIOINTC_R_MAX];
+};
+
+#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
new file mode 100644
index 000000000..33eff1d4f
--- /dev/null
+++ b/include/hw/intc/xlnx-zynqmp-ipi.h
@@ -0,0 +1,56 @@
+/*
+ * QEMU model of the IPI Inter Processor Interrupt block
+ *
+ * Copyright (c) 2014 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_IPI_H
+#define XLNX_ZYNQMP_IPI_H
+
+#include "hw/sysbus.h"
+#include "hw/register.h"
+#include "qom/object.h"
+
+#define TYPE_XLNX_ZYNQMP_IPI "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
+
+struct XlnxZynqMPIPI {
+ /* Private */
+ SysBusDevice parent_obj;
+
+ /* Public */
+ MemoryRegion iomem;
+ qemu_irq irq;
+
+ qemu_irq irq_trig_out[NUM_IPIS];
+ qemu_irq irq_obs_out[NUM_IPIS];
+
+ uint32_t regs[R_XLNX_ZYNQMP_IPI_MAX];
+ RegisterInfo regs_info[R_XLNX_ZYNQMP_IPI_MAX];
+};
+
+#endif /* XLNX_ZYNQMP_IPI_H */
diff --git a/include/hw/ipack/ipack.h b/include/hw/ipack/ipack.h
new file mode 100644
index 000000000..cbcdda509
--- /dev/null
+++ b/include/hw/ipack/ipack.h
@@ -0,0 +1,81 @@
+/*
+ * QEMU IndustryPack emulation
+ *
+ * Copyright (C) 2012 Igalia, S.L.
+ * Author: Alberto Garcia <berto@igalia.com>
+ *
+ * This code is licensed under the GNU GPL v2 or (at your option) any
+ * later version.
+ */
+
+#ifndef QEMU_IPACK_H
+#define QEMU_IPACK_H
+
+#include "hw/qdev-core.h"
+#include "qom/object.h"
+
+
+#define TYPE_IPACK_BUS "IndustryPack"
+OBJECT_DECLARE_SIMPLE_TYPE(IPackBus, IPACK_BUS)
+
+struct IPackBus {
+ /*< private >*/
+ BusState parent_obj;
+
+ /* All fields are private */
+ uint8_t n_slots;
+ uint8_t free_slot;
+ qemu_irq_handler set_irq;
+};
+
+
+#define TYPE_IPACK_DEVICE "ipack-device"
+OBJECT_DECLARE_TYPE(IPackDevice, IPackDeviceClass,
+ IPACK_DEVICE)
+
+struct IPackDeviceClass {
+ /*< private >*/
+ DeviceClass parent_class;
+ /*< public >*/
+
+ DeviceRealize realize;
+ DeviceUnrealize unrealize;
+
+ uint16_t (*io_read)(IPackDevice *dev, uint8_t addr);
+ void (*io_write)(IPackDevice *dev, uint8_t addr, uint16_t val);
+
+ uint16_t (*id_read)(IPackDevice *dev, uint8_t addr);
+ void (*id_write)(IPackDevice *dev, uint8_t addr, uint16_t val);
+
+ uint16_t (*int_read)(IPackDevice *dev, uint8_t addr);
+ void (*int_write)(IPackDevice *dev, uint8_t addr, uint16_t val);
+
+ uint16_t (*mem_read16)(IPackDevice *dev, uint32_t addr);
+ void (*mem_write16)(IPackDevice *dev, uint32_t addr, uint16_t val);
+
+ uint8_t (*mem_read8)(IPackDevice *dev, uint32_t addr);
+ void (*mem_write8)(IPackDevice *dev, uint32_t addr, uint8_t val);
+};
+
+struct IPackDevice {
+ /*< private >*/
+ DeviceState parent_obj;
+ /*< public >*/
+
+ int32_t slot;
+ /* IRQ objects for the IndustryPack INT0# and INT1# */
+ qemu_irq *irq;
+};
+
+extern const VMStateDescription vmstate_ipack_device;
+
+#define VMSTATE_IPACK_DEVICE(_field, _state) \
+ VMSTATE_STRUCT(_field, _state, 1, vmstate_ipack_device, IPackDevice)
+
+IPackDevice *ipack_device_find(IPackBus *bus, int32_t slot);
+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
new file mode 100644
index 000000000..77a7213ed
--- /dev/null
+++ b/include/hw/ipmi/ipmi.h
@@ -0,0 +1,305 @@
+/*
+ * IPMI base class
+ *
+ * Copyright (c) 2015 Corey Minyard, MontaVista Software, LLC
+ *
+ * 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_IPMI_H
+#define HW_IPMI_H
+
+#include "exec/memory.h"
+#include "hw/qdev-core.h"
+#include "qom/object.h"
+
+#define MAX_IPMI_MSG_SIZE 300
+
+enum ipmi_op {
+ IPMI_RESET_CHASSIS,
+ IPMI_POWEROFF_CHASSIS,
+ IPMI_POWERON_CHASSIS,
+ IPMI_POWERCYCLE_CHASSIS,
+ IPMI_PULSE_DIAG_IRQ,
+ IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP,
+ IPMI_SEND_NMI
+};
+
+#define IPMI_CC_INVALID_CMD 0xc1
+#define IPMI_CC_COMMAND_INVALID_FOR_LUN 0xc2
+#define IPMI_CC_TIMEOUT 0xc3
+#define IPMI_CC_OUT_OF_SPACE 0xc4
+#define IPMI_CC_INVALID_RESERVATION 0xc5
+#define IPMI_CC_REQUEST_DATA_TRUNCATED 0xc6
+#define IPMI_CC_REQUEST_DATA_LENGTH_INVALID 0xc7
+#define IPMI_CC_PARM_OUT_OF_RANGE 0xc9
+#define IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES 0xca
+#define IPMI_CC_REQ_ENTRY_NOT_PRESENT 0xcb
+#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
+
+#define IPMI_DEBUG 1
+
+/* Specified in the SMBIOS spec. */
+#define IPMI_SMBIOS_KCS 0x01
+#define IPMI_SMBIOS_SMIC 0x02
+#define IPMI_SMBIOS_BT 0x03
+#define IPMI_SMBIOS_SSIF 0x04
+
+/*
+ * Used for transferring information to interfaces that add
+ * entries to firmware tables.
+ */
+typedef struct IPMIFwInfo {
+ const char *interface_name;
+ int interface_type;
+ uint8_t ipmi_spec_major_revision;
+ uint8_t ipmi_spec_minor_revision;
+ uint8_t i2c_slave_address;
+ uint32_t uuid;
+
+ uint64_t base_address;
+ uint64_t register_length;
+ uint8_t register_spacing;
+ enum {
+ IPMI_MEMSPACE_IO,
+ IPMI_MEMSPACE_MEM32,
+ IPMI_MEMSPACE_MEM64,
+ IPMI_MEMSPACE_SMBUS
+ } memspace;
+
+ int interrupt_number;
+ enum {
+ IPMI_LEVEL_IRQ,
+ IPMI_EDGE_IRQ
+ } irq_type;
+} IPMIFwInfo;
+
+/*
+ * Called by each instantiated IPMI interface device to get it's uuid.
+ */
+uint32_t ipmi_next_uuid(void);
+
+/* IPMI Interface types (KCS, SMIC, BT) are prefixed with this */
+#define TYPE_IPMI_INTERFACE_PREFIX "ipmi-interface-"
+
+/*
+ * An IPMI Interface, the interface for talking between the target
+ * and the BMC.
+ */
+#define TYPE_IPMI_INTERFACE "ipmi-interface"
+#define IPMI_INTERFACE(obj) \
+ INTERFACE_CHECK(IPMIInterface, (obj), TYPE_IPMI_INTERFACE)
+typedef struct IPMIInterfaceClass IPMIInterfaceClass;
+DECLARE_CLASS_CHECKERS(IPMIInterfaceClass, IPMI_INTERFACE,
+ TYPE_IPMI_INTERFACE)
+
+typedef struct IPMIInterface IPMIInterface;
+
+struct IPMIInterfaceClass {
+ InterfaceClass parent;
+
+ /*
+ * min_size is the requested I/O size and must be a power of 2.
+ * This is so PCI (or other busses) can request a bigger range.
+ * Use 0 for the default.
+ */
+ void (*init)(struct IPMIInterface *s, unsigned int min_size, Error **errp);
+
+ /*
+ * Perform various operations on the hardware. If checkonly is
+ * true, it will return if the operation can be performed, but it
+ * will not do the operation.
+ */
+ int (*do_hw_op)(struct IPMIInterface *s, enum ipmi_op op, int checkonly);
+
+ /*
+ * Enable/disable irqs on the interface when the BMC requests this.
+ */
+ void (*set_irq_enable)(struct IPMIInterface *s, int val);
+
+ /*
+ * Handle an event that occurred on the interface, generally the.
+ * target writing to a register.
+ */
+ void (*handle_if_event)(struct IPMIInterface *s);
+
+ /*
+ * The interfaces use this to perform certain ops
+ */
+ void (*set_atn)(struct IPMIInterface *s, int val, int irq);
+
+ /*
+ * Got an IPMI warm/cold reset.
+ */
+ void (*reset)(struct IPMIInterface *s, bool is_cold);
+
+ /*
+ * Handle a response from the bmc.
+ */
+ void (*handle_rsp)(struct IPMIInterface *s, uint8_t msg_id,
+ unsigned char *rsp, unsigned int rsp_len);
+
+ /*
+ * Set by the owner to hold the backend data for the interface.
+ */
+ void *(*get_backend_data)(struct IPMIInterface *s);
+
+ /*
+ * Return the firmware info for a device.
+ */
+ void (*get_fwinfo)(struct IPMIInterface *s, IPMIFwInfo *info);
+};
+
+/*
+ * Define a BMC simulator (or perhaps a connection to a real BMC)
+ */
+#define TYPE_IPMI_BMC "ipmi-bmc"
+OBJECT_DECLARE_TYPE(IPMIBmc, IPMIBmcClass,
+ IPMI_BMC)
+
+struct IPMIBmc {
+ DeviceState parent;
+
+ uint8_t slave_addr;
+
+ IPMIInterface *intf;
+};
+
+struct IPMIBmcClass {
+ DeviceClass parent;
+
+ /* Called when the system resets to report to the bmc. */
+ void (*handle_reset)(struct IPMIBmc *s);
+
+ /*
+ * Handle a command to the bmc.
+ */
+ void (*handle_command)(struct IPMIBmc *s,
+ uint8_t *cmd, unsigned int cmd_len,
+ unsigned int max_cmd_len,
+ uint8_t msg_id);
+};
+
+/*
+ * Add a link property to obj that points to a BMC.
+ */
+void ipmi_bmc_find_and_link(Object *obj, Object **bmc);
+
+#ifdef IPMI_DEBUG
+#define ipmi_debug(fs, ...) \
+ fprintf(stderr, "IPMI (%s): " fs, __func__, ##__VA_ARGS__)
+#else
+#define ipmi_debug(fs, ...)
+#endif
+
+struct ipmi_sdr_header {
+ uint8_t rec_id[2];
+ uint8_t sdr_version; /* 0x51 */
+ uint8_t rec_type;
+ uint8_t rec_length;
+};
+#define IPMI_SDR_HEADER_SIZE sizeof(struct ipmi_sdr_header)
+
+#define ipmi_sdr_recid(sdr) ((sdr)->rec_id[0] | ((sdr)->rec_id[1] << 8))
+#define ipmi_sdr_length(sdr) ((sdr)->rec_length + IPMI_SDR_HEADER_SIZE)
+
+/*
+ * 43.2 SDR Type 02h. Compact Sensor Record
+ */
+#define IPMI_SDR_COMPACT_TYPE 2
+
+struct ipmi_sdr_compact {
+ struct ipmi_sdr_header header;
+
+ uint8_t sensor_owner_id;
+ uint8_t sensor_owner_lun;
+ uint8_t sensor_owner_number; /* byte 8 */
+ uint8_t entity_id;
+ uint8_t entity_instance;
+ uint8_t sensor_init;
+ uint8_t sensor_caps;
+ uint8_t sensor_type;
+ uint8_t reading_type;
+ uint8_t assert_mask[2]; /* byte 16 */
+ uint8_t deassert_mask[2];
+ uint8_t discrete_mask[2];
+ uint8_t sensor_unit1;
+ uint8_t sensor_unit2;
+ uint8_t sensor_unit3;
+ uint8_t sensor_direction[2]; /* byte 24 */
+ uint8_t positive_threshold;
+ uint8_t negative_threshold;
+ uint8_t reserved[3];
+ uint8_t oem;
+ uint8_t id_str_len; /* byte 32 */
+ uint8_t id_string[16];
+};
+
+typedef uint8_t ipmi_sdr_compact_buffer[sizeof(struct ipmi_sdr_compact)];
+
+int ipmi_bmc_sdr_find(IPMIBmc *b, uint16_t recid,
+ const struct ipmi_sdr_compact **sdr, uint16_t *nextrec);
+void ipmi_bmc_gen_event(IPMIBmc *b, uint8_t *evt, bool log);
+
+#define TYPE_IPMI_BMC_SIMULATOR "ipmi-bmc-sim"
+OBJECT_DECLARE_SIMPLE_TYPE(IPMIBmcSim, IPMI_BMC_SIMULATOR)
+
+
+typedef struct RspBuffer {
+ uint8_t buffer[MAX_IPMI_MSG_SIZE];
+ unsigned int len;
+} RspBuffer;
+
+static inline void rsp_buffer_set_error(RspBuffer *rsp, uint8_t byte)
+{
+ rsp->buffer[2] = byte;
+}
+
+/* Add a byte to the response. */
+static inline void rsp_buffer_push(RspBuffer *rsp, uint8_t byte)
+{
+ if (rsp->len >= sizeof(rsp->buffer)) {
+ rsp_buffer_set_error(rsp, IPMI_CC_REQUEST_DATA_TRUNCATED);
+ return;
+ }
+ rsp->buffer[rsp->len++] = byte;
+}
+
+typedef struct IPMICmdHandler {
+ void (*cmd_handler)(IPMIBmcSim *s,
+ uint8_t *cmd, unsigned int cmd_len,
+ RspBuffer *rsp);
+ unsigned int cmd_len_min;
+} IPMICmdHandler;
+
+typedef struct IPMINetfn {
+ unsigned int cmd_nums;
+ const IPMICmdHandler *cmd_handlers;
+} IPMINetfn;
+
+int ipmi_sim_register_netfn(IPMIBmcSim *s, unsigned int netfn,
+ const IPMINetfn *netfnd);
+
+#endif
diff --git a/include/hw/ipmi/ipmi_bt.h b/include/hw/ipmi/ipmi_bt.h
new file mode 100644
index 000000000..8a4316ea7
--- /dev/null
+++ b/include/hw/ipmi/ipmi_bt.h
@@ -0,0 +1,73 @@
+/*
+ * QEMU IPMI BT emulation
+ *
+ * Copyright (c) 2015 Corey Minyard, MontaVista Software, LLC
+ *
+ * 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_IPMI_BT_H
+#define HW_IPMI_BT_H
+
+#include "hw/ipmi/ipmi.h"
+
+typedef struct IPMIBT {
+ IPMIBmc *bmc;
+
+ bool do_wake;
+
+ bool obf_irq_set;
+ bool atn_irq_set;
+ bool irqs_enabled;
+
+ uint8_t outmsg[MAX_IPMI_MSG_SIZE];
+ uint32_t outpos;
+ uint32_t outlen;
+
+ uint8_t inmsg[MAX_IPMI_MSG_SIZE];
+ uint32_t inlen;
+
+ uint8_t control_reg;
+ uint8_t mask_reg;
+
+ /*
+ * This is a response number that we send with the command to make
+ * sure that the response matches the command.
+ */
+ uint8_t waiting_rsp;
+ uint8_t waiting_seq;
+
+ uint32_t io_base;
+ unsigned long io_length;
+ MemoryRegion io;
+ unsigned long size_mask;
+
+ void (*raise_irq)(struct IPMIBT *ib);
+ void (*lower_irq)(struct IPMIBT *ib);
+ void *opaque;
+
+ bool use_irq;
+} IPMIBT;
+
+void ipmi_bt_get_fwinfo(IPMIBT *ik, IPMIFwInfo *info);
+void ipmi_bt_class_init(IPMIInterfaceClass *iic);
+extern const VMStateDescription vmstate_IPMIBT;
+int ipmi_bt_vmstate_post_load(void *opaque, int version);
+
+#endif /* HW_IPMI_BT_H */
diff --git a/include/hw/ipmi/ipmi_kcs.h b/include/hw/ipmi/ipmi_kcs.h
new file mode 100644
index 000000000..6e6ef4c53
--- /dev/null
+++ b/include/hw/ipmi/ipmi_kcs.h
@@ -0,0 +1,76 @@
+/*
+ * QEMU IPMI KCS emulation
+ *
+ * Copyright (c) 2015,2017 Corey Minyard, MontaVista Software, LLC
+ *
+ * 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_IPMI_KCS_H
+#define HW_IPMI_KCS_H
+
+#include "hw/ipmi/ipmi.h"
+
+typedef struct IPMIKCS {
+ IPMIBmc *bmc;
+
+ bool do_wake;
+
+ bool obf_irq_set;
+ bool atn_irq_set;
+ bool irqs_enabled;
+
+ uint8_t outmsg[MAX_IPMI_MSG_SIZE];
+ uint32_t outpos;
+ uint32_t outlen;
+
+ uint8_t inmsg[MAX_IPMI_MSG_SIZE];
+ uint32_t inlen;
+ bool write_end;
+
+ uint8_t status_reg;
+ uint8_t data_out_reg;
+
+ int16_t data_in_reg; /* -1 means not written */
+ int16_t cmd_reg;
+
+ /*
+ * This is a response number that we send with the command to make
+ * sure that the response matches the command.
+ */
+ uint8_t waiting_rsp;
+
+ uint32_t io_base;
+ unsigned long io_length;
+ MemoryRegion io;
+ unsigned long size_mask;
+
+ void (*raise_irq)(struct IPMIKCS *ik);
+ void (*lower_irq)(struct IPMIKCS *ik);
+ void *opaque;
+
+ bool use_irq;
+} IPMIKCS;
+
+void ipmi_kcs_get_fwinfo(IPMIKCS *ik, IPMIFwInfo *info);
+void ipmi_kcs_class_init(IPMIInterfaceClass *iic);
+extern const VMStateDescription vmstate_IPMIKCS;
+int ipmi_kcs_vmstate_post_load(void *opaque, int version);
+
+#endif /* HW_IPMI_KCS_H */
diff --git a/include/hw/irq.h b/include/hw/irq.h
new file mode 100644
index 000000000..dc7abf199
--- /dev/null
+++ b/include/hw/irq.h
@@ -0,0 +1,76 @@
+#ifndef QEMU_IRQ_H
+#define QEMU_IRQ_H
+
+/* Generic IRQ/GPIO pin infrastructure. */
+
+#define TYPE_IRQ "irq"
+
+void qemu_set_irq(qemu_irq irq, int level);
+
+static inline void qemu_irq_raise(qemu_irq irq)
+{
+ qemu_set_irq(irq, 1);
+}
+
+static inline void qemu_irq_lower(qemu_irq irq)
+{
+ qemu_set_irq(irq, 0);
+}
+
+static inline void qemu_irq_pulse(qemu_irq irq)
+{
+ qemu_set_irq(irq, 1);
+ qemu_set_irq(irq, 0);
+}
+
+/* Returns an array of N IRQs. Each IRQ is assigned the argument handler and
+ * opaque data.
+ */
+qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n);
+
+/*
+ * Allocates a single IRQ. The irq is assigned with a handler, an opaque
+ * data and the interrupt number.
+ */
+qemu_irq qemu_allocate_irq(qemu_irq_handler handler, void *opaque, int n);
+
+/* Extends an Array of IRQs. Old IRQs have their handlers and opaque data
+ * preserved. New IRQs are assigned the argument handler and opaque data.
+ */
+qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, qemu_irq_handler handler,
+ void *opaque, int n);
+
+void qemu_free_irqs(qemu_irq *s, int n);
+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);
+
+/**
+ * qemu_irq_is_connected: Return true if IRQ line is wired up
+ *
+ * If a qemu_irq has a device on the other (receiving) end of it,
+ * return true; otherwise return false.
+ *
+ * Usually device models don't need to care whether the machine model
+ * has wired up their outbound qemu_irq lines, because functions like
+ * qemu_set_irq() silently do nothing if there is nothing on the other
+ * end of the line. However occasionally a device model will want to
+ * provide default behaviour if its output is left floating, and
+ * it can use this function to identify when that is the case.
+ */
+static inline bool qemu_irq_is_connected(qemu_irq irq)
+{
+ return irq != NULL;
+}
+
+#endif
diff --git a/include/hw/isa/apm.h b/include/hw/isa/apm.h
new file mode 100644
index 000000000..b6e070c00
--- /dev/null
+++ b/include/hw/isa/apm.h
@@ -0,0 +1,25 @@
+#ifndef APM_H
+#define APM_H
+
+#include "exec/memory.h"
+
+#define APM_CNT_IOPORT 0xb2
+#define ACPI_PORT_SMI_CMD APM_CNT_IOPORT
+
+typedef void (*apm_ctrl_changed_t)(uint32_t val, void *arg);
+
+typedef struct APMState {
+ uint8_t apmc;
+ uint8_t apms;
+
+ apm_ctrl_changed_t callback;
+ void *arg;
+ MemoryRegion io;
+} APMState;
+
+void apm_init(PCIDevice *dev, APMState *s, apm_ctrl_changed_t callback,
+ void *arg);
+
+extern const VMStateDescription vmstate_apm;
+
+#endif /* APM_H */
diff --git a/include/hw/isa/i8259_internal.h b/include/hw/isa/i8259_internal.h
new file mode 100644
index 000000000..a6ae8a583
--- /dev/null
+++ b/include/hw/isa/i8259_internal.h
@@ -0,0 +1,79 @@
+/*
+ * QEMU 8259 - internal interfaces
+ *
+ * Copyright (c) 2011 Jan Kiszka, Siemens AG
+ *
+ * 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 QEMU_I8259_INTERNAL_H
+#define QEMU_I8259_INTERNAL_H
+
+#include "hw/isa/isa.h"
+#include "hw/intc/intc.h"
+#include "hw/intc/i8259.h"
+#include "qom/object.h"
+
+
+#define TYPE_PIC_COMMON "pic-common"
+OBJECT_DECLARE_TYPE(PICCommonState, PICCommonClass, PIC_COMMON)
+
+struct PICCommonClass {
+ ISADeviceClass parent_class;
+
+ void (*pre_save)(PICCommonState *s);
+ void (*post_load)(PICCommonState *s);
+};
+
+struct PICCommonState {
+ ISADevice parent_obj;
+
+ uint8_t last_irr; /* edge detection */
+ uint8_t irr; /* interrupt request register */
+ uint8_t imr; /* interrupt mask register */
+ uint8_t isr; /* interrupt service register */
+ uint8_t priority_add; /* highest irq priority */
+ uint8_t irq_base;
+ uint8_t read_reg_select;
+ uint8_t poll;
+ uint8_t special_mask;
+ uint8_t init_state;
+ uint8_t auto_eoi;
+ uint8_t rotate_on_auto_eoi;
+ uint8_t special_fully_nested_mode;
+ uint8_t init4; /* true if 4 byte init */
+ uint8_t single_mode; /* true if slave pic is not initialized */
+ uint8_t elcr; /* PIIX edge/trigger selection*/
+ uint8_t elcr_mask;
+ qemu_irq int_out[1];
+ uint32_t master; /* reflects /SP input pin */
+ uint32_t iobase;
+ uint32_t elcr_addr;
+ MemoryRegion base_io;
+ MemoryRegion elcr_io;
+};
+
+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
new file mode 100644
index 000000000..d4417b34b
--- /dev/null
+++ b/include/hw/isa/isa.h
@@ -0,0 +1,152 @@
+#ifndef HW_ISA_H
+#define HW_ISA_H
+
+/* ISA bus */
+
+#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"
+OBJECT_DECLARE_TYPE(ISADevice, ISADeviceClass, ISA_DEVICE)
+
+#define TYPE_ISA_BUS "ISA"
+OBJECT_DECLARE_SIMPLE_TYPE(ISABus, 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;
+}
+
+#define TYPE_ISADMA "isa-dma"
+
+typedef struct IsaDmaClass IsaDmaClass;
+DECLARE_CLASS_CHECKERS(IsaDmaClass, ISADMA,
+ TYPE_ISADMA)
+#define ISADMA(obj) \
+ INTERFACE_CHECK(IsaDma, (obj), TYPE_ISADMA)
+
+typedef enum {
+ ISADMA_TRANSFER_VERIFY,
+ ISADMA_TRANSFER_READ,
+ ISADMA_TRANSFER_WRITE,
+ ISADMA_TRANSFER_ILLEGAL,
+} IsaDmaTransferMode;
+
+typedef int (*IsaDmaTransferHandler)(void *opaque, int nchan, int pos,
+ int size);
+
+struct IsaDmaClass {
+ InterfaceClass parent;
+
+ bool (*has_autoinitialization)(IsaDma *obj, int nchan);
+ int (*read_memory)(IsaDma *obj, int nchan, void *buf, int pos, int len);
+ int (*write_memory)(IsaDma *obj, int nchan, void *buf, int pos, int len);
+ void (*hold_DREQ)(IsaDma *obj, int nchan);
+ void (*release_DREQ)(IsaDma *obj, int nchan);
+ void (*schedule)(IsaDma *obj);
+ void (*register_channel)(IsaDma *obj, int nchan,
+ IsaDmaTransferHandler transfer_handler,
+ void *opaque);
+};
+
+struct ISADeviceClass {
+ DeviceClass parent_class;
+ void (*build_aml)(ISADevice *dev, Aml *scope);
+};
+
+struct ISABus {
+ /*< private >*/
+ BusState parent_obj;
+ /*< public >*/
+
+ MemoryRegion *address_space;
+ MemoryRegion *address_space_io;
+ qemu_irq *irqs;
+ IsaDma *dma[2];
+};
+
+struct ISADevice {
+ /*< private >*/
+ 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_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);
+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);
+
+/**
+ * isa_register_ioport: Install an I/O port region on the ISA bus.
+ *
+ * Register an I/O port region via memory_region_add_subregion
+ * inside the ISA I/O address space.
+ *
+ * @dev: the ISADevice against which these are registered; may be NULL.
+ * @io: the #MemoryRegion being registered.
+ * @start: the base I/O port.
+ */
+void isa_register_ioport(ISADevice *dev, MemoryRegion *io, uint16_t start);
+
+/**
+ * isa_register_portio_list: Initialize a set of ISA io ports
+ *
+ * Several ISA devices have many dis-joint I/O ports. Worse, these I/O
+ * ports can be interleaved with I/O ports from other devices. This
+ * function makes it easy to create multiple MemoryRegions for a single
+ * device and use the legacy portio routines.
+ *
+ * @dev: the ISADevice against which these are registered; may be NULL.
+ * @piolist: the PortioList associated with the io ports
+ * @start: the base I/O port against which the portio->offset is applied.
+ * @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)
+ */
+int 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"
+
+#endif
diff --git a/include/hw/isa/pc87312.h b/include/hw/isa/pc87312.h
new file mode 100644
index 000000000..edaf723f4
--- /dev/null
+++ b/include/hw/isa/pc87312.h
@@ -0,0 +1,56 @@
+/*
+ * QEMU National Semiconductor PC87312 (Super I/O)
+ *
+ * Copyright (c) 2010-2012 Herve Poussineau
+ * Copyright (c) 2011-2012 Andreas Färber
+ *
+ * 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 QEMU_PC87312_H
+#define QEMU_PC87312_H
+
+#include "hw/isa/superio.h"
+#include "qom/object.h"
+
+
+#define TYPE_PC87312 "pc87312"
+OBJECT_DECLARE_SIMPLE_TYPE(PC87312State, PC87312)
+
+struct PC87312State {
+ /*< private >*/
+ ISASuperIODevice parent_dev;
+ /*< public >*/
+
+ uint16_t iobase;
+ uint8_t config; /* initial configuration */
+
+ struct {
+ ISADevice *dev;
+ } ide;
+
+ MemoryRegion io;
+
+ uint8_t read_id_step;
+ uint8_t selected_index;
+
+ uint8_t regs[3];
+};
+
+
+#endif
diff --git a/include/hw/isa/superio.h b/include/hw/isa/superio.h
new file mode 100644
index 000000000..b9f5c1915
--- /dev/null
+++ b/include/hw/isa/superio.h
@@ -0,0 +1,60 @@
+/*
+ * Generic ISA Super I/O
+ *
+ * Copyright (c) 2018 Philippe Mathieu-Daudé
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef HW_ISA_SUPERIO_H
+#define HW_ISA_SUPERIO_H
+
+#include "sysemu/sysemu.h"
+#include "hw/isa/isa.h"
+#include "qom/object.h"
+
+#define TYPE_ISA_SUPERIO "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
+
+struct ISASuperIODevice {
+ /*< private >*/
+ ISADevice parent_obj;
+ /*< public >*/
+
+ ISADevice *parallel[MAX_PARALLEL_PORTS];
+ ISADevice *serial[SUPERIO_MAX_SERIAL_PORTS];
+ ISADevice *floppy;
+ ISADevice *kbc;
+ ISADevice *ide;
+};
+
+typedef struct ISASuperIOFuncs {
+ size_t count;
+ bool (*is_enabled)(ISASuperIODevice *sio, uint8_t index);
+ uint16_t (*get_iobase)(ISASuperIODevice *sio, uint8_t index);
+ unsigned int (*get_irq)(ISASuperIODevice *sio, uint8_t index);
+ unsigned int (*get_dma)(ISASuperIODevice *sio, uint8_t index);
+} ISASuperIOFuncs;
+
+struct ISASuperIOClass {
+ /*< private >*/
+ ISADeviceClass parent_class;
+ /*< public >*/
+ DeviceRealize parent_realize;
+
+ ISASuperIOFuncs parallel;
+ ISASuperIOFuncs serial;
+ ISASuperIOFuncs floppy;
+ ISASuperIOFuncs ide;
+};
+
+#define TYPE_FDC37M81X_SUPERIO "fdc37m81x-superio"
+#define TYPE_SMC37C669_SUPERIO "smc37c669-superio"
+
+#endif /* HW_ISA_SUPERIO_H */
diff --git a/include/hw/isa/vt82c686.h b/include/hw/isa/vt82c686.h
new file mode 100644
index 000000000..56ac141be
--- /dev/null
+++ b/include/hw/isa/vt82c686.h
@@ -0,0 +1,15 @@
+#ifndef HW_VT82C686_H
+#define HW_VT82C686_H
+
+#include "hw/pci/pci.h"
+
+#define TYPE_VT82C686B_ISA "vt82c686b-isa"
+#define TYPE_VT82C686B_PM "vt82c686b-pm"
+#define TYPE_VT8231_ISA "vt8231-isa"
+#define TYPE_VT8231_PM "vt8231-pm"
+#define TYPE_VIA_AC97 "via-ac97"
+#define TYPE_VIA_MC97 "via-mc97"
+
+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
new file mode 100644
index 000000000..7994071c4
--- /dev/null
+++ b/include/hw/kvm/clock.h
@@ -0,0 +1,28 @@
+/*
+ * 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(bool create_always);
+
+#else /* CONFIG_KVM */
+
+static inline void kvmclock_create(bool create_always)
+{
+}
+
+#endif /* !CONFIG_KVM */
+
+#endif
diff --git a/include/hw/loader-fit.h b/include/hw/loader-fit.h
new file mode 100644
index 000000000..0832e379d
--- /dev/null
+++ b/include/hw/loader-fit.h
@@ -0,0 +1,41 @@
+/*
+ * Flattened Image Tree loader.
+ *
+ * Copyright (c) 2016 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.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 HW_LOADER_FIT_H
+#define HW_LOADER_FIT_H
+
+#include "exec/hwaddr.h"
+
+struct fit_loader_match {
+ const char *compatible;
+ const void *data;
+};
+
+struct fit_loader {
+ const struct fit_loader_match *matches;
+ hwaddr (*addr_to_phys)(void *opaque, uint64_t addr);
+ const void *(*fdt_filter)(void *opaque, const void *fdt,
+ const void *match_data, hwaddr *load_addr);
+ const void *(*kernel_filter)(void *opaque, const void *kernel,
+ hwaddr *load_addr, hwaddr *entry_addr);
+};
+
+int load_fit(const struct fit_loader *ldr, const char *filename, void *opaque);
+
+#endif /* HW_LOADER_FIT_H */
diff --git a/include/hw/loader.h b/include/hw/loader.h
new file mode 100644
index 000000000..4fa485bd6
--- /dev/null
+++ b/include/hw/loader.h
@@ -0,0 +1,346 @@
+#ifndef LOADER_H
+#define LOADER_H
+#include "hw/nvram/fw_cfg.h"
+
+/* loader.c */
+/**
+ * get_image_size: retrieve size of an image file
+ * @filename: Path to the image file
+ *
+ * Returns the size of the image file on success, -1 otherwise.
+ * On error, errno is also set as appropriate.
+ */
+int64_t get_image_size(const char *filename);
+/**
+ * load_image_size: load an image file into specified buffer
+ * @filename: Path to the image file
+ * @addr: Buffer to load image into
+ * @size: Size of buffer in bytes
+ *
+ * Load an image file from disk into the specified buffer.
+ * If the image is larger than the specified buffer, only
+ * @size bytes are read (this is not considered an error).
+ *
+ * Prefer to use the GLib function g_file_get_contents() rather
+ * than a "get_image_size()/g_malloc()/load_image_size()" sequence.
+ *
+ * Returns the number of bytes read, or -1 on error. On error,
+ * errno is also set as appropriate.
+ */
+ssize_t load_image_size(const char *filename, void *addr, size_t size);
+
+/**load_image_targphys_as:
+ * @filename: Path to the image file
+ * @addr: Address to load the image to
+ * @max_sz: The maximum size of the image to load
+ * @as: The AddressSpace to load the ELF to. The value of address_space_memory
+ * is used if nothing is supplied here.
+ *
+ * Load a fixed image into memory.
+ *
+ * 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);
+
+/**load_targphys_hex_as:
+ * @filename: Path to the .hex file
+ * @entry: Store the entry point given by the .hex file
+ * @as: The AddressSpace to load the .hex file to. The value of
+ * address_space_memory is used if nothing is supplied here.
+ *
+ * Load a fixed .hex file into memory.
+ *
+ * Returns the size of the loaded .hex file on success, -1 otherwise.
+ */
+int 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);
+
+/**
+ * load_image_mr: load an image into a memory region
+ * @filename: Path to the image file
+ * @mr: Memory Region to load into
+ *
+ * Load the specified file into the memory region.
+ * The file loaded is registered as a ROM, so its contents will be
+ * reinstated whenever the system is reset.
+ * 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);
+
+/* This is the limit on the maximum uncompressed image size that
+ * load_image_gzipped_buffer() and load_image_gzipped() will read. It prevents
+ * g_malloc() in those functions from allocating a huge amount of memory.
+ */
+#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);
+
+#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(ssize_t error);
+
+/** load_elf_ram_sym:
+ * @filename: Path of ELF file
+ * @elf_note_fn: optional function to parse ELF Note type
+ * passed via @translate_opaque
+ * @translate_fn: optional function to translate load addresses
+ * @translate_opaque: opaque data passed to @translate_fn
+ * @pentry: Populated with program entry point. Ignored if NULL.
+ * @lowaddr: Populated with lowest loaded address. Ignored if NULL.
+ * @highaddr: Populated with highest loaded address. Ignored if NULL.
+ * @pflags: Populated with ELF processor-specific flags. Ignore if NULL.
+ * @bigendian: Expected ELF endianness. 0 for LE otherwise BE
+ * @elf_machine: Expected ELF machine type
+ * @clear_lsb: Set to mask off LSB of addresses (Some architectures use
+ * this for non-address data)
+ * @data_swab: Set to order of byte swapping for data. 0 for no swap, 1
+ * for swapping bytes within halfwords, 2 for bytes within
+ * words and 3 for within doublewords.
+ * @as: The AddressSpace to load the ELF to. The value of address_space_memory
+ * is used if nothing is supplied here.
+ * @load_rom : Load ELF binary as ROM
+ * @sym_cb: Callback function for symbol table entries
+ *
+ * Load an ELF file's contents to the emulated system's address space.
+ * Clients may optionally specify a callback to perform address
+ * translations. @pentry, @lowaddr and @highaddr are optional pointers
+ * which will be populated with various load information. @bigendian and
+ * @elf_machine give the expected endianness and machine for the ELF the
+ * load will fail if the target ELF does not match. Some architectures
+ * have some architecture-specific behaviours that come into effect when
+ * their particular values for @elf_machine are set.
+ * If @elf_machine is EM_NONE then the machine type will be read from the
+ * ELF header and no checks will be carried out against the machine type.
+ */
+typedef void (*symbol_fn_t)(const char *st_name, int st_info,
+ uint64_t st_value, uint64_t st_size);
+
+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
+ */
+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
+ */
+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.
+ */
+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
+ * @hdr: Buffer to populate with header data. Header data will not be
+ * filled if set to NULL.
+ * @is64: Set to true if the ELF is 64bit. Ignored if set to NULL
+ * @errp: Populated with an error in failure cases
+ *
+ * Inspect an ELF file's header. Read its full header contents into a
+ * buffer and/or determine if the ELF is 64bit.
+ */
+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);
+
+#define LOAD_UIMAGE_LOADADDR_INVALID (-1)
+
+/** load_uimage_as:
+ * @filename: Path of uimage file
+ * @ep: Populated with program entry point. Ignored if NULL.
+ * @loadaddr: load address if none specified in the image or when loading a
+ * ramdisk. Populated with the load address. Ignored if NULL or
+ * LOAD_UIMAGE_LOADADDR_INVALID (images which do not specify a load
+ * address will not be loadable).
+ * @is_linux: Is set to true if the image loaded is Linux. Ignored if NULL.
+ * @translate_fn: optional function to translate load addresses
+ * @translate_opaque: opaque data passed to @translate_fn
+ * @as: The AddressSpace to load the ELF to. The value of address_space_memory
+ * is used if nothing is supplied here.
+ *
+ * Loads a u-boot image into memory.
+ *
+ * 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);
+
+/** 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);
+
+/**
+ * load_ramdisk_as:
+ * @filename: Path to the ramdisk image
+ * @addr: Memory address to load the ramdisk to
+ * @max_sz: Maximum allowed ramdisk size (for non-u-boot ramdisks)
+ * @as: The AddressSpace to load the ELF to. The value of address_space_memory
+ * is used if nothing is supplied here.
+ *
+ * Load a ramdisk image with U-Boot header to the specified memory
+ * address.
+ *
+ * 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);
+
+/**
+ * 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 gunzip(void *dst, size_t dstlen, uint8_t *src, size_t srclen);
+
+ssize_t read_targphys(const char *name,
+ int fd, hwaddr dst_addr, size_t nbytes);
+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);
+MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len,
+ size_t max_len, hwaddr addr,
+ const char *fw_file_name,
+ FWCfgCallback fw_callback,
+ void *callback_opaque, AddressSpace *as,
+ bool read_only);
+int rom_add_elf_program(const char *name, GMappedFile *mapped_file, void *data,
+ size_t datasize, size_t romsize, hwaddr addr,
+ AddressSpace *as);
+int rom_check_and_register_reset(void);
+void rom_set_fw(FWCfgState *f);
+void rom_set_order_override(int order);
+void rom_reset_order_override(void);
+
+/**
+ * rom_transaction_begin:
+ *
+ * Call this before of a series of rom_add_*() calls. Call
+ * rom_transaction_end() afterwards to commit or abort. These functions are
+ * useful for undoing a series of rom_add_*() calls if image file loading fails
+ * partway through.
+ */
+void rom_transaction_begin(void);
+
+/**
+ * rom_transaction_end:
+ * @commit: true to commit added roms, false to drop added roms
+ *
+ * Call this after a series of rom_add_*() calls. See rom_transaction_begin().
+ */
+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) \
+ rom_add_file(_f, NULL, _a, _i, false, NULL, NULL)
+#define rom_add_blob_fixed(_f, _b, _l, _a) \
+ rom_add_blob(_f, _b, _l, _l, _a, NULL, NULL, NULL, NULL, true)
+#define rom_add_file_mr(_f, _mr, _i) \
+ rom_add_file(_f, NULL, 0, _i, false, _mr, NULL)
+#define rom_add_file_as(_f, _as, _i) \
+ rom_add_file(_f, NULL, 0, _i, false, NULL, _as)
+#define rom_add_file_fixed_as(_f, _a, _i, _as) \
+ rom_add_file(_f, NULL, _a, _i, false, NULL, _as)
+#define rom_add_blob_fixed_as(_f, _b, _l, _a, _as) \
+ rom_add_blob(_f, _b, _l, _l, _a, NULL, NULL, NULL, _as, true)
+
+int rom_add_vga(const char *file);
+int 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)
+
+#endif
diff --git a/include/hw/m68k/mcf.h b/include/hw/m68k/mcf.h
new file mode 100644
index 000000000..decf17ce4
--- /dev/null
+++ b/include/hw/m68k/mcf.h
@@ -0,0 +1,23 @@
+#ifndef HW_MCF_H
+#define HW_MCF_H
+/* Motorola ColdFire device prototypes. */
+
+#include "target/m68k/cpu-qom.h"
+
+/* mcf_uart.c */
+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);
+
+/* mcf_intc.c */
+qemu_irq *mcf_intc_init(struct MemoryRegion *sysmem,
+ hwaddr base,
+ M68kCPU *cpu);
+
+/* mcf5206.c */
+#define TYPE_MCF5206_MBAR "mcf5206-mbar"
+
+#endif
diff --git a/include/hw/m68k/mcf_fec.h b/include/hw/m68k/mcf_fec.h
new file mode 100644
index 000000000..80d4f651b
--- /dev/null
+++ b/include/hw/m68k/mcf_fec.h
@@ -0,0 +1,19 @@
+/*
+ * Definitions for the ColdFire Fast Ethernet Controller emulation.
+ *
+ * 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 HW_M68K_MCF_FEC_H
+#define HW_M68K_MCF_FEC_H
+#include "qom/object.h"
+
+#define TYPE_MCF_FEC_NET "mcf-fec"
+OBJECT_DECLARE_SIMPLE_TYPE(mcf_fec_state, MCF_FEC_NET)
+
+#define FEC_NUM_IRQ 13
+
+#endif
diff --git a/include/hw/m68k/next-cube.h b/include/hw/m68k/next-cube.h
new file mode 100644
index 000000000..43577282d
--- /dev/null
+++ b/include/hw/m68k/next-cube.h
@@ -0,0 +1,56 @@
+/*
+ * 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
+
+#define TYPE_NEXTFB "next-fb"
+
+#define TYPE_NEXTKBD "next-kbd"
+
+enum next_dma_chan {
+ NEXTDMA_FD,
+ NEXTDMA_ENRX,
+ NEXTDMA_ENTX,
+ NEXTDMA_SCSI,
+ NEXTDMA_SCC,
+ NEXTDMA_SND
+};
+
+#define DMA_ENABLE 0x01000000
+#define DMA_SUPDATE 0x02000000
+#define DMA_COMPLETE 0x08000000
+
+#define DMA_M2DEV 0x0
+#define DMA_SETENABLE 0x00010000
+#define DMA_SETSUPDATE 0x00020000
+#define DMA_DEV2M 0x00040000
+#define DMA_CLRCOMPLETE 0x00080000
+#define DMA_RESET 0x00100000
+
+enum next_irqs {
+ NEXT_FD_I,
+ NEXT_KBD_I,
+ NEXT_PWR_I,
+ NEXT_ENRX_I,
+ NEXT_ENTX_I,
+ NEXT_SCSI_I,
+ NEXT_CLK_I,
+ NEXT_SCC_I,
+ NEXT_ENTX_DMA_I,
+ NEXT_ENRX_DMA_I,
+ NEXT_SCSI_DMA_I,
+ NEXT_SCC_DMA_I,
+ NEXT_SND_I,
+ NEXT_NUM_IRQS
+};
+
+#endif /* NEXT_CUBE_H */
diff --git a/include/hw/mem/memory-device.h b/include/hw/mem/memory-device.h
new file mode 100644
index 000000000..48d2611fc
--- /dev/null
+++ b/include/hw/mem/memory-device.h
@@ -0,0 +1,117 @@
+/*
+ * Memory Device Interface
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * Authors:
+ * David Hildenbrand <david@redhat.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 MEMORY_DEVICE_H
+#define MEMORY_DEVICE_H
+
+#include "hw/qdev-core.h"
+#include "qapi/qapi-types-machine.h"
+#include "qom/object.h"
+
+#define TYPE_MEMORY_DEVICE "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)
+
+typedef struct MemoryDeviceState MemoryDeviceState;
+
+/**
+ * MemoryDeviceClass:
+ *
+ * All memory devices need to implement TYPE_MEMORY_DEVICE as an interface.
+ *
+ * A memory device is a device that owns a memory region which is
+ * mapped into guest physical address space at a certain address. The
+ * address in guest physical memory can either be specified explicitly
+ * or get assigned automatically.
+ *
+ * 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.
+ */
+struct MemoryDeviceClass {
+ /* private */
+ InterfaceClass parent_class;
+
+ /*
+ * Return the address of the memory device in guest physical memory.
+ *
+ * Called when (un)plugging a memory device or when iterating over
+ * all memory devices mapped into guest physical address space.
+ *
+ * If "0" is returned, no address has been specified by the user and
+ * no address has been assigned to this memory device yet.
+ */
+ uint64_t (*get_addr)(const MemoryDeviceState *md);
+
+ /*
+ * Set the address of the memory device in guest physical memory.
+ *
+ * Called when plugging the memory device to configure the determined
+ * address in guest physical memory.
+ */
+ void (*set_addr)(MemoryDeviceState *md, uint64_t addr, Error **errp);
+
+ /*
+ * Return the amount of memory provided by the memory device currently
+ * usable ("plugged") by the VM.
+ *
+ * Called when calculating the total amount of ram available to the
+ * VM (e.g. to report memory stats to the user).
+ *
+ * This is helpful for devices that dynamically manage the amount of
+ * memory accessible by the guest via the reserved memory region. For
+ * most devices, this corresponds to the size of the memory region.
+ */
+ uint64_t (*get_plugged_size)(const MemoryDeviceState *md, Error **errp);
+
+ /*
+ * Return the memory region of the memory device.
+ *
+ * Called when (un)plugging the memory device, to (un)map the
+ * memory region in guest physical memory, but also to detect the
+ * required alignment during address assignment or when the size of the
+ * memory region is required.
+ */
+ MemoryRegion *(*get_memory_region)(MemoryDeviceState *md, Error **errp);
+
+ /*
+ * 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);
+};
+
+MemoryDeviceInfoList *qmp_memory_device_list(void);
+uint64_t get_plugged_memory_size(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);
+void memory_device_unplug(MemoryDeviceState *md, MachineState *ms);
+uint64_t memory_device_get_region_size(const MemoryDeviceState *md,
+ Error **errp);
+
+#endif
diff --git a/include/hw/mem/npcm7xx_mc.h b/include/hw/mem/npcm7xx_mc.h
new file mode 100644
index 000000000..7ed38be24
--- /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
new file mode 100644
index 000000000..bcf62f825
--- /dev/null
+++ b/include/hw/mem/nvdimm.h
@@ -0,0 +1,161 @@
+/*
+ * Non-Volatile Dual In-line Memory Module Virtualization Implementation
+ *
+ * Copyright(C) 2015 Intel Corporation.
+ *
+ * Author:
+ * Xiao Guangrong <guangrong.xiao@linux.intel.com>
+ *
+ * NVDIMM specifications and some documents can be found at:
+ * NVDIMM ACPI device and NFIT are introduced in ACPI 6:
+ * http://www.uefi.org/sites/default/files/resources/ACPI_6.0.pdf
+ * NVDIMM Namespace specification:
+ * http://pmem.io/documents/NVDIMM_Namespace_Spec.pdf
+ * DSM Interface Example:
+ * http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf
+ * Driver Writer's Guide:
+ * http://pmem.io/documents/NVDIMM_Driver_Writers_Guide.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 QEMU_NVDIMM_H
+#define QEMU_NVDIMM_H
+
+#include "hw/mem/pc-dimm.h"
+#include "hw/acpi/bios-linker-loader.h"
+#include "qemu/uuid.h"
+#include "hw/acpi/aml-build.h"
+#include "qom/object.h"
+
+#define NVDIMM_DEBUG 0
+#define nvdimm_debug(fmt, ...) \
+ do { \
+ if (NVDIMM_DEBUG) { \
+ fprintf(stderr, "nvdimm: " fmt, ## __VA_ARGS__); \
+ } \
+ } while (0)
+
+/*
+ * The minimum label data size is required by NVDIMM Namespace
+ * specification, see the chapter 2 Namespaces:
+ * "NVDIMMs following the NVDIMM Block Mode Specification use an area
+ * at least 128KB in size, which holds around 1000 labels."
+ */
+#define MIN_NAMESPACE_LABEL_SIZE (128UL << 10)
+
+#define TYPE_NVDIMM "nvdimm"
+OBJECT_DECLARE_TYPE(NVDIMMDevice, NVDIMMClass, NVDIMM)
+
+#define NVDIMM_LABEL_SIZE_PROP "label-size"
+#define NVDIMM_UUID_PROP "uuid"
+#define NVDIMM_UNARMED_PROP "unarmed"
+
+struct NVDIMMDevice {
+ /* private */
+ PCDIMMDevice parent_obj;
+
+ /* public */
+
+ /*
+ * the size of label data in NVDIMM device which is presented to
+ * guest via __DSM "Get Namespace Label Size" function.
+ */
+ uint64_t label_size;
+
+ /*
+ * the address of label data which is read by __DSM "Get Namespace
+ * Label Data" function and written by __DSM "Set Namespace Label
+ * Data" function.
+ */
+ void *label_data;
+
+ /*
+ * it's the PMEM region in NVDIMM device, which is presented to
+ * guest via ACPI NFIT and _FIT method if NVDIMM hotplug is supported.
+ */
+ MemoryRegion *nvdimm_mr;
+
+ /*
+ * The 'on' value results in the unarmed flag set in ACPI NFIT,
+ * which can be used to notify guest implicitly that the host
+ * backend (e.g., files on HDD, /dev/pmemX, etc.) cannot guarantee
+ * the guest write persistence.
+ */
+ bool unarmed;
+
+ /*
+ * The PPC64 - spapr requires each nvdimm device have a uuid.
+ */
+ QemuUUID uuid;
+};
+
+struct NVDIMMClass {
+ /* private */
+ PCDIMMDeviceClass parent_class;
+
+ /* public */
+
+ /* read @size bytes from NVDIMM label data at @offset into @buf. */
+ void (*read_label_data)(NVDIMMDevice *nvdimm, void *buf,
+ uint64_t size, uint64_t offset);
+ /* 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);
+};
+
+#define NVDIMM_DSM_MEM_FILE "etc/acpi/nvdimm-mem"
+
+/*
+ * 32 bits IO port starting from 0x0a18 in guest is reserved for
+ * NVDIMM ACPI emulation.
+ */
+#define NVDIMM_ACPI_IO_BASE 0x0a18
+#define NVDIMM_ACPI_IO_LEN 4
+
+/*
+ * NvdimmFitBuffer:
+ * @fit: FIT structures for present NVDIMMs. It is updated when
+ * the NVDIMM device is plugged or unplugged.
+ * @dirty: It allows OSPM to detect change and restart read in
+ * progress if there is any.
+ */
+struct NvdimmFitBuffer {
+ GArray *fit;
+ bool dirty;
+};
+typedef struct NvdimmFitBuffer NvdimmFitBuffer;
+
+struct NVDIMMState {
+ /* detect if NVDIMM support is enabled. */
+ bool is_enabled;
+
+ /* the data of the fw_cfg file NVDIMM_DSM_MEM_FILE. */
+ GArray *dsm_mem;
+
+ NvdimmFitBuffer fit_buf;
+
+ /* the IO region used by OSPM to transfer control to QEMU. */
+ MemoryRegion io_mr;
+
+ /*
+ * Platform capabilities, section 5.2.25.9 of ACPI 6.2 Errata A
+ */
+ int32_t persistence;
+ char *persistence_string;
+ struct AcpiGenericAddress dsm_io;
+};
+typedef struct NVDIMMState NVDIMMState;
+
+void nvdimm_init_acpi_state(NVDIMMState *state, MemoryRegion *io,
+ struct AcpiGenericAddress dsm_io,
+ FWCfgState *fw_cfg, Object *owner);
+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, 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
new file mode 100644
index 000000000..1473e6db6
--- /dev/null
+++ b/include/hw/mem/pc-dimm.h
@@ -0,0 +1,72 @@
+/*
+ * PC DIMM device
+ *
+ * Copyright ProfitBricks GmbH 2012
+ * Copyright (C) 2013-2014 Red Hat Inc
+ *
+ * Authors:
+ * Vasilis Liaskovitis <vasilis.liaskovitis@profitbricks.com>
+ * Igor Mammedov <imammedo@redhat.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_PC_DIMM_H
+#define QEMU_PC_DIMM_H
+
+#include "exec/memory.h"
+#include "hw/qdev-core.h"
+#include "qom/object.h"
+
+#define TYPE_PC_DIMM "pc-dimm"
+OBJECT_DECLARE_TYPE(PCDIMMDevice, PCDIMMDeviceClass,
+ PC_DIMM)
+
+#define PC_DIMM_ADDR_PROP "addr"
+#define PC_DIMM_SLOT_PROP "slot"
+#define PC_DIMM_NODE_PROP "node"
+#define PC_DIMM_SIZE_PROP "size"
+#define PC_DIMM_MEMDEV_PROP "memdev"
+
+#define PC_DIMM_UNASSIGNED_SLOT -1
+
+/**
+ * PCDIMMDevice:
+ * @addr: starting guest physical address, where @PCDIMMDevice is mapped.
+ * Default value: 0, means that address is auto-allocated.
+ * @node: numa node to which @PCDIMMDevice is attached.
+ * @slot: slot number into which @PCDIMMDevice is plugged in.
+ * Default value: -1, means that slot is auto-allocated.
+ * @hostmem: host memory backend providing memory for @PCDIMMDevice
+ */
+struct PCDIMMDevice {
+ /* private */
+ DeviceState parent_obj;
+
+ /* public */
+ uint64_t addr;
+ uint32_t node;
+ int32_t slot;
+ HostMemoryBackend *hostmem;
+};
+
+/**
+ * PCDIMMDeviceClass:
+ * @realize: called after common dimm is realized so that the dimm based
+ * devices get the chance to do specified operations.
+ */
+struct PCDIMMDeviceClass {
+ /* private */
+ DeviceClass parent_class;
+
+ /* public */
+ void (*realize)(PCDIMMDevice *dimm, Error **errp);
+};
+
+void pc_dimm_pre_plug(PCDIMMDevice *dimm, MachineState *machine,
+ const uint64_t *legacy_align, 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 000000000..f9863b154
--- /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
new file mode 100644
index 000000000..c03007999
--- /dev/null
+++ b/include/hw/mips/bios.h
@@ -0,0 +1,14 @@
+#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 000000000..b5f48d71b
--- /dev/null
+++ b/include/hw/mips/bootloader.h
@@ -0,0 +1,22 @@
+/*
+ * 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(uint32_t **p, target_ulong jump_addr);
+void bl_gen_jump_kernel(uint32_t **p, target_ulong sp, target_ulong a0,
+ target_ulong a1, target_ulong a2, target_ulong a3,
+ target_ulong kernel_addr);
+void bl_gen_write_ulong(uint32_t **p, target_ulong addr, target_ulong val);
+void bl_gen_write_u32(uint32_t **p, target_ulong addr, uint32_t val);
+void bl_gen_write_u64(uint32_t **p, target_ulong addr, uint64_t val);
+
+#endif
diff --git a/include/hw/mips/cps.h b/include/hw/mips/cps.h
new file mode 100644
index 000000000..04d636246
--- /dev/null
+++ b/include/hw/mips/cps.h
@@ -0,0 +1,52 @@
+/*
+ * Coherent Processing System emulation.
+ *
+ * Copyright (c) 2016 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.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 MIPS_CPS_H
+#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"
+OBJECT_DECLARE_SIMPLE_TYPE(MIPSCPSState, MIPS_CPS)
+
+struct MIPSCPSState {
+ SysBusDevice parent_obj;
+
+ uint32_t num_vp;
+ uint32_t num_irq;
+ char *cpu_type;
+
+ MemoryRegion container;
+ MIPSGCRState gcr;
+ MIPSGICState gic;
+ MIPSCPCState cpc;
+ MIPSITUState itu;
+ Clock *clock;
+};
+
+qemu_irq get_cps_irq(MIPSCPSState *cps, int pin_number);
+
+#endif
diff --git a/include/hw/mips/cpudevs.h b/include/hw/mips/cpudevs.h
new file mode 100644
index 000000000..f7c9728fa
--- /dev/null
+++ b/include/hw/mips/cpudevs.h
@@ -0,0 +1,14 @@
+#ifndef HW_MIPS_CPUDEVS_H
+#define HW_MIPS_CPUDEVS_H
+
+#include "target/mips/cpu-qom.h"
+
+/* Definitions for MIPS CPU internal devices. */
+
+/* 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
new file mode 100644
index 000000000..6c9c8805f
--- /dev/null
+++ b/include/hw/mips/mips.h
@@ -0,0 +1,25 @@
+#ifndef HW_MIPS_H
+#define HW_MIPS_H
+/* Definitions for mips board emulation. */
+
+#include "qemu/units.h"
+
+/* Kernels can be configured with 64KB pages */
+#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);
+
+/* rc4030.c */
+typedef struct rc4030DMAState *rc4030_dma;
+void rc4030_dma_read(void *dma, uint8_t *buf, int len);
+void rc4030_dma_write(void *dma, uint8_t *buf, int len);
+
+DeviceState *rc4030_init(rc4030_dma **dmas, IOMMUMemoryRegion **dma_mr);
+
+#endif
diff --git a/include/hw/misc/a9scu.h b/include/hw/misc/a9scu.h
new file mode 100644
index 000000000..c3759fb8c
--- /dev/null
+++ b/include/hw/misc/a9scu.h
@@ -0,0 +1,32 @@
+/*
+ * Cortex-A9MPCore Snoop Control Unit (SCU) emulation.
+ *
+ * Copyright (c) 2009 CodeSourcery.
+ * Copyright (c) 2011 Linaro Limited.
+ * Written by Paul Brook, Peter Maydell.
+ *
+ * This code is licensed under the GPL.
+ */
+#ifndef HW_MISC_A9SCU_H
+#define HW_MISC_A9SCU_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+/* A9MP private memory region. */
+
+struct A9SCUState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ MemoryRegion iomem;
+ uint32_t control;
+ uint32_t status;
+ uint32_t num_cpu;
+};
+
+#define TYPE_A9_SCU "a9-scu"
+OBJECT_DECLARE_SIMPLE_TYPE(A9SCUState, A9_SCU)
+
+#endif
diff --git a/include/hw/misc/allwinner-cpucfg.h b/include/hw/misc/allwinner-cpucfg.h
new file mode 100644
index 000000000..a717b4729
--- /dev/null
+++ b/include/hw/misc/allwinner-cpucfg.h
@@ -0,0 +1,51 @@
+/*
+ * Allwinner CPU Configuration Module emulation
+ *
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.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_CPUCFG_H
+#define HW_MISC_ALLWINNER_CPUCFG_H
+
+#include "qom/object.h"
+#include "hw/sysbus.h"
+
+/**
+ * Object model
+ * @{
+ */
+
+#define TYPE_AW_CPUCFG "allwinner-cpucfg"
+OBJECT_DECLARE_SIMPLE_TYPE(AwCpuCfgState, AW_CPUCFG)
+
+/** @} */
+
+/**
+ * Allwinner CPU Configuration Module instance state
+ */
+struct AwCpuCfgState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ MemoryRegion iomem;
+ uint32_t gen_ctrl;
+ uint32_t super_standby;
+ uint32_t entry_addr;
+
+};
+
+#endif /* HW_MISC_ALLWINNER_CPUCFG_H */
diff --git a/include/hw/misc/allwinner-h3-ccu.h b/include/hw/misc/allwinner-h3-ccu.h
new file mode 100644
index 000000000..a04875bfc
--- /dev/null
+++ b/include/hw/misc/allwinner-h3-ccu.h
@@ -0,0 +1,65 @@
+/*
+ * Allwinner H3 Clock Control Unit emulation
+ *
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.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_H3_CCU_H
+#define HW_MISC_ALLWINNER_H3_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_H3_CCU_IOSIZE (0x400)
+
+/** Total number of known registers */
+#define AW_H3_CCU_REGS_NUM (AW_H3_CCU_IOSIZE / sizeof(uint32_t))
+
+/** @} */
+
+/**
+ * @name Object model
+ * @{
+ */
+
+#define TYPE_AW_H3_CCU "allwinner-h3-ccu"
+OBJECT_DECLARE_SIMPLE_TYPE(AwH3ClockCtlState, AW_H3_CCU)
+
+/** @} */
+
+/**
+ * Allwinner H3 CCU object instance state.
+ */
+struct AwH3ClockCtlState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ /** Maps I/O registers in physical memory */
+ MemoryRegion iomem;
+
+ /** Array of hardware registers */
+ uint32_t regs[AW_H3_CCU_REGS_NUM];
+
+};
+
+#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
new file mode 100644
index 000000000..0b6c877ef
--- /dev/null
+++ b/include/hw/misc/allwinner-h3-dramc.h
@@ -0,0 +1,105 @@
+/*
+ * Allwinner H3 SDRAM Controller emulation
+ *
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.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_H3_DRAMC_H
+#define HW_MISC_ALLWINNER_H3_DRAMC_H
+
+#include "qom/object.h"
+#include "hw/sysbus.h"
+#include "exec/hwaddr.h"
+
+/**
+ * Constants
+ * @{
+ */
+
+/** Highest register address used by DRAMCOM module */
+#define AW_H3_DRAMCOM_REGS_MAXADDR (0x804)
+
+/** Total number of known DRAMCOM registers */
+#define AW_H3_DRAMCOM_REGS_NUM (AW_H3_DRAMCOM_REGS_MAXADDR / \
+ sizeof(uint32_t))
+
+/** Highest register address used by DRAMCTL module */
+#define AW_H3_DRAMCTL_REGS_MAXADDR (0x88c)
+
+/** Total number of known DRAMCTL registers */
+#define AW_H3_DRAMCTL_REGS_NUM (AW_H3_DRAMCTL_REGS_MAXADDR / \
+ sizeof(uint32_t))
+
+/** Highest register address used by DRAMPHY module */
+#define AW_H3_DRAMPHY_REGS_MAXADDR (0x4)
+
+/** Total number of known DRAMPHY registers */
+#define AW_H3_DRAMPHY_REGS_NUM (AW_H3_DRAMPHY_REGS_MAXADDR / \
+ sizeof(uint32_t))
+
+/** @} */
+
+/**
+ * Object model
+ * @{
+ */
+
+#define TYPE_AW_H3_DRAMC "allwinner-h3-dramc"
+OBJECT_DECLARE_SIMPLE_TYPE(AwH3DramCtlState, AW_H3_DRAMC)
+
+/** @} */
+
+/**
+ * Allwinner H3 SDRAM Controller object instance state.
+ */
+struct AwH3DramCtlState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ /** Physical base address for start of RAM */
+ hwaddr ram_addr;
+
+ /** Total RAM size in megabytes */
+ uint32_t ram_size;
+
+ /**
+ * @name Memory Regions
+ * @{
+ */
+
+ MemoryRegion row_mirror; /**< Simulates rows for RAM size detection */
+ MemoryRegion row_mirror_alias; /**< Alias of the row which is mirrored */
+ MemoryRegion dramcom_iomem; /**< DRAMCOM module I/O registers */
+ MemoryRegion dramctl_iomem; /**< DRAMCTL module I/O registers */
+ MemoryRegion dramphy_iomem; /**< DRAMPHY module I/O registers */
+
+ /** @} */
+
+ /**
+ * @name Hardware Registers
+ * @{
+ */
+
+ uint32_t dramcom[AW_H3_DRAMCOM_REGS_NUM]; /**< Array of DRAMCOM registers */
+ uint32_t dramctl[AW_H3_DRAMCTL_REGS_NUM]; /**< Array of DRAMCTL registers */
+ uint32_t dramphy[AW_H3_DRAMPHY_REGS_NUM] ;/**< Array of DRAMPHY registers */
+
+ /** @} */
+
+};
+
+#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
new file mode 100644
index 000000000..ec1c22053
--- /dev/null
+++ b/include/hw/misc/allwinner-h3-sysctrl.h
@@ -0,0 +1,66 @@
+/*
+ * Allwinner H3 System Control emulation
+ *
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.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_H3_SYSCTRL_H
+#define HW_MISC_ALLWINNER_H3_SYSCTRL_H
+
+#include "qom/object.h"
+#include "hw/sysbus.h"
+
+/**
+ * @name Constants
+ * @{
+ */
+
+/** Highest register address used by System Control device */
+#define AW_H3_SYSCTRL_REGS_MAXADDR (0x30)
+
+/** Total number of known registers */
+#define AW_H3_SYSCTRL_REGS_NUM ((AW_H3_SYSCTRL_REGS_MAXADDR / \
+ sizeof(uint32_t)) + 1)
+
+/** @} */
+
+/**
+ * @name Object model
+ * @{
+ */
+
+#define TYPE_AW_H3_SYSCTRL "allwinner-h3-sysctrl"
+OBJECT_DECLARE_SIMPLE_TYPE(AwH3SysCtrlState, AW_H3_SYSCTRL)
+
+/** @} */
+
+/**
+ * Allwinner H3 System Control object instance state
+ */
+struct AwH3SysCtrlState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ /** Maps I/O registers in physical memory */
+ MemoryRegion iomem;
+
+ /** Array of hardware registers */
+ uint32_t regs[AW_H3_SYSCTRL_REGS_NUM];
+
+};
+
+#endif /* HW_MISC_ALLWINNER_H3_SYSCTRL_H */
diff --git a/include/hw/misc/allwinner-sid.h b/include/hw/misc/allwinner-sid.h
new file mode 100644
index 000000000..3bfa887a9
--- /dev/null
+++ b/include/hw/misc/allwinner-sid.h
@@ -0,0 +1,59 @@
+/*
+ * Allwinner Security ID emulation
+ *
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.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_SID_H
+#define HW_MISC_ALLWINNER_SID_H
+
+#include "qom/object.h"
+#include "hw/sysbus.h"
+#include "qemu/uuid.h"
+
+/**
+ * Object model
+ * @{
+ */
+
+#define TYPE_AW_SID "allwinner-sid"
+OBJECT_DECLARE_SIMPLE_TYPE(AwSidState, AW_SID)
+
+/** @} */
+
+/**
+ * Allwinner Security ID object instance state
+ */
+struct AwSidState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ /** Maps I/O registers in physical memory */
+ MemoryRegion iomem;
+
+ /** Control register defines how and what to read */
+ uint32_t control;
+
+ /** RdKey register contains the data retrieved by the device */
+ uint32_t rdkey;
+
+ /** Stores the emulated device identifier */
+ QemuUUID identifier;
+
+};
+
+#endif /* HW_MISC_ALLWINNER_SID_H */
diff --git a/include/hw/misc/arm11scu.h b/include/hw/misc/arm11scu.h
new file mode 100644
index 000000000..e5c0282ae
--- /dev/null
+++ b/include/hw/misc/arm11scu.h
@@ -0,0 +1,30 @@
+/*
+ * ARM11MPCore Snoop Control Unit (SCU) emulation
+ *
+ * Copyright (c) 2006-2007 CodeSourcery.
+ * Copyright (c) 2013 SUSE LINUX Products GmbH
+ * Written by Paul Brook and Andreas Färber
+ *
+ * This code is licensed under the GPL.
+ */
+
+#ifndef HW_MISC_ARM11SCU_H
+#define HW_MISC_ARM11SCU_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_ARM11_SCU "arm11-scu"
+OBJECT_DECLARE_SIMPLE_TYPE(ARM11SCUState, ARM11_SCU)
+
+struct ARM11SCUState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ uint32_t control;
+ uint32_t num_cpu;
+ MemoryRegion iomem;
+};
+
+#endif
diff --git a/include/hw/misc/arm_integrator_debug.h b/include/hw/misc/arm_integrator_debug.h
new file mode 100644
index 000000000..798b08216
--- /dev/null
+++ b/include/hw/misc/arm_integrator_debug.h
@@ -0,0 +1,19 @@
+/*
+ * ARM Integrator Board Debug, switch and LED section
+ *
+ * Browse the data sheet:
+ *
+ * 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>
+ *
+ * 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 ARM_INTEGRATOR_DEBUG_H
+#define ARM_INTEGRATOR_DEBUG_H
+
+#define TYPE_INTEGRATOR_DEBUG "integrator_debug"
+
+#endif
diff --git a/include/hw/misc/armsse-cpu-pwrctrl.h b/include/hw/misc/armsse-cpu-pwrctrl.h
new file mode 100644
index 000000000..51d45ede7
--- /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
new file mode 100644
index 000000000..9c0926322
--- /dev/null
+++ b/include/hw/misc/armsse-cpuid.h
@@ -0,0 +1,42 @@
+/*
+ * ARM SSE-200 CPU_IDENTITY register block
+ *
+ * Copyright (c) 2019 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_IDENTITY" register block which is part of the
+ * Arm SSE-200 and documented in
+ * https://developer.arm.com/documentation/101104/latest/
+ *
+ * QEMU interface:
+ * + QOM property "CPUID": the value to use for the CPUID register
+ * + sysbus MMIO region 0: the system information register bank
+ */
+
+#ifndef HW_MISC_ARMSSE_CPUID_H
+#define HW_MISC_ARMSSE_CPUID_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_ARMSSE_CPUID "armsse-cpuid"
+OBJECT_DECLARE_SIMPLE_TYPE(ARMSSECPUID, ARMSSE_CPUID)
+
+struct ARMSSECPUID {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+
+ /* Properties */
+ uint32_t cpuid;
+};
+
+#endif
diff --git a/include/hw/misc/armsse-mhu.h b/include/hw/misc/armsse-mhu.h
new file mode 100644
index 000000000..41925ded8
--- /dev/null
+++ b/include/hw/misc/armsse-mhu.h
@@ -0,0 +1,45 @@
+/*
+ * ARM SSE-200 Message Handling Unit (MHU)
+ *
+ * Copyright (c) 2019 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 Message Handling Unit (MHU) which is part of the
+ * Arm SSE-200 and documented in
+ * https://developer.arm.com/documentation/101104/latest/
+ *
+ * QEMU interface:
+ * + sysbus MMIO region 0: the system information register bank
+ * + sysbus IRQ 0: interrupt for CPU 0
+ * + sysbus IRQ 1: interrupt for CPU 1
+ */
+
+#ifndef HW_MISC_ARMSSE_MHU_H
+#define HW_MISC_ARMSSE_MHU_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_ARMSSE_MHU "armsse-mhu"
+OBJECT_DECLARE_SIMPLE_TYPE(ARMSSEMHU, ARMSSE_MHU)
+
+struct ARMSSEMHU {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+ qemu_irq cpu0irq;
+ qemu_irq cpu1irq;
+
+ uint32_t cpu0intr;
+ uint32_t cpu1intr;
+};
+
+#endif
diff --git a/include/hw/misc/armv7m_ras.h b/include/hw/misc/armv7m_ras.h
new file mode 100644
index 000000000..ba6daccf3
--- /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 000000000..94d5ada95
--- /dev/null
+++ b/include/hw/misc/aspeed_hace.h
@@ -0,0 +1,43 @@
+/*
+ * 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"
+OBJECT_DECLARE_TYPE(AspeedHACEState, AspeedHACEClass, ASPEED_HACE)
+
+#define ASPEED_HACE_NR_REGS (0x64 >> 2)
+
+struct AspeedHACEState {
+ SysBusDevice parent;
+
+ MemoryRegion iomem;
+ qemu_irq irq;
+
+ uint32_t regs[ASPEED_HACE_NR_REGS];
+
+ MemoryRegion *dram_mr;
+ AddressSpace dram_as;
+};
+
+
+struct AspeedHACEClass {
+ SysBusDeviceClass parent_class;
+
+ uint32_t src_mask;
+ uint32_t dest_mask;
+ uint32_t hash_mask;
+};
+
+#endif /* _ASPEED_HACE_H_ */
diff --git a/include/hw/misc/aspeed_lpc.h b/include/hw/misc/aspeed_lpc.h
new file mode 100644
index 000000000..df418cfcd
--- /dev/null
+++ b/include/hw/misc/aspeed_lpc.h
@@ -0,0 +1,47 @@
+/*
+ * 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"
+
+#include <stdint.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_scu.h b/include/hw/misc/aspeed_scu.h
new file mode 100644
index 000000000..c14aff2bc
--- /dev/null
+++ b/include/hw/misc/aspeed_scu.h
@@ -0,0 +1,319 @@
+/*
+ * ASPEED System Control Unit
+ *
+ * Andrew Jeffery <andrew@aj.id.au>
+ *
+ * Copyright 2016 IBM Corp.
+ *
+ * This code is licensed under the GPL version 2 or later. See
+ * the COPYING file in the top-level directory.
+ */
+#ifndef ASPEED_SCU_H
+#define ASPEED_SCU_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_ASPEED_SCU "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 ASPEED_SCU_NR_REGS (0x1A8 >> 2)
+#define ASPEED_AST2600_SCU_NR_REGS (0xE20 >> 2)
+
+struct AspeedSCUState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+
+ uint32_t regs[ASPEED_AST2600_SCU_NR_REGS];
+ uint32_t silicon_rev;
+ uint32_t hw_strap1;
+ uint32_t hw_strap2;
+ uint32_t hw_prot_key;
+};
+
+#define AST2400_A0_SILICON_REV 0x02000303U
+#define AST2400_A1_SILICON_REV 0x02010303U
+#define AST2500_A0_SILICON_REV 0x04000303U
+#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 ASPEED_IS_AST2500(si_rev) ((((si_rev) >> 24) & 0xff) == 0x04)
+
+extern bool is_supported_silicon_rev(uint32_t silicon_rev);
+
+
+struct AspeedSCUClass {
+ SysBusDeviceClass parent_class;
+
+ const uint32_t *resets;
+ uint32_t (*calc_hpll)(AspeedSCUState *s, uint32_t hpll_reg);
+ uint32_t apb_divider;
+ uint32_t nr_regs;
+ const MemoryRegionOps *ops;
+};
+
+#define ASPEED_SCU_PROT_KEY 0x1688A8A8
+
+uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s);
+
+/*
+ * Extracted from Aspeed SDK v00.03.21. Fixes and extra definitions
+ * were added.
+ *
+ * Original header file :
+ * arch/arm/mach-aspeed/include/mach/regs-scu.h
+ *
+ * Copyright (C) 2012-2020 ASPEED Technology Inc.
+ *
+ * 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.
+ *
+ * History :
+ * 1. 2012/12/29 Ryan Chen Create
+ */
+
+/* SCU08 Clock Selection Register
+ *
+ * 31 Enable Video Engine clock dynamic slow down
+ * 30:28 Video Engine clock slow down setting
+ * 27 2D Engine GCLK clock source selection
+ * 26 2D Engine GCLK clock throttling enable
+ * 25:23 APB PCLK divider selection
+ * 22:20 LPC Host LHCLK divider selection
+ * 19 LPC Host LHCLK clock generation/output enable control
+ * 18:16 MAC AHB bus clock divider selection
+ * 15 SD/SDIO clock running enable
+ * 14:12 SD/SDIO divider selection
+ * 11 Reserved
+ * 10:8 Video port output clock delay control bit
+ * 7 ARM CPU/AHB clock slow down enable
+ * 6:4 ARM CPU/AHB clock slow down setting
+ * 3:2 ECLK clock source selection
+ * 1 CPU/AHB clock slow down idle timer
+ * 0 CPU/AHB clock dynamic slow down enable (defined in bit[6:4])
+ */
+#define SCU_CLK_GET_PCLK_DIV(x) (((x) >> 23) & 0x7)
+
+/* SCU24 H-PLL Parameter Register (for Aspeed AST2400 SOC)
+ *
+ * 18 H-PLL parameter selection
+ * 0: Select H-PLL by strapping resistors
+ * 1: Select H-PLL by the programmed registers (SCU24[17:0])
+ * 17 Enable H-PLL bypass mode
+ * 16 Turn off H-PLL
+ * 10:5 H-PLL Numerator
+ * 4 H-PLL Output Divider
+ * 3:0 H-PLL Denumerator
+ *
+ * (Output frequency) = 24MHz * (2-OD) * [(Numerator+2) / (Denumerator+1)]
+ */
+
+#define SCU_AST2400_H_PLL_PROGRAMMED (0x1 << 18)
+#define SCU_AST2400_H_PLL_BYPASS_EN (0x1 << 17)
+#define SCU_AST2400_H_PLL_OFF (0x1 << 16)
+
+/* SCU24 H-PLL Parameter Register (for Aspeed AST2500 SOC)
+ *
+ * 21 Enable H-PLL reset
+ * 20 Enable H-PLL bypass mode
+ * 19 Turn off H-PLL
+ * 18:13 H-PLL Post Divider
+ * 12:5 H-PLL Numerator (M)
+ * 4:0 H-PLL Denumerator (N)
+ *
+ * (Output frequency) = CLKIN(24MHz) * [(M+1) / (N+1)] / (P+1)
+ *
+ * The default frequency is 792Mhz when CLKIN = 24MHz
+ */
+
+#define SCU_H_PLL_BYPASS_EN (0x1 << 20)
+#define SCU_H_PLL_OFF (0x1 << 19)
+
+/* SCU70 Hardware Strapping Register definition (for Aspeed AST2400 SOC)
+ *
+ * 31:29 Software defined strapping registers
+ * 28:27 DRAM size setting (for VGA driver use)
+ * 26:24 DRAM configuration setting
+ * 23 Enable 25 MHz reference clock input
+ * 22 Enable GPIOE pass-through mode
+ * 21 Enable GPIOD pass-through mode
+ * 20 Disable LPC to decode SuperIO 0x2E/0x4E address
+ * 19 Disable ACPI function
+ * 23,18 Clock source selection
+ * 17 Enable BMC 2nd boot watchdog timer
+ * 16 SuperIO configuration address selection
+ * 15 VGA Class Code selection
+ * 14 Enable LPC dedicated reset pin function
+ * 13:12 SPI mode selection
+ * 11:10 CPU/AHB clock frequency ratio selection
+ * 9:8 H-PLL default clock frequency selection
+ * 7 Define MAC#2 interface
+ * 6 Define MAC#1 interface
+ * 5 Enable VGA BIOS ROM
+ * 4 Boot flash memory extended option
+ * 3:2 VGA memory size selection
+ * 1:0 BMC CPU boot code selection
+ */
+#define SCU_AST2400_HW_STRAP_SW_DEFINE(x) ((x) << 29)
+#define SCU_AST2400_HW_STRAP_SW_DEFINE_MASK (0x7 << 29)
+
+#define SCU_AST2400_HW_STRAP_DRAM_SIZE(x) ((x) << 27)
+#define SCU_AST2400_HW_STRAP_DRAM_SIZE_MASK (0x3 << 27)
+#define DRAM_SIZE_64MB 0
+#define DRAM_SIZE_128MB 1
+#define DRAM_SIZE_256MB 2
+#define DRAM_SIZE_512MB 3
+
+#define SCU_AST2400_HW_STRAP_DRAM_CONFIG(x) ((x) << 24)
+#define SCU_AST2400_HW_STRAP_DRAM_CONFIG_MASK (0x7 << 24)
+
+#define SCU_HW_STRAP_GPIOE_PT_EN (0x1 << 22)
+#define SCU_HW_STRAP_GPIOD_PT_EN (0x1 << 21)
+#define SCU_HW_STRAP_LPC_DEC_SUPER_IO (0x1 << 20)
+#define SCU_AST2400_HW_STRAP_ACPI_DIS (0x1 << 19)
+
+/* bit 23, 18 [1,0] */
+#define SCU_AST2400_HW_STRAP_SET_CLK_SOURCE(x) (((((x) & 0x3) >> 1) << 23) \
+ | (((x) & 0x1) << 18))
+#define SCU_AST2400_HW_STRAP_GET_CLK_SOURCE(x) (((((x) >> 23) & 0x1) << 1) \
+ | (((x) >> 18) & 0x1))
+#define SCU_AST2400_HW_STRAP_CLK_SOURCE_MASK ((0x1 << 23) | (0x1 << 18))
+#define SCU_HW_STRAP_CLK_25M_IN (0x1 << 23)
+#define AST2400_CLK_24M_IN 0
+#define AST2400_CLK_48M_IN 1
+#define AST2400_CLK_25M_IN_24M_USB_CKI 2
+#define AST2400_CLK_25M_IN_48M_USB_CKI 3
+
+#define SCU_HW_STRAP_CLK_48M_IN (0x1 << 18)
+#define SCU_HW_STRAP_2ND_BOOT_WDT (0x1 << 17)
+#define SCU_HW_STRAP_SUPER_IO_CONFIG (0x1 << 16)
+#define SCU_HW_STRAP_VGA_CLASS_CODE (0x1 << 15)
+#define SCU_HW_STRAP_LPC_RESET_PIN (0x1 << 14)
+
+#define SCU_HW_STRAP_SPI_MODE(x) ((x) << 12)
+#define SCU_HW_STRAP_SPI_MODE_MASK (0x3 << 12)
+#define SCU_HW_STRAP_SPI_DIS 0
+#define SCU_HW_STRAP_SPI_MASTER 1
+#define SCU_HW_STRAP_SPI_M_S_EN 2
+#define SCU_HW_STRAP_SPI_PASS_THROUGH 3
+
+#define SCU_AST2400_HW_STRAP_SET_CPU_AHB_RATIO(x) ((x) << 10)
+#define SCU_AST2400_HW_STRAP_GET_CPU_AHB_RATIO(x) (((x) >> 10) & 3)
+#define SCU_AST2400_HW_STRAP_CPU_AHB_RATIO_MASK (0x3 << 10)
+#define AST2400_CPU_AHB_RATIO_1_1 0
+#define AST2400_CPU_AHB_RATIO_2_1 1
+#define AST2400_CPU_AHB_RATIO_4_1 2
+#define AST2400_CPU_AHB_RATIO_3_1 3
+
+#define SCU_AST2400_HW_STRAP_GET_H_PLL_CLK(x) (((x) >> 8) & 0x3)
+#define SCU_AST2400_HW_STRAP_H_PLL_CLK_MASK (0x3 << 8)
+#define AST2400_CPU_384MHZ 0
+#define AST2400_CPU_360MHZ 1
+#define AST2400_CPU_336MHZ 2
+#define AST2400_CPU_408MHZ 3
+
+#define SCU_HW_STRAP_MAC1_RGMII (0x1 << 7)
+#define SCU_HW_STRAP_MAC0_RGMII (0x1 << 6)
+#define SCU_HW_STRAP_VGA_BIOS_ROM (0x1 << 5)
+#define SCU_HW_STRAP_SPI_WIDTH (0x1 << 4)
+
+#define SCU_HW_STRAP_VGA_SIZE_GET(x) (((x) >> 2) & 0x3)
+#define SCU_HW_STRAP_VGA_MASK (0x3 << 2)
+#define SCU_HW_STRAP_VGA_SIZE_SET(x) ((x) << 2)
+#define VGA_8M_DRAM 0
+#define VGA_16M_DRAM 1
+#define VGA_32M_DRAM 2
+#define VGA_64M_DRAM 3
+
+#define SCU_AST2400_HW_STRAP_BOOT_MODE(x) (x)
+#define AST2400_NOR_BOOT 0
+#define AST2400_NAND_BOOT 1
+#define AST2400_SPI_BOOT 2
+#define AST2400_DIS_BOOT 3
+
+/*
+ * SCU70 Hardware strapping register definition (for Aspeed AST2500
+ * SoC and higher)
+ *
+ * 31 Enable SPI Flash Strap Auto Fetch Mode
+ * 30 Enable GPIO Strap Mode
+ * 29 Select UART Debug Port
+ * 28 Reserved (1)
+ * 27 Enable fast reset mode for ARM ICE debugger
+ * 26 Enable eSPI flash mode
+ * 25 Enable eSPI mode
+ * 24 Select DDR4 SDRAM
+ * 23 Select 25 MHz reference clock input mode
+ * 22 Enable GPIOE pass-through mode
+ * 21 Enable GPIOD pass-through mode
+ * 20 Disable LPC to decode SuperIO 0x2E/0x4E address
+ * 19 Enable ACPI function
+ * 18 Select USBCKI input frequency
+ * 17 Enable BMC 2nd boot watchdog timer
+ * 16 SuperIO configuration address selection
+ * 15 VGA Class Code selection
+ * 14 Select dedicated LPC reset input
+ * 13:12 SPI mode selection
+ * 11:9 AXI/AHB clock frequency ratio selection
+ * 8 Reserved (0)
+ * 7 Define MAC#2 interface
+ * 6 Define MAC#1 interface
+ * 5 Enable dedicated VGA BIOS ROM
+ * 4 Reserved (0)
+ * 3:2 VGA memory size selection
+ * 1 Reserved (1)
+ * 0 Disable CPU boot
+ */
+#define SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE (0x1 << 31)
+#define SCU_AST2500_HW_STRAP_GPIO_STRAP_ENABLE (0x1 << 30)
+#define SCU_AST2500_HW_STRAP_UART_DEBUG (0x1 << 29)
+#define UART_DEBUG_UART1 0
+#define UART_DEBUG_UART5 1
+#define SCU_AST2500_HW_STRAP_RESERVED28 (0x1 << 28)
+
+#define SCU_AST2500_HW_STRAP_FAST_RESET_DBG (0x1 << 27)
+#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)
+#define USBCKI_FREQ_24MHZ 0
+#define USBCKI_FREQ_28MHZ 1
+
+#define SCU_AST2500_HW_STRAP_SET_AXI_AHB_RATIO(x) ((x) << 9)
+#define SCU_AST2500_HW_STRAP_GET_AXI_AHB_RATIO(x) (((x) >> 9) & 7)
+#define SCU_AST2500_HW_STRAP_CPU_AXI_RATIO_MASK (0x7 << 9)
+#define AXI_AHB_RATIO_UNDEFINED 0
+#define AXI_AHB_RATIO_2_1 1
+#define AXI_AHB_RATIO_3_1 2
+#define AXI_AHB_RATIO_4_1 3
+#define AXI_AHB_RATIO_5_1 4
+#define AXI_AHB_RATIO_6_1 5
+#define AXI_AHB_RATIO_7_1 6
+#define AXI_AHB_RATIO_8_1 7
+
+#define SCU_AST2500_HW_STRAP_RESERVED1 (0x1 << 1)
+#define SCU_AST2500_HW_STRAP_DIS_BOOT (0x1 << 0)
+
+#define AST2500_HW_STRAP1_DEFAULTS ( \
+ SCU_AST2500_HW_STRAP_RESERVED28 | \
+ SCU_HW_STRAP_2ND_BOOT_WDT | \
+ SCU_HW_STRAP_VGA_CLASS_CODE | \
+ SCU_HW_STRAP_LPC_RESET_PIN | \
+ SCU_AST2500_HW_STRAP_SET_AXI_AHB_RATIO(AXI_AHB_RATIO_2_1) | \
+ SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) | \
+ SCU_AST2500_HW_STRAP_RESERVED1)
+
+#endif /* ASPEED_SCU_H */
diff --git a/include/hw/misc/aspeed_sdmc.h b/include/hw/misc/aspeed_sdmc.h
new file mode 100644
index 000000000..ec2d59a14
--- /dev/null
+++ b/include/hw/misc/aspeed_sdmc.h
@@ -0,0 +1,56 @@
+/*
+ * ASPEED SDRAM Memory Controller
+ *
+ * Copyright (C) 2016 IBM Corp.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+#ifndef ASPEED_SDMC_H
+#define ASPEED_SDMC_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_ASPEED_SDMC "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"
+
+/*
+ * 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)
+
+struct AspeedSDMCState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+
+ uint32_t regs[ASPEED_SDMC_NR_REGS];
+ uint64_t ram_size;
+ uint64_t max_ram_size;
+};
+
+
+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);
+};
+
+#endif /* ASPEED_SDMC_H */
diff --git a/include/hw/misc/aspeed_xdma.h b/include/hw/misc/aspeed_xdma.h
new file mode 100644
index 000000000..b1478fd1c
--- /dev/null
+++ b/include/hw/misc/aspeed_xdma.h
@@ -0,0 +1,46 @@
+/*
+ * ASPEED XDMA Controller
+ * Eddie James <eajames@linux.ibm.com>
+ *
+ * Copyright (C) 2019 IBM Corp.
+ * 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 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
+
+struct AspeedXDMAState {
+ SysBusDevice parent;
+
+ MemoryRegion iomem;
+ qemu_irq irq;
+
+ char bmc_cmdq_readp_set;
+ uint32_t regs[ASPEED_XDMA_NUM_REGS];
+};
+
+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
new file mode 100644
index 000000000..b05799d2f
--- /dev/null
+++ b/include/hw/misc/auxbus.h
@@ -0,0 +1,142 @@
+/*
+ * auxbus.h
+ *
+ * Copyright (C)2014 : GreenSocs Ltd
+ * http://www.greensocs.com/ , email: info@greensocs.com
+ *
+ * Developed by :
+ * Frederic Konrad <fred.konrad@greensocs.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_AUXBUS_H
+#define HW_MISC_AUXBUS_H
+
+#include "exec/memory.h"
+#include "hw/qdev-core.h"
+#include "qom/object.h"
+
+typedef struct AUXSlave AUXSlave;
+typedef enum AUXCommand AUXCommand;
+typedef enum AUXReply AUXReply;
+
+#define TYPE_AUXTOI2C "aux-to-i2c-bridge"
+OBJECT_DECLARE_SIMPLE_TYPE(AUXTOI2CState, AUXTOI2C)
+
+enum AUXCommand {
+ WRITE_I2C = 0,
+ READ_I2C = 1,
+ WRITE_I2C_STATUS = 2,
+ WRITE_I2C_MOT = 4,
+ READ_I2C_MOT = 5,
+ WRITE_AUX = 8,
+ READ_AUX = 9
+};
+
+enum AUXReply {
+ AUX_I2C_ACK = 0,
+ AUX_NACK = 1,
+ AUX_DEFER = 2,
+ AUX_I2C_NACK = 4,
+ AUX_I2C_DEFER = 8
+};
+
+#define TYPE_AUX_BUS "aux-bus"
+OBJECT_DECLARE_SIMPLE_TYPE(AUXBus, AUX_BUS)
+
+struct AUXBus {
+ /* < private > */
+ BusState qbus;
+
+ /* < public > */
+ AUXSlave *current_dev;
+ AUXSlave *dev;
+ uint32_t last_i2c_address;
+ AUXCommand last_transaction;
+
+ AUXTOI2CState *bridge;
+
+ MemoryRegion *aux_io;
+ AddressSpace aux_addr_space;
+};
+
+#define TYPE_AUX_SLAVE "aux-slave"
+OBJECT_DECLARE_SIMPLE_TYPE(AUXSlave, AUX_SLAVE)
+
+struct AUXSlave {
+ /* < private > */
+ DeviceState parent_obj;
+
+ /* < public > */
+ MemoryRegion *mmio;
+};
+
+/**
+ * aux_bus_init: Initialize an AUX bus.
+ *
+ * Returns the new AUX bus created.
+ *
+ * @parent The device where this bus is located.
+ * @name The name of the bus.
+ */
+AUXBus *aux_bus_init(DeviceState *parent, const char *name);
+
+/**
+ * aux_bus_realize: Realize an AUX bus.
+ *
+ * @bus: The AUX bus.
+ */
+void aux_bus_realize(AUXBus *bus);
+
+/*
+ * aux_request: Make a request on the bus.
+ *
+ * Returns the reply of the request.
+ *
+ * @bus Ths bus where the request happen.
+ * @cmd The command requested.
+ * @address The 20bits address of the slave.
+ * @len The length of the read or write.
+ * @data The data array which will be filled or read during transfer.
+ */
+AUXReply aux_request(AUXBus *bus, AUXCommand cmd, uint32_t address,
+ uint8_t len, uint8_t *data);
+
+/*
+ * aux_get_i2c_bus: Get the i2c bus for I2C over AUX command.
+ *
+ * Returns the i2c bus associated to this AUX bus.
+ *
+ * @bus The AUX bus.
+ */
+I2CBus *aux_get_i2c_bus(AUXBus *bus);
+
+/*
+ * aux_init_mmio: Init an mmio for an AUX slave.
+ *
+ * @aux_slave The AUX slave.
+ * @mmio The mmio to be registered.
+ */
+void aux_init_mmio(AUXSlave *aux_slave, MemoryRegion *mmio);
+
+/* aux_map_slave: Map the mmio for an AUX slave on the bus.
+ *
+ * @dev The AUX slave.
+ * @addr The address for the slave's mmio.
+ */
+void aux_map_slave(AUXSlave *dev, hwaddr addr);
+
+#endif /* HW_MISC_AUXBUS_H */
diff --git a/include/hw/misc/avr_power.h b/include/hw/misc/avr_power.h
new file mode 100644
index 000000000..388e421aa
--- /dev/null
+++ b/include/hw/misc/avr_power.h
@@ -0,0 +1,46 @@
+/*
+ * AVR Power Reduction Management
+ *
+ * Copyright (c) 2019-2020 Michael Rolnik
+ *
+ * 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_MISC_AVR_POWER_H
+#define HW_MISC_AVR_POWER_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+
+#define TYPE_AVR_MASK "avr-power"
+OBJECT_DECLARE_SIMPLE_TYPE(AVRMaskState, AVR_MASK)
+
+struct AVRMaskState {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /* <public> */
+ MemoryRegion iomem;
+
+ uint8_t val;
+ qemu_irq irq[8];
+};
+
+#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 000000000..3df4ceedd
--- /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_CPRMAN_H
+#define HW_MISC_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 000000000..339759b30
--- /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_CPRMAN_INTERNALS_H
+#define HW_MISC_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
new file mode 100644
index 000000000..ade27af25
--- /dev/null
+++ b/include/hw/misc/bcm2835_mbox.h
@@ -0,0 +1,39 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ *
+ * 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_MBOX_H
+#define BCM2835_MBOX_H
+
+#include "bcm2835_mbox_defs.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_BCM2835_MBOX "bcm2835-mbox"
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835MboxState, BCM2835_MBOX)
+
+typedef struct {
+ uint32_t reg[MBOX_SIZE];
+ uint32_t count;
+ uint32_t status;
+ uint32_t config;
+} BCM2835Mbox;
+
+struct BCM2835MboxState {
+ /*< private >*/
+ SysBusDevice busdev;
+ /*< public >*/
+ MemoryRegion *mbox_mr;
+ AddressSpace mbox_as;
+ MemoryRegion iomem;
+ qemu_irq arm_irq;
+
+ bool mbox_irq_disabled;
+ bool available[MBOX_CHAN_COUNT];
+ BCM2835Mbox mbox[2];
+};
+
+#endif
diff --git a/include/hw/misc/bcm2835_mbox_defs.h b/include/hw/misc/bcm2835_mbox_defs.h
new file mode 100644
index 000000000..9670bf33a
--- /dev/null
+++ b/include/hw/misc/bcm2835_mbox_defs.h
@@ -0,0 +1,29 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ *
+ * 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_MBOX_DEFS_H
+#define BCM2835_MBOX_DEFS_H
+
+/* Constants shared with the ARM identifying separate mailbox channels */
+#define MBOX_CHAN_POWER 0 /* for use by the power management interface */
+#define MBOX_CHAN_FB 1 /* for use by the frame buffer */
+#define MBOX_CHAN_VCHIQ 3 /* for use by the VCHIQ interface */
+#define MBOX_CHAN_PROPERTY 8 /* for use by the property channel */
+#define MBOX_CHAN_COUNT 9
+
+#define MBOX_SIZE 32
+#define MBOX_INVALID_DATA 0x0f
+
+/* Layout of the private address space used for communication between
+ * the mbox device emulation, and child devices: each channel occupies
+ * 16 bytes of address space, but only two registers are presently defined.
+ */
+#define MBOX_AS_CHAN_SHIFT 4
+#define MBOX_AS_DATA 0 /* request / response data (RW at offset 0) */
+#define MBOX_AS_PENDING 4 /* pending response status (RO at offset 4) */
+
+#endif /* BCM2835_MBOX_DEFS_H */
diff --git a/include/hw/misc/bcm2835_mphi.h b/include/hw/misc/bcm2835_mphi.h
new file mode 100644
index 000000000..751363f49
--- /dev/null
+++ b/include/hw/misc/bcm2835_mphi.h
@@ -0,0 +1,44 @@
+/*
+ * BCM2835 SOC MPHI state definitions
+ *
+ * Copyright (c) 2020 Paul Zimmerman <pauldzim@gmail.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 HW_MISC_BCM2835_MPHI_H
+#define HW_MISC_BCM2835_MPHI_H
+
+#include "hw/irq.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define MPHI_MMIO_SIZE 0x1000
+
+typedef struct BCM2835MphiState BCM2835MphiState;
+
+struct BCM2835MphiState {
+ SysBusDevice parent_obj;
+ qemu_irq irq;
+ MemoryRegion iomem;
+
+ uint32_t outdda;
+ uint32_t outddb;
+ uint32_t ctrl;
+ uint32_t intstat;
+ uint32_t swirq;
+};
+
+#define TYPE_BCM2835_MPHI "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 000000000..303b9a6f6
--- /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
new file mode 100644
index 000000000..712b76b7a
--- /dev/null
+++ b/include/hw/misc/bcm2835_property.h
@@ -0,0 +1,36 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ *
+ * 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_PROPERTY_H
+#define BCM2835_PROPERTY_H
+
+#include "hw/sysbus.h"
+#include "net/net.h"
+#include "hw/display/bcm2835_fb.h"
+#include "qom/object.h"
+
+#define TYPE_BCM2835_PROPERTY "bcm2835-property"
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835PropertyState, BCM2835_PROPERTY)
+
+struct BCM2835PropertyState {
+ /*< private >*/
+ SysBusDevice busdev;
+ /*< public >*/
+
+ MemoryRegion *dma_mr;
+ AddressSpace dma_as;
+ MemoryRegion iomem;
+ qemu_irq mbox_irq;
+ BCM2835FBState *fbdev;
+
+ MACAddr macaddr;
+ uint32_t board_rev;
+ uint32_t addr;
+ bool pending;
+};
+
+#endif
diff --git a/include/hw/misc/bcm2835_rng.h b/include/hw/misc/bcm2835_rng.h
new file mode 100644
index 000000000..7c1fb3ef4
--- /dev/null
+++ b/include/hw/misc/bcm2835_rng.h
@@ -0,0 +1,27 @@
+/*
+ * BCM2835 Random Number Generator emulation
+ *
+ * Copyright (C) 2017 Marcin Chojnacki <marcinch7@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 BCM2835_RNG_H
+#define BCM2835_RNG_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_BCM2835_RNG "bcm2835-rng"
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835RngState, BCM2835_RNG)
+
+struct BCM2835RngState {
+ SysBusDevice busdev;
+ MemoryRegion iomem;
+
+ uint32_t rng_ctrl;
+ uint32_t rng_status;
+};
+
+#endif
diff --git a/include/hw/misc/bcm2835_thermal.h b/include/hw/misc/bcm2835_thermal.h
new file mode 100644
index 000000000..f90f9e487
--- /dev/null
+++ b/include/hw/misc/bcm2835_thermal.h
@@ -0,0 +1,27 @@
+/*
+ * BCM2835 dummy thermal sensor
+ *
+ * Copyright (C) 2019 Philippe Mathieu-Daudé <f4bug@amsat.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_MISC_BCM2835_THERMAL_H
+#define HW_MISC_BCM2835_THERMAL_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_BCM2835_THERMAL "bcm2835-thermal"
+
+OBJECT_DECLARE_SIMPLE_TYPE(Bcm2835ThermalState, BCM2835_THERMAL)
+
+struct Bcm2835ThermalState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+ MemoryRegion iomem;
+ uint32_t ctl;
+};
+
+#endif
diff --git a/include/hw/misc/cbus.h b/include/hw/misc/cbus.h
new file mode 100644
index 000000000..533498402
--- /dev/null
+++ b/include/hw/misc/cbus.h
@@ -0,0 +1,31 @@
+/*
+ * CBUS three-pin bus and the Retu / Betty / Tahvo / Vilma / Avilma /
+ * Hinku / Vinku / Ahne / Pihi chips used in various Nokia platforms.
+ * Based on reverse-engineering of a linux driver.
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Written by Andrzej Zaborowski
+ *
+ * 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_MISC_CBUS_H
+#define HW_MISC_CBUS_H
+
+
+typedef struct {
+ qemu_irq clk;
+ qemu_irq dat;
+ qemu_irq sel;
+} CBus;
+
+CBus *cbus_init(qemu_irq dat_out);
+void cbus_attach(CBus *bus, void *slave_opaque);
+
+void *retu_init(qemu_irq irq, int vilma);
+void *tahvo_init(qemu_irq irq, int betty);
+
+void retu_key_event(void *retu, int state);
+
+#endif
diff --git a/include/hw/misc/empty_slot.h b/include/hw/misc/empty_slot.h
new file mode 100644
index 000000000..dec56e56a
--- /dev/null
+++ b/include/hw/misc/empty_slot.h
@@ -0,0 +1,19 @@
+/*
+ * QEMU Empty Slot
+ *
+ * The empty_slot device emulates known to a bus but not connected devices.
+ *
+ * Copyright (c) 2010 Artyom Tarasenko
+ *
+ * This code is licensed under the GNU GPL v2 or (at your option) any later
+ * version.
+ */
+
+#ifndef HW_EMPTY_SLOT_H
+#define HW_EMPTY_SLOT_H
+
+#include "exec/hwaddr.h"
+
+void empty_slot_init(const char *name, hwaddr addr, uint64_t slot_size);
+
+#endif
diff --git a/include/hw/misc/grlib_ahb_apb_pnp.h b/include/hw/misc/grlib_ahb_apb_pnp.h
new file mode 100644
index 000000000..bab0b5f47
--- /dev/null
+++ b/include/hw/misc/grlib_ahb_apb_pnp.h
@@ -0,0 +1,57 @@
+/*
+ * GRLIB AHB APB PNP
+ *
+ * Copyright (C) 2019 AdaCore
+ *
+ * Developed by :
+ * Frederic Konrad <frederic.konrad@adacore.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 GRLIB_AHB_APB_PNP_H
+#define GRLIB_AHB_APB_PNP_H
+#include "qom/object.h"
+
+#define TYPE_GRLIB_AHB_PNP "grlib-ahbpnp"
+OBJECT_DECLARE_SIMPLE_TYPE(AHBPnp, GRLIB_AHB_PNP)
+
+#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,
+ int type);
+void grlib_apb_pnp_add_entry(APBPnp *dev, uint32_t address, uint32_t mask,
+ uint8_t vendor, uint16_t device, uint8_t version,
+ uint8_t irq, int type);
+
+/* VENDORS */
+#define GRLIB_VENDOR_GAISLER (0x01)
+/* DEVICES */
+#define GRLIB_LEON3_DEV (0x03)
+#define GRLIB_APBMST_DEV (0x06)
+#define GRLIB_APBUART_DEV (0x0C)
+#define GRLIB_IRQMP_DEV (0x0D)
+#define GRLIB_GPTIMER_DEV (0x11)
+/* TYPE */
+#define GRLIB_CPU_AREA (0x00)
+#define GRLIB_APBIO_AREA (0x01)
+#define GRLIB_AHBMEM_AREA (0x02)
+
+#define GRLIB_AHB_MASTER (0x00)
+#define GRLIB_AHB_SLAVE (0x01)
+
+#endif /* GRLIB_AHB_APB_PNP_H */
diff --git a/include/hw/misc/imx25_ccm.h b/include/hw/misc/imx25_ccm.h
new file mode 100644
index 000000000..c3b89018c
--- /dev/null
+++ b/include/hw/misc/imx25_ccm.h
@@ -0,0 +1,80 @@
+/*
+ * IMX25 Clock Control Module
+ *
+ * Copyright (C) 2012 NICTA
+ * Updated by 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 IMX25_CCM_H
+#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
+#define IMX25_CCM_CCTL_REG 2
+#define IMX25_CCM_CGCR0_REG 3
+#define IMX25_CCM_CGCR1_REG 4
+#define IMX25_CCM_CGCR2_REG 5
+#define IMX25_CCM_PCDR0_REG 6
+#define IMX25_CCM_PCDR1_REG 7
+#define IMX25_CCM_PCDR2_REG 8
+#define IMX25_CCM_PCDR3_REG 9
+#define IMX25_CCM_RCSR_REG 10
+#define IMX25_CCM_CRDR_REG 11
+#define IMX25_CCM_DCVR0_REG 12
+#define IMX25_CCM_DCVR1_REG 13
+#define IMX25_CCM_DCVR2_REG 14
+#define IMX25_CCM_DCVR3_REG 15
+#define IMX25_CCM_LTR0_REG 16
+#define IMX25_CCM_LTR1_REG 17
+#define IMX25_CCM_LTR2_REG 18
+#define IMX25_CCM_LTR3_REG 19
+#define IMX25_CCM_LTBR0_REG 20
+#define IMX25_CCM_LTBR1_REG 21
+#define IMX25_CCM_PMCR0_REG 22
+#define IMX25_CCM_PMCR1_REG 23
+#define IMX25_CCM_PMCR2_REG 24
+#define IMX25_CCM_MCR_REG 25
+#define IMX25_CCM_LPIMR0_REG 26
+#define IMX25_CCM_LPIMR1_REG 27
+#define IMX25_CCM_MAX_REG 28
+
+/* CCTL */
+#define CCTL_ARM_CLK_DIV_SHIFT (30)
+#define CCTL_ARM_CLK_DIV_MASK (0x3)
+#define CCTL_AHB_CLK_DIV_SHIFT (28)
+#define CCTL_AHB_CLK_DIV_MASK (0x3)
+#define CCTL_MPLL_BYPASS_SHIFT (22)
+#define CCTL_MPLL_BYPASS_MASK (0x1)
+#define CCTL_USB_DIV_SHIFT (16)
+#define CCTL_USB_DIV_MASK (0x3F)
+#define CCTL_ARM_SRC_SHIFT (13)
+#define CCTL_ARM_SRC_MASK (0x1)
+#define CCTL_UPLL_DIS_SHIFT (23)
+#define CCTL_UPLL_DIS_MASK (0x1)
+
+#define EXTRACT(value, name) (((value) >> CCTL_##name##_SHIFT) \
+ & CCTL_##name##_MASK)
+#define INSERT(value, name) (((value) & CCTL_##name##_MASK) << \
+ CCTL_##name##_SHIFT)
+
+#define TYPE_IMX25_CCM "imx25.ccm"
+OBJECT_DECLARE_SIMPLE_TYPE(IMX25CCMState, IMX25_CCM)
+
+struct IMX25CCMState {
+ /* <private> */
+ IMXCCMState parent_obj;
+
+ /* <public> */
+ MemoryRegion iomem;
+
+ uint32_t reg[IMX25_CCM_MAX_REG];
+
+};
+
+#endif /* IMX25_CCM_H */
diff --git a/include/hw/misc/imx31_ccm.h b/include/hw/misc/imx31_ccm.h
new file mode 100644
index 000000000..18e08ee84
--- /dev/null
+++ b/include/hw/misc/imx31_ccm.h
@@ -0,0 +1,89 @@
+/*
+ * IMX31 Clock Control Module
+ *
+ * Copyright (C) 2012 NICTA
+ * Updated by 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 IMX31_CCM_H
+#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
+#define IMX31_CCM_PDR1_REG 2
+#define IMX31_CCM_RCSR_REG 3
+#define IMX31_CCM_MPCTL_REG 4
+#define IMX31_CCM_UPCTL_REG 5
+#define IMX31_CCM_SPCTL_REG 6
+#define IMX31_CCM_COSR_REG 7
+#define IMX31_CCM_CGR0_REG 8
+#define IMX31_CCM_CGR1_REG 9
+#define IMX31_CCM_CGR2_REG 10
+#define IMX31_CCM_WIMR_REG 11
+#define IMX31_CCM_LDC_REG 12
+#define IMX31_CCM_DCVR0_REG 13
+#define IMX31_CCM_DCVR1_REG 14
+#define IMX31_CCM_DCVR2_REG 15
+#define IMX31_CCM_DCVR3_REG 16
+#define IMX31_CCM_LTR0_REG 17
+#define IMX31_CCM_LTR1_REG 18
+#define IMX31_CCM_LTR2_REG 19
+#define IMX31_CCM_LTR3_REG 20
+#define IMX31_CCM_LTBR0_REG 21
+#define IMX31_CCM_LTBR1_REG 22
+#define IMX31_CCM_PMCR0_REG 23
+#define IMX31_CCM_PMCR1_REG 24
+#define IMX31_CCM_PDR2_REG 25
+#define IMX31_CCM_MAX_REG 26
+
+/* CCMR */
+#define CCMR_FPME (1<<0)
+#define CCMR_MPE (1<<3)
+#define CCMR_MDS (1<<7)
+#define CCMR_FPMF (1<<26)
+#define CCMR_PRCS (3<<1)
+
+#define PMCR0_DFSUP1 (1<<31)
+
+/* PDR0 */
+#define PDR0_MCU_PODF_SHIFT (0)
+#define PDR0_MCU_PODF_MASK (0x7)
+#define PDR0_MAX_PODF_SHIFT (3)
+#define PDR0_MAX_PODF_MASK (0x7)
+#define PDR0_IPG_PODF_SHIFT (6)
+#define PDR0_IPG_PODF_MASK (0x3)
+#define PDR0_NFC_PODF_SHIFT (8)
+#define PDR0_NFC_PODF_MASK (0x7)
+#define PDR0_HSP_PODF_SHIFT (11)
+#define PDR0_HSP_PODF_MASK (0x7)
+#define PDR0_PER_PODF_SHIFT (16)
+#define PDR0_PER_PODF_MASK (0x1f)
+#define PDR0_CSI_PODF_SHIFT (23)
+#define PDR0_CSI_PODF_MASK (0x1ff)
+
+#define EXTRACT(value, name) (((value) >> PDR0_##name##_PODF_SHIFT) \
+ & PDR0_##name##_PODF_MASK)
+#define INSERT(value, name) (((value) & PDR0_##name##_PODF_MASK) << \
+ PDR0_##name##_PODF_SHIFT)
+
+#define TYPE_IMX31_CCM "imx31.ccm"
+OBJECT_DECLARE_SIMPLE_TYPE(IMX31CCMState, IMX31_CCM)
+
+struct IMX31CCMState {
+ /* <private> */
+ IMXCCMState parent_obj;
+
+ /* <public> */
+ MemoryRegion iomem;
+
+ uint32_t reg[IMX31_CCM_MAX_REG];
+
+};
+
+#endif /* IMX31_CCM_H */
diff --git a/include/hw/misc/imx6_ccm.h b/include/hw/misc/imx6_ccm.h
new file mode 100644
index 000000000..ccf46d735
--- /dev/null
+++ b/include/hw/misc/imx6_ccm.h
@@ -0,0 +1,198 @@
+/*
+ * IMX6 Clock Control Module
+ *
+ * Copyright (C) 2012 NICTA
+ * Updated by 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 IMX6_CCM_H
+#define IMX6_CCM_H
+
+#include "hw/misc/imx_ccm.h"
+#include "qemu/bitops.h"
+#include "qom/object.h"
+
+#define CCM_CCR 0
+#define CCM_CCDR 1
+#define CCM_CSR 2
+#define CCM_CCSR 3
+#define CCM_CACRR 4
+#define CCM_CBCDR 5
+#define CCM_CBCMR 6
+#define CCM_CSCMR1 7
+#define CCM_CSCMR2 8
+#define CCM_CSCDR1 9
+#define CCM_CS1CDR 10
+#define CCM_CS2CDR 11
+#define CCM_CDCDR 12
+#define CCM_CHSCCDR 13
+#define CCM_CSCDR2 14
+#define CCM_CSCDR3 15
+#define CCM_CDHIPR 18
+#define CCM_CTOR 20
+#define CCM_CLPCR 21
+#define CCM_CISR 22
+#define CCM_CIMR 23
+#define CCM_CCOSR 24
+#define CCM_CGPR 25
+#define CCM_CCGR0 26
+#define CCM_CCGR1 27
+#define CCM_CCGR2 28
+#define CCM_CCGR3 29
+#define CCM_CCGR4 30
+#define CCM_CCGR5 31
+#define CCM_CCGR6 32
+#define CCM_CMEOR 34
+#define CCM_MAX 35
+
+#define CCM_ANALOG_PLL_ARM 0
+#define CCM_ANALOG_PLL_ARM_SET 1
+#define CCM_ANALOG_PLL_ARM_CLR 2
+#define CCM_ANALOG_PLL_ARM_TOG 3
+#define CCM_ANALOG_PLL_USB1 4
+#define CCM_ANALOG_PLL_USB1_SET 5
+#define CCM_ANALOG_PLL_USB1_CLR 6
+#define CCM_ANALOG_PLL_USB1_TOG 7
+#define CCM_ANALOG_PLL_USB2 8
+#define CCM_ANALOG_PLL_USB2_SET 9
+#define CCM_ANALOG_PLL_USB2_CLR 10
+#define CCM_ANALOG_PLL_USB2_TOG 11
+#define CCM_ANALOG_PLL_SYS 12
+#define CCM_ANALOG_PLL_SYS_SET 13
+#define CCM_ANALOG_PLL_SYS_CLR 14
+#define CCM_ANALOG_PLL_SYS_TOG 15
+#define CCM_ANALOG_PLL_SYS_SS 16
+#define CCM_ANALOG_PLL_SYS_NUM 20
+#define CCM_ANALOG_PLL_SYS_DENOM 24
+#define CCM_ANALOG_PLL_AUDIO 28
+#define CCM_ANALOG_PLL_AUDIO_SET 29
+#define CCM_ANALOG_PLL_AUDIO_CLR 30
+#define CCM_ANALOG_PLL_AUDIO_TOG 31
+#define CCM_ANALOG_PLL_AUDIO_NUM 32
+#define CCM_ANALOG_PLL_AUDIO_DENOM 36
+#define CCM_ANALOG_PLL_VIDEO 40
+#define CCM_ANALOG_PLL_VIDEO_SET 41
+#define CCM_ANALOG_PLL_VIDEO_CLR 42
+#define CCM_ANALOG_PLL_VIDEO_TOG 44
+#define CCM_ANALOG_PLL_VIDEO_NUM 46
+#define CCM_ANALOG_PLL_VIDEO_DENOM 48
+#define CCM_ANALOG_PLL_MLB 52
+#define CCM_ANALOG_PLL_MLB_SET 53
+#define CCM_ANALOG_PLL_MLB_CLR 54
+#define CCM_ANALOG_PLL_MLB_TOG 55
+#define CCM_ANALOG_PLL_ENET 56
+#define CCM_ANALOG_PLL_ENET_SET 57
+#define CCM_ANALOG_PLL_ENET_CLR 58
+#define CCM_ANALOG_PLL_ENET_TOG 59
+#define CCM_ANALOG_PFD_480 60
+#define CCM_ANALOG_PFD_480_SET 61
+#define CCM_ANALOG_PFD_480_CLR 62
+#define CCM_ANALOG_PFD_480_TOG 63
+#define CCM_ANALOG_PFD_528 64
+#define CCM_ANALOG_PFD_528_SET 65
+#define CCM_ANALOG_PFD_528_CLR 66
+#define CCM_ANALOG_PFD_528_TOG 67
+
+/* PMU registers */
+#define PMU_REG_1P1 68
+#define PMU_REG_3P0 72
+#define PMU_REG_2P5 76
+#define PMU_REG_CORE 80
+
+#define CCM_ANALOG_MISC0 84
+#define PMU_MISC0 84
+#define CCM_ANALOG_MISC0_SET 85
+#define CCM_ANALOG_MISC0_CLR 86
+#define CCM_ANALOG_MISC0_TOG 87
+
+#define PMU_MISC1 88
+#define PMU_MISC1_SET 89
+#define PMU_MISC1_CLR 90
+#define PMU_MISC1_TOG 91
+
+#define CCM_ANALOG_MISC2 92
+#define PMU_MISC2 92
+#define CCM_ANALOG_MISC2_SET 93
+#define CCM_ANALOG_MISC2_CLR 94
+#define CCM_ANALOG_MISC2_TOG 95
+
+#define USB_ANALOG_USB1_VBUS_DETECT 104
+#define USB_ANALOG_USB1_VBUS_DETECT_SET 105
+#define USB_ANALOG_USB1_VBUS_DETECT_CLR 106
+#define USB_ANALOG_USB1_VBUS_DETECT_TOG 107
+#define USB_ANALOG_USB1_CHRG_DETECT 108
+#define USB_ANALOG_USB1_CHRG_DETECT_SET 109
+#define USB_ANALOG_USB1_CHRG_DETECT_CLR 110
+#define USB_ANALOG_USB1_CHRG_DETECT_TOG 111
+#define USB_ANALOG_USB1_VBUS_DETECT_STAT 112
+#define USB_ANALOG_USB1_CHRG_DETECT_STAT 116
+#define USB_ANALOG_USB1_MISC 124
+#define USB_ANALOG_USB1_MISC_SET 125
+#define USB_ANALOG_USB1_MISC_CLR 126
+#define USB_ANALOG_USB1_MISC_TOG 127
+#define USB_ANALOG_USB2_VBUS_DETECT 128
+#define USB_ANALOG_USB2_VBUS_DETECT_SET 129
+#define USB_ANALOG_USB2_VBUS_DETECT_CLR 130
+#define USB_ANALOG_USB2_VBUS_DETECT_TOG 131
+#define USB_ANALOG_USB2_CHRG_DETECT 132
+#define USB_ANALOG_USB2_CHRG_DETECT_SET 133
+#define USB_ANALOG_USB2_CHRG_DETECT_CLR 134
+#define USB_ANALOG_USB2_CHRG_DETECT_TOG 135
+#define USB_ANALOG_USB2_VBUS_DETECT_STAT 136
+#define USB_ANALOG_USB2_CHRG_DETECT_STAT 140
+#define USB_ANALOG_USB2_MISC 148
+#define USB_ANALOG_USB2_MISC_SET 149
+#define USB_ANALOG_USB2_MISC_CLR 150
+#define USB_ANALOG_USB2_MISC_TOG 151
+#define USB_ANALOG_DIGPROG 152
+#define CCM_ANALOG_MAX 153
+
+/* CCM_CBCMR */
+#define PRE_PERIPH_CLK_SEL_SHIFT (18)
+#define PRE_PERIPH_CLK_SEL_LENGTH (2)
+
+/* CCM_CBCDR */
+#define AHB_PODF_SHIFT (10)
+#define AHB_PODF_LENGTH (3)
+#define IPG_PODF_SHIFT (8)
+#define IPG_PODF_LENGTH (2)
+
+/* CCM_CSCMR1 */
+#define PERCLK_PODF_SHIFT (0)
+#define PERCLK_PODF_LENGTH (6)
+
+/* CCM_ANALOG_PFD_528 */
+#define PFD0_FRAC_SHIFT (0)
+#define PFD0_FRAC_LENGTH (6)
+#define PFD2_FRAC_SHIFT (16)
+#define PFD2_FRAC_LENGTH (6)
+
+/* CCM_ANALOG_PLL_SYS */
+#define DIV_SELECT_SHIFT (0)
+#define DIV_SELECT_LENGTH (1)
+
+#define CCM_ANALOG_PLL_LOCK (1 << 31);
+
+#define EXTRACT(value, name) extract32(value, name##_SHIFT, name##_LENGTH)
+
+#define TYPE_IMX6_CCM "imx6.ccm"
+OBJECT_DECLARE_SIMPLE_TYPE(IMX6CCMState, IMX6_CCM)
+
+struct IMX6CCMState {
+ /* <private> */
+ IMXCCMState parent_obj;
+
+ /* <public> */
+ MemoryRegion container;
+ MemoryRegion ioccm;
+ MemoryRegion ioanalog;
+
+ uint32_t ccm[CCM_MAX];
+ uint32_t analog[CCM_ANALOG_MAX];
+
+};
+
+#endif /* IMX6_CCM_H */
diff --git a/include/hw/misc/imx6_src.h b/include/hw/misc/imx6_src.h
new file mode 100644
index 000000000..f380da381
--- /dev/null
+++ b/include/hw/misc/imx6_src.h
@@ -0,0 +1,74 @@
+/*
+ * IMX6 System Reset Controller
+ *
+ * Copyright (C) 2012 NICTA
+ * Updated by 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 IMX6_SRC_H
+#define IMX6_SRC_H
+
+#include "hw/sysbus.h"
+#include "qemu/bitops.h"
+#include "qom/object.h"
+
+#define SRC_SCR 0
+#define SRC_SBMR1 1
+#define SRC_SRSR 2
+#define SRC_SISR 5
+#define SRC_SIMR 6
+#define SRC_SBMR2 7
+#define SRC_GPR1 8
+#define SRC_GPR2 9
+#define SRC_GPR3 10
+#define SRC_GPR4 11
+#define SRC_GPR5 12
+#define SRC_GPR6 13
+#define SRC_GPR7 14
+#define SRC_GPR8 15
+#define SRC_GPR9 16
+#define SRC_GPR10 17
+#define SRC_MAX 18
+
+/* SRC_SCR */
+#define CORE3_ENABLE_SHIFT 24
+#define CORE3_ENABLE_LENGTH 1
+#define CORE2_ENABLE_SHIFT 23
+#define CORE2_ENABLE_LENGTH 1
+#define CORE1_ENABLE_SHIFT 22
+#define CORE1_ENABLE_LENGTH 1
+#define CORE3_RST_SHIFT 16
+#define CORE3_RST_LENGTH 1
+#define CORE2_RST_SHIFT 15
+#define CORE2_RST_LENGTH 1
+#define CORE1_RST_SHIFT 14
+#define CORE1_RST_LENGTH 1
+#define CORE0_RST_SHIFT 13
+#define CORE0_RST_LENGTH 1
+#define SW_IPU1_RST_SHIFT 3
+#define SW_IPU1_RST_LENGTH 1
+#define SW_IPU2_RST_SHIFT 12
+#define SW_IPU2_RST_LENGTH 1
+#define WARM_RST_ENABLE_SHIFT 0
+#define WARM_RST_ENABLE_LENGTH 1
+
+#define EXTRACT(value, name) extract32(value, name##_SHIFT, name##_LENGTH)
+
+#define TYPE_IMX6_SRC "imx6.src"
+OBJECT_DECLARE_SIMPLE_TYPE(IMX6SRCState, IMX6_SRC)
+
+struct IMX6SRCState {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /* <public> */
+ MemoryRegion iomem;
+
+ uint32_t regs[SRC_MAX];
+
+};
+
+#endif /* IMX6_SRC_H */
diff --git a/include/hw/misc/imx6ul_ccm.h b/include/hw/misc/imx6ul_ccm.h
new file mode 100644
index 000000000..edb5f784d
--- /dev/null
+++ b/include/hw/misc/imx6ul_ccm.h
@@ -0,0 +1,227 @@
+/*
+ * IMX6UL Clock Control Module
+ *
+ * Copyright (C) 2018 by 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 IMX6UL_CCM_H
+#define IMX6UL_CCM_H
+
+#include "hw/misc/imx_ccm.h"
+#include "qemu/bitops.h"
+#include "qom/object.h"
+
+#define CCM_CCR 0
+#define CCM_CCDR 1
+#define CCM_CSR 2
+#define CCM_CCSR 3
+#define CCM_CACRR 4
+#define CCM_CBCDR 5
+#define CCM_CBCMR 6
+#define CCM_CSCMR1 7
+#define CCM_CSCMR2 8
+#define CCM_CSCDR1 9
+#define CCM_CS1CDR 10
+#define CCM_CS2CDR 11
+#define CCM_CDCDR 12
+#define CCM_CHSCCDR 13
+#define CCM_CSCDR2 14
+#define CCM_CSCDR3 15
+#define CCM_CDHIPR 18
+#define CCM_CTOR 20
+#define CCM_CLPCR 21
+#define CCM_CISR 22
+#define CCM_CIMR 23
+#define CCM_CCOSR 24
+#define CCM_CGPR 25
+#define CCM_CCGR0 26
+#define CCM_CCGR1 27
+#define CCM_CCGR2 28
+#define CCM_CCGR3 29
+#define CCM_CCGR4 30
+#define CCM_CCGR5 31
+#define CCM_CCGR6 32
+#define CCM_CMEOR 34
+#define CCM_MAX 35
+
+#define CCM_ANALOG_PLL_ARM 0
+#define CCM_ANALOG_PLL_ARM_SET 1
+#define CCM_ANALOG_PLL_ARM_CLR 2
+#define CCM_ANALOG_PLL_ARM_TOG 3
+#define CCM_ANALOG_PLL_USB1 4
+#define CCM_ANALOG_PLL_USB1_SET 5
+#define CCM_ANALOG_PLL_USB1_CLR 6
+#define CCM_ANALOG_PLL_USB1_TOG 7
+#define CCM_ANALOG_PLL_USB2 8
+#define CCM_ANALOG_PLL_USB2_SET 9
+#define CCM_ANALOG_PLL_USB2_CLR 10
+#define CCM_ANALOG_PLL_USB2_TOG 11
+#define CCM_ANALOG_PLL_SYS 12
+#define CCM_ANALOG_PLL_SYS_SET 13
+#define CCM_ANALOG_PLL_SYS_CLR 14
+#define CCM_ANALOG_PLL_SYS_TOG 15
+#define CCM_ANALOG_PLL_SYS_SS 16
+#define CCM_ANALOG_PLL_SYS_NUM 20
+#define CCM_ANALOG_PLL_SYS_DENOM 24
+#define CCM_ANALOG_PLL_AUDIO 28
+#define CCM_ANALOG_PLL_AUDIO_SET 29
+#define CCM_ANALOG_PLL_AUDIO_CLR 30
+#define CCM_ANALOG_PLL_AUDIO_TOG 31
+#define CCM_ANALOG_PLL_AUDIO_NUM 32
+#define CCM_ANALOG_PLL_AUDIO_DENOM 36
+#define CCM_ANALOG_PLL_VIDEO 40
+#define CCM_ANALOG_PLL_VIDEO_SET 41
+#define CCM_ANALOG_PLL_VIDEO_CLR 42
+#define CCM_ANALOG_PLL_VIDEO_TOG 44
+#define CCM_ANALOG_PLL_VIDEO_NUM 46
+#define CCM_ANALOG_PLL_VIDEO_DENOM 48
+#define CCM_ANALOG_PLL_ENET 56
+#define CCM_ANALOG_PLL_ENET_SET 57
+#define CCM_ANALOG_PLL_ENET_CLR 58
+#define CCM_ANALOG_PLL_ENET_TOG 59
+#define CCM_ANALOG_PFD_480 60
+#define CCM_ANALOG_PFD_480_SET 61
+#define CCM_ANALOG_PFD_480_CLR 62
+#define CCM_ANALOG_PFD_480_TOG 63
+#define CCM_ANALOG_PFD_528 64
+#define CCM_ANALOG_PFD_528_SET 65
+#define CCM_ANALOG_PFD_528_CLR 66
+#define CCM_ANALOG_PFD_528_TOG 67
+
+/* PMU registers */
+#define PMU_REG_1P1 68
+#define PMU_REG_3P0 72
+#define PMU_REG_2P5 76
+#define PMU_REG_CORE 80
+
+#define CCM_ANALOG_MISC0 84
+#define PMU_MISC0 CCM_ANALOG_MISC0
+#define CCM_ANALOG_MISC0_SET 85
+#define PMU_MISC0_SET CCM_ANALOG_MISC0_SET
+#define CCM_ANALOG_MISC0_CLR 86
+#define PMU_MISC0_CLR CCM_ANALOG_MISC0_CLR
+#define CCM_ANALOG_MISC0_TOG 87
+#define PMU_MISC0_TOG CCM_ANALOG_MISC0_TOG
+
+#define CCM_ANALOG_MISC1 88
+#define PMU_MISC1 CCM_ANALOG_MISC1
+#define CCM_ANALOG_MISC1_SET 89
+#define PMU_MISC1_SET CCM_ANALOG_MISC1_SET
+#define CCM_ANALOG_MISC1_CLR 90
+#define PMU_MISC1_CLR CCM_ANALOG_MISC1_CLR
+#define CCM_ANALOG_MISC1_TOG 91
+#define PMU_MISC1_TOG CCM_ANALOG_MISC1_TOG
+
+#define CCM_ANALOG_MISC2 92
+#define PMU_MISC2 CCM_ANALOG_MISC2
+#define CCM_ANALOG_MISC2_SET 93
+#define PMU_MISC2_SET CCM_ANALOG_MISC2_SET
+#define CCM_ANALOG_MISC2_CLR 94
+#define PMU_MISC2_CLR CCM_ANALOG_MISC2_CLR
+#define CCM_ANALOG_MISC2_TOG 95
+#define PMU_MISC2_TOG CCM_ANALOG_MISC2_TOG
+
+#define TEMPMON_TEMPSENSE0 96
+#define TEMPMON_TEMPSENSE0_SET 97
+#define TEMPMON_TEMPSENSE0_CLR 98
+#define TEMPMON_TEMPSENSE0_TOG 99
+#define TEMPMON_TEMPSENSE1 100
+#define TEMPMON_TEMPSENSE1_SET 101
+#define TEMPMON_TEMPSENSE1_CLR 102
+#define TEMPMON_TEMPSENSE1_TOG 103
+#define TEMPMON_TEMPSENSE2 164
+#define TEMPMON_TEMPSENSE2_SET 165
+#define TEMPMON_TEMPSENSE2_CLR 166
+#define TEMPMON_TEMPSENSE2_TOG 167
+
+#define PMU_LOWPWR_CTRL 155
+#define PMU_LOWPWR_CTRL_SET 156
+#define PMU_LOWPWR_CTRL_CLR 157
+#define PMU_LOWPWR_CTRL_TOG 158
+
+#define USB_ANALOG_USB1_VBUS_DETECT 104
+#define USB_ANALOG_USB1_VBUS_DETECT_SET 105
+#define USB_ANALOG_USB1_VBUS_DETECT_CLR 106
+#define USB_ANALOG_USB1_VBUS_DETECT_TOG 107
+#define USB_ANALOG_USB1_CHRG_DETECT 108
+#define USB_ANALOG_USB1_CHRG_DETECT_SET 109
+#define USB_ANALOG_USB1_CHRG_DETECT_CLR 110
+#define USB_ANALOG_USB1_CHRG_DETECT_TOG 111
+#define USB_ANALOG_USB1_VBUS_DETECT_STAT 112
+#define USB_ANALOG_USB1_CHRG_DETECT_STAT 116
+#define USB_ANALOG_USB1_MISC 124
+#define USB_ANALOG_USB1_MISC_SET 125
+#define USB_ANALOG_USB1_MISC_CLR 126
+#define USB_ANALOG_USB1_MISC_TOG 127
+#define USB_ANALOG_USB2_VBUS_DETECT 128
+#define USB_ANALOG_USB2_VBUS_DETECT_SET 129
+#define USB_ANALOG_USB2_VBUS_DETECT_CLR 130
+#define USB_ANALOG_USB2_VBUS_DETECT_TOG 131
+#define USB_ANALOG_USB2_CHRG_DETECT 132
+#define USB_ANALOG_USB2_CHRG_DETECT_SET 133
+#define USB_ANALOG_USB2_CHRG_DETECT_CLR 134
+#define USB_ANALOG_USB2_CHRG_DETECT_TOG 135
+#define USB_ANALOG_USB2_VBUS_DETECT_STAT 136
+#define USB_ANALOG_USB2_CHRG_DETECT_STAT 140
+#define USB_ANALOG_USB2_MISC 148
+#define USB_ANALOG_USB2_MISC_SET 149
+#define USB_ANALOG_USB2_MISC_CLR 150
+#define USB_ANALOG_USB2_MISC_TOG 151
+#define USB_ANALOG_DIGPROG 152
+#define CCM_ANALOG_MAX 4096
+
+/* CCM_CBCMR */
+#define R_CBCMR_PRE_PERIPH_CLK_SEL_SHIFT (18)
+#define R_CBCMR_PRE_PERIPH_CLK_SEL_LENGTH (2)
+#define R_CBCMR_PERIPH_CLK2_SEL_SHIFT (12)
+#define R_CBCMR_PERIPH_CLK2_SEL_LENGTH (2)
+
+/* CCM_CBCDR */
+#define R_CBCDR_AHB_PODF_SHIFT (10)
+#define R_CBCDR_AHB_PODF_LENGTH (3)
+#define R_CBCDR_IPG_PODF_SHIFT (8)
+#define R_CBCDR_IPG_PODF_LENGTH (2)
+#define R_CBCDR_PERIPH_CLK_SEL_SHIFT (25)
+#define R_CBCDR_PERIPH_CLK_SEL_LENGTH (1)
+#define R_CBCDR_PERIPH_CLK2_PODF_SHIFT (27)
+#define R_CBCDR_PERIPH_CLK2_PODF_LENGTH (3)
+
+/* CCM_CSCMR1 */
+#define R_CSCMR1_PERCLK_PODF_SHIFT (0)
+#define R_CSCMR1_PERCLK_PODF_LENGTH (6)
+#define R_CSCMR1_PERCLK_CLK_SEL_SHIFT (6)
+#define R_CSCMR1_PERCLK_CLK_SEL_LENGTH (1)
+
+/* CCM_ANALOG_PFD_528 */
+#define R_ANALOG_PFD_528_PFD0_FRAC_SHIFT (0)
+#define R_ANALOG_PFD_528_PFD0_FRAC_LENGTH (6)
+#define R_ANALOG_PFD_528_PFD2_FRAC_SHIFT (16)
+#define R_ANALOG_PFD_528_PFD2_FRAC_LENGTH (6)
+
+/* CCM_ANALOG_PLL_SYS */
+#define R_ANALOG_PLL_SYS_DIV_SELECT_SHIFT (0)
+#define R_ANALOG_PLL_SYS_DIV_SELECT_LENGTH (1)
+
+#define CCM_ANALOG_PLL_LOCK (1 << 31);
+
+#define TYPE_IMX6UL_CCM "imx6ul.ccm"
+OBJECT_DECLARE_SIMPLE_TYPE(IMX6ULCCMState, IMX6UL_CCM)
+
+struct IMX6ULCCMState {
+ /* <private> */
+ IMXCCMState parent_obj;
+
+ /* <public> */
+ MemoryRegion container;
+ MemoryRegion ioccm;
+ MemoryRegion ioanalog;
+
+ uint32_t ccm[CCM_MAX];
+ uint32_t analog[CCM_ANALOG_MAX];
+
+};
+
+#endif /* IMX6UL_CCM_H */
diff --git a/include/hw/misc/imx7_ccm.h b/include/hw/misc/imx7_ccm.h
new file mode 100644
index 000000000..dcaebfb4e
--- /dev/null
+++ b/include/hw/misc/imx7_ccm.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX7 CCM, PMU and ANALOG IP blocks emulation code
+ *
+ * Author: Andrey Smirnov <andrew.smirnov@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 IMX7_CCM_H
+#define IMX7_CCM_H
+
+#include "hw/misc/imx_ccm.h"
+#include "qemu/bitops.h"
+#include "qom/object.h"
+
+enum IMX7AnalogRegisters {
+ ANALOG_PLL_ARM,
+ ANALOG_PLL_ARM_SET,
+ ANALOG_PLL_ARM_CLR,
+ ANALOG_PLL_ARM_TOG,
+ ANALOG_PLL_DDR,
+ ANALOG_PLL_DDR_SET,
+ ANALOG_PLL_DDR_CLR,
+ ANALOG_PLL_DDR_TOG,
+ ANALOG_PLL_DDR_SS,
+ ANALOG_PLL_DDR_SS_SET,
+ ANALOG_PLL_DDR_SS_CLR,
+ ANALOG_PLL_DDR_SS_TOG,
+ ANALOG_PLL_DDR_NUM,
+ ANALOG_PLL_DDR_NUM_SET,
+ ANALOG_PLL_DDR_NUM_CLR,
+ ANALOG_PLL_DDR_NUM_TOG,
+ ANALOG_PLL_DDR_DENOM,
+ ANALOG_PLL_DDR_DENOM_SET,
+ ANALOG_PLL_DDR_DENOM_CLR,
+ ANALOG_PLL_DDR_DENOM_TOG,
+ ANALOG_PLL_480,
+ ANALOG_PLL_480_SET,
+ ANALOG_PLL_480_CLR,
+ ANALOG_PLL_480_TOG,
+ ANALOG_PLL_480A,
+ ANALOG_PLL_480A_SET,
+ ANALOG_PLL_480A_CLR,
+ ANALOG_PLL_480A_TOG,
+ ANALOG_PLL_480B,
+ ANALOG_PLL_480B_SET,
+ ANALOG_PLL_480B_CLR,
+ ANALOG_PLL_480B_TOG,
+ ANALOG_PLL_ENET,
+ ANALOG_PLL_ENET_SET,
+ ANALOG_PLL_ENET_CLR,
+ ANALOG_PLL_ENET_TOG,
+ ANALOG_PLL_AUDIO,
+ ANALOG_PLL_AUDIO_SET,
+ ANALOG_PLL_AUDIO_CLR,
+ ANALOG_PLL_AUDIO_TOG,
+ ANALOG_PLL_AUDIO_SS,
+ ANALOG_PLL_AUDIO_SS_SET,
+ ANALOG_PLL_AUDIO_SS_CLR,
+ ANALOG_PLL_AUDIO_SS_TOG,
+ ANALOG_PLL_AUDIO_NUM,
+ ANALOG_PLL_AUDIO_NUM_SET,
+ ANALOG_PLL_AUDIO_NUM_CLR,
+ ANALOG_PLL_AUDIO_NUM_TOG,
+ ANALOG_PLL_AUDIO_DENOM,
+ ANALOG_PLL_AUDIO_DENOM_SET,
+ ANALOG_PLL_AUDIO_DENOM_CLR,
+ ANALOG_PLL_AUDIO_DENOM_TOG,
+ ANALOG_PLL_VIDEO,
+ ANALOG_PLL_VIDEO_SET,
+ ANALOG_PLL_VIDEO_CLR,
+ ANALOG_PLL_VIDEO_TOG,
+ ANALOG_PLL_VIDEO_SS,
+ ANALOG_PLL_VIDEO_SS_SET,
+ ANALOG_PLL_VIDEO_SS_CLR,
+ ANALOG_PLL_VIDEO_SS_TOG,
+ ANALOG_PLL_VIDEO_NUM,
+ ANALOG_PLL_VIDEO_NUM_SET,
+ ANALOG_PLL_VIDEO_NUM_CLR,
+ ANALOG_PLL_VIDEO_NUM_TOG,
+ ANALOG_PLL_VIDEO_DENOM,
+ ANALOG_PLL_VIDEO_DENOM_SET,
+ ANALOG_PLL_VIDEO_DENOM_CLR,
+ ANALOG_PLL_VIDEO_DENOM_TOG,
+ ANALOG_PLL_MISC0,
+ ANALOG_PLL_MISC0_SET,
+ ANALOG_PLL_MISC0_CLR,
+ ANALOG_PLL_MISC0_TOG,
+
+ ANALOG_DIGPROG = 0x800 / sizeof(uint32_t),
+ ANALOG_MAX,
+
+ ANALOG_PLL_LOCK = BIT(31)
+};
+
+enum IMX7CCMRegisters {
+ CCM_MAX = 0xBE00 / sizeof(uint32_t) + 1,
+};
+
+enum IMX7PMURegisters {
+ PMU_MAX = 0x140 / sizeof(uint32_t),
+};
+
+#define TYPE_IMX7_CCM "imx7.ccm"
+OBJECT_DECLARE_SIMPLE_TYPE(IMX7CCMState, IMX7_CCM)
+
+struct IMX7CCMState {
+ /* <private> */
+ IMXCCMState parent_obj;
+
+ /* <public> */
+ MemoryRegion iomem;
+
+ uint32_t ccm[CCM_MAX];
+};
+
+
+#define TYPE_IMX7_ANALOG "imx7.analog"
+OBJECT_DECLARE_SIMPLE_TYPE(IMX7AnalogState, IMX7_ANALOG)
+
+struct IMX7AnalogState {
+ /* <private> */
+ IMXCCMState parent_obj;
+
+ /* <public> */
+ struct {
+ MemoryRegion container;
+ MemoryRegion analog;
+ MemoryRegion digprog;
+ MemoryRegion pmu;
+ } mmio;
+
+ uint32_t analog[ANALOG_MAX];
+ uint32_t pmu[PMU_MAX];
+};
+
+#endif /* IMX7_CCM_H */
diff --git a/include/hw/misc/imx7_gpr.h b/include/hw/misc/imx7_gpr.h
new file mode 100644
index 000000000..df364bd8f
--- /dev/null
+++ b/include/hw/misc/imx7_gpr.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX7 GPR IP block emulation code
+ *
+ * Author: Andrey Smirnov <andrew.smirnov@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 IMX7_GPR_H
+#define IMX7_GPR_H
+
+#include "qemu/bitops.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_IMX7_GPR "imx7.gpr"
+OBJECT_DECLARE_SIMPLE_TYPE(IMX7GPRState, IMX7_GPR)
+
+struct IMX7GPRState {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ MemoryRegion mmio;
+};
+
+#endif /* IMX7_GPR_H */
diff --git a/include/hw/misc/imx7_snvs.h b/include/hw/misc/imx7_snvs.h
new file mode 100644
index 000000000..14a1d6fe6
--- /dev/null
+++ b/include/hw/misc/imx7_snvs.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX7 SNVS block emulation code
+ *
+ * Author: Andrey Smirnov <andrew.smirnov@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 IMX7_SNVS_H
+#define IMX7_SNVS_H
+
+#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)
+};
+
+#define TYPE_IMX7_SNVS "imx7.snvs"
+OBJECT_DECLARE_SIMPLE_TYPE(IMX7SNVSState, IMX7_SNVS)
+
+struct IMX7SNVSState {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ MemoryRegion mmio;
+};
+
+#endif /* IMX7_SNVS_H */
diff --git a/include/hw/misc/imx_ccm.h b/include/hw/misc/imx_ccm.h
new file mode 100644
index 000000000..7e5678e97
--- /dev/null
+++ b/include/hw/misc/imx_ccm.h
@@ -0,0 +1,63 @@
+/*
+ * IMX Clock Control Module base class
+ *
+ * Copyright (C) 2012 NICTA
+ * Updated by 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 IMX_CCM_H
+#define IMX_CCM_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define CKIL_FREQ 32768 /* nominal 32khz clock */
+
+/* PLL control registers */
+#define PD(v) (((v) >> 26) & 0xf)
+#define MFD(v) (((v) >> 16) & 0x3ff)
+#define MFI(v) (((v) >> 10) & 0xf);
+#define MFN(v) ((v) & 0x3ff)
+
+#define PLL_PD(x) (((x) & 0xf) << 26)
+#define PLL_MFD(x) (((x) & 0x3ff) << 16)
+#define PLL_MFI(x) (((x) & 0xf) << 10)
+#define PLL_MFN(x) (((x) & 0x3ff) << 0)
+
+#define TYPE_IMX_CCM "imx.ccm"
+OBJECT_DECLARE_TYPE(IMXCCMState, IMXCCMClass, IMX_CCM)
+
+struct IMXCCMState {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /* <public> */
+
+};
+
+typedef enum {
+ CLK_NONE,
+ CLK_IPG,
+ CLK_IPG_HIGH,
+ CLK_32k,
+ CLK_EXT,
+ CLK_HIGH_DIV,
+ CLK_HIGH,
+} IMXClk;
+
+struct IMXCCMClass {
+ /* <private> */
+ SysBusDeviceClass parent_class;
+
+ /* <public> */
+ uint32_t (*get_clock_frequency)(IMXCCMState *s, IMXClk clk);
+};
+
+uint32_t imx_ccm_calc_pll(uint32_t pllreg, uint32_t base_freq);
+
+uint32_t imx_ccm_get_clock_frequency(IMXCCMState *s, IMXClk clock);
+
+#endif /* IMX_CCM_H */
diff --git a/include/hw/misc/imx_rngc.h b/include/hw/misc/imx_rngc.h
new file mode 100644
index 000000000..34ad69922
--- /dev/null
+++ b/include/hw/misc/imx_rngc.h
@@ -0,0 +1,36 @@
+/*
+ * Freescale i.MX RNGC emulation
+ *
+ * Copyright (C) 2020 Martin Kaiser <martin@kaiser.cx>
+ *
+ * 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 IMX_RNGC_H
+#define IMX_RNGC_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_IMX_RNGC "imx.rngc"
+OBJECT_DECLARE_SIMPLE_TYPE(IMXRNGCState, IMX_RNGC)
+
+struct IMXRNGCState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+
+ uint8_t op_self_test;
+ uint8_t op_seed;
+ uint8_t mask;
+ bool auto_seed;
+
+ QEMUBH *self_test_bh;
+ QEMUBH *seed_bh;
+ qemu_irq irq;
+};
+
+#endif /* IMX_RNGC_H */
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
new file mode 100644
index 000000000..79a362832
--- /dev/null
+++ b/include/hw/misc/iotkit-secctl.h
@@ -0,0 +1,127 @@
+/*
+ * ARM IoT Kit security controller
+ *
+ * Copyright (c) 2018 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 security controller which is part of the
+ * Arm IoT Kit and documented in
+ * https://developer.arm.com/documentation/ecm0601256/latest
+ *
+ * QEMU interface:
+ * + sysbus MMIO region 0 is the "secure privilege control block" registers
+ * + sysbus MMIO region 1 is the "non-secure privilege control block" registers
+ * + named GPIO output "sec_resp_cfg" indicating whether blocked accesses
+ * should RAZ/WI or bus error
+ * + named GPIO output "nsc_cfg" whose value tracks the NSCCFG register value
+ * + named GPIO output "msc_irq" for the combined IRQ line from the MSCs
+ * Controlling the 2 APB PPCs in the IoTKit:
+ * + named GPIO outputs apb_ppc0_nonsec[0..2] and apb_ppc1_nonsec
+ * + named GPIO outputs apb_ppc0_ap[0..2] and apb_ppc1_ap
+ * + named GPIO outputs apb_ppc{0,1}_irq_enable
+ * + named GPIO outputs apb_ppc{0,1}_irq_clear
+ * + named GPIO inputs apb_ppc{0,1}_irq_status
+ * Controlling each of the 4 expansion APB PPCs which a system using the IoTKit
+ * might provide:
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_nonsec[0..15]
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_ap[0..15]
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_enable
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_clear
+ * + named GPIO inputs apb_ppcexp{0,1,2,3}_irq_status
+ * Controlling each of the 4 expansion AHB PPCs which a system using the IoTKit
+ * might provide:
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_nonsec[0..15]
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_ap[0..15]
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_enable
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_clear
+ * + named GPIO inputs ahb_ppcexp{0,1,2,3}_irq_status
+ * Controlling the (up to) 4 MPCs in the IoTKit/SSE:
+ * + named GPIO inputs mpc_status[0..3]
+ * Controlling each of the 16 expansion MPCs which a system using the IoTKit
+ * might provide:
+ * + named GPIO inputs mpcexp_status[0..15]
+ * Controlling each of the 16 expansion MSCs which a system using the IoTKit
+ * might provide:
+ * + named GPIO inputs mscexp_status[0..15]
+ * + named GPIO outputs mscexp_clear[0..15]
+ * + named GPIO outputs mscexp_ns[0..15]
+ */
+
+#ifndef IOTKIT_SECCTL_H
+#define IOTKIT_SECCTL_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_IOTKIT_SECCTL "iotkit-secctl"
+OBJECT_DECLARE_SIMPLE_TYPE(IoTKitSecCtl, IOTKIT_SECCTL)
+
+#define IOTS_APB_PPC0_NUM_PORTS 3
+#define IOTS_APB_PPC1_NUM_PORTS 1
+#define IOTS_PPC_NUM_PORTS 16
+#define IOTS_NUM_APB_PPC 2
+#define IOTS_NUM_APB_EXP_PPC 4
+#define IOTS_NUM_AHB_EXP_PPC 4
+#define IOTS_NUM_EXP_MPC 16
+#define IOTS_NUM_MPC 4
+#define IOTS_NUM_EXP_MSC 16
+
+
+/* State and IRQ lines relating to a PPC. For the
+ * PPCs in the IoTKit not all the IRQ lines are used.
+ */
+typedef struct IoTKitSecCtlPPC {
+ qemu_irq nonsec[IOTS_PPC_NUM_PORTS];
+ qemu_irq ap[IOTS_PPC_NUM_PORTS];
+ qemu_irq irq_enable;
+ qemu_irq irq_clear;
+
+ uint32_t ns;
+ uint32_t sp;
+ uint32_t nsp;
+
+ /* Number of ports actually present */
+ int numports;
+ /* Offset of this PPC's interrupt bits in SECPPCINTSTAT */
+ int irq_bit_offset;
+ IoTKitSecCtl *parent;
+} IoTKitSecCtlPPC;
+
+struct IoTKitSecCtl {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ qemu_irq sec_resp_cfg;
+ qemu_irq nsc_cfg_irq;
+
+ MemoryRegion s_regs;
+ MemoryRegion ns_regs;
+
+ uint32_t secppcintstat;
+ uint32_t secppcinten;
+ uint32_t secrespcfg;
+ uint32_t nsccfg;
+ uint32_t brginten;
+ uint32_t mpcintstatus;
+
+ uint32_t secmscintstat;
+ uint32_t secmscinten;
+ uint32_t nsmscexp;
+ qemu_irq mscexp_clear[IOTS_NUM_EXP_MSC];
+ qemu_irq mscexp_ns[IOTS_NUM_EXP_MSC];
+ qemu_irq msc_irq;
+
+ 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
new file mode 100644
index 000000000..481e27f4d
--- /dev/null
+++ b/include/hw/misc/iotkit-sysctl.h
@@ -0,0 +1,73 @@
+/*
+ * ARM IoTKit system control element
+ *
+ * Copyright (c) 2018 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 control element" which is part of the
+ * Arm IoTKit and documented in
+ * https://developer.arm.com/documentation/ecm0601256/latest
+ * Specifically, it implements the "system information block" and
+ * "system control register" blocks.
+ *
+ * QEMU interface:
+ * + 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
+ */
+
+#ifndef HW_MISC_IOTKIT_SYSCTL_H
+#define HW_MISC_IOTKIT_SYSCTL_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_IOTKIT_SYSCTL "iotkit-sysctl"
+OBJECT_DECLARE_SIMPLE_TYPE(IoTKitSysCtl, IOTKIT_SYSCTL)
+
+struct IoTKitSysCtl {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+
+ uint32_t secure_debug;
+ uint32_t reset_syndrome;
+ uint32_t reset_mask;
+ uint32_t gretreg;
+ uint32_t initsvtor0;
+ uint32_t cpuwait;
+ uint32_t wicctrl;
+ uint32_t scsecctrl;
+ uint32_t fclk_div;
+ uint32_t sysclk_div;
+ uint32_t clock_force;
+ 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 sse_version;
+ uint32_t cpuwait_rst;
+ uint32_t initsvtor0_rst;
+ uint32_t initsvtor1_rst;
+};
+
+#endif
diff --git a/include/hw/misc/iotkit-sysinfo.h b/include/hw/misc/iotkit-sysinfo.h
new file mode 100644
index 000000000..91c23f90d
--- /dev/null
+++ b/include/hw/misc/iotkit-sysinfo.h
@@ -0,0 +1,45 @@
+/*
+ * ARM IoTKit system information block
+ *
+ * Copyright (c) 2018 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 information block" which is part of the
+ * Arm IoTKit and documented in
+ * 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
+ * + sysbus MMIO region 0: the system information register bank
+ */
+
+#ifndef HW_MISC_IOTKIT_SYSINFO_H
+#define HW_MISC_IOTKIT_SYSINFO_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_IOTKIT_SYSINFO "iotkit-sysinfo"
+OBJECT_DECLARE_SIMPLE_TYPE(IoTKitSysInfo, IOTKIT_SYSINFO)
+
+struct IoTKitSysInfo {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+
+ /* Properties */
+ uint32_t sys_version;
+ uint32_t sys_config;
+ uint32_t sse_version;
+ uint32_t iidr;
+};
+
+#endif
diff --git a/include/hw/misc/ivshmem.h b/include/hw/misc/ivshmem.h
new file mode 100644
index 000000000..433ef53d7
--- /dev/null
+++ b/include/hw/misc/ivshmem.h
@@ -0,0 +1,25 @@
+
+/*
+ * Inter-VM Shared Memory PCI device.
+ *
+ * Author:
+ * Cam Macdonell <cam@cs.ualberta.ca>
+ *
+ * Based On: cirrus_vga.c
+ * Copyright (c) 2004 Fabrice Bellard
+ * Copyright (c) 2004 Makoto Suzuki (suzu)
+ *
+ * and rtl8139.c
+ * Copyright (c) 2006 Igor Kovalenko
+ *
+ * This code is licensed under the GNU GPL v2.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+#ifndef IVSHMEM_H
+#define IVSHMEM_H
+
+#define IVSHMEM_PROTOCOL_VERSION 0
+
+#endif /* IVSHMEM_H */
diff --git a/include/hw/misc/led.h b/include/hw/misc/led.h
new file mode 100644
index 000000000..29c087957
--- /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
new file mode 100644
index 000000000..b44556586
--- /dev/null
+++ b/include/hw/misc/mac_via.h
@@ -0,0 +1,117 @@
+/*
+ *
+ * Copyright (c) 2011-2018 Laurent Vivier
+ *
+ * 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_MISC_MAC_VIA_H
+#define HW_MISC_MAC_VIA_H
+
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+#include "hw/misc/mos6522.h"
+#include "qom/object.h"
+
+
+#define VIA_SIZE 0x2000
+
+/* VIA 1 */
+#define VIA1_IRQ_ONE_SECOND_BIT 0
+#define VIA1_IRQ_60HZ_BIT 1
+#define VIA1_IRQ_ADB_READY_BIT 2
+#define VIA1_IRQ_ADB_DATA_BIT 3
+#define VIA1_IRQ_ADB_CLOCK_BIT 4
+
+#define VIA1_IRQ_NB 8
+
+#define VIA1_IRQ_ONE_SECOND (1 << VIA1_IRQ_ONE_SECOND_BIT)
+#define VIA1_IRQ_60HZ (1 << VIA1_IRQ_60HZ_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 TYPE_MOS6522_Q800_VIA1 "mos6522-q800-via1"
+OBJECT_DECLARE_SIMPLE_TYPE(MOS6522Q800VIA1State, MOS6522_Q800_VIA1)
+
+struct MOS6522Q800VIA1State {
+ /*< private >*/
+ MOS6522State parent_obj;
+
+ MemoryRegion via_mem;
+
+ qemu_irq irqs[VIA1_IRQ_NB];
+ qemu_irq auxmode_irq;
+ uint8_t last_b;
+
+ /* RTC */
+ uint8_t PRAM[256];
+ BlockBackend *blk;
+ VMChangeStateEntry *vmstate;
+
+ uint32_t tick_offset;
+
+ uint8_t data_out;
+ int data_out_cnt;
+ uint8_t data_in;
+ uint8_t data_in_cnt;
+ uint8_t cmd;
+ int wprotect;
+ int alt;
+
+ /* ADB */
+ ADBBusState adb_bus;
+ qemu_irq adb_data_ready;
+ int adb_data_in_size;
+ int adb_data_in_index;
+ int adb_data_out_index;
+ uint8_t adb_data_in[128];
+ uint8_t adb_data_out[16];
+ uint8_t adb_autopoll_cmd;
+
+ /* external timers */
+ QEMUTimer *one_second_timer;
+ int64_t next_second;
+ QEMUTimer *sixty_hz_timer;
+ int64_t next_sixty_hz;
+};
+
+
+/* VIA 2 */
+#define VIA2_IRQ_SCSI_DATA_BIT 0
+#define VIA2_IRQ_NUBUS_BIT 1
+#define VIA2_IRQ_UNUSED_BIT 2
+#define VIA2_IRQ_SCSI_BIT 3
+#define VIA2_IRQ_ASC_BIT 4
+
+#define VIA2_IRQ_NB 8
+
+#define VIA2_IRQ_SCSI_DATA (1 << VIA2_IRQ_SCSI_DATA_BIT)
+#define VIA2_IRQ_NUBUS (1 << VIA2_IRQ_NUBUS_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 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
new file mode 100644
index 000000000..a71deec96
--- /dev/null
+++ b/include/hw/misc/macio/cuda.h
@@ -0,0 +1,102 @@
+/*
+ * QEMU PowerMac CUDA device support
+ *
+ * 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 CUDA_H
+#define CUDA_H
+
+#include "hw/misc/mos6522.h"
+#include "qom/object.h"
+
+/* CUDA commands (2nd byte) */
+#define CUDA_WARM_START 0x0
+#define CUDA_AUTOPOLL 0x1
+#define CUDA_GET_6805_ADDR 0x2
+#define CUDA_GET_TIME 0x3
+#define CUDA_GET_PRAM 0x7
+#define CUDA_SET_6805_ADDR 0x8
+#define CUDA_SET_TIME 0x9
+#define CUDA_POWERDOWN 0xa
+#define CUDA_POWERUP_TIME 0xb
+#define CUDA_SET_PRAM 0xc
+#define CUDA_MS_RESET 0xd
+#define CUDA_SEND_DFAC 0xe
+#define CUDA_BATTERY_SWAP_SENSE 0x10
+#define CUDA_RESET_SYSTEM 0x11
+#define CUDA_SET_IPL 0x12
+#define CUDA_FILE_SERVER_FLAG 0x13
+#define CUDA_SET_AUTO_RATE 0x14
+#define CUDA_GET_AUTO_RATE 0x16
+#define CUDA_SET_DEVICE_LIST 0x19
+#define CUDA_GET_DEVICE_LIST 0x1a
+#define CUDA_SET_ONE_SECOND_MODE 0x1b
+#define CUDA_SET_POWER_MESSAGES 0x21
+#define CUDA_GET_SET_IIC 0x22
+#define CUDA_WAKEUP 0x23
+#define CUDA_TIMER_TICKLE 0x24
+#define CUDA_COMBINED_FORMAT_IIC 0x25
+
+
+/* MOS6522 CUDA */
+struct MOS6522CUDAState {
+ /*< private >*/
+ MOS6522State parent_obj;
+};
+
+#define TYPE_MOS6522_CUDA "mos6522-cuda"
+OBJECT_DECLARE_SIMPLE_TYPE(MOS6522CUDAState, MOS6522_CUDA)
+
+/* Cuda */
+#define TYPE_CUDA "cuda"
+OBJECT_DECLARE_SIMPLE_TYPE(CUDAState, CUDA)
+
+struct CUDAState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+ MemoryRegion mem;
+
+ ADBBusState adb_bus;
+ MOS6522CUDAState mos6522_cuda;
+
+ uint32_t tick_offset;
+ uint64_t tb_frequency;
+
+ uint8_t last_b;
+ uint8_t last_acr;
+
+ /* MacOS 9 is racy and requires a delay upon setting the SR_INT bit */
+ uint64_t sr_delay_ns;
+ QEMUTimer *sr_delay_timer;
+
+ int data_in_size;
+ int data_in_index;
+ int data_out_index;
+
+ qemu_irq irq;
+ uint8_t data_in[128];
+ uint8_t data_out[16];
+};
+
+#endif /* CUDA_H */
diff --git a/include/hw/misc/macio/gpio.h b/include/hw/misc/macio/gpio.h
new file mode 100644
index 000000000..7d2aa886c
--- /dev/null
+++ b/include/hw/misc/macio/gpio.h
@@ -0,0 +1,49 @@
+/*
+ * PowerMac NewWorld MacIO GPIO emulation
+ *
+ * Copyright (c) 2016 Benjamin Herrenschmidt
+ * Copyright (c) 2018 Mark Cave-Ayland
+ *
+ * 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 MACIO_GPIO_H
+#define MACIO_GPIO_H
+
+#include "hw/ppc/openpic.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_MACIO_GPIO "macio-gpio"
+OBJECT_DECLARE_SIMPLE_TYPE(MacIOGPIOState, MACIO_GPIO)
+
+struct MacIOGPIOState {
+ /*< private >*/
+ SysBusDevice parent;
+ /*< public >*/
+
+ MemoryRegion gpiomem;
+ qemu_irq gpio_extirqs[10];
+ uint8_t gpio_levels[8];
+ uint8_t gpio_regs[36]; /* XXX Check count */
+};
+
+void macio_set_gpio(MacIOGPIOState *s, uint32_t gpio, bool state);
+
+#endif
diff --git a/include/hw/misc/macio/macio.h b/include/hw/misc/macio/macio.h
new file mode 100644
index 000000000..6c05f3bfd
--- /dev/null
+++ b/include/hw/misc/macio/macio.h
@@ -0,0 +1,123 @@
+/*
+ * PowerMac MacIO device emulation
+ *
+ * Copyright (c) 2005-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 MACIO_H
+#define MACIO_H
+
+#include "hw/char/escc.h"
+#include "hw/pci/pci.h"
+#include "hw/ide/internal.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/ppc/mac_dbdma.h"
+#include "hw/ppc/openpic.h"
+#include "qom/object.h"
+
+/* MacIO virtual bus */
+#define TYPE_MACIO_BUS "macio-bus"
+OBJECT_DECLARE_SIMPLE_TYPE(MacIOBusState, MACIO_BUS)
+
+struct MacIOBusState {
+ /*< private >*/
+ BusState parent_obj;
+};
+
+/* MacIO IDE */
+#define TYPE_MACIO_IDE "macio-ide"
+OBJECT_DECLARE_SIMPLE_TYPE(MACIOIDEState, MACIO_IDE)
+
+struct MACIOIDEState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+ uint32_t addr;
+ uint32_t channel;
+ qemu_irq real_ide_irq;
+ qemu_irq real_dma_irq;
+ qemu_irq ide_irq;
+ qemu_irq dma_irq;
+
+ MemoryRegion mem;
+ IDEBus bus;
+ IDEDMA dma;
+ void *dbdma;
+ bool dma_active;
+ uint32_t timing_reg;
+ uint32_t irq_reg;
+};
+
+void macio_ide_init_drives(MACIOIDEState *ide, DriveInfo **hd_table);
+void macio_ide_register_dma(MACIOIDEState *ide);
+
+#define TYPE_MACIO "macio"
+OBJECT_DECLARE_SIMPLE_TYPE(MacIOState, MACIO)
+
+struct MacIOState {
+ /*< private >*/
+ PCIDevice parent;
+ /*< public >*/
+
+ MacIOBusState macio_bus;
+ MemoryRegion bar;
+ CUDAState cuda;
+ PMUState pmu;
+ DBDMAState dbdma;
+ ESCCState escc;
+ uint64_t frequency;
+};
+
+#define TYPE_OLDWORLD_MACIO "macio-oldworld"
+OBJECT_DECLARE_SIMPLE_TYPE(OldWorldMacIOState, OLDWORLD_MACIO)
+
+struct OldWorldMacIOState {
+ /*< private >*/
+ MacIOState parent_obj;
+ /*< public >*/
+
+ HeathrowState pic;
+
+ MacIONVRAMState nvram;
+ MACIOIDEState ide[2];
+};
+
+#define TYPE_NEWWORLD_MACIO "macio-newworld"
+OBJECT_DECLARE_SIMPLE_TYPE(NewWorldMacIOState, NEWWORLD_MACIO)
+
+struct NewWorldMacIOState {
+ /*< private >*/
+ MacIOState parent_obj;
+ /*< public >*/
+
+ bool has_pmu;
+ bool has_adb;
+ OpenPICState pic;
+ MACIOIDEState ide[2];
+ MacIOGPIOState gpio;
+};
+
+#endif /* MACIO_H */
diff --git a/include/hw/misc/macio/pmu.h b/include/hw/misc/macio/pmu.h
new file mode 100644
index 000000000..78237d99a
--- /dev/null
+++ b/include/hw/misc/macio/pmu.h
@@ -0,0 +1,236 @@
+/*
+ * Definitions for talking to the PMU. The PMU is a microcontroller
+ * which controls battery charging and system power on PowerBook 3400
+ * and 2400 models as well as the RTC and various other things.
+ *
+ * Copyright (C) 1998 Paul Mackerras.
+ * Copyright (C) 2016 Ben Herrenschmidt
+ */
+
+#ifndef PMU_H
+#define PMU_H
+
+#include "hw/misc/mos6522.h"
+#include "hw/misc/macio/gpio.h"
+#include "qom/object.h"
+
+/*
+ * PMU commands
+ */
+
+#define PMU_POWER_CTRL0 0x10 /* control power of some devices */
+#define PMU_POWER_CTRL 0x11 /* control power of some devices */
+#define PMU_ADB_CMD 0x20 /* send ADB packet */
+#define PMU_ADB_POLL_OFF 0x21 /* disable ADB auto-poll */
+#define PMU_WRITE_NVRAM 0x33 /* write non-volatile RAM */
+#define PMU_READ_NVRAM 0x3b /* read non-volatile RAM */
+#define PMU_SET_RTC 0x30 /* set real-time clock */
+#define PMU_READ_RTC 0x38 /* read real-time clock */
+#define PMU_SET_VOLBUTTON 0x40 /* set volume up/down position */
+#define PMU_BACKLIGHT_BRIGHT 0x41 /* set backlight brightness */
+#define PMU_GET_VOLBUTTON 0x48 /* get volume up/down position */
+#define PMU_PCEJECT 0x4c /* eject PC-card from slot */
+#define PMU_BATTERY_STATE 0x6b /* report battery state etc. */
+#define PMU_SMART_BATTERY_STATE 0x6f /* report battery state (new way) */
+#define PMU_SET_INTR_MASK 0x70 /* set PMU interrupt mask */
+#define PMU_INT_ACK 0x78 /* read interrupt bits */
+#define PMU_SHUTDOWN 0x7e /* turn power off */
+#define PMU_CPU_SPEED 0x7d /* control CPU speed on some models */
+#define PMU_SLEEP 0x7f /* put CPU to sleep */
+#define PMU_POWER_EVENTS 0x8f /* Send power-event commands to PMU */
+#define PMU_I2C_CMD 0x9a /* I2C operations */
+#define PMU_RESET 0xd0 /* reset CPU */
+#define PMU_GET_BRIGHTBUTTON 0xd9 /* report brightness up/down pos */
+#define PMU_GET_COVER 0xdc /* report cover open/closed */
+#define PMU_SYSTEM_READY 0xdf /* tell PMU we are awake */
+#define PMU_DOWNLOAD_STATUS 0xe2 /* Called by MacOS during boot... */
+#define PMU_READ_PMU_RAM 0xe8 /* read the PMU RAM... ??? */
+#define PMU_GET_VERSION 0xea /* read the PMU version */
+
+/* Bits to use with the PMU_POWER_CTRL0 command */
+#define PMU_POW0_ON 0x80 /* OR this to power ON the device */
+#define PMU_POW0_OFF 0x00 /* leave bit 7 to 0 to power it OFF */
+#define PMU_POW0_HARD_DRIVE 0x04 /* Hard drive power
+ * (on wallstreet/lombard ?) */
+
+/* Bits to use with the PMU_POWER_CTRL command */
+#define PMU_POW_ON 0x80 /* OR this to power ON the device */
+#define PMU_POW_OFF 0x00 /* leave bit 7 to 0 to power it OFF */
+#define PMU_POW_BACKLIGHT 0x01 /* backlight power */
+#define PMU_POW_CHARGER 0x02 /* battery charger power */
+#define PMU_POW_IRLED 0x04 /* IR led power (on wallstreet) */
+#define PMU_POW_MEDIABAY 0x08 /* media bay power
+ * (wallstreet/lombard ?) */
+
+/* Bits in PMU interrupt and interrupt mask bytes */
+#define PMU_INT_PCEJECT 0x04 /* PC-card eject buttons */
+#define PMU_INT_SNDBRT 0x08 /* sound/brightness up/down buttons */
+#define PMU_INT_ADB 0x10 /* ADB autopoll or reply data */
+#define PMU_INT_BATTERY 0x20 /* Battery state change */
+#define PMU_INT_ENVIRONMENT 0x40 /* Environment interrupts */
+#define PMU_INT_TICK 0x80 /* 1-second tick interrupt */
+
+/* Other bits in PMU interrupt valid when PMU_INT_ADB is set */
+#define PMU_INT_ADB_AUTO 0x04 /* ADB autopoll, when PMU_INT_ADB */
+#define PMU_INT_WAITING_CHARGER 0x01 /* ??? */
+#define PMU_INT_AUTO_SRQ_POLL 0x02 /* ??? */
+
+/* Bits in the environement message (either obtained via PMU_GET_COVER,
+ * or via PMU_INT_ENVIRONMENT on core99 */
+#define PMU_ENV_LID_CLOSED 0x01 /* The lid is closed */
+
+/* I2C related definitions */
+#define PMU_I2C_MODE_SIMPLE 0
+#define PMU_I2C_MODE_STDSUB 1
+#define PMU_I2C_MODE_COMBINED 2
+
+#define PMU_I2C_BUS_STATUS 0
+#define PMU_I2C_BUS_SYSCLK 1
+#define PMU_I2C_BUS_POWER 2
+
+#define PMU_I2C_STATUS_OK 0
+#define PMU_I2C_STATUS_DATAREAD 1
+#define PMU_I2C_STATUS_BUSY 0xfe
+
+/* Kind of PMU (model) */
+enum {
+ PMU_UNKNOWN,
+ PMU_OHARE_BASED, /* 2400, 3400, 3500 (old G3 powerbook) */
+ PMU_HEATHROW_BASED, /* PowerBook G3 series */
+ PMU_PADDINGTON_BASED, /* 1999 PowerBook G3 */
+ PMU_KEYLARGO_BASED, /* Core99 motherboard (PMU99) */
+ PMU_68K_V1, /* 68K PMU, version 1 */
+ PMU_68K_V2, /* 68K PMU, version 2 */
+};
+
+/* PMU PMU_POWER_EVENTS commands */
+enum {
+ PMU_PWR_GET_POWERUP_EVENTS = 0x00,
+ PMU_PWR_SET_POWERUP_EVENTS = 0x01,
+ PMU_PWR_CLR_POWERUP_EVENTS = 0x02,
+ PMU_PWR_GET_WAKEUP_EVENTS = 0x03,
+ PMU_PWR_SET_WAKEUP_EVENTS = 0x04,
+ PMU_PWR_CLR_WAKEUP_EVENTS = 0x05,
+};
+
+/* Power events wakeup bits */
+enum {
+ PMU_PWR_WAKEUP_KEY = 0x01, /* Wake on key press */
+ PMU_PWR_WAKEUP_AC_INSERT = 0x02, /* Wake on AC adapter plug */
+ PMU_PWR_WAKEUP_AC_CHANGE = 0x04,
+ PMU_PWR_WAKEUP_LID_OPEN = 0x08,
+ PMU_PWR_WAKEUP_RING = 0x10,
+};
+
+/*
+ * This table indicates for each PMU opcode:
+ * - the number of data bytes to be sent with the command, or -1
+ * if a length byte should be sent,
+ * - the number of response bytes which the PMU will return, or
+ * -1 if it will send a length byte.
+ */
+
+static const int8_t pmu_data_len[256][2] = {
+/* 0 1 2 3 4 5 6 7 */
+ {-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
+ {-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},
+ { 1, 0},{ 1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
+ { 0, 1},{ 0, 1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},{ 0, 0},
+ {-1, 0},{ 0, 0},{ 2, 0},{ 1, 0},{ 1, 0},{-1, 0},{-1, 0},{-1, 0},
+ { 0, -1},{ 0, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},{ 0, -1},
+ { 4, 0},{20, 0},{-1, 0},{ 3, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
+ { 0, 4},{ 0, 20},{ 2, -1},{ 2, 1},{ 3, -1},{-1, -1},{-1, -1},{ 4, 0},
+ { 1, 0},{ 1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
+ { 0, 1},{ 0, 1},{-1, -1},{ 1, 0},{ 1, 0},{-1, -1},{-1, -1},{-1, -1},
+ { 1, 0},{ 0, 0},{ 2, 0},{ 2, 0},{-1, 0},{ 1, 0},{ 3, 0},{ 1, 0},
+ { 0, 1},{ 1, 0},{ 0, 2},{ 0, 2},{ 0, -1},{-1, -1},{-1, -1},{-1, -1},
+ { 2, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
+ { 0, 3},{ 0, 3},{ 0, 2},{ 0, 8},{ 0, -1},{ 0, -1},{-1, -1},{-1, -1},
+ { 1, 0},{ 1, 0},{ 1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
+ { 0, -1},{ 0, -1},{-1, -1},{-1, -1},{-1, -1},{ 5, 1},{ 4, 1},{ 4, 1},
+ { 4, 0},{-1, 0},{ 0, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
+ { 0, 5},{-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},
+ { 1, 0},{ 2, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
+ { 0, 1},{ 0, 1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},
+ { 2, 0},{ 2, 0},{ 2, 0},{ 4, 0},{-1, 0},{ 0, 0},{-1, 0},{-1, 0},
+ { 1, 1},{ 1, 0},{ 3, 0},{ 2, 0},{-1, -1},{-1, -1},{-1, -1},{-1, -1},
+ {-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
+ {-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},
+ {-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
+ {-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},
+ { 0, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
+ { 1, 1},{ 1, 1},{-1, -1},{-1, -1},{ 0, 1},{ 0, -1},{-1, -1},{-1, -1},
+ {-1, 0},{ 4, 0},{ 0, 1},{-1, 0},{-1, 0},{ 4, 0},{-1, 0},{-1, 0},
+ { 3, -1},{-1, -1},{ 0, 1},{-1, -1},{ 0, -1},{-1, -1},{-1, -1},{ 0, 0},
+ {-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
+ {-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1},
+};
+
+/* Command protocol state machine */
+typedef enum {
+ pmu_state_idle, /* Waiting for command */
+ pmu_state_cmd, /* Receiving command */
+ pmu_state_rsp, /* Responding to command */
+} PMUCmdState;
+
+/* MOS6522 PMU */
+struct MOS6522PMUState {
+ /*< private >*/
+ MOS6522State parent_obj;
+};
+
+#define TYPE_MOS6522_PMU "mos6522-pmu"
+OBJECT_DECLARE_SIMPLE_TYPE(MOS6522PMUState, MOS6522_PMU)
+/**
+ * PMUState:
+ * @last_b: last value of B register
+ */
+
+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;
+
+ /* PMU low level protocol state */
+ PMUCmdState cmd_state;
+ uint8_t last_b;
+ uint8_t cmd;
+ uint32_t cmdlen;
+ uint32_t rsplen;
+ uint8_t cmd_buf_pos;
+ uint8_t cmd_buf[128];
+ uint8_t cmd_rsp_pos;
+ uint8_t cmd_rsp_sz;
+ uint8_t cmd_rsp[128];
+
+ /* PMU events/interrupts */
+ uint8_t intbits;
+ uint8_t intmask;
+
+ /* ADB */
+ bool has_adb;
+ ADBBusState adb_bus;
+ uint8_t adb_reply_size;
+ uint8_t adb_reply[ADB_MAX_OUT_LEN];
+
+ /* RTC */
+ uint32_t tick_offset;
+ QEMUTimer *one_sec_timer;
+ int64_t one_sec_target;
+
+ /* GPIO */
+ MacIOGPIOState *gpio;
+};
+
+#define TYPE_VIA_PMU "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 000000000..2baa1413b
--- /dev/null
+++ b/include/hw/misc/mchp_pfsoc_dmc.h
@@ -0,0 +1,56 @@
+/*
+ * 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
+
+/* 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 000000000..9235523e3
--- /dev/null
+++ b/include/hw/misc/mchp_pfsoc_ioscb.h
@@ -0,0 +1,50 @@
+/*
+ * 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
+
+typedef struct MchpPfSoCIoscbState {
+ SysBusDevice parent;
+ MemoryRegion container;
+ MemoryRegion lane01;
+ MemoryRegion lane23;
+ MemoryRegion ctrl;
+ MemoryRegion cfg;
+ 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;
+} 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 000000000..546ba68f6
--- /dev/null
+++ b/include/hw/misc/mchp_pfsoc_sysreg.h
@@ -0,0 +1,39 @@
+/*
+ * 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
+
+#define MCHP_PFSOC_SYSREG_REG_SIZE 0x2000
+
+typedef struct MchpPfSoCSysregState {
+ SysBusDevice parent;
+ MemoryRegion sysreg;
+} 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
new file mode 100644
index 000000000..9fa58942d
--- /dev/null
+++ b/include/hw/misc/mips_cmgcr.h
@@ -0,0 +1,91 @@
+/*
+ * 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) 2015 Imagination Technologies
+ *
+ */
+
+#ifndef MIPS_CMGCR_H
+#define MIPS_CMGCR_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_MIPS_GCR "mips-gcr"
+OBJECT_DECLARE_SIMPLE_TYPE(MIPSGCRState, MIPS_GCR)
+
+#define GCR_BASE_ADDR 0x1fbf8000ULL
+#define GCR_ADDRSPACE_SZ 0x8000
+
+/* Offsets to register blocks */
+#define MIPS_GCB_OFS 0x0000 /* Global Control Block */
+#define MIPS_CLCB_OFS 0x2000 /* Core Local Control Block */
+#define MIPS_COCB_OFS 0x4000 /* Core Other Control Block */
+#define MIPS_GDB_OFS 0x6000 /* Global Debug Block */
+
+/* Global Control Block Register Map */
+#define GCR_CONFIG_OFS 0x0000
+#define GCR_BASE_OFS 0x0008
+#define GCR_REV_OFS 0x0030
+#define GCR_GIC_BASE_OFS 0x0080
+#define GCR_CPC_BASE_OFS 0x0088
+#define GCR_GIC_STATUS_OFS 0x00D0
+#define GCR_CPC_STATUS_OFS 0x00F0
+#define GCR_L2_CONFIG_OFS 0x0130
+
+/* Core Local and Core Other Block Register Map */
+#define GCR_CL_CONFIG_OFS 0x0010
+#define GCR_CL_OTHER_OFS 0x0018
+#define GCR_CL_RESETBASE_OFS 0x0020
+
+/* GCR_L2_CONFIG register fields */
+#define GCR_L2_CONFIG_BYPASS_SHF 20
+#define GCR_L2_CONFIG_BYPASS_MSK ((0x1ULL) << GCR_L2_CONFIG_BYPASS_SHF)
+
+/* GCR_BASE register fields */
+#define GCR_BASE_GCRBASE_MSK 0xffffffff8000ULL
+
+/* GCR_GIC_BASE register fields */
+#define GCR_GIC_BASE_GICEN_MSK 1
+#define GCR_GIC_BASE_GICBASE_MSK 0xFFFFFFFE0000ULL
+#define GCR_GIC_BASE_MSK (GCR_GIC_BASE_GICEN_MSK | GCR_GIC_BASE_GICBASE_MSK)
+
+/* GCR_CPC_BASE register fields */
+#define GCR_CPC_BASE_CPCEN_MSK 1
+#define GCR_CPC_BASE_CPCBASE_MSK 0xFFFFFFFF8000ULL
+#define GCR_CPC_BASE_MSK (GCR_CPC_BASE_CPCEN_MSK | GCR_CPC_BASE_CPCBASE_MSK)
+
+/* GCR_CL_OTHER_OFS register fields */
+#define GCR_CL_OTHER_VPOTHER_MSK 0x7
+#define GCR_CL_OTHER_MSK GCR_CL_OTHER_VPOTHER_MSK
+
+/* GCR_CL_RESETBASE_OFS register fields */
+#define GCR_CL_RESET_BASE_RESETBASE_MSK 0xFFFFF000U
+#define GCR_CL_RESET_BASE_MSK GCR_CL_RESET_BASE_RESETBASE_MSK
+
+typedef struct MIPSGCRVPState MIPSGCRVPState;
+struct MIPSGCRVPState {
+ uint32_t other;
+ uint64_t reset_base;
+};
+
+struct MIPSGCRState {
+ SysBusDevice parent_obj;
+
+ int32_t gcr_rev;
+ int32_t num_vps;
+ hwaddr gcr_base;
+ MemoryRegion iomem;
+ MemoryRegion *cpc_mr;
+ MemoryRegion *gic_mr;
+
+ uint64_t cpc_base;
+ uint64_t gic_base;
+
+ /* VP Local/Other Registers */
+ MIPSGCRVPState *vps;
+};
+
+#endif /* MIPS_CMGCR_H */
diff --git a/include/hw/misc/mips_cpc.h b/include/hw/misc/mips_cpc.h
new file mode 100644
index 000000000..fcafbd5e0
--- /dev/null
+++ b/include/hw/misc/mips_cpc.h
@@ -0,0 +1,50 @@
+/*
+ * Cluster Power Controller emulation
+ *
+ * Copyright (c) 2016 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.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 MIPS_CPC_H
+#define MIPS_CPC_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define CPC_ADDRSPACE_SZ 0x6000
+
+/* CPC blocks offsets relative to base address */
+#define CPC_CL_BASE_OFS 0x2000
+#define CPC_CO_BASE_OFS 0x4000
+
+/* CPC register offsets relative to block offsets */
+#define CPC_VP_STOP_OFS 0x20
+#define CPC_VP_RUN_OFS 0x28
+#define CPC_VP_RUNNING_OFS 0x30
+
+#define TYPE_MIPS_CPC "mips-cpc"
+OBJECT_DECLARE_SIMPLE_TYPE(MIPSCPCState, MIPS_CPC)
+
+struct MIPSCPCState {
+ SysBusDevice parent_obj;
+
+ uint32_t num_vp;
+ uint64_t vp_start_running; /* VPs running from restart */
+
+ MemoryRegion mr;
+ uint64_t vp_running; /* Indicates which VPs are in the run state */
+};
+
+#endif /* MIPS_CPC_H */
diff --git a/include/hw/misc/mips_itu.h b/include/hw/misc/mips_itu.h
new file mode 100644
index 000000000..50d961106
--- /dev/null
+++ b/include/hw/misc/mips_itu.h
@@ -0,0 +1,83 @@
+/*
+ * Inter-Thread Communication Unit emulation.
+ *
+ * Copyright (c) 2016 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.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 MIPS_ITU_H
+#define MIPS_ITU_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_MIPS_ITU "mips-itu"
+OBJECT_DECLARE_SIMPLE_TYPE(MIPSITUState, MIPS_ITU)
+
+#define ITC_CELL_DEPTH_SHIFT 2
+#define ITC_CELL_DEPTH (1u << ITC_CELL_DEPTH_SHIFT)
+
+typedef struct ITCStorageCell {
+ struct {
+ uint8_t FIFODepth; /* Log2 of the cell depth */
+ uint8_t FIFOPtr; /* Number of elements in a FIFO cell */
+ uint8_t FIFO; /* 1 - FIFO cell, 0 - Semaphore cell */
+ uint8_t T; /* Trap Bit */
+ uint8_t F; /* Full Bit */
+ uint8_t E; /* Empty Bit */
+ } tag;
+
+ /* Index of the oldest element in the queue */
+ uint8_t fifo_out;
+
+ /* Circular buffer for FIFO. Semaphore cells use index 0 only */
+ uint64_t data[ITC_CELL_DEPTH];
+
+ /* Bitmap tracking blocked threads on the cell.
+ TODO: support >64 threads ? */
+ uint64_t blocked_threads;
+} ITCStorageCell;
+
+#define ITC_ADDRESSMAP_NUM 2
+
+struct MIPSITUState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ int32_t num_fifo;
+ int32_t num_semaphores;
+
+ /* ITC Storage */
+ ITCStorageCell *cell;
+ MemoryRegion storage_io;
+
+ /* ITC Configuration Tags */
+ uint64_t ITCAddressMap[ITC_ADDRESSMAP_NUM];
+ MemoryRegion tag_io;
+
+ /* ITU Control Register */
+ uint64_t icr0;
+
+ /* SAAR */
+ bool saar_present;
+ void *saar;
+
+};
+
+/* Get ITC Configuration Tag memory region. */
+MemoryRegion *mips_itu_get_tag_region(MIPSITUState *itu);
+
+#endif /* MIPS_ITU_H */
diff --git a/include/hw/misc/mos6522.h b/include/hw/misc/mos6522.h
new file mode 100644
index 000000000..fc95d22b0
--- /dev/null
+++ b/include/hw/misc/mos6522.h
@@ -0,0 +1,150 @@
+/*
+ * QEMU MOS6522 VIA emulation
+ *
+ * Copyright (c) 2004-2007 Fabrice Bellard
+ * Copyright (c) 2007 Jocelyn Mayer
+ * Copyright (c) 2018 Mark Cave-Ayland
+ *
+ * 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 MOS6522_H
+#define MOS6522_H
+
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+#include "hw/input/adb.h"
+#include "qom/object.h"
+
+/* Bits in ACR */
+#define SR_CTRL 0x1c /* Shift register control bits */
+#define SR_EXT 0x0c /* Shift on external clock */
+#define SR_OUT 0x10 /* Shift out if 1 */
+
+/* Bits in IFR and IER */
+#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 */
+
+/* Bits in ACR */
+#define T1MODE 0xc0 /* Timer 1 mode */
+#define T1MODE_CONT 0x40 /* continuous interrupts */
+
+/* VIA registers */
+#define VIA_REG_B 0x00
+#define VIA_REG_A 0x01
+#define VIA_REG_DIRB 0x02
+#define VIA_REG_DIRA 0x03
+#define VIA_REG_T1CL 0x04
+#define VIA_REG_T1CH 0x05
+#define VIA_REG_T1LL 0x06
+#define VIA_REG_T1LH 0x07
+#define VIA_REG_T2CL 0x08
+#define VIA_REG_T2CH 0x09
+#define VIA_REG_SR 0x0a
+#define VIA_REG_ACR 0x0b
+#define VIA_REG_PCR 0x0c
+#define VIA_REG_IFR 0x0d
+#define VIA_REG_IER 0x0e
+#define VIA_REG_ANH 0x0f
+
+/**
+ * MOS6522Timer:
+ * @counter_value: counter value at load time
+ */
+typedef struct MOS6522Timer {
+ int index;
+ uint16_t latch;
+ uint16_t counter_value;
+ int64_t load_time;
+ int64_t next_irq_time;
+ uint64_t frequency;
+ QEMUTimer *timer;
+} MOS6522Timer;
+
+/**
+ * MOS6522State:
+ * @b: B-side data
+ * @a: A-side data
+ * @dirb: B-side direction (1=output)
+ * @dira: A-side direction (1=output)
+ * @sr: Shift register
+ * @acr: Auxiliary control register
+ * @pcr: Peripheral control register
+ * @ifr: Interrupt flag register
+ * @ier: Interrupt enable register
+ * @anh: A-side data, no handshake
+ * @last_b: last value of B register
+ * @last_acr: last value of ACR register
+ */
+struct MOS6522State {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ MemoryRegion mem;
+ /* VIA registers */
+ uint8_t b;
+ uint8_t a;
+ uint8_t dirb;
+ uint8_t dira;
+ uint8_t sr;
+ uint8_t acr;
+ uint8_t pcr;
+ uint8_t ifr;
+ uint8_t ier;
+
+ MOS6522Timer timers[2];
+ uint64_t frequency;
+
+ qemu_irq irq;
+};
+
+#define TYPE_MOS6522 "mos6522"
+OBJECT_DECLARE_TYPE(MOS6522State, MOS6522DeviceClass, MOS6522)
+
+struct MOS6522DeviceClass {
+ DeviceClass parent_class;
+
+ DeviceReset parent_reset;
+ void (*set_sr_int)(MOS6522State *dev);
+ 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);
+};
+
+
+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);
+
+#endif /* MOS6522_H */
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
new file mode 100644
index 000000000..7b8bd604d
--- /dev/null
+++ b/include/hw/misc/mps2-fpgaio.h
@@ -0,0 +1,62 @@
+/*
+ * ARM MPS2 FPGAIO emulation
+ *
+ * Copyright (c) 2018 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 FPGAIO register block in the AN505
+ * FPGA image for the MPS2 dev board; it is documented in the
+ * application note:
+ * https://developer.arm.com/documentation/dai0505/latest/
+ *
+ * QEMU interface:
+ * + sysbus MMIO region 0: the register bank
+ */
+
+#ifndef MPS2_FPGAIO_H
+#define MPS2_FPGAIO_H
+
+#include "hw/sysbus.h"
+#include "hw/misc/led.h"
+#include "qom/object.h"
+
+#define TYPE_MPS2_FPGAIO "mps2-fpgaio"
+OBJECT_DECLARE_SIMPLE_TYPE(MPS2FPGAIO, MPS2_FPGAIO)
+
+#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;
+ /* Values of COUNTER and PSCNTR at time pscntr_sync_ticks */
+ uint32_t counter;
+ uint32_t pscntr;
+
+ uint32_t prescale_clk;
+
+ /* These hold the CLOCK_VIRTUAL ns tick when the CLK1HZ/CLK100HZ was zero */
+ int64_t clk1hz_tick_offset;
+ int64_t clk100hz_tick_offset;
+};
+
+#endif
diff --git a/include/hw/misc/mps2-scc.h b/include/hw/misc/mps2-scc.h
new file mode 100644
index 000000000..3b2d13ac9
--- /dev/null
+++ b/include/hw/misc/mps2-scc.h
@@ -0,0 +1,69 @@
+/*
+ * ARM MPS2 SCC emulation
+ *
+ * Copyright (c) 2017 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 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"
+OBJECT_DECLARE_SIMPLE_TYPE(MPS2SCC, MPS2_SCC)
+
+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 cfgdata_rtn;
+ uint32_t cfgdata_out;
+ uint32_t cfgctrl;
+ uint32_t cfgstat;
+ uint32_t dll;
+ uint32_t aid;
+ uint32_t id;
+ 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
new file mode 100644
index 000000000..fc1890e71
--- /dev/null
+++ b/include/hw/misc/msf2-sysreg.h
@@ -0,0 +1,78 @@
+/*
+ * Microsemi SmartFusion2 SYSREG
+ *
+ * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@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.
+ */
+
+#ifndef HW_MSF2_SYSREG_H
+#define HW_MSF2_SYSREG_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+enum {
+ ESRAM_CR = 0x00 / 4,
+ ESRAM_MAX_LAT,
+ DDR_CR,
+ ENVM_CR,
+ ENVM_REMAP_BASE_CR,
+ ENVM_REMAP_FAB_CR,
+ CC_CR,
+ CC_REGION_CR,
+ CC_LOCK_BASE_ADDR_CR,
+ CC_FLUSH_INDX_CR,
+ DDRB_BUF_TIMER_CR,
+ DDRB_NB_ADDR_CR,
+ DDRB_NB_SIZE_CR,
+ DDRB_CR,
+
+ SOFT_RESET_CR = 0x48 / 4,
+ M3_CR,
+
+ GPIO_SYSRESET_SEL_CR = 0x58 / 4,
+
+ MDDR_CR = 0x60 / 4,
+
+ MSSDDR_PLL_STATUS_LOW_CR = 0x90 / 4,
+ MSSDDR_PLL_STATUS_HIGH_CR,
+ MSSDDR_FACC1_CR,
+ MSSDDR_FACC2_CR,
+
+ MSSDDR_PLL_STATUS = 0x150 / 4,
+};
+
+#define MSF2_SYSREG_MMIO_SIZE 0x300
+
+#define TYPE_MSF2_SYSREG "msf2-sysreg"
+OBJECT_DECLARE_SIMPLE_TYPE(MSF2SysregState, MSF2_SYSREG)
+
+struct MSF2SysregState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+
+ uint8_t apb0div;
+ uint8_t apb1div;
+
+ uint32_t regs[MSF2_SYSREG_MMIO_SIZE / 4];
+};
+
+#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 000000000..d5c8d16ca
--- /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"
+#define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), TYPE_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 000000000..13109d9d3
--- /dev/null
+++ b/include/hw/misc/npcm7xx_gcr.h
@@ -0,0 +1,43 @@
+/*
+ * 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"
+
+/*
+ * 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))
+
+typedef 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;
+} NPCM7xxGCRState;
+
+#define TYPE_NPCM7XX_GCR "npcm7xx-gcr"
+#define NPCM7XX_GCR(obj) OBJECT_CHECK(NPCM7xxGCRState, (obj), TYPE_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 000000000..36785e3ba
--- /dev/null
+++ b/include/hw/misc/npcm7xx_mft.h
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+typedef 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];
+} NPCM7xxMFTState;
+
+#define TYPE_NPCM7XX_MFT "npcm7xx-mft"
+#define NPCM7XX_MFT(obj) \
+ OBJECT_CHECK(NPCM7xxMFTState, (obj), TYPE_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 000000000..7ad632a93
--- /dev/null
+++ b/include/hw/misc/npcm7xx_pwm.h
@@ -0,0 +1,107 @@
+/*
+ * 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"
+#define NPCM7XX_PWM(obj) \
+ OBJECT_CHECK(NPCM7xxPWMState, (obj), TYPE_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 000000000..5e85fd439
--- /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"
+
+typedef struct NPCM7xxRNGState {
+ SysBusDevice parent;
+
+ MemoryRegion iomem;
+
+ uint8_t rngcs;
+ uint8_t rngd;
+ uint8_t rngmode;
+} NPCM7xxRNGState;
+
+#define TYPE_NPCM7XX_RNG "npcm7xx-rng"
+#define NPCM7XX_RNG(obj) OBJECT_CHECK(NPCM7xxRNGState, (obj), TYPE_NPCM7XX_RNG)
+
+#endif /* NPCM7XX_RNG_H */
diff --git a/include/hw/misc/nrf51_rng.h b/include/hw/misc/nrf51_rng.h
new file mode 100644
index 000000000..9aff9a76f
--- /dev/null
+++ b/include/hw/misc/nrf51_rng.h
@@ -0,0 +1,85 @@
+/*
+ * nRF51 Random Number Generator
+ *
+ * QEMU interface:
+ * + Property "period_unfiltered_us": Time between two biased values in
+ * microseconds.
+ * + Property "period_filtered_us": Time between two unbiased values in
+ * microseconds.
+ * + sysbus MMIO regions 0: Memory Region with tasks, events and registers
+ * to be mapped to the peripherals instance address by the SOC.
+ * + Named GPIO output "irq": Interrupt line of the peripheral. Must be
+ * connected to the associated peripheral interrupt line of the NVIC.
+ * + Named GPIO output "eep_valrdy": Event set when new random value is ready
+ * to be read.
+ * + Named GPIO input "tep_start": Task that triggers start of continuous
+ * generation of random values.
+ * + Named GPIO input "tep_stop": Task that ends continuous generation of
+ * random values.
+ *
+ * Accuracy of the peripheral model:
+ * + Stochastic properties of different configurations of the random source
+ * are not modeled.
+ * + Generation of unfiltered and filtered random values take at least the
+ * average generation time stated in the production specification;
+ * non-deterministic generation times are not modeled.
+ *
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
+ *
+ * This code is licensed under the GPL version 2 or later. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef NRF51_RNG_H
+#define NRF51_RNG_H
+
+#include "hw/sysbus.h"
+#include "qemu/timer.h"
+#include "qom/object.h"
+#define TYPE_NRF51_RNG "nrf51_soc.rng"
+OBJECT_DECLARE_SIMPLE_TYPE(NRF51RNGState, NRF51_RNG)
+
+#define NRF51_RNG_SIZE 0x1000
+
+#define NRF51_RNG_TASK_START 0x000
+#define NRF51_RNG_TASK_STOP 0x004
+#define NRF51_RNG_EVENT_VALRDY 0x100
+#define NRF51_RNG_REG_SHORTS 0x200
+#define NRF51_RNG_REG_SHORTS_VALRDY_STOP 0
+#define NRF51_RNG_REG_INTEN 0x300
+#define NRF51_RNG_REG_INTEN_VALRDY 0
+#define NRF51_RNG_REG_INTENSET 0x304
+#define NRF51_RNG_REG_INTENCLR 0x308
+#define NRF51_RNG_REG_CONFIG 0x504
+#define NRF51_RNG_REG_CONFIG_DECEN 0
+#define NRF51_RNG_REG_VALUE 0x508
+
+struct NRF51RNGState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion mmio;
+ qemu_irq irq;
+
+ /* Event End Points */
+ qemu_irq eep_valrdy;
+
+ QEMUTimer timer;
+
+ /* Time between generation of successive unfiltered values in us */
+ uint16_t period_unfiltered_us;
+ /* Time between generation of successive filtered values in us */
+ uint16_t period_filtered_us;
+
+ uint8_t value;
+
+ uint32_t active;
+ uint32_t event_valrdy;
+ uint32_t shortcut_stop_on_valrdy;
+ uint32_t interrupt_enabled;
+ uint32_t filter_enabled;
+
+};
+
+
+#endif /* NRF51_RNG_H */
diff --git a/include/hw/misc/pca9552.h b/include/hw/misc/pca9552.h
new file mode 100644
index 000000000..b6f4e264f
--- /dev/null
+++ b/include/hw/misc/pca9552.h
@@ -0,0 +1,37 @@
+/*
+ * PCA9552 I2C LED blinker
+ *
+ * Copyright (c) 2017-2018, IBM Corporation.
+ *
+ * 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 PCA9552_H
+#define PCA9552_H
+
+#include "hw/i2c/i2c.h"
+#include "qom/object.h"
+
+#define TYPE_PCA9552 "pca9552"
+#define TYPE_PCA955X "pca955x"
+typedef struct PCA955xState PCA955xState;
+DECLARE_INSTANCE_CHECKER(PCA955xState, PCA955X,
+ TYPE_PCA955X)
+
+#define PCA955X_NR_REGS 10
+#define PCA955X_PIN_COUNT_MAX 16
+
+struct PCA955xState {
+ /*< private >*/
+ I2CSlave i2c;
+ /*< public >*/
+
+ uint8_t len;
+ uint8_t pointer;
+
+ uint8_t regs[PCA955X_NR_REGS];
+ qemu_irq gpio[PCA955X_PIN_COUNT_MAX];
+ char *description; /* For debugging purpose only */
+};
+
+#endif
diff --git a/include/hw/misc/pca9552_regs.h b/include/hw/misc/pca9552_regs.h
new file mode 100644
index 000000000..d8051cfbd
--- /dev/null
+++ b/include/hw/misc/pca9552_regs.h
@@ -0,0 +1,32 @@
+/*
+ * PCA9552 I2C LED blinker registers
+ *
+ * Copyright (c) 2017-2018, IBM Corporation.
+ *
+ * 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 PCA9552_REGS_H
+#define PCA9552_REGS_H
+
+/*
+ * Bits [0:3] are used to address a specific register.
+ */
+#define PCA9552_INPUT0 0 /* read only input register 0 */
+#define PCA9552_INPUT1 1 /* read only input register 1 */
+#define PCA9552_PSC0 2 /* read/write frequency prescaler 0 */
+#define PCA9552_PWM0 3 /* read/write PWM register 0 */
+#define PCA9552_PSC1 4 /* read/write frequency prescaler 1 */
+#define PCA9552_PWM1 5 /* read/write PWM register 1 */
+#define PCA9552_LS0 6 /* read/write LED0 to LED3 selector */
+#define PCA9552_LS1 7 /* read/write LED4 to LED7 selector */
+#define PCA9552_LS2 8 /* read/write LED8 to LED11 selector */
+#define PCA9552_LS3 9 /* read/write LED12 to LED15 selector */
+
+/*
+ * Bit [4] is used to activate the Auto-Increment option of the
+ * register address
+ */
+#define PCA9552_AUTOINC (1 << 4)
+
+#endif
diff --git a/include/hw/misc/pvpanic.h b/include/hw/misc/pvpanic.h
new file mode 100644
index 000000000..ca3c5bb53
--- /dev/null
+++ b/include/hw/misc/pvpanic.h
@@ -0,0 +1,53 @@
+/*
+ * QEMU simulated pvpanic device.
+ *
+ * Copyright Fujitsu, Corp. 2013
+ *
+ * Authors:
+ * Wen Congyang <wency@cn.fujitsu.com>
+ * Hu Tao <hutao@cn.fujitsu.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_MISC_PVPANIC_H
+#define HW_MISC_PVPANIC_H
+
+#include "qom/object.h"
+
+#define TYPE_PVPANIC_ISA_DEVICE "pvpanic"
+#define TYPE_PVPANIC_PCI_DEVICE "pvpanic-pci"
+
+#define PVPANIC_IOPORT_PROP "ioport"
+
+/* The bit of supported pv event, TODO: include uapi header and remove this */
+#define PVPANIC_F_PANICKED 0
+#define PVPANIC_F_CRASHLOADED 1
+
+/* The pv event value */
+#define PVPANIC_PANICKED (1 << PVPANIC_F_PANICKED)
+#define PVPANIC_CRASHLOADED (1 << PVPANIC_F_CRASHLOADED)
+
+/*
+ * 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);
+
+static inline uint16_t pvpanic_port(void)
+{
+ Object *o = object_resolve_path_type("", TYPE_PVPANIC_ISA_DEVICE, NULL);
+ if (!o) {
+ return 0;
+ }
+ return object_property_get_uint(o, PVPANIC_IOPORT_PROP, NULL);
+}
+
+#endif
diff --git a/include/hw/misc/sifive_e_prci.h b/include/hw/misc/sifive_e_prci.h
new file mode 100644
index 000000000..262ca1618
--- /dev/null
+++ b/include/hw/misc/sifive_e_prci.h
@@ -0,0 +1,73 @@
+/*
+ * QEMU SiFive E PRCI (Power, Reset, Clock, Interrupt) interface
+ *
+ * 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_E_PRCI_H
+#define HW_SIFIVE_E_PRCI_H
+#include "qom/object.h"
+
+enum {
+ SIFIVE_E_PRCI_HFROSCCFG = 0x0,
+ SIFIVE_E_PRCI_HFXOSCCFG = 0x4,
+ SIFIVE_E_PRCI_PLLCFG = 0x8,
+ SIFIVE_E_PRCI_PLLOUTDIV = 0xC
+};
+
+enum {
+ SIFIVE_E_PRCI_HFROSCCFG_RDY = (1 << 31),
+ SIFIVE_E_PRCI_HFROSCCFG_EN = (1 << 30)
+};
+
+enum {
+ SIFIVE_E_PRCI_HFXOSCCFG_RDY = (1 << 31),
+ SIFIVE_E_PRCI_HFXOSCCFG_EN = (1 << 30)
+};
+
+enum {
+ SIFIVE_E_PRCI_PLLCFG_PLLSEL = (1 << 16),
+ SIFIVE_E_PRCI_PLLCFG_REFSEL = (1 << 17),
+ SIFIVE_E_PRCI_PLLCFG_BYPASS = (1 << 18),
+ SIFIVE_E_PRCI_PLLCFG_LOCK = (1 << 31)
+};
+
+enum {
+ SIFIVE_E_PRCI_PLLOUTDIV_DIV1 = (1 << 8)
+};
+
+#define SIFIVE_E_PRCI_REG_SIZE 0x1000
+
+#define TYPE_SIFIVE_E_PRCI "riscv.sifive.e.prci"
+
+typedef struct SiFiveEPRCIState SiFiveEPRCIState;
+DECLARE_INSTANCE_CHECKER(SiFiveEPRCIState, SIFIVE_E_PRCI,
+ TYPE_SIFIVE_E_PRCI)
+
+struct SiFiveEPRCIState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion mmio;
+ uint32_t hfrosccfg;
+ uint32_t hfxosccfg;
+ uint32_t pllcfg;
+ uint32_t plloutdiv;
+};
+
+DeviceState *sifive_e_prci_create(hwaddr addr);
+
+#endif
diff --git a/include/hw/misc/sifive_test.h b/include/hw/misc/sifive_test.h
new file mode 100644
index 000000000..88a38d00c
--- /dev/null
+++ b/include/hw/misc/sifive_test.h
@@ -0,0 +1,47 @@
+/*
+ * QEMU Test Finisher interface
+ *
+ * Copyright (c) 2018 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_TEST_H
+#define HW_SIFIVE_TEST_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_SIFIVE_TEST "riscv.sifive.test"
+
+typedef struct SiFiveTestState SiFiveTestState;
+DECLARE_INSTANCE_CHECKER(SiFiveTestState, SIFIVE_TEST,
+ TYPE_SIFIVE_TEST)
+
+struct SiFiveTestState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion mmio;
+};
+
+enum {
+ FINISHER_FAIL = 0x3333,
+ FINISHER_PASS = 0x5555,
+ FINISHER_RESET = 0x7777
+};
+
+DeviceState *sifive_test_create(hwaddr addr);
+
+#endif
diff --git a/include/hw/misc/sifive_u_otp.h b/include/hw/misc/sifive_u_otp.h
new file mode 100644
index 000000000..5d0d7df45
--- /dev/null
+++ b/include/hw/misc/sifive_u_otp.h
@@ -0,0 +1,87 @@
+/*
+ * QEMU SiFive U OTP (One-Time Programmable) Memory interface
+ *
+ * Copyright (c) 2019 Bin Meng <bmeng.cn@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 HW_SIFIVE_U_OTP_H
+#define HW_SIFIVE_U_OTP_H
+#include "qom/object.h"
+
+#define SIFIVE_U_OTP_PA 0x00
+#define SIFIVE_U_OTP_PAIO 0x04
+#define SIFIVE_U_OTP_PAS 0x08
+#define SIFIVE_U_OTP_PCE 0x0C
+#define SIFIVE_U_OTP_PCLK 0x10
+#define SIFIVE_U_OTP_PDIN 0x14
+#define SIFIVE_U_OTP_PDOUT 0x18
+#define SIFIVE_U_OTP_PDSTB 0x1C
+#define SIFIVE_U_OTP_PPROG 0x20
+#define SIFIVE_U_OTP_PTC 0x24
+#define SIFIVE_U_OTP_PTM 0x28
+#define SIFIVE_U_OTP_PTM_REP 0x2C
+#define SIFIVE_U_OTP_PTR 0x30
+#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)
+
+#define SIFIVE_U_OTP_PTRIM_EN (1 << 0)
+
+#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"
+
+typedef struct SiFiveUOTPState SiFiveUOTPState;
+DECLARE_INSTANCE_CHECKER(SiFiveUOTPState, SIFIVE_U_OTP,
+ TYPE_SIFIVE_U_OTP)
+
+struct SiFiveUOTPState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion mmio;
+ uint32_t pa;
+ uint32_t paio;
+ uint32_t pas;
+ uint32_t pce;
+ uint32_t pclk;
+ uint32_t pdin;
+ uint32_t pdstb;
+ uint32_t pprog;
+ uint32_t ptc;
+ uint32_t ptm;
+ uint32_t ptm_rep;
+ uint32_t ptr;
+ 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;
+ BlockBackend *blk;
+};
+
+#endif /* HW_SIFIVE_U_OTP_H */
diff --git a/include/hw/misc/sifive_u_prci.h b/include/hw/misc/sifive_u_prci.h
new file mode 100644
index 000000000..d9ebf40b7
--- /dev/null
+++ b/include/hw/misc/sifive_u_prci.h
@@ -0,0 +1,93 @@
+/*
+ * QEMU SiFive U PRCI (Power, Reset, Clock, Interrupt) interface
+ *
+ * Copyright (c) 2019 Bin Meng <bmeng.cn@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 HW_SIFIVE_U_PRCI_H
+#define HW_SIFIVE_U_PRCI_H
+#include "qom/object.h"
+
+#define SIFIVE_U_PRCI_HFXOSCCFG 0x00
+#define SIFIVE_U_PRCI_COREPLLCFG0 0x04
+#define SIFIVE_U_PRCI_DDRPLLCFG0 0x0C
+#define SIFIVE_U_PRCI_DDRPLLCFG1 0x10
+#define SIFIVE_U_PRCI_GEMGXLPLLCFG0 0x1C
+#define SIFIVE_U_PRCI_GEMGXLPLLCFG1 0x20
+#define SIFIVE_U_PRCI_CORECLKSEL 0x24
+#define SIFIVE_U_PRCI_DEVICESRESET 0x28
+#define SIFIVE_U_PRCI_CLKMUXSTATUS 0x2C
+
+/*
+ * Current FU540-C000 manual says ready bit is at bit 29, but
+ * freedom-u540-c000-bootloader codes (ux00prci.h) says it is at bit 31.
+ * We have to trust the actual code that works.
+ *
+ * see https://github.com/sifive/freedom-u540-c000-bootloader
+ */
+
+#define SIFIVE_U_PRCI_HFXOSCCFG_EN (1 << 30)
+#define SIFIVE_U_PRCI_HFXOSCCFG_RDY (1 << 31)
+
+/* xxxPLLCFG0 register bits */
+#define SIFIVE_U_PRCI_PLLCFG0_DIVR (1 << 0)
+#define SIFIVE_U_PRCI_PLLCFG0_DIVF (31 << 6)
+#define SIFIVE_U_PRCI_PLLCFG0_DIVQ (3 << 15)
+#define SIFIVE_U_PRCI_PLLCFG0_FSE (1 << 25)
+#define SIFIVE_U_PRCI_PLLCFG0_LOCK (1 << 31)
+
+/* xxxPLLCFG1 register bits */
+#define SIFIVE_U_PRCI_PLLCFG1_CKE (1 << 24)
+
+/* coreclksel register bits */
+#define SIFIVE_U_PRCI_CORECLKSEL_HFCLK (1 << 0)
+
+
+#define SIFIVE_U_PRCI_REG_SIZE 0x1000
+
+#define TYPE_SIFIVE_U_PRCI "riscv.sifive.u.prci"
+
+typedef struct SiFiveUPRCIState SiFiveUPRCIState;
+DECLARE_INSTANCE_CHECKER(SiFiveUPRCIState, SIFIVE_U_PRCI,
+ TYPE_SIFIVE_U_PRCI)
+
+struct SiFiveUPRCIState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion mmio;
+ uint32_t hfxosccfg;
+ uint32_t corepllcfg0;
+ uint32_t ddrpllcfg0;
+ uint32_t ddrpllcfg1;
+ uint32_t gemgxlpllcfg0;
+ uint32_t gemgxlpllcfg1;
+ uint32_t coreclksel;
+ uint32_t devicesreset;
+ uint32_t clkmuxstatus;
+};
+
+/*
+ * Clock indexes for use by Device Tree data and the PRCI driver.
+ *
+ * These values are from sifive-fu540-prci.h in the Linux kernel.
+ */
+#define PRCI_CLK_COREPLL 0
+#define PRCI_CLK_DDRPLL 1
+#define PRCI_CLK_GEMGXLPLL 2
+#define PRCI_CLK_TLCLK 3
+
+#endif /* HW_SIFIVE_U_PRCI_H */
diff --git a/include/hw/misc/stm32f2xx_syscfg.h b/include/hw/misc/stm32f2xx_syscfg.h
new file mode 100644
index 000000000..8595a3b31
--- /dev/null
+++ b/include/hw/misc/stm32f2xx_syscfg.h
@@ -0,0 +1,58 @@
+/*
+ * STM32F2XX SYSCFG
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * 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_STM32F2XX_SYSCFG_H
+#define HW_STM32F2XX_SYSCFG_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define SYSCFG_MEMRMP 0x00
+#define SYSCFG_PMC 0x04
+#define SYSCFG_EXTICR1 0x08
+#define SYSCFG_EXTICR2 0x0C
+#define SYSCFG_EXTICR3 0x10
+#define SYSCFG_EXTICR4 0x14
+#define SYSCFG_CMPCR 0x20
+
+#define TYPE_STM32F2XX_SYSCFG "stm32f2xx-syscfg"
+OBJECT_DECLARE_SIMPLE_TYPE(STM32F2XXSyscfgState, STM32F2XX_SYSCFG)
+
+struct STM32F2XXSyscfgState {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /* <public> */
+ MemoryRegion mmio;
+
+ uint32_t syscfg_memrmp;
+ uint32_t syscfg_pmc;
+ uint32_t syscfg_exticr1;
+ uint32_t syscfg_exticr2;
+ uint32_t syscfg_exticr3;
+ uint32_t syscfg_exticr4;
+ uint32_t syscfg_cmpcr;
+};
+
+#endif /* HW_STM32F2XX_SYSCFG_H */
diff --git a/include/hw/misc/stm32f4xx_exti.h b/include/hw/misc/stm32f4xx_exti.h
new file mode 100644
index 000000000..ea6b0097b
--- /dev/null
+++ b/include/hw/misc/stm32f4xx_exti.h
@@ -0,0 +1,59 @@
+/*
+ * STM32F4XX EXTI
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * 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_STM_EXTI_H
+#define HW_STM_EXTI_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define EXTI_IMR 0x00
+#define EXTI_EMR 0x04
+#define EXTI_RTSR 0x08
+#define EXTI_FTSR 0x0C
+#define EXTI_SWIER 0x10
+#define EXTI_PR 0x14
+
+#define TYPE_STM32F4XX_EXTI "stm32f4xx-exti"
+OBJECT_DECLARE_SIMPLE_TYPE(STM32F4xxExtiState, STM32F4XX_EXTI)
+
+#define NUM_GPIO_EVENT_IN_LINES 16
+#define NUM_INTERRUPT_OUT_LINES 16
+
+struct STM32F4xxExtiState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion mmio;
+
+ uint32_t exti_imr;
+ uint32_t exti_emr;
+ uint32_t exti_rtsr;
+ uint32_t exti_ftsr;
+ uint32_t exti_swier;
+ uint32_t exti_pr;
+
+ qemu_irq irq[NUM_INTERRUPT_OUT_LINES];
+};
+
+#endif
diff --git a/include/hw/misc/stm32f4xx_syscfg.h b/include/hw/misc/stm32f4xx_syscfg.h
new file mode 100644
index 000000000..6f8ca4922
--- /dev/null
+++ b/include/hw/misc/stm32f4xx_syscfg.h
@@ -0,0 +1,60 @@
+/*
+ * STM32F4xx SYSCFG
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * 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_STM_SYSCFG_H
+#define HW_STM_SYSCFG_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define SYSCFG_MEMRMP 0x00
+#define SYSCFG_PMC 0x04
+#define SYSCFG_EXTICR1 0x08
+#define SYSCFG_EXTICR2 0x0C
+#define SYSCFG_EXTICR3 0x10
+#define SYSCFG_EXTICR4 0x14
+#define SYSCFG_CMPCR 0x20
+
+#define TYPE_STM32F4XX_SYSCFG "stm32f4xx-syscfg"
+OBJECT_DECLARE_SIMPLE_TYPE(STM32F4xxSyscfgState, STM32F4XX_SYSCFG)
+
+#define SYSCFG_NUM_EXTICR 4
+
+struct STM32F4xxSyscfgState {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /* <public> */
+ MemoryRegion mmio;
+
+ uint32_t syscfg_memrmp;
+ uint32_t syscfg_pmc;
+ uint32_t syscfg_exticr[SYSCFG_NUM_EXTICR];
+ uint32_t syscfg_cmpcr;
+
+ qemu_irq irq;
+ qemu_irq gpio_out[16];
+};
+
+#endif
diff --git a/include/hw/misc/tz-mpc.h b/include/hw/misc/tz-mpc.h
new file mode 100644
index 000000000..74d5d822c
--- /dev/null
+++ b/include/hw/misc/tz-mpc.h
@@ -0,0 +1,80 @@
+/*
+ * ARM AHB5 TrustZone Memory Protection Controller emulation
+ *
+ * Copyright (c) 2018 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 TrustZone memory protection controller (MPC).
+ * It is documented in the ARM CoreLink SIE-200 System IP for Embedded TRM
+ * (DDI 0571G):
+ * https://developer.arm.com/products/architecture/m-profile/docs/ddi0571/g
+ *
+ * The MPC sits in front of memory and allows secure software to
+ * configure it to either pass through or reject transactions.
+ * Rejected transactions may be configured to either be aborted, or to
+ * behave as RAZ/WI. An interrupt can be signalled for a rejected transaction.
+ *
+ * The MPC has a register interface which the guest uses to configure it.
+ *
+ * QEMU interface:
+ * + sysbus MMIO region 0: MemoryRegion for the MPC's config registers
+ * + sysbus MMIO region 1: MemoryRegion for the upstream end of the MPC
+ * + Property "downstream": MemoryRegion defining the downstream memory
+ * + Named GPIO output "irq": set for a transaction-failed interrupt
+ */
+
+#ifndef TZ_MPC_H
+#define TZ_MPC_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_TZ_MPC "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"
+
+
+struct TZMPC {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+
+ /* State */
+ uint32_t ctrl;
+ uint32_t blk_idx;
+ uint32_t int_stat;
+ uint32_t int_en;
+ uint32_t int_info1;
+ uint32_t int_info2;
+
+ uint32_t *blk_lut;
+
+ qemu_irq irq;
+
+ /* Properties */
+ MemoryRegion *downstream;
+
+ hwaddr blocksize;
+ uint32_t blk_max;
+
+ /* MemoryRegions exposed to user */
+ MemoryRegion regmr;
+ IOMMUMemoryRegion upstream;
+
+ /* MemoryRegion used internally */
+ MemoryRegion blocked_io;
+
+ AddressSpace downstream_as;
+ AddressSpace blocked_io_as;
+};
+
+#endif
diff --git a/include/hw/misc/tz-msc.h b/include/hw/misc/tz-msc.h
new file mode 100644
index 000000000..77cc7f240
--- /dev/null
+++ b/include/hw/misc/tz-msc.h
@@ -0,0 +1,80 @@
+/*
+ * ARM TrustZone master security controller emulation
+ *
+ * Copyright (c) 2018 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 TrustZone master security controller (MSC).
+ * It is documented in the ARM CoreLink SIE-200 System IP for Embedded TRM
+ * (DDI 0571G):
+ * https://developer.arm.com/products/architecture/m-profile/docs/ddi0571/g
+ *
+ * The MSC sits in front of a device which can be a bus master (such as
+ * a DMA controller) and allows secure software to configure it to either
+ * pass through or reject transactions made by that bus master.
+ * Rejected transactions may be configured to either be aborted, or to
+ * behave as RAZ/WI. An interrupt can be signalled for a rejected transaction.
+ *
+ * The MSC has no register interface -- it is configured purely by a
+ * collection of input signals from other hardware in the system. Typically
+ * they are either hardwired or exposed in an ad-hoc register interface by
+ * the SoC that uses the MSC.
+ *
+ * We don't currently implement the irq_enable GPIO input, because on
+ * the MPS2 FPGA images it is always tied high, which is awkward to
+ * implement in QEMU.
+ *
+ * QEMU interface:
+ * + Named GPIO input "cfg_nonsec": set to 1 if the bus master should be
+ * treated as nonsecure, or 0 for secure
+ * + Named GPIO input "cfg_sec_resp": set to 1 if a rejected transaction should
+ * result in a transaction error, or 0 for the transaction to RAZ/WI
+ * + Named GPIO input "irq_clear": set to 1 to clear a pending interrupt
+ * + Named GPIO output "irq": set for a transaction-failed interrupt
+ * + Property "downstream": MemoryRegion defining where bus master transactions
+ * are made if they are not blocked
+ * + Property "idau": an object implementing IDAUInterface, which defines which
+ * addresses should be treated as secure and which as non-secure.
+ * This need not be the same IDAU as the one used by the CPU.
+ * + sysbus MMIO region 0: MemoryRegion defining the upstream end of the MSC;
+ * this should be passed to the bus master device as the region it should
+ * make memory transactions to
+ */
+
+#ifndef TZ_MSC_H
+#define TZ_MSC_H
+
+#include "hw/sysbus.h"
+#include "target/arm/idau.h"
+#include "qom/object.h"
+
+#define TYPE_TZ_MSC "tz-msc"
+OBJECT_DECLARE_SIMPLE_TYPE(TZMSC, TZ_MSC)
+
+struct TZMSC {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+
+ /* State: these just track the values of our input signals */
+ bool cfg_nonsec;
+ bool cfg_sec_resp;
+ bool irq_clear;
+ /* State: are we asserting irq ? */
+ bool irq_status;
+
+ qemu_irq irq;
+ MemoryRegion *downstream;
+ AddressSpace downstream_as;
+ MemoryRegion upstream;
+ IDAUInterface *idau;
+};
+
+#endif
diff --git a/include/hw/misc/tz-ppc.h b/include/hw/misc/tz-ppc.h
new file mode 100644
index 000000000..021d671b2
--- /dev/null
+++ b/include/hw/misc/tz-ppc.h
@@ -0,0 +1,107 @@
+/*
+ * ARM TrustZone peripheral protection controller emulation
+ *
+ * Copyright (c) 2018 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 TrustZone peripheral protection controller (PPC).
+ * It is documented in the ARM CoreLink SIE-200 System IP for Embedded TRM
+ * (DDI 0571G):
+ * https://developer.arm.com/products/architecture/m-profile/docs/ddi0571/g
+ *
+ * The PPC sits in front of peripherals and allows secure software to
+ * configure it to either pass through or reject transactions.
+ * Rejected transactions may be configured to either be aborted, or to
+ * behave as RAZ/WI. An interrupt can be signalled for a rejected transaction.
+ *
+ * The PPC has no register interface -- it is configured purely by a
+ * collection of input signals from other hardware in the system. Typically
+ * they are either hardwired or exposed in an ad-hoc register interface by
+ * the SoC that uses the PPC.
+ *
+ * This QEMU model can be used to model either the AHB5 or APB4 TZ PPC,
+ * since the only difference between them is that the AHB version has a
+ * "default" port which has no security checks applied. In QEMU the default
+ * port can be emulated simply by wiring its downstream devices directly
+ * into the parent address space, since the PPC does not need to intercept
+ * transactions there.
+ *
+ * In the hardware, selection of which downstream port to use is done by
+ * the user's decode logic asserting one of the hsel[] signals. In QEMU,
+ * we provide 16 MMIO regions, one per port, and the user maps these into
+ * the desired addresses to implement the address decode.
+ *
+ * QEMU interface:
+ * + sysbus MMIO regions 0..15: MemoryRegions defining the upstream end
+ * of each of the 16 ports of the PPC. When a port is unused (i.e. no
+ * downstream MemoryRegion is connected to it) at the end of the 0..15
+ * range then no sysbus MMIO region is created for its upstream. When an
+ * unused port lies in the middle of the range with other used ports at
+ * higher port numbers, a dummy MMIO region is created to ensure that
+ * port N's upstream is always sysbus MMIO region N. Dummy regions should
+ * not be mapped, and will assert if any access is made to them.
+ * + Property "port[0..15]": MemoryRegion defining the downstream device(s)
+ * for each of the 16 ports of the PPC
+ * + Named GPIO inputs "cfg_nonsec[0..15]": set to 1 if the port should be
+ * accessible to NonSecure transactions
+ * + Named GPIO inputs "cfg_ap[0..15]": set to 1 if the port should be
+ * accessible to non-privileged transactions
+ * + Named GPIO input "cfg_sec_resp": set to 1 if a rejected transaction should
+ * result in a transaction error, or 0 for the transaction to RAZ/WI
+ * + Named GPIO input "irq_enable": set to 1 to enable interrupts
+ * + Named GPIO input "irq_clear": set to 1 to clear a pending interrupt
+ * + Named GPIO output "irq": set for a transaction-failed interrupt
+ * + Property "NONSEC_MASK": if a bit is set in this mask then accesses to
+ * the associated port do not have the TZ security check performed. (This
+ * corresponds to the hardware allowing this to be set as a Verilog
+ * parameter.)
+ */
+
+#ifndef TZ_PPC_H
+#define TZ_PPC_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_TZ_PPC "tz-ppc"
+OBJECT_DECLARE_SIMPLE_TYPE(TZPPC, TZ_PPC)
+
+#define TZ_NUM_PORTS 16
+
+
+typedef struct TZPPCPort {
+ TZPPC *ppc;
+ MemoryRegion upstream;
+ AddressSpace downstream_as;
+ MemoryRegion *downstream;
+} TZPPCPort;
+
+struct TZPPC {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+
+ /* State: these just track the values of our input signals */
+ bool cfg_nonsec[TZ_NUM_PORTS];
+ bool cfg_ap[TZ_NUM_PORTS];
+ bool cfg_sec_resp;
+ bool irq_enable;
+ bool irq_clear;
+ /* State: are we asserting irq ? */
+ bool irq_status;
+
+ qemu_irq irq;
+
+ /* Properties */
+ uint32_t nonsec_mask;
+
+ TZPPCPort port[TZ_NUM_PORTS];
+};
+
+#endif
diff --git a/include/hw/misc/unimp.h b/include/hw/misc/unimp.h
new file mode 100644
index 000000000..518d627dc
--- /dev/null
+++ b/include/hw/misc/unimp.h
@@ -0,0 +1,54 @@
+/*
+ * "Unimplemented" device
+ *
+ * Copyright Linaro Limited, 2017
+ * Written by Peter Maydell
+ */
+
+#ifndef HW_MISC_UNIMP_H
+#define HW_MISC_UNIMP_H
+
+#include "hw/qdev-properties.h"
+#include "hw/sysbus.h"
+#include "qapi/error.h"
+#include "qom/object.h"
+
+#define TYPE_UNIMPLEMENTED_DEVICE "unimplemented-device"
+
+OBJECT_DECLARE_SIMPLE_TYPE(UnimplementedDeviceState, UNIMPLEMENTED_DEVICE)
+
+struct UnimplementedDeviceState {
+ SysBusDevice parent_obj;
+ MemoryRegion iomem;
+ unsigned offset_fmt_width;
+ char *name;
+ uint64_t size;
+};
+
+/**
+ * create_unimplemented_device: create and map a dummy device
+ * @name: name of the device for debug logging
+ * @base: base address of the device's MMIO region
+ * @size: size of the device's MMIO region
+ *
+ * This utility function creates and maps an instance of unimplemented-device,
+ * which is a dummy device which simply logs all guest accesses to
+ * it via the qemu_log LOG_UNIMP debug log.
+ * The device is mapped at priority -1000, which means that you can
+ * use it to cover a large region and then map other devices on top of it
+ * if necessary.
+ */
+static inline void create_unimplemented_device(const char *name,
+ hwaddr base,
+ hwaddr size)
+{
+ DeviceState *dev = qdev_new(TYPE_UNIMPLEMENTED_DEVICE);
+
+ qdev_prop_set_string(dev, "name", name);
+ qdev_prop_set_uint64(dev, "size", size);
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
+
+ sysbus_mmio_map_overlap(SYS_BUS_DEVICE(dev), 0, base, -1000);
+}
+
+#endif
diff --git a/include/hw/misc/virt_ctrl.h b/include/hw/misc/virt_ctrl.h
new file mode 100644
index 000000000..25a237e51
--- /dev/null
+++ b/include/hw/misc/virt_ctrl.h
@@ -0,0 +1,22 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Virt system Controller
+ */
+
+#ifndef VIRT_CTRL_H
+#define VIRT_CTRL_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
new file mode 100644
index 000000000..0b7b55d40
--- /dev/null
+++ b/include/hw/misc/vmcoreinfo.h
@@ -0,0 +1,41 @@
+/*
+ * Virtual Machine coreinfo device
+ *
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * Authors: Marc-André Lureau <marcandre.lureau@redhat.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 VMCOREINFO_H
+#define VMCOREINFO_H
+
+#include "hw/qdev-core.h"
+#include "standard-headers/linux/qemu_fw_cfg.h"
+#include "qom/object.h"
+
+#define VMCOREINFO_DEVICE "vmcoreinfo"
+typedef struct VMCoreInfoState VMCoreInfoState;
+DECLARE_INSTANCE_CHECKER(VMCoreInfoState, VMCOREINFO,
+ VMCOREINFO_DEVICE)
+
+typedef struct fw_cfg_vmcoreinfo FWCfgVMCoreInfo;
+
+struct VMCoreInfoState {
+ DeviceState parent_obj;
+
+ bool has_vmcoreinfo;
+ FWCfgVMCoreInfo vmcoreinfo;
+};
+
+/* returns NULL unless there is exactly one device */
+static inline VMCoreInfoState *vmcoreinfo_find(void)
+{
+ Object *o = object_resolve_path_type("", VMCOREINFO_DEVICE, NULL);
+
+ return o ? VMCOREINFO(o) : NULL;
+}
+
+#endif
diff --git a/include/hw/misc/xlnx-versal-xramc.h b/include/hw/misc/xlnx-versal-xramc.h
new file mode 100644
index 000000000..d3d186267
--- /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/net/allwinner-sun8i-emac.h b/include/hw/net/allwinner-sun8i-emac.h
new file mode 100644
index 000000000..460a58f1c
--- /dev/null
+++ b/include/hw/net/allwinner-sun8i-emac.h
@@ -0,0 +1,104 @@
+/*
+ * Allwinner Sun8i Ethernet MAC emulation
+ *
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.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_NET_ALLWINNER_SUN8I_EMAC_H
+#define HW_NET_ALLWINNER_SUN8I_EMAC_H
+
+#include "qom/object.h"
+#include "net/net.h"
+#include "hw/sysbus.h"
+
+/**
+ * Object model
+ * @{
+ */
+
+#define TYPE_AW_SUN8I_EMAC "allwinner-sun8i-emac"
+OBJECT_DECLARE_SIMPLE_TYPE(AwSun8iEmacState, AW_SUN8I_EMAC)
+
+/** @} */
+
+/**
+ * Allwinner Sun8i EMAC object instance state
+ */
+struct AwSun8iEmacState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ /** Maps I/O registers in physical memory */
+ MemoryRegion iomem;
+
+ /** 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;
+
+ /** Generic Network Interface Controller (NIC) configuration */
+ NICConf conf;
+
+ /**
+ * @name Media Independent Interface (MII)
+ * @{
+ */
+
+ uint8_t mii_phy_addr; /**< PHY address */
+ uint32_t mii_cr; /**< Control */
+ uint32_t mii_st; /**< Status */
+ uint32_t mii_adv; /**< Advertised Abilities */
+
+ /** @} */
+
+ /**
+ * @name Hardware Registers
+ * @{
+ */
+
+ uint32_t basic_ctl0; /**< Basic Control 0 */
+ uint32_t basic_ctl1; /**< Basic Control 1 */
+ uint32_t int_en; /**< Interrupt Enable */
+ uint32_t int_sta; /**< Interrupt Status */
+ uint32_t frm_flt; /**< Receive Frame Filter */
+
+ uint32_t rx_ctl0; /**< Receive Control 0 */
+ uint32_t rx_ctl1; /**< Receive Control 1 */
+ uint32_t rx_desc_head; /**< Receive Descriptor List Address */
+ uint32_t rx_desc_curr; /**< Current Receive Descriptor Address */
+
+ uint32_t tx_ctl0; /**< Transmit Control 0 */
+ uint32_t tx_ctl1; /**< Transmit Control 1 */
+ uint32_t tx_desc_head; /**< Transmit Descriptor List Address */
+ uint32_t tx_desc_curr; /**< Current Transmit Descriptor Address */
+ uint32_t tx_flowctl; /**< Transmit Flow Control */
+
+ uint32_t mii_cmd; /**< Management Interface Command */
+ uint32_t mii_data; /**< Management Interface Data */
+
+ /** @} */
+
+};
+
+#endif /* HW_NET_ALLWINNER_SUN8I_H */
diff --git a/include/hw/net/allwinner_emac.h b/include/hw/net/allwinner_emac.h
new file mode 100644
index 000000000..534e74898
--- /dev/null
+++ b/include/hw/net/allwinner_emac.h
@@ -0,0 +1,177 @@
+/*
+ * Emulation of Allwinner EMAC Fast Ethernet controller and
+ * Realtek RTL8201CP PHY
+ *
+ * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
+ *
+ * Allwinner EMAC register definitions from Linux kernel are:
+ * Copyright 2012 Stefan Roese <sr@denx.de>
+ * Copyright 2013 Maxime Ripard <maxime.ripard@free-electrons.com>
+ * Copyright 1997 Sten Wang
+ *
+ * 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 ALLWINNER_EMAC_H
+#define ALLWINNER_EMAC_H
+
+#include "qemu/units.h"
+#include "net/net.h"
+#include "qemu/fifo8.h"
+#include "hw/net/mii.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_AW_EMAC "allwinner-emac"
+OBJECT_DECLARE_SIMPLE_TYPE(AwEmacState, AW_EMAC)
+
+/*
+ * Allwinner EMAC register list
+ */
+#define EMAC_CTL_REG 0x00
+
+#define EMAC_TX_MODE_REG 0x04
+#define EMAC_TX_FLOW_REG 0x08
+#define EMAC_TX_CTL0_REG 0x0C
+#define EMAC_TX_CTL1_REG 0x10
+#define EMAC_TX_INS_REG 0x14
+#define EMAC_TX_PL0_REG 0x18
+#define EMAC_TX_PL1_REG 0x1C
+#define EMAC_TX_STA_REG 0x20
+#define EMAC_TX_IO_DATA_REG 0x24
+#define EMAC_TX_IO_DATA1_REG 0x28
+#define EMAC_TX_TSVL0_REG 0x2C
+#define EMAC_TX_TSVH0_REG 0x30
+#define EMAC_TX_TSVL1_REG 0x34
+#define EMAC_TX_TSVH1_REG 0x38
+
+#define EMAC_RX_CTL_REG 0x3C
+#define EMAC_RX_HASH0_REG 0x40
+#define EMAC_RX_HASH1_REG 0x44
+#define EMAC_RX_STA_REG 0x48
+#define EMAC_RX_IO_DATA_REG 0x4C
+#define EMAC_RX_FBC_REG 0x50
+
+#define EMAC_INT_CTL_REG 0x54
+#define EMAC_INT_STA_REG 0x58
+
+#define EMAC_MAC_CTL0_REG 0x5C
+#define EMAC_MAC_CTL1_REG 0x60
+#define EMAC_MAC_IPGT_REG 0x64
+#define EMAC_MAC_IPGR_REG 0x68
+#define EMAC_MAC_CLRT_REG 0x6C
+#define EMAC_MAC_MAXF_REG 0x70
+#define EMAC_MAC_SUPP_REG 0x74
+#define EMAC_MAC_TEST_REG 0x78
+#define EMAC_MAC_MCFG_REG 0x7C
+#define EMAC_MAC_MCMD_REG 0x80
+#define EMAC_MAC_MADR_REG 0x84
+#define EMAC_MAC_MWTD_REG 0x88
+#define EMAC_MAC_MRDD_REG 0x8C
+#define EMAC_MAC_MIND_REG 0x90
+#define EMAC_MAC_SSRR_REG 0x94
+#define EMAC_MAC_A0_REG 0x98
+#define EMAC_MAC_A1_REG 0x9C
+#define EMAC_MAC_A2_REG 0xA0
+
+#define EMAC_SAFX_L_REG0 0xA4
+#define EMAC_SAFX_H_REG0 0xA8
+#define EMAC_SAFX_L_REG1 0xAC
+#define EMAC_SAFX_H_REG1 0xB0
+#define EMAC_SAFX_L_REG2 0xB4
+#define EMAC_SAFX_H_REG2 0xB8
+#define EMAC_SAFX_L_REG3 0xBC
+#define EMAC_SAFX_H_REG3 0xC0
+
+/* CTL register fields */
+#define EMAC_CTL_RESET (1 << 0)
+#define EMAC_CTL_TX_EN (1 << 1)
+#define EMAC_CTL_RX_EN (1 << 2)
+
+/* TX MODE register fields */
+#define EMAC_TX_MODE_ABORTED_FRAME_EN (1 << 0)
+#define EMAC_TX_MODE_DMA_EN (1 << 1)
+
+/* RX CTL register fields */
+#define EMAC_RX_CTL_AUTO_DRQ_EN (1 << 1)
+#define EMAC_RX_CTL_DMA_EN (1 << 2)
+#define EMAC_RX_CTL_PASS_ALL_EN (1 << 4)
+#define EMAC_RX_CTL_PASS_CTL_EN (1 << 5)
+#define EMAC_RX_CTL_PASS_CRC_ERR_EN (1 << 6)
+#define EMAC_RX_CTL_PASS_LEN_ERR_EN (1 << 7)
+#define EMAC_RX_CTL_PASS_LEN_OOR_EN (1 << 8)
+#define EMAC_RX_CTL_ACCEPT_UNICAST_EN (1 << 16)
+#define EMAC_RX_CTL_DA_FILTER_EN (1 << 17)
+#define EMAC_RX_CTL_ACCEPT_MULTICAST_EN (1 << 20)
+#define EMAC_RX_CTL_HASH_FILTER_EN (1 << 21)
+#define EMAC_RX_CTL_ACCEPT_BROADCAST_EN (1 << 22)
+#define EMAC_RX_CTL_SA_FILTER_EN (1 << 24)
+#define EMAC_RX_CTL_SA_FILTER_INVERT_EN (1 << 25)
+
+/* RX IO DATA register fields */
+#define EMAC_RX_HEADER(len, status) (((len) & 0xffff) | ((status) << 16))
+#define EMAC_RX_IO_DATA_STATUS_CRC_ERR (1 << 4)
+#define EMAC_RX_IO_DATA_STATUS_LEN_ERR (3 << 5)
+#define EMAC_RX_IO_DATA_STATUS_OK (1 << 7)
+#define EMAC_UNDOCUMENTED_MAGIC 0x0143414d /* header for RX frames */
+
+/* INT CTL and INT STA registers fields */
+#define EMAC_INT_TX_CHAN(x) (1 << (x))
+#define EMAC_INT_RX (1 << 8)
+
+/* Due to lack of specifications, size of fifos is chosen arbitrarily */
+#define TX_FIFO_SIZE (4 * KiB)
+#define RX_FIFO_SIZE (32 * KiB)
+
+#define NUM_TX_FIFOS 2
+#define RX_HDR_SIZE 8
+#define CRC_SIZE 4
+
+#define PHY_REG_SHIFT 0
+#define PHY_ADDR_SHIFT 8
+
+typedef struct RTL8201CPState {
+ uint16_t bmcr;
+ uint16_t bmsr;
+ uint16_t anar;
+ uint16_t anlpar;
+} RTL8201CPState;
+
+struct AwEmacState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ MemoryRegion iomem;
+ qemu_irq irq;
+ NICState *nic;
+ NICConf conf;
+ RTL8201CPState mii;
+ uint8_t phy_addr;
+
+ uint32_t ctl;
+ uint32_t tx_mode;
+ uint32_t rx_ctl;
+ uint32_t int_ctl;
+ uint32_t int_sta;
+ uint32_t phy_target;
+
+ Fifo8 rx_fifo;
+ uint32_t rx_num_packets;
+ uint32_t rx_packet_size;
+ uint32_t rx_packet_pos;
+
+ Fifo8 tx_fifo[NUM_TX_FIFOS];
+ uint32_t tx_length[NUM_TX_FIFOS];
+ uint32_t tx_channel;
+};
+
+#endif
diff --git a/include/hw/net/cadence_gem.h b/include/hw/net/cadence_gem.h
new file mode 100644
index 000000000..91ebb5c8a
--- /dev/null
+++ b/include/hw/net/cadence_gem.h
@@ -0,0 +1,97 @@
+/*
+ * QEMU Cadence GEM emulation
+ *
+ * Copyright (c) 2011 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 CADENCE_GEM_H
+#define CADENCE_GEM_H
+#include "qom/object.h"
+
+#define TYPE_CADENCE_GEM "cadence_gem"
+OBJECT_DECLARE_SIMPLE_TYPE(CadenceGEMState, CADENCE_GEM)
+
+#include "net/net.h"
+#include "hw/sysbus.h"
+
+#define CADENCE_GEM_MAXREG (0x00000800 / 4) /* Last valid GEM address */
+
+/* Max number of words in a DMA descriptor. */
+#define DESC_MAX_NUM_WORDS 6
+
+#define MAX_PRIORITY_QUEUES 8
+#define MAX_TYPE1_SCREENERS 16
+#define MAX_TYPE2_SCREENERS 16
+
+#define MAX_JUMBO_FRAME_SIZE_MASK 0x3FFF
+#define MAX_FRAME_SIZE MAX_JUMBO_FRAME_SIZE_MASK
+
+struct CadenceGEMState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+ MemoryRegion *dma_mr;
+ AddressSpace dma_as;
+ NICState *nic;
+ NICConf conf;
+ qemu_irq irq[MAX_PRIORITY_QUEUES];
+
+ /* Static properties */
+ uint8_t num_priority_queues;
+ uint8_t num_type1_screeners;
+ uint8_t num_type2_screeners;
+ uint32_t revision;
+ uint16_t jumbo_max_len;
+
+ /* GEM registers backing store */
+ uint32_t regs[CADENCE_GEM_MAXREG];
+ /* Mask of register bits which are write only */
+ uint32_t regs_wo[CADENCE_GEM_MAXREG];
+ /* Mask of register bits which are read only */
+ uint32_t regs_ro[CADENCE_GEM_MAXREG];
+ /* Mask of register bits which are clear on read */
+ uint32_t regs_rtc[CADENCE_GEM_MAXREG];
+ /* 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];
+
+ uint8_t phy_loop; /* Are we in phy loopback? */
+
+ /* The current DMA descriptor pointers */
+ uint32_t rx_desc_addr[MAX_PRIORITY_QUEUES];
+ uint32_t tx_desc_addr[MAX_PRIORITY_QUEUES];
+
+ uint8_t can_rx_state; /* Debug only */
+
+ uint8_t tx_packet[MAX_FRAME_SIZE];
+ uint8_t rx_packet[MAX_FRAME_SIZE];
+ uint32_t rx_desc[MAX_PRIORITY_QUEUES][DESC_MAX_NUM_WORDS];
+
+ bool sar_active[4];
+};
+
+#endif
diff --git a/include/hw/net/ftgmac100.h b/include/hw/net/ftgmac100.h
new file mode 100644
index 000000000..765d1538a
--- /dev/null
+++ b/include/hw/net/ftgmac100.h
@@ -0,0 +1,87 @@
+/*
+ * Faraday FTGMAC100 Gigabit Ethernet
+ *
+ * Copyright (C) 2016-2017, IBM Corporation.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+
+#ifndef FTGMAC100_H
+#define FTGMAC100_H
+#include "qom/object.h"
+
+#define TYPE_FTGMAC100 "ftgmac100"
+OBJECT_DECLARE_SIMPLE_TYPE(FTGMAC100State, FTGMAC100)
+
+#include "hw/sysbus.h"
+#include "net/net.h"
+
+/*
+ * Max frame size for the receiving buffer
+ */
+#define FTGMAC100_MAX_FRAME_SIZE 9220
+
+struct FTGMAC100State {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ NICState *nic;
+ NICConf conf;
+ qemu_irq irq;
+ MemoryRegion iomem;
+
+ uint8_t frame[FTGMAC100_MAX_FRAME_SIZE];
+
+ uint32_t irq_state;
+ uint32_t isr;
+ uint32_t ier;
+ uint32_t rx_enabled;
+ uint32_t rx_ring;
+ uint32_t rx_descriptor;
+ uint32_t tx_ring;
+ uint32_t tx_descriptor;
+ uint32_t math[2];
+ uint32_t rbsr;
+ uint32_t itc;
+ uint32_t aptcr;
+ uint32_t dblac;
+ uint32_t revr;
+ uint32_t fear1;
+ uint32_t tpafcr;
+ uint32_t maccr;
+ uint32_t phycr;
+ uint32_t phydata;
+ uint32_t fcr;
+
+
+ uint32_t phy_status;
+ uint32_t phy_control;
+ uint32_t phy_advertise;
+ uint32_t phy_int;
+ uint32_t phy_int_mask;
+
+ bool aspeed;
+ uint32_t txdes0_edotr;
+ uint32_t rxdes0_edorr;
+};
+
+#define TYPE_ASPEED_MII "aspeed-mmi"
+OBJECT_DECLARE_SIMPLE_TYPE(AspeedMiiState, ASPEED_MII)
+
+/*
+ * AST2600 MII controller
+ */
+struct AspeedMiiState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ FTGMAC100State *nic;
+
+ MemoryRegion iomem;
+ uint32_t phycr;
+ uint32_t phydata;
+};
+
+#endif
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
new file mode 100644
index 000000000..e3a8755db
--- /dev/null
+++ b/include/hw/net/imx_fec.h
@@ -0,0 +1,280 @@
+/*
+ * i.MX FEC/ENET Ethernet Controller emulation.
+ *
+ * Copyright (c) 2013 Jean-Christophe Dubois. <jcd@tribudubois.net>
+ *
+ * Based on Coldfire Fast Ethernet Controller emulation.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ *
+ * 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 IMX_FEC_H
+#define IMX_FEC_H
+#include "qom/object.h"
+
+#define TYPE_IMX_FEC "imx.fec"
+OBJECT_DECLARE_SIMPLE_TYPE(IMXFECState, IMX_FEC)
+
+#define TYPE_IMX_ENET "imx.enet"
+
+#include "hw/sysbus.h"
+#include "net/net.h"
+
+#define ENET_EIR 1
+#define ENET_EIMR 2
+#define ENET_RDAR 4
+#define ENET_TDAR 5
+#define ENET_ECR 9
+#define ENET_MMFR 16
+#define ENET_MSCR 17
+#define ENET_MIBC 25
+#define ENET_RCR 33
+#define ENET_TCR 49
+#define ENET_PALR 57
+#define ENET_PAUR 58
+#define ENET_OPD 59
+#define ENET_IAUR 70
+#define ENET_IALR 71
+#define ENET_GAUR 72
+#define ENET_GALR 73
+#define ENET_TFWR 81
+#define ENET_FRBR 83
+#define ENET_FRSR 84
+#define ENET_TDSR1 89
+#define ENET_TDSR2 92
+#define ENET_RDSR 96
+#define ENET_TDSR 97
+#define ENET_MRBR 98
+#define ENET_RSFL 100
+#define ENET_RSEM 101
+#define ENET_RAEM 102
+#define ENET_RAFL 103
+#define ENET_TSEM 104
+#define ENET_TAEM 105
+#define ENET_TAFL 106
+#define ENET_TIPG 107
+#define ENET_FTRL 108
+#define ENET_TACC 112
+#define ENET_RACC 113
+#define ENET_TDAR1 121
+#define ENET_TDAR2 123
+#define ENET_MIIGSK_CFGR 192
+#define ENET_MIIGSK_ENR 194
+#define ENET_ATCR 256
+#define ENET_ATVR 257
+#define ENET_ATOFF 258
+#define ENET_ATPER 259
+#define ENET_ATCOR 260
+#define ENET_ATINC 261
+#define ENET_ATSTMP 262
+#define ENET_TGSR 385
+#define ENET_TCSR0 386
+#define ENET_TCCR0 387
+#define ENET_TCSR1 388
+#define ENET_TCCR1 389
+#define ENET_TCSR2 390
+#define ENET_TCCR2 391
+#define ENET_TCSR3 392
+#define ENET_TCCR3 393
+#define ENET_MAX 400
+
+
+/* EIR and EIMR */
+#define ENET_INT_HB (1 << 31)
+#define ENET_INT_BABR (1 << 30)
+#define ENET_INT_BABT (1 << 29)
+#define ENET_INT_GRA (1 << 28)
+#define ENET_INT_TXF (1 << 27)
+#define ENET_INT_TXB (1 << 26)
+#define ENET_INT_RXF (1 << 25)
+#define ENET_INT_RXB (1 << 24)
+#define ENET_INT_MII (1 << 23)
+#define ENET_INT_EBERR (1 << 22)
+#define ENET_INT_LC (1 << 21)
+#define ENET_INT_RL (1 << 20)
+#define ENET_INT_UN (1 << 19)
+#define ENET_INT_PLR (1 << 18)
+#define ENET_INT_WAKEUP (1 << 17)
+#define ENET_INT_TS_AVAIL (1 << 16)
+#define ENET_INT_TS_TIMER (1 << 15)
+#define ENET_INT_TXF2 (1 << 7)
+#define ENET_INT_TXB2 (1 << 6)
+#define ENET_INT_TXF1 (1 << 3)
+#define ENET_INT_TXB1 (1 << 2)
+
+#define ENET_INT_MAC (ENET_INT_HB | ENET_INT_BABR | ENET_INT_BABT | \
+ ENET_INT_GRA | ENET_INT_TXF | ENET_INT_TXB | \
+ ENET_INT_RXF | ENET_INT_RXB | ENET_INT_MII | \
+ ENET_INT_EBERR | ENET_INT_LC | ENET_INT_RL | \
+ ENET_INT_UN | ENET_INT_PLR | ENET_INT_WAKEUP | \
+ ENET_INT_TS_AVAIL | ENET_INT_TXF1 | \
+ ENET_INT_TXB1 | ENET_INT_TXF2 | ENET_INT_TXB2)
+
+/* RDAR */
+#define ENET_RDAR_RDAR (1 << 24)
+
+/* TDAR */
+#define ENET_TDAR_TDAR (1 << 24)
+
+/* ECR */
+#define ENET_ECR_RESET (1 << 0)
+#define ENET_ECR_ETHEREN (1 << 1)
+#define ENET_ECR_MAGICEN (1 << 2)
+#define ENET_ECR_SLEEP (1 << 3)
+#define ENET_ECR_EN1588 (1 << 4)
+#define ENET_ECR_SPEED (1 << 5)
+#define ENET_ECR_DBGEN (1 << 6)
+#define ENET_ECR_STOPEN (1 << 7)
+#define ENET_ECR_DSBWP (1 << 8)
+
+/* MIBC */
+#define ENET_MIBC_MIB_DIS (1 << 31)
+#define ENET_MIBC_MIB_IDLE (1 << 30)
+#define ENET_MIBC_MIB_CLEAR (1 << 29)
+
+/* RCR */
+#define ENET_RCR_LOOP (1 << 0)
+#define ENET_RCR_DRT (1 << 1)
+#define ENET_RCR_MII_MODE (1 << 2)
+#define ENET_RCR_PROM (1 << 3)
+#define ENET_RCR_BC_REJ (1 << 4)
+#define ENET_RCR_FCE (1 << 5)
+#define ENET_RCR_RGMII_EN (1 << 6)
+#define ENET_RCR_RMII_MODE (1 << 8)
+#define ENET_RCR_RMII_10T (1 << 9)
+#define ENET_RCR_PADEN (1 << 12)
+#define ENET_RCR_PAUFWD (1 << 13)
+#define ENET_RCR_CRCFWD (1 << 14)
+#define ENET_RCR_CFEN (1 << 15)
+#define ENET_RCR_MAX_FL_SHIFT (16)
+#define ENET_RCR_MAX_FL_LENGTH (14)
+#define ENET_RCR_NLC (1 << 30)
+#define ENET_RCR_GRS (1 << 31)
+
+#define ENET_MAX_FRAME_SIZE (1 << ENET_RCR_MAX_FL_LENGTH)
+
+/* TCR */
+#define ENET_TCR_GTS (1 << 0)
+#define ENET_TCR_FDEN (1 << 2)
+#define ENET_TCR_TFC_PAUSE (1 << 3)
+#define ENET_TCR_RFC_PAUSE (1 << 4)
+#define ENET_TCR_ADDSEL_SHIFT (5)
+#define ENET_TCR_ADDSEL_LENGTH (3)
+#define ENET_TCR_CRCFWD (1 << 9)
+
+/* RDSR */
+#define ENET_TWFR_TFWR_SHIFT (0)
+#define ENET_TWFR_TFWR_LENGTH (6)
+#define ENET_TWFR_STRFWD (1 << 8)
+
+#define ENET_RACC_SHIFT16 BIT(7)
+
+/* Buffer Descriptor. */
+typedef struct {
+ uint16_t length;
+ uint16_t flags;
+ uint32_t data;
+} IMXFECBufDesc;
+
+#define ENET_BD_R (1 << 15)
+#define ENET_BD_E (1 << 15)
+#define ENET_BD_O1 (1 << 14)
+#define ENET_BD_W (1 << 13)
+#define ENET_BD_O2 (1 << 12)
+#define ENET_BD_L (1 << 11)
+#define ENET_BD_TC (1 << 10)
+#define ENET_BD_ABC (1 << 9)
+#define ENET_BD_M (1 << 8)
+#define ENET_BD_BC (1 << 7)
+#define ENET_BD_MC (1 << 6)
+#define ENET_BD_LG (1 << 5)
+#define ENET_BD_NO (1 << 4)
+#define ENET_BD_CR (1 << 2)
+#define ENET_BD_OV (1 << 1)
+#define ENET_BD_TR (1 << 0)
+
+typedef struct {
+ uint16_t length;
+ uint16_t flags;
+ uint32_t data;
+ uint16_t status;
+ uint16_t option;
+ uint16_t checksum;
+ uint16_t head_proto;
+ uint32_t last_buffer;
+ uint32_t timestamp;
+ uint32_t reserved[2];
+} IMXENETBufDesc;
+
+#define ENET_BD_ME (1 << 15)
+#define ENET_BD_TX_INT (1 << 14)
+#define ENET_BD_TS (1 << 13)
+#define ENET_BD_PINS (1 << 12)
+#define ENET_BD_IINS (1 << 11)
+#define ENET_BD_PE (1 << 10)
+#define ENET_BD_CE (1 << 9)
+#define ENET_BD_UC (1 << 8)
+#define ENET_BD_RX_INT (1 << 7)
+
+#define ENET_BD_TXE (1 << 15)
+#define ENET_BD_UE (1 << 13)
+#define ENET_BD_EE (1 << 12)
+#define ENET_BD_FE (1 << 11)
+#define ENET_BD_LCE (1 << 10)
+#define ENET_BD_OE (1 << 9)
+#define ENET_BD_TSE (1 << 8)
+#define ENET_BD_ICE (1 << 5)
+#define ENET_BD_PCR (1 << 4)
+#define ENET_BD_VLAN (1 << 2)
+#define ENET_BD_IPV6 (1 << 1)
+#define ENET_BD_FRAG (1 << 0)
+
+#define ENET_BD_BDU (1 << 31)
+
+#define ENET_TX_RING_NUM 3
+
+#define FSL_IMX25_FEC_SIZE 0x4000
+
+struct IMXFECState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ NICState *nic;
+ NICConf conf;
+ qemu_irq irq[2];
+ MemoryRegion iomem;
+
+ uint32_t regs[ENET_MAX];
+ uint32_t rx_descriptor;
+
+ uint32_t tx_descriptor[ENET_TX_RING_NUM];
+ uint32_t tx_ring_num;
+
+ uint32_t phy_status;
+ uint32_t phy_control;
+ uint32_t phy_advertise;
+ uint32_t phy_int;
+ uint32_t phy_int_mask;
+ uint32_t phy_num;
+
+ bool is_fec;
+
+ /* Buffer used to assemble a Tx frame */
+ uint8_t frame[ENET_MAX_FRAME_SIZE];
+};
+
+#endif
diff --git a/include/hw/net/lan9118.h b/include/hw/net/lan9118.h
new file mode 100644
index 000000000..3d0c67f33
--- /dev/null
+++ b/include/hw/net/lan9118.h
@@ -0,0 +1,20 @@
+/*
+ * SMSC LAN9118 Ethernet interface emulation
+ *
+ * Copyright (c) 2009 CodeSourcery, LLC.
+ * 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_NET_LAN9118_H
+#define HW_NET_LAN9118_H
+
+#include "net/net.h"
+
+#define TYPE_LAN9118 "lan9118"
+
+void lan9118_init(NICInfo *, uint32_t, qemu_irq);
+
+#endif
diff --git a/include/hw/net/lance.h b/include/hw/net/lance.h
new file mode 100644
index 000000000..f645d6af6
--- /dev/null
+++ b/include/hw/net/lance.h
@@ -0,0 +1,48 @@
+/*
+ * QEMU Lance (Am7990) device emulation
+ *
+ * Copyright (c) 2004 Antony T Curtis
+ * Copyright (c) 2017 Mark Cave-Ayland
+ *
+ * This represents the Sparc32 lance (Am7990) ethernet device which is an
+ * earlier register-compatible member of the AMD PC-Net II (Am79C970A) family.
+ *
+ * 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 LANCE_H
+#define LANCE_H
+
+#include "net/net.h"
+#include "hw/net/pcnet.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_LANCE "lance"
+typedef struct SysBusPCNetState SysBusPCNetState;
+DECLARE_INSTANCE_CHECKER(SysBusPCNetState, SYSBUS_PCNET,
+ TYPE_LANCE)
+
+struct SysBusPCNetState {
+ SysBusDevice parent_obj;
+
+ PCNetState state;
+};
+
+#endif
diff --git a/include/hw/net/lasi_82596.h b/include/hw/net/lasi_82596.h
new file mode 100644
index 000000000..7b62b0483
--- /dev/null
+++ b/include/hw/net/lasi_82596.h
@@ -0,0 +1,31 @@
+/*
+ * QEMU LASI i82596 device emulation
+ *
+ * Copyright (c) 201 Helge Deller <deller@gmx.de>
+ *
+ */
+
+#ifndef LASI_82596_H
+#define LASI_82596_H
+
+#include "net/net.h"
+#include "hw/net/i82596.h"
+#include "qom/object.h"
+
+#define TYPE_LASI_82596 "lasi_82596"
+typedef struct SysBusI82596State SysBusI82596State;
+DECLARE_INSTANCE_CHECKER(SysBusI82596State, SYSBUS_I82596,
+ TYPE_LASI_82596)
+
+struct SysBusI82596State {
+ SysBusDevice parent_obj;
+
+ I82596State state;
+ uint16_t last_val;
+ int val_index:1;
+};
+
+SysBusI82596State *lasi_82596_init(MemoryRegion *addr_space,
+ hwaddr hpa, qemu_irq irq);
+
+#endif
diff --git a/include/hw/net/mii.h b/include/hw/net/mii.h
new file mode 100644
index 000000000..4ae4dcce7
--- /dev/null
+++ b/include/hw/net/mii.h
@@ -0,0 +1,115 @@
+/*
+ * Common network MII address and register definitions.
+ *
+ * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
+ *
+ * Allwinner EMAC register definitions from Linux kernel are:
+ * Copyright 2012 Stefan Roese <sr@denx.de>
+ * Copyright 2013 Maxime Ripard <maxime.ripard@free-electrons.com>
+ * Copyright 1997 Sten Wang
+ *
+ * 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 MII_H
+#define MII_H
+
+/* PHY registers */
+#define MII_BMCR 0 /* Basic mode control register */
+#define MII_BMSR 1 /* Basic mode status register */
+#define MII_PHYID1 2 /* ID register 1 */
+#define MII_PHYID2 3 /* ID register 2 */
+#define MII_ANAR 4 /* Autonegotiation advertisement */
+#define MII_ANLPAR 5 /* Autonegotiation lnk partner abilities */
+#define MII_ANER 6 /* Autonegotiation expansion */
+#define MII_ANNP 7 /* Autonegotiation next page */
+#define MII_ANLPRNP 8 /* Autonegotiation link partner rx next page */
+#define MII_CTRL1000 9 /* 1000BASE-T control */
+#define MII_STAT1000 10 /* 1000BASE-T status */
+#define MII_MDDACR 13 /* MMD access control */
+#define MII_MDDAADR 14 /* MMD access address data */
+#define MII_EXTSTAT 15 /* Extended Status */
+#define MII_NSR 16
+#define MII_LBREMR 17
+#define MII_REC 18
+#define MII_SNRDR 19
+#define MII_TEST 25
+
+/* PHY registers fields */
+#define MII_BMCR_RESET (1 << 15)
+#define MII_BMCR_LOOPBACK (1 << 14)
+#define MII_BMCR_SPEED100 (1 << 13) /* LSB of Speed (100) */
+#define MII_BMCR_SPEED MII_BMCR_SPEED100
+#define MII_BMCR_AUTOEN (1 << 12) /* Autonegotiation enable */
+#define MII_BMCR_PDOWN (1 << 11) /* Enable low power state */
+#define MII_BMCR_ISOLATE (1 << 10) /* Isolate data paths from MII */
+#define MII_BMCR_ANRESTART (1 << 9) /* Auto negotiation restart */
+#define MII_BMCR_FD (1 << 8) /* Set duplex mode */
+#define MII_BMCR_CTST (1 << 7) /* Collision test */
+#define MII_BMCR_SPEED1000 (1 << 6) /* MSB of Speed (1000) */
+
+#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 */
+#define MII_BMSR_10T_HD (1 << 11) /* Can do 10mbps, half-duplex */
+#define MII_BMSR_100T2_FD (1 << 10) /* Can do 100mbps T2, full-duplex */
+#define MII_BMSR_100T2_HD (1 << 9) /* Can do 100mbps T2, half-duplex */
+#define MII_BMSR_EXTSTAT (1 << 8) /* Extended status in register 15 */
+#define MII_BMSR_MFPS (1 << 6) /* MII Frame Preamble Suppression */
+#define MII_BMSR_AN_COMP (1 << 5) /* Auto-negotiation complete */
+#define MII_BMSR_RFAULT (1 << 4) /* Remote fault */
+#define MII_BMSR_AUTONEG (1 << 3) /* Able to do auto-negotiation */
+#define MII_BMSR_LINK_ST (1 << 2) /* Link status */
+#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 (1 << 10) /* Try for pause */
+#define MII_ANAR_TXFD (1 << 8)
+#define MII_ANAR_TX (1 << 7)
+#define MII_ANAR_10FD (1 << 6)
+#define MII_ANAR_10 (1 << 5)
+#define MII_ANAR_CSMACD (1 << 0)
+
+#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_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_CTRL1000_FULL (1 << 9) /* 1000BASE-T full duplex */
+#define MII_CTRL1000_HALF (1 << 8) /* 1000BASE-T half duplex */
+
+#define MII_STAT1000_FULL (1 << 11) /* 1000BASE-T full duplex */
+#define MII_STAT1000_HALF (1 << 10) /* 1000BASE-T half duplex */
+
+/* List of vendor identifiers */
+/* RealTek 8201 */
+#define RTL8201CP_PHYID1 0x0000
+#define RTL8201CP_PHYID2 0x8201
+
+/* RealTek 8211E */
+#define RTL8211E_PHYID1 0x001c
+#define RTL8211E_PHYID2 0xc915
+
+/* National Semiconductor DP83840 */
+#define DP83840_PHYID1 0x2000
+#define DP83840_PHYID2 0x5c01
+
+/* National Semiconductor DP83848 */
+#define DP83848_PHYID1 0x2000
+#define DP83848_PHYID2 0x5c90
+
+#endif /* MII_H */
diff --git a/include/hw/net/msf2-emac.h b/include/hw/net/msf2-emac.h
new file mode 100644
index 000000000..846ba6e6d
--- /dev/null
+++ b/include/hw/net/msf2-emac.h
@@ -0,0 +1,53 @@
+/*
+ * QEMU model of the Smartfusion2 Ethernet MAC.
+ *
+ * Copyright (c) 2020 Subbaraya Sundeep <sundeep.lkml@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 "exec/memory.h"
+#include "net/net.h"
+#include "net/eth.h"
+#include "qom/object.h"
+
+#define TYPE_MSS_EMAC "msf2-emac"
+OBJECT_DECLARE_SIMPLE_TYPE(MSF2EmacState, MSS_EMAC)
+
+#define R_MAX (0x1a0 / 4)
+#define PHY_MAX_REGS 32
+
+struct MSF2EmacState {
+ SysBusDevice parent;
+
+ MemoryRegion mmio;
+ MemoryRegion *dma_mr;
+ AddressSpace dma_as;
+
+ qemu_irq irq;
+ NICState *nic;
+ NICConf conf;
+
+ uint8_t mac_addr[ETH_ALEN];
+ uint32_t rx_desc;
+ uint16_t phy_regs[PHY_MAX_REGS];
+
+ uint32_t regs[R_MAX];
+};
diff --git a/include/hw/net/ne2000-isa.h b/include/hw/net/ne2000-isa.h
new file mode 100644
index 000000000..af59ee0b0
--- /dev/null
+++ b/include/hw/net/ne2000-isa.h
@@ -0,0 +1,39 @@
+/*
+ * QEMU NE2000 emulation -- isa bus windup
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * 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_NET_NE2000_ISA_H
+#define HW_NET_NE2000_ISA_H
+
+#include "hw/isa/isa.h"
+#include "hw/qdev-properties.h"
+#include "net/net.h"
+#include "qapi/error.h"
+
+#define TYPE_ISA_NE2000 "ne2k_isa"
+
+static inline ISADevice *isa_ne2000_init(ISABus *bus, int base, int irq,
+ NICInfo *nd)
+{
+ ISADevice *d;
+
+ qemu_check_nic_model(nd, "ne2k_isa");
+
+ d = isa_try_new(TYPE_ISA_NE2000);
+ if (d) {
+ DeviceState *dev = DEVICE(d);
+
+ qdev_prop_set_uint32(dev, "iobase", base);
+ qdev_prop_set_uint32(dev, "irq", irq);
+ qdev_set_nic_properties(dev, nd);
+ isa_realize_and_unref(d, bus, &error_fatal);
+ }
+ return d;
+}
+
+#endif
diff --git a/include/hw/net/npcm7xx_emc.h b/include/hw/net/npcm7xx_emc.h
new file mode 100644
index 000000000..eac7f2981
--- /dev/null
+++ b/include/hw/net/npcm7xx_emc.h
@@ -0,0 +1,286 @@
+/*
+ * 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;
+};
+
+typedef struct NPCM7xxEMCState NPCM7xxEMCState;
+
+#define TYPE_NPCM7XX_EMC "npcm7xx-emc"
+#define NPCM7XX_EMC(obj) \
+ OBJECT_CHECK(NPCM7xxEMCState, (obj), TYPE_NPCM7XX_EMC)
+
+#endif /* NPCM7XX_EMC_H */
diff --git a/include/hw/net/smc91c111.h b/include/hw/net/smc91c111.h
new file mode 100644
index 000000000..df5b11dce
--- /dev/null
+++ b/include/hw/net/smc91c111.h
@@ -0,0 +1,18 @@
+/*
+ * SMSC 91C111 Ethernet interface emulation
+ *
+ * Copyright (c) 2005 CodeSourcery, LLC.
+ * 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_NET_SMC91C111_H
+#define HW_NET_SMC91C111_H
+
+#include "net/net.h"
+
+void smc91c111_init(NICInfo *, uint32_t, qemu_irq);
+
+#endif
diff --git a/include/hw/net/xlnx-zynqmp-can.h b/include/hw/net/xlnx-zynqmp-can.h
new file mode 100644
index 000000000..eb1558708
--- /dev/null
+++ b/include/hw/net/xlnx-zynqmp-can.h
@@ -0,0 +1,78 @@
+/*
+ * 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/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
new file mode 100644
index 000000000..fff41bebc
--- /dev/null
+++ b/include/hw/nmi.h
@@ -0,0 +1,45 @@
+/*
+ * NMI monitor handler class and helpers definitions.
+ *
+ * Copyright IBM Corp., 2014
+ *
+ * Author: Alexey Kardashevskiy <aik@ozlabs.ru>
+ *
+ * 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 NMI_H
+#define NMI_H
+
+#include "qom/object.h"
+
+#define TYPE_NMI "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;
+
+struct NMIClass {
+ InterfaceClass parent_class;
+
+ void (*nmi_monitor_handler)(NMIState *n, int cpu_index, Error **errp);
+};
+
+void nmi_monitor_handle(int cpu_index, Error **errp);
+
+#endif /* NMI_H */
diff --git a/include/hw/nubus/mac-nubus-bridge.h b/include/hw/nubus/mac-nubus-bridge.h
new file mode 100644
index 000000000..70ab50ab2
--- /dev/null
+++ b/include/hw/nubus/mac-nubus-bridge.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013-2018 Laurent Vivier <laurent@vivier.eu>
+ *
+ * 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_NUBUS_MAC_H
+#define HW_NUBUS_MAC_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"
+OBJECT_DECLARE_SIMPLE_TYPE(MacNubusBridge, MAC_NUBUS_BRIDGE)
+
+struct MacNubusBridge {
+ NubusBridge parent_obj;
+
+ MemoryRegion super_slot_alias;
+ MemoryRegion slot_alias;
+};
+
+#endif
diff --git a/include/hw/nubus/nubus.h b/include/hw/nubus/nubus.h
new file mode 100644
index 000000000..b3b4d2ead
--- /dev/null
+++ b/include/hw/nubus/nubus.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2013-2018 Laurent Vivier <laurent@vivier.eu>
+ *
+ * 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_NUBUS_NUBUS_H
+#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 0xe
+
+#define NUBUS_SLOT_BASE (NUBUS_SUPER_SLOT_SIZE * \
+ (NUBUS_SUPER_SLOT_NB + 1))
+
+#define NUBUS_SLOT_SIZE 0x01000000
+#define NUBUS_FIRST_SLOT 0x0
+#define NUBUS_LAST_SLOT 0xf
+#define NUBUS_SLOT_NB (NUBUS_LAST_SLOT - NUBUS_FIRST_SLOT + 1)
+
+#define NUBUS_IRQS 16
+
+#define TYPE_NUBUS_DEVICE "nubus-device"
+OBJECT_DECLARE_SIMPLE_TYPE(NubusDevice, NUBUS_DEVICE)
+
+#define TYPE_NUBUS_BUS "nubus-bus"
+OBJECT_DECLARE_SIMPLE_TYPE(NubusBus, NUBUS_BUS)
+
+#define TYPE_NUBUS_BRIDGE "nubus-bridge"
+OBJECT_DECLARE_SIMPLE_TYPE(NubusBridge, NUBUS_BRIDGE);
+
+struct NubusBus {
+ BusState qbus;
+
+ AddressSpace nubus_as;
+ MemoryRegion nubus_mr;
+
+ MemoryRegion super_slot_io;
+ MemoryRegion slot_io;
+
+ uint16_t slot_available_mask;
+
+ qemu_irq irqs[NUBUS_IRQS];
+};
+
+#define NUBUS_DECL_ROM_MAX_SIZE (128 * KiB)
+
+struct NubusDevice {
+ DeviceState qdev;
+
+ int32_t slot;
+ MemoryRegion super_slot_mem;
+ MemoryRegion slot_mem;
+
+ char *romfile;
+ MemoryRegion decl_rom;
+};
+
+void nubus_set_irq(NubusDevice *nd, int level);
+
+struct NubusBridge {
+ SysBusDevice parent_obj;
+
+ NubusBus bus;
+};
+
+#endif
diff --git a/include/hw/nvram/chrp_nvram.h b/include/hw/nvram/chrp_nvram.h
new file mode 100644
index 000000000..4a0f5c21b
--- /dev/null
+++ b/include/hw/nvram/chrp_nvram.h
@@ -0,0 +1,57 @@
+/*
+ * Common Hardware Reference Platform NVRAM functions.
+ *
+ * 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.
+ *
+ * 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 CHRP_NVRAM_H
+#define CHRP_NVRAM_H
+
+#include "qemu/bswap.h"
+
+/* OpenBIOS NVRAM partition */
+typedef struct {
+ uint8_t signature;
+ uint8_t checksum;
+ uint16_t len; /* Big endian, length divided by 16 */
+ char name[12];
+} ChrpNvramPartHdr;
+
+#define CHRP_NVPART_SYSTEM 0x70
+#define CHRP_NVPART_FREE 0x7f
+
+static inline void
+chrp_nvram_finish_partition(ChrpNvramPartHdr *header, uint32_t size)
+{
+ unsigned int i, sum;
+ uint8_t *tmpptr;
+
+ /* Length divided by 16 */
+ header->len = cpu_to_be16(size >> 4);
+
+ /* Checksum */
+ tmpptr = (uint8_t *)header;
+ sum = *tmpptr;
+ for (i = 0; i < 14; i++) {
+ sum += tmpptr[2 + i];
+ sum = (sum + ((sum & 0xff00) >> 8)) & 0xff;
+ }
+ header->checksum = sum & 0xff;
+}
+
+/* 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/eeprom93xx.h b/include/hw/nvram/eeprom93xx.h
new file mode 100644
index 000000000..8ba0e287f
--- /dev/null
+++ b/include/hw/nvram/eeprom93xx.h
@@ -0,0 +1,40 @@
+/*
+ * QEMU EEPROM 93xx emulation
+ *
+ * Copyright (c) 2006-2007 Stefan Weil
+ *
+ * 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 EEPROM93XX_H
+#define EEPROM93XX_H
+
+typedef struct _eeprom_t eeprom_t;
+
+/* Create a new EEPROM with (nwords * 2) bytes. */
+eeprom_t *eeprom93xx_new(DeviceState *dev, uint16_t nwords);
+
+/* Destroy an existing EEPROM. */
+void eeprom93xx_free(DeviceState *dev, eeprom_t *eeprom);
+
+/* Read from the EEPROM. */
+uint16_t eeprom93xx_read(eeprom_t *eeprom);
+
+/* Write to the EEPROM. */
+void eeprom93xx_write(eeprom_t *eeprom, int eecs, int eesk, int eedi);
+
+/* Get EEPROM data array. */
+uint16_t *eeprom93xx_data(eeprom_t *eeprom);
+
+#endif /* EEPROM93XX_H */
diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h
new file mode 100644
index 000000000..0e7a8bc7a
--- /dev/null
+++ b/include/hw/nvram/fw_cfg.h
@@ -0,0 +1,345 @@
+#ifndef FW_CFG_H
+#define FW_CFG_H
+
+#include "exec/hwaddr.h"
+#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"
+
+OBJECT_DECLARE_SIMPLE_TYPE(FWCfgState, FW_CFG)
+OBJECT_DECLARE_SIMPLE_TYPE(FWCfgIoState, FW_CFG_IO)
+OBJECT_DECLARE_SIMPLE_TYPE(FWCfgMemState, FW_CFG_MEM)
+
+typedef struct FWCfgDataGeneratorClass FWCfgDataGeneratorClass;
+DECLARE_CLASS_CHECKERS(FWCfgDataGeneratorClass, FW_CFG_DATA_GENERATOR,
+ TYPE_FW_CFG_DATA_GENERATOR_INTERFACE)
+
+struct FWCfgDataGeneratorClass {
+ /*< private >*/
+ InterfaceClass parent_class;
+ /*< public >*/
+
+ /**
+ * get_data:
+ * @obj: the object implementing this interface
+ * @errp: pointer to a NULL-initialized error object
+ *
+ * Returns: reference to a byte array containing the data on success,
+ * or NULL on error.
+ *
+ * The caller should release the reference when no longer
+ * required.
+ */
+ GByteArray *(*get_data)(Object *obj, Error **errp);
+};
+
+typedef struct fw_cfg_file FWCfgFile;
+
+#define FW_CFG_ORDER_OVERRIDE_VGA 70
+#define FW_CFG_ORDER_OVERRIDE_NIC 80
+#define FW_CFG_ORDER_OVERRIDE_USER 100
+#define FW_CFG_ORDER_OVERRIDE_DEVICE 110
+
+void fw_cfg_set_order_override(FWCfgState *fw_cfg, int order);
+void fw_cfg_reset_order_override(FWCfgState *fw_cfg);
+
+typedef struct FWCfgFiles {
+ uint32_t count;
+ FWCfgFile f[];
+} FWCfgFiles;
+
+typedef struct fw_cfg_dma_access FWCfgDmaAccess;
+
+typedef void (*FWCfgCallback)(void *opaque);
+typedef void (*FWCfgWriteCallback)(void *opaque, off_t start, size_t len);
+
+struct FWCfgState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ uint16_t file_slots;
+ FWCfgEntry *entries[2];
+ int *entry_order;
+ FWCfgFiles *files;
+ uint16_t cur_entry;
+ uint32_t cur_offset;
+ Notifier machine_ready;
+
+ int fw_cfg_order_override;
+
+ bool dma_enabled;
+ dma_addr_t dma_addr;
+ AddressSpace *dma_as;
+ MemoryRegion dma_iomem;
+
+ /* restore during migration */
+ bool acpi_mr_restore;
+ uint64_t table_mr_size;
+ uint64_t linker_mr_size;
+ uint64_t rsdp_mr_size;
+};
+
+struct FWCfgIoState {
+ /*< private >*/
+ FWCfgState parent_obj;
+ /*< public >*/
+
+ MemoryRegion comb_iomem;
+};
+
+struct FWCfgMemState {
+ /*< private >*/
+ FWCfgState parent_obj;
+ /*< public >*/
+
+ MemoryRegion ctl_iomem, data_iomem;
+ uint32_t data_width;
+ MemoryRegionOps wide_data_ops;
+};
+
+/**
+ * fw_cfg_add_bytes:
+ * @s: fw_cfg device being modified
+ * @key: selector key value for new fw_cfg item
+ * @data: pointer to start of item data
+ * @len: size of item data
+ *
+ * Add a new fw_cfg item, available by selecting the given key, as a raw
+ * "blob" of the given size. The data referenced by the starting pointer
+ * is only linked, NOT copied, into the data structure of the fw_cfg device.
+ */
+void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len);
+
+/**
+ * fw_cfg_add_string:
+ * @s: fw_cfg device being modified
+ * @key: selector key value for new fw_cfg item
+ * @value: NUL-terminated ascii string
+ *
+ * Add a new fw_cfg item, available by selecting the given key. The item
+ * data will consist of a dynamically allocated copy of the provided string,
+ * including its NUL terminator.
+ */
+void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value);
+
+/**
+ * fw_cfg_modify_string:
+ * @s: fw_cfg device being modified
+ * @key: selector key value for new fw_cfg item
+ * @value: NUL-terminated ascii string
+ *
+ * Replace the fw_cfg item available by selecting the given key. The new
+ * data will consist of a dynamically allocated copy of the provided string,
+ * including its NUL terminator. The data being replaced, assumed to have
+ * been dynamically allocated during an earlier call to either
+ * fw_cfg_add_string() or fw_cfg_modify_string(), is freed before returning.
+ */
+void fw_cfg_modify_string(FWCfgState *s, uint16_t key, const char *value);
+
+/**
+ * fw_cfg_add_i16:
+ * @s: fw_cfg device being modified
+ * @key: selector key value for new fw_cfg item
+ * @value: 16-bit integer
+ *
+ * Add a new fw_cfg item, available by selecting the given key. The item
+ * data will consist of a dynamically allocated copy of the given 16-bit
+ * value, converted to little-endian representation.
+ */
+void fw_cfg_add_i16(FWCfgState *s, uint16_t key, uint16_t value);
+
+/**
+ * fw_cfg_modify_i16:
+ * @s: fw_cfg device being modified
+ * @key: selector key value for new fw_cfg item
+ * @value: 16-bit integer
+ *
+ * Replace the fw_cfg item available by selecting the given key. The new
+ * data will consist of a dynamically allocated copy of the given 16-bit
+ * value, converted to little-endian representation. The data being replaced,
+ * assumed to have been dynamically allocated during an earlier call to
+ * either fw_cfg_add_i16() or fw_cfg_modify_i16(), is freed before returning.
+ */
+void fw_cfg_modify_i16(FWCfgState *s, uint16_t key, uint16_t value);
+
+/**
+ * fw_cfg_add_i32:
+ * @s: fw_cfg device being modified
+ * @key: selector key value for new fw_cfg item
+ * @value: 32-bit integer
+ *
+ * Add a new fw_cfg item, available by selecting the given key. The item
+ * data will consist of a dynamically allocated copy of the given 32-bit
+ * value, converted to little-endian representation.
+ */
+void fw_cfg_add_i32(FWCfgState *s, uint16_t key, uint32_t value);
+
+/**
+ * fw_cfg_modify_i32:
+ * @s: fw_cfg device being modified
+ * @key: selector key value for new fw_cfg item
+ * @value: 32-bit integer
+ *
+ * Replace the fw_cfg item available by selecting the given key. The new
+ * data will consist of a dynamically allocated copy of the given 32-bit
+ * value, converted to little-endian representation. The data being replaced,
+ * assumed to have been dynamically allocated during an earlier call to
+ * either fw_cfg_add_i32() or fw_cfg_modify_i32(), is freed before returning.
+ */
+void fw_cfg_modify_i32(FWCfgState *s, uint16_t key, uint32_t value);
+
+/**
+ * fw_cfg_add_i64:
+ * @s: fw_cfg device being modified
+ * @key: selector key value for new fw_cfg item
+ * @value: 64-bit integer
+ *
+ * Add a new fw_cfg item, available by selecting the given key. The item
+ * data will consist of a dynamically allocated copy of the given 64-bit
+ * value, converted to little-endian representation.
+ */
+void fw_cfg_add_i64(FWCfgState *s, uint16_t key, uint64_t value);
+
+/**
+ * fw_cfg_modify_i64:
+ * @s: fw_cfg device being modified
+ * @key: selector key value for new fw_cfg item
+ * @value: 64-bit integer
+ *
+ * Replace the fw_cfg item available by selecting the given key. The new
+ * data will consist of a dynamically allocated copy of the given 64-bit
+ * value, converted to little-endian representation. The data being replaced,
+ * assumed to have been dynamically allocated during an earlier call to
+ * either fw_cfg_add_i64() or fw_cfg_modify_i64(), is freed before returning.
+ */
+void fw_cfg_modify_i64(FWCfgState *s, uint16_t key, uint64_t value);
+
+/**
+ * fw_cfg_add_file:
+ * @s: fw_cfg device being modified
+ * @filename: name of new fw_cfg file item
+ * @data: pointer to start of item data
+ * @len: size of item data
+ *
+ * Add a new NAMED fw_cfg item as a raw "blob" of the given size. The data
+ * referenced by the starting pointer is only linked, NOT copied, into the
+ * data structure of the fw_cfg device.
+ * The next available (unused) selector key starting at FW_CFG_FILE_FIRST
+ * will be used; also, a new entry will be added to the file directory
+ * structure residing at key value FW_CFG_FILE_DIR, containing the item name,
+ * data size, and assigned selector key value.
+ */
+void fw_cfg_add_file(FWCfgState *s, const char *filename, void *data,
+ size_t len);
+
+/**
+ * fw_cfg_add_file_callback:
+ * @s: fw_cfg device being modified
+ * @filename: name of new fw_cfg file item
+ * @select_cb: callback function when selecting
+ * @write_cb: callback function after a write
+ * @callback_opaque: argument to be passed into callback function
+ * @data: pointer to start of item data
+ * @len: size of item data
+ * @read_only: is file read only
+ *
+ * Add a new NAMED fw_cfg item as a raw "blob" of the given size. The data
+ * referenced by the starting pointer is only linked, NOT copied, into the
+ * data structure of the fw_cfg device.
+ * The next available (unused) selector key starting at FW_CFG_FILE_FIRST
+ * will be used; also, a new entry will be added to the file directory
+ * structure residing at key value FW_CFG_FILE_DIR, containing the item name,
+ * data size, and assigned selector key value.
+ * Additionally, set a callback function (and argument) to be called each
+ * time this item is selected (by having its selector key either written to
+ * the fw_cfg control register, or passed to QEMU in FWCfgDmaAccess.control
+ * with FW_CFG_DMA_CTL_SELECT).
+ */
+void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
+ FWCfgCallback select_cb,
+ FWCfgWriteCallback write_cb,
+ void *callback_opaque,
+ void *data, size_t len, bool read_only);
+
+/**
+ * fw_cfg_modify_file:
+ * @s: fw_cfg device being modified
+ * @filename: name of new fw_cfg file item
+ * @data: pointer to start of item data
+ * @len: size of item data
+ *
+ * Replace a NAMED fw_cfg item. If an existing item is found, its callback
+ * information will be cleared, and a pointer to its data will be returned
+ * to the caller, so that it may be freed if necessary. If an existing item
+ * is not found, this call defaults to fw_cfg_add_file(), and NULL is
+ * returned to the caller.
+ * In either case, the new item data is only linked, NOT copied, into the
+ * data structure of the fw_cfg device.
+ *
+ * Returns: pointer to old item's data, or NULL if old item does not exist.
+ */
+void *fw_cfg_modify_file(FWCfgState *s, const char *filename, void *data,
+ size_t len);
+
+/**
+ * fw_cfg_add_from_generator:
+ * @s: fw_cfg device being modified
+ * @filename: name of new fw_cfg file item
+ * @gen_id: name of object implementing FW_CFG_DATA_GENERATOR interface
+ * @errp: pointer to a NULL initialized error object
+ *
+ * Add a new NAMED fw_cfg item with the content generated from the
+ * @gen_id object. The data generated by the @gen_id object is copied
+ * into the data structure of the fw_cfg device.
+ * The next available (unused) selector key starting at FW_CFG_FILE_FIRST
+ * will be used; also, a new entry will be added to the file directory
+ * structure residing at key value FW_CFG_FILE_DIR, containing the item name,
+ * data size, and assigned selector key value.
+ *
+ * Returns: %true on success, %false on error.
+ */
+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);
+FWCfgState *fw_cfg_init_mem(hwaddr ctl_addr, hwaddr data_addr);
+FWCfgState *fw_cfg_init_mem_wide(hwaddr ctl_addr,
+ hwaddr data_addr, uint32_t data_width,
+ hwaddr dma_addr, AddressSpace *dma_as);
+
+FWCfgState *fw_cfg_find(void);
+bool fw_cfg_dma_enabled(void *opaque);
+
+/**
+ * fw_cfg_arch_key_name:
+ *
+ * @key: The uint16 selector key.
+ *
+ * The key is architecture-specific (the FW_CFG_ARCH_LOCAL mask is expected
+ * to be set in the key).
+ *
+ * Returns: The stringified architecture-specific name if the selector
+ * refers to a well-known numerically defined item, or NULL on
+ * key lookup failure.
+ */
+const char *fw_cfg_arch_key_name(uint16_t key);
+
+#endif
diff --git a/include/hw/nvram/npcm7xx_otp.h b/include/hw/nvram/npcm7xx_otp.h
new file mode 100644
index 000000000..156bbd151
--- /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.
+ */
+extern 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
new file mode 100644
index 000000000..d85e788df
--- /dev/null
+++ b/include/hw/nvram/nrf51_nvm.h
@@ -0,0 +1,65 @@
+/*
+ * Nordic Semiconductor nRF51 non-volatile memory
+ *
+ * It provides an interface to erase regions in flash memory.
+ * Furthermore it provides the user and factory information registers.
+ *
+ * QEMU interface:
+ * + sysbus MMIO regions 0: NVMC peripheral registers
+ * + sysbus MMIO regions 1: FICR peripheral registers
+ * + sysbus MMIO regions 2: UICR peripheral registers
+ * + flash-size property: flash size in bytes.
+ *
+ * Accuracy of the peripheral model:
+ * + Code regions (MPU configuration) are disregarded.
+ *
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
+ *
+ * This code is licensed under the GPL version 2 or later. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+#ifndef NRF51_NVM_H
+#define NRF51_NVM_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+#define TYPE_NRF51_NVM "nrf51_soc.nvm"
+OBJECT_DECLARE_SIMPLE_TYPE(NRF51NVMState, NRF51_NVM)
+
+#define NRF51_UICR_FIXTURE_SIZE 64
+
+#define NRF51_NVMC_SIZE 0x1000
+
+#define NRF51_NVMC_READY 0x400
+#define NRF51_NVMC_READY_READY 0x01
+#define NRF51_NVMC_CONFIG 0x504
+#define NRF51_NVMC_CONFIG_MASK 0x03
+#define NRF51_NVMC_CONFIG_WEN 0x01
+#define NRF51_NVMC_CONFIG_EEN 0x02
+#define NRF51_NVMC_ERASEPCR1 0x508
+#define NRF51_NVMC_ERASEPCR0 0x510
+#define NRF51_NVMC_ERASEALL 0x50C
+#define NRF51_NVMC_ERASEUICR 0x514
+#define NRF51_NVMC_ERASE 0x01
+
+#define NRF51_UICR_SIZE 0x100
+
+struct NRF51NVMState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion mmio;
+ MemoryRegion ficr;
+ MemoryRegion uicr;
+ MemoryRegion flash;
+
+ uint32_t uicr_content[NRF51_UICR_FIXTURE_SIZE];
+ uint32_t flash_size;
+ uint8_t *storage;
+
+ uint32_t config;
+
+};
+
+
+#endif
diff --git a/include/hw/nvram/sun_nvram.h b/include/hw/nvram/sun_nvram.h
new file mode 100644
index 000000000..68eaa6030
--- /dev/null
+++ b/include/hw/nvram/sun_nvram.h
@@ -0,0 +1,34 @@
+#ifndef SUN_NVRAM_H
+#define SUN_NVRAM_H
+
+/* Sun IDPROM structure at the end of NVRAM */
+/* from http://www.squirrel.com/squirrel/sun-nvram-hostid.faq.html */
+struct Sun_nvram {
+ uint8_t type; /* always 01 */
+ uint8_t machine_id; /* first byte of host id (machine type) */
+ uint8_t macaddr[6]; /* 6 byte ethernet address (first 3 bytes 08, 00, 20) */
+ uint8_t date[4]; /* date of manufacture */
+ uint8_t hostid[3]; /* remaining 3 bytes of host id (serial number) */
+ uint8_t checksum; /* bitwise xor of previous bytes */
+};
+
+static inline void
+Sun_init_header(struct Sun_nvram *header, const uint8_t *macaddr, int machine_id)
+{
+ uint8_t tmp, *tmpptr;
+ unsigned int i;
+
+ header->type = 1;
+ header->machine_id = machine_id & 0xff;
+ memcpy(&header->macaddr, macaddr, 6);
+ memcpy(&header->hostid , &macaddr[3], 3);
+
+ /* Calculate checksum */
+ tmp = 0;
+ tmpptr = (uint8_t *)header;
+ for (i = 0; i < 15; i++)
+ tmp ^= tmpptr[i];
+
+ header->checksum = tmp;
+}
+#endif /* SUN_NVRAM_H */
diff --git a/include/hw/nvram/xlnx-bbram.h b/include/hw/nvram/xlnx-bbram.h
new file mode 100644
index 000000000..87d59ef3c
--- /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 000000000..58414e468
--- /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 000000000..a873dc5cb
--- /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 000000000..6b051ec4f
--- /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/or-irq.h b/include/hw/or-irq.h
new file mode 100644
index 000000000..f2f0a2738
--- /dev/null
+++ b/include/hw/or-irq.h
@@ -0,0 +1,51 @@
+/*
+ * QEMU IRQ/GPIO common code.
+ *
+ * Copyright (c) 2016 Alistair Francis <alistair@alistair23.me>.
+ *
+ * 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_OR_IRQ_H
+#define HW_OR_IRQ_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_OR_IRQ "or-irq"
+
+/* This can safely be increased if necessary without breaking
+ * migration compatibility (as long as it remains greater than 15).
+ */
+#define MAX_OR_LINES 48
+
+typedef struct OrIRQState qemu_or_irq;
+
+DECLARE_INSTANCE_CHECKER(qemu_or_irq, OR_IRQ,
+ TYPE_OR_IRQ)
+
+struct OrIRQState {
+ DeviceState parent_obj;
+
+ qemu_irq out_irq;
+ bool levels[MAX_OR_LINES];
+ uint16_t num_lines;
+};
+
+#endif
diff --git a/include/hw/pci-bridge/simba.h b/include/hw/pci-bridge/simba.h
new file mode 100644
index 000000000..979cb1743
--- /dev/null
+++ b/include/hw/pci-bridge/simba.h
@@ -0,0 +1,42 @@
+/*
+ * QEMU Simba PCI bridge
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ * Copyright (c) 2012,2013 Artyom Tarasenko
+ * Copyright (c) 2017 Mark Cave-Ayland
+ *
+ * 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_PCI_BRIDGE_SIMBA_H
+#define HW_PCI_BRIDGE_SIMBA_H
+
+#include "hw/pci/pci_bridge.h"
+#include "qom/object.h"
+
+
+struct SimbaPCIBridge {
+ /*< private >*/
+ PCIBridge parent_obj;
+};
+
+#define TYPE_SIMBA_PCI_BRIDGE "pbm-bridge"
+OBJECT_DECLARE_SIMPLE_TYPE(SimbaPCIBridge, SIMBA_PCI_BRIDGE)
+
+#endif
diff --git a/include/hw/pci-host/designware.h b/include/hw/pci-host/designware.h
new file mode 100644
index 000000000..6d9b51ae6
--- /dev/null
+++ b/include/hw/pci-host/designware.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * Designware PCIe IP block emulation
+ *
+ * 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 DESIGNWARE_H
+#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"
+OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIEHost, DESIGNWARE_PCIE_HOST)
+
+#define TYPE_DESIGNWARE_PCIE_ROOT "designware-pcie-root"
+OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIERoot, DESIGNWARE_PCIE_ROOT)
+
+struct DesignwarePCIERoot;
+
+typedef struct DesignwarePCIEViewport {
+ DesignwarePCIERoot *root;
+
+ MemoryRegion cfg;
+ MemoryRegion mem;
+
+ uint64_t base;
+ uint64_t target;
+ uint32_t limit;
+ uint32_t cr[2];
+
+ bool inbound;
+} DesignwarePCIEViewport;
+
+typedef struct DesignwarePCIEMSIBank {
+ uint32_t enable;
+ uint32_t mask;
+ uint32_t status;
+} DesignwarePCIEMSIBank;
+
+typedef struct DesignwarePCIEMSI {
+ uint64_t base;
+ MemoryRegion iomem;
+
+#define DESIGNWARE_PCIE_NUM_MSI_BANKS 1
+
+ DesignwarePCIEMSIBank intr[DESIGNWARE_PCIE_NUM_MSI_BANKS];
+} DesignwarePCIEMSI;
+
+struct DesignwarePCIERoot {
+ PCIBridge parent_obj;
+
+ uint32_t atu_viewport;
+
+#define DESIGNWARE_PCIE_VIEWPORT_OUTBOUND 0
+#define DESIGNWARE_PCIE_VIEWPORT_INBOUND 1
+#define DESIGNWARE_PCIE_NUM_VIEWPORTS 4
+
+ DesignwarePCIEViewport viewports[2][DESIGNWARE_PCIE_NUM_VIEWPORTS];
+ DesignwarePCIEMSI msi;
+};
+
+struct DesignwarePCIEHost {
+ PCIHostState parent_obj;
+
+ DesignwarePCIERoot root;
+
+ struct {
+ AddressSpace address_space;
+ MemoryRegion address_space_root;
+
+ MemoryRegion memory;
+ MemoryRegion io;
+
+ qemu_irq irqs[4];
+ } pci;
+
+ MemoryRegion mmio;
+};
+
+#endif /* DESIGNWARE_H */
diff --git a/include/hw/pci-host/gpex.h b/include/hw/pci-host/gpex.h
new file mode 100644
index 000000000..fcf8b6382
--- /dev/null
+++ b/include/hw/pci-host/gpex.h
@@ -0,0 +1,73 @@
+/*
+ * QEMU Generic PCI Express Bridge Emulation
+ *
+ * Copyright (C) 2015 Alexander Graf <agraf@suse.de>
+ *
+ * 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_GPEX_H
+#define HW_GPEX_H
+
+#include "exec/hwaddr.h"
+#include "hw/sysbus.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pcie_host.h"
+#include "qom/object.h"
+
+#define TYPE_GPEX_HOST "gpex-pcihost"
+OBJECT_DECLARE_SIMPLE_TYPE(GPEXHost, GPEX_HOST)
+
+#define TYPE_GPEX_ROOT_DEVICE "gpex-root"
+OBJECT_DECLARE_SIMPLE_TYPE(GPEXRootState, GPEX_ROOT_DEVICE)
+
+#define GPEX_NUM_IRQS 4
+
+struct GPEXRootState {
+ /*< private >*/
+ PCIDevice parent_obj;
+ /*< public >*/
+};
+
+struct GPEXHost {
+ /*< private >*/
+ PCIExpressHost parent_obj;
+ /*< public >*/
+
+ GPEXRootState gpex_root;
+
+ 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];
+
+ bool allow_unmapped_accesses;
+};
+
+struct GPEXConfig {
+ MemMapEntry ecam;
+ MemMapEntry mmio32;
+ MemMapEntry mmio64;
+ MemMapEntry pio;
+ int irq;
+ PCIBus *bus;
+};
+
+int gpex_set_irq_num(GPEXHost *s, int index, int gsi);
+
+void acpi_dsdt_add_gpex(Aml *scope, struct GPEXConfig *cfg);
+
+#endif /* HW_GPEX_H */
diff --git a/include/hw/pci-host/i440fx.h b/include/hw/pci-host/i440fx.h
new file mode 100644
index 000000000..f068aaba8
--- /dev/null
+++ b/include/hw/pci-host/i440fx.h
@@ -0,0 +1,49 @@
+/*
+ * QEMU i440FX North Bridge Emulation
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * 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_PCI_I440FX_H
+#define HW_PCI_I440FX_H
+
+#include "hw/pci/pci_bus.h"
+#include "hw/pci-host/pam.h"
+#include "qom/object.h"
+
+#define TYPE_I440FX_PCI_HOST_BRIDGE "i440FX-pcihost"
+#define TYPE_I440FX_PCI_DEVICE "i440FX"
+
+OBJECT_DECLARE_SIMPLE_TYPE(PCII440FXState, I440FX_PCI_DEVICE)
+
+struct PCII440FXState {
+ /*< private >*/
+ PCIDevice parent_obj;
+ /*< public >*/
+
+ MemoryRegion *system_memory;
+ MemoryRegion *pci_address_space;
+ MemoryRegion *ram_memory;
+ PAMMemoryRegion pam_regions[PAM_REGIONS_COUNT];
+ MemoryRegion smram_region;
+ MemoryRegion smram, low_smram;
+};
+
+#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);
+
+
+#endif
diff --git a/include/hw/pci-host/mv64361.h b/include/hw/pci-host/mv64361.h
new file mode 100644
index 000000000..9cdb35cb3
--- /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
new file mode 100644
index 000000000..c1fd06ba2
--- /dev/null
+++ b/include/hw/pci-host/pam.h
@@ -0,0 +1,94 @@
+#ifndef QEMU_PAM_H
+#define QEMU_PAM_H
+
+/*
+ * Copyright (c) 2006 Fabrice Bellard
+ * Copyright (c) 2011 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ * Copyright (c) 2012 Jason Baron <jbaron@redhat.com>
+ *
+ * Split out from piix.c
+ *
+ * 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.
+ */
+
+/*
+ * SMRAM memory area and PAM memory area in Legacy address range for PC.
+ * PAM: Programmable Attribute Map registers
+ *
+ * 0xa0000 - 0xbffff compatible SMRAM
+ *
+ * 0xc0000 - 0xc3fff Expansion area memory segments
+ * 0xc4000 - 0xc7fff
+ * 0xc8000 - 0xcbfff
+ * 0xcc000 - 0xcffff
+ * 0xd0000 - 0xd3fff
+ * 0xd4000 - 0xd7fff
+ * 0xd8000 - 0xdbfff
+ * 0xdc000 - 0xdffff
+ * 0xe0000 - 0xe3fff Extended System BIOS Area Memory Segments
+ * 0xe4000 - 0xe7fff
+ * 0xe8000 - 0xebfff
+ * 0xec000 - 0xeffff
+ *
+ * 0xf0000 - 0xfffff System BIOS Area Memory Segments
+ */
+
+#include "exec/memory.h"
+
+#define SMRAM_C_BASE 0xa0000
+#define SMRAM_C_END 0xc0000
+#define SMRAM_C_SIZE 0x20000
+
+#define PAM_EXPAN_BASE 0xc0000
+#define PAM_EXPAN_SIZE 0x04000
+
+#define PAM_EXBIOS_BASE 0xe0000
+#define PAM_EXBIOS_SIZE 0x04000
+
+#define PAM_BIOS_BASE 0xf0000
+#define PAM_BIOS_END 0xfffff
+/* 64KB: Intel 3 series express chipset family p. 58*/
+#define PAM_BIOS_SIZE 0x10000
+
+/* PAM registers: log nibble and high nibble*/
+#define PAM_ATTR_WE ((uint8_t)2)
+#define PAM_ATTR_RE ((uint8_t)1)
+#define PAM_ATTR_MASK ((uint8_t)3)
+
+/* SMRAM register */
+#define SMRAM_D_OPEN ((uint8_t)(1 << 6))
+#define SMRAM_D_CLS ((uint8_t)(1 << 5))
+#define SMRAM_D_LCK ((uint8_t)(1 << 4))
+#define SMRAM_G_SMRAME ((uint8_t)(1 << 3))
+#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 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
new file mode 100644
index 000000000..e2a2e3624
--- /dev/null
+++ b/include/hw/pci-host/pnv_phb3.h
@@ -0,0 +1,167 @@
+/*
+ * QEMU PowerPC PowerNV (POWER8) PHB3 model
+ *
+ * Copyright (c) 2014-2020, IBM Corporation.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+
+#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"
+
+typedef struct PnvPHB3 PnvPHB3;
+
+/*
+ * PHB3 XICS Source for MSIs
+ */
+#define TYPE_PHB3_MSI "phb3-msi"
+typedef struct Phb3MsiState Phb3MsiState;
+DECLARE_INSTANCE_CHECKER(Phb3MsiState, PHB3_MSI,
+ TYPE_PHB3_MSI)
+
+#define PHB3_MAX_MSI 2048
+
+struct Phb3MsiState {
+ ICSState ics;
+ qemu_irq *qirqs;
+
+ PnvPHB3 *phb;
+ uint64_t rba[PHB3_MAX_MSI / 64];
+ uint32_t rba_sum;
+};
+
+void pnv_phb3_msi_update_config(Phb3MsiState *msis, uint32_t base,
+ uint32_t count);
+void pnv_phb3_msi_send(Phb3MsiState *msis, uint64_t addr, uint16_t data,
+ int32_t dev_pe);
+void pnv_phb3_msi_ffi(Phb3MsiState *msis, uint64_t val);
+void pnv_phb3_msi_pic_print_info(Phb3MsiState *msis, Monitor *mon);
+
+
+/*
+ * We have one such address space wrapper per possible device under
+ * the PHB since they need to be assigned statically at qemu device
+ * creation time. The relationship to a PE is done later dynamically.
+ * This means we can potentially create a lot of these guys. Q35
+ * stores them as some kind of radix tree but we never really need to
+ * do fast lookups so instead we simply keep a QLIST of them for now,
+ * we can add the radix if needed later on.
+ *
+ * We do cache the PE number to speed things up a bit though.
+ */
+typedef struct PnvPhb3DMASpace {
+ PCIBus *bus;
+ uint8_t devfn;
+ int pe_num; /* Cached PE number */
+#define PHB_INVALID_PE (-1)
+ PnvPHB3 *phb;
+ AddressSpace dma_as;
+ IOMMUMemoryRegion dma_mr;
+ MemoryRegion msi32_mr;
+ MemoryRegion msi64_mr;
+ QLIST_ENTRY(PnvPhb3DMASpace) list;
+} PnvPhb3DMASpace;
+
+/*
+ * PHB3 Power Bus Common Queue
+ */
+#define TYPE_PNV_PBCQ "pnv-pbcq"
+OBJECT_DECLARE_SIMPLE_TYPE(PnvPBCQState, PNV_PBCQ)
+
+struct PnvPBCQState {
+ DeviceState parent;
+
+ uint32_t nest_xbase;
+ uint32_t spci_xbase;
+ uint32_t pci_xbase;
+#define PBCQ_NEST_REGS_COUNT 0x46
+#define PBCQ_PCI_REGS_COUNT 0x15
+#define PBCQ_SPCI_REGS_COUNT 0x5
+
+ uint64_t nest_regs[PBCQ_NEST_REGS_COUNT];
+ uint64_t spci_regs[PBCQ_SPCI_REGS_COUNT];
+ uint64_t pci_regs[PBCQ_PCI_REGS_COUNT];
+ MemoryRegion mmbar0;
+ MemoryRegion mmbar1;
+ MemoryRegion phbbar;
+ uint64_t mmio0_base;
+ uint64_t mmio0_size;
+ uint64_t mmio1_base;
+ uint64_t mmio1_size;
+ PnvPHB3 *phb;
+
+ MemoryRegion xscom_nest_regs;
+ MemoryRegion xscom_pci_regs;
+ MemoryRegion xscom_spci_regs;
+};
+
+/*
+ * PHB3 PCIe Root port
+ */
+#define TYPE_PNV_PHB3_ROOT_BUS "pnv-phb3-root-bus"
+
+#define TYPE_PNV_PHB3_ROOT_PORT "pnv-phb3-root-port"
+
+typedef struct PnvPHB3RootPort {
+ PCIESlot parent_obj;
+} PnvPHB3RootPort;
+
+/*
+ * PHB3 PCIe Host Bridge for PowerNV machines (POWER8)
+ */
+#define TYPE_PNV_PHB3 "pnv-phb3"
+OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB3, PNV_PHB3)
+
+#define PNV_PHB3_NUM_M64 16
+#define PNV_PHB3_NUM_REGS (0x1000 >> 3)
+#define PNV_PHB3_NUM_LSI 8
+#define PNV_PHB3_NUM_PE 256
+
+#define PCI_MMIO_TOTAL_SIZE (0x1ull << 60)
+
+struct PnvPHB3 {
+ PCIExpressHost parent_obj;
+
+ uint32_t chip_id;
+ uint32_t phb_id;
+ char bus_path[8];
+
+ uint64_t regs[PNV_PHB3_NUM_REGS];
+ MemoryRegion mr_regs;
+
+ MemoryRegion mr_m32;
+ MemoryRegion mr_m64[PNV_PHB3_NUM_M64];
+ MemoryRegion pci_mmio;
+ MemoryRegion pci_io;
+
+ uint64_t ioda_LIST[8];
+ uint64_t ioda_LXIVT[8];
+ uint64_t ioda_TVT[512];
+ uint64_t ioda_M64BT[16];
+ uint64_t ioda_MDT[256];
+ uint64_t ioda_PEEV[4];
+
+ uint32_t total_irq;
+ ICSState lsis;
+ qemu_irq *qirqs;
+ Phb3MsiState msis;
+
+ PnvPBCQState pbcq;
+
+ PnvPHB3RootPort root;
+
+ QLIST_HEAD(, PnvPhb3DMASpace) dma_spaces;
+};
+
+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);
+
+#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
new file mode 100644
index 000000000..a174ef1f7
--- /dev/null
+++ b/include/hw/pci-host/pnv_phb3_regs.h
@@ -0,0 +1,450 @@
+/*
+ * QEMU PowerPC PowerNV (POWER8) PHB3 model
+ *
+ * Copyright (c) 2013-2020, IBM Corporation.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+
+#ifndef PCI_HOST_PNV_PHB3_REGS_H
+#define PCI_HOST_PNV_PHB3_REGS_H
+
+#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
+ */
+
+#define PBCQ_NEST_IRSN_COMPARE 0x1a
+#define PBCQ_NEST_IRSN_COMP PPC_BITMASK(0, 18)
+#define PBCQ_NEST_IRSN_MASK 0x1b
+#define PBCQ_NEST_LSI_SRC_ID 0x1f
+#define PBCQ_NEST_LSI_SRC PPC_BITMASK(0, 7)
+#define PBCQ_NEST_REGS_COUNT 0x46
+#define PBCQ_NEST_MMIO_BAR0 0x40
+#define PBCQ_NEST_MMIO_BAR1 0x41
+#define PBCQ_NEST_PHB_BAR 0x42
+#define PBCQ_NEST_MMIO_MASK0 0x43
+#define PBCQ_NEST_MMIO_MASK1 0x44
+#define PBCQ_NEST_BAR_EN 0x45
+#define PBCQ_NEST_BAR_EN_MMIO0 PPC_BIT(0)
+#define PBCQ_NEST_BAR_EN_MMIO1 PPC_BIT(1)
+#define PBCQ_NEST_BAR_EN_PHB PPC_BIT(2)
+#define PBCQ_NEST_BAR_EN_IRSN_RX PPC_BIT(3)
+#define PBCQ_NEST_BAR_EN_IRSN_TX PPC_BIT(4)
+
+#define PBCQ_PCI_REGS_COUNT 0x15
+#define PBCQ_PCI_BAR2 0x0b
+
+#define PBCQ_SPCI_REGS_COUNT 0x5
+#define PBCQ_SPCI_ASB_ADDR 0x0
+#define PBCQ_SPCI_ASB_STATUS 0x1
+#define PBCQ_SPCI_ASB_DATA 0x2
+#define PBCQ_SPCI_AIB_CAPP_EN 0x3
+#define PBCQ_SPCI_CAPP_SEC_TMR 0x4
+
+/*
+ * PHB MMIO registers
+ */
+
+/* PHB Fundamental register set A */
+#define PHB_LSI_SOURCE_ID 0x100
+#define PHB_LSI_SRC_ID PPC_BITMASK(5, 12)
+#define PHB_DMA_CHAN_STATUS 0x110
+#define PHB_DMA_CHAN_ANY_ERR PPC_BIT(27)
+#define PHB_DMA_CHAN_ANY_ERR1 PPC_BIT(28)
+#define PHB_DMA_CHAN_ANY_FREEZE PPC_BIT(29)
+#define PHB_CPU_LOADSTORE_STATUS 0x120
+#define PHB_CPU_LS_ANY_ERR PPC_BIT(27)
+#define PHB_CPU_LS_ANY_ERR1 PPC_BIT(28)
+#define PHB_CPU_LS_ANY_FREEZE PPC_BIT(29)
+#define PHB_DMA_MSI_NODE_ID 0x128
+#define PHB_DMAMSI_NID_FIXED PPC_BIT(0)
+#define PHB_DMAMSI_NID PPC_BITMASK(24, 31)
+#define PHB_CONFIG_DATA 0x130
+#define PHB_LOCK0 0x138
+#define PHB_CONFIG_ADDRESS 0x140
+#define PHB_CA_ENABLE PPC_BIT(0)
+#define PHB_CA_BUS PPC_BITMASK(4, 11)
+#define PHB_CA_DEV PPC_BITMASK(12, 16)
+#define PHB_CA_FUNC PPC_BITMASK(17, 19)
+#define PHB_CA_REG PPC_BITMASK(20, 31)
+#define PHB_CA_PE PPC_BITMASK(40, 47)
+#define PHB_LOCK1 0x148
+#define PHB_IVT_BAR 0x150
+#define PHB_IVT_BAR_ENABLE PPC_BIT(0)
+#define PHB_IVT_BASE_ADDRESS_MASK PPC_BITMASK(14, 48)
+#define PHB_IVT_LENGTH_MASK PPC_BITMASK(52, 63)
+#define PHB_RBA_BAR 0x158
+#define PHB_RBA_BAR_ENABLE PPC_BIT(0)
+#define PHB_RBA_BASE_ADDRESS PPC_BITMASK(14, 55)
+#define PHB_PHB3_CONFIG 0x160
+#define PHB_PHB3C_64B_TCE_EN PPC_BIT(2)
+#define PHB_PHB3C_32BIT_MSI_EN PPC_BIT(8)
+#define PHB_PHB3C_64BIT_MSI_EN PPC_BIT(14)
+#define PHB_PHB3C_M32_EN PPC_BIT(16)
+#define PHB_RTT_BAR 0x168
+#define PHB_RTT_BAR_ENABLE PPC_BIT(0)
+#define PHB_RTT_BASE_ADDRESS_MASK PPC_BITMASK(14, 46)
+#define PHB_PELTV_BAR 0x188
+#define PHB_PELTV_BAR_ENABLE PPC_BIT(0)
+#define PHB_PELTV_BASE_ADDRESS PPC_BITMASK(14, 50)
+#define PHB_M32_BASE_ADDR 0x190
+#define PHB_M32_BASE_MASK 0x198
+#define PHB_M32_START_ADDR 0x1a0
+#define PHB_PEST_BAR 0x1a8
+#define PHB_PEST_BAR_ENABLE PPC_BIT(0)
+#define PHB_PEST_BASE_ADDRESS PPC_BITMASK(14, 51)
+#define PHB_M64_UPPER_BITS 0x1f0
+#define PHB_INTREP_TIMER 0x1f8
+#define PHB_DMARD_SYNC 0x200
+#define PHB_DMARD_SYNC_START PPC_BIT(0)
+#define PHB_DMARD_SYNC_COMPLETE PPC_BIT(1)
+#define PHB_RTC_INVALIDATE 0x208
+#define PHB_RTC_INVALIDATE_ALL PPC_BIT(0)
+#define PHB_RTC_INVALIDATE_RID PPC_BITMASK(16, 31)
+#define PHB_TCE_KILL 0x210
+#define PHB_TCE_KILL_ALL PPC_BIT(0)
+#define PHB_TCE_SPEC_CTL 0x218
+#define PHB_IODA_ADDR 0x220
+#define PHB_IODA_AD_AUTOINC PPC_BIT(0)
+#define PHB_IODA_AD_TSEL PPC_BITMASK(11, 15)
+#define PHB_IODA_AD_TADR PPC_BITMASK(55, 63)
+#define PHB_IODA_DATA0 0x228
+#define PHB_FFI_REQUEST 0x238
+#define PHB_FFI_LOCK_CLEAR PPC_BIT(3)
+#define PHB_FFI_REQUEST_ISN PPC_BITMASK(49, 59)
+#define PHB_FFI_LOCK 0x240
+#define PHB_FFI_LOCK_STATE PPC_BIT(0)
+#define PHB_XIVE_UPDATE 0x248 /* Broken in DD1 */
+#define PHB_PHB3_GEN_CAP 0x250
+#define PHB_PHB3_TCE_CAP 0x258
+#define PHB_PHB3_IRQ_CAP 0x260
+#define PHB_PHB3_EEH_CAP 0x268
+#define PHB_IVC_INVALIDATE 0x2a0
+#define PHB_IVC_INVALIDATE_ALL PPC_BIT(0)
+#define PHB_IVC_INVALIDATE_SID PPC_BITMASK(16, 31)
+#define PHB_IVC_UPDATE 0x2a8
+#define PHB_IVC_UPDATE_ENABLE_P PPC_BIT(0)
+#define PHB_IVC_UPDATE_ENABLE_Q PPC_BIT(1)
+#define PHB_IVC_UPDATE_ENABLE_SERVER PPC_BIT(2)
+#define PHB_IVC_UPDATE_ENABLE_PRI PPC_BIT(3)
+#define PHB_IVC_UPDATE_ENABLE_GEN PPC_BIT(4)
+#define PHB_IVC_UPDATE_ENABLE_CON PPC_BIT(5)
+#define PHB_IVC_UPDATE_GEN_MATCH PPC_BITMASK(6, 7)
+#define PHB_IVC_UPDATE_SERVER PPC_BITMASK(8, 23)
+#define PHB_IVC_UPDATE_PRI PPC_BITMASK(24, 31)
+#define PHB_IVC_UPDATE_GEN PPC_BITMASK(32, 33)
+#define PHB_IVC_UPDATE_P PPC_BITMASK(34, 34)
+#define PHB_IVC_UPDATE_Q PPC_BITMASK(35, 35)
+#define PHB_IVC_UPDATE_SID PPC_BITMASK(48, 63)
+#define PHB_PAPR_ERR_INJ_CTL 0x2b0
+#define PHB_PAPR_ERR_INJ_CTL_INB PPC_BIT(0)
+#define PHB_PAPR_ERR_INJ_CTL_OUTB PPC_BIT(1)
+#define PHB_PAPR_ERR_INJ_CTL_STICKY PPC_BIT(2)
+#define PHB_PAPR_ERR_INJ_CTL_CFG PPC_BIT(3)
+#define PHB_PAPR_ERR_INJ_CTL_RD PPC_BIT(4)
+#define PHB_PAPR_ERR_INJ_CTL_WR PPC_BIT(5)
+#define PHB_PAPR_ERR_INJ_CTL_FREEZE PPC_BIT(6)
+#define PHB_PAPR_ERR_INJ_ADDR 0x2b8
+#define PHB_PAPR_ERR_INJ_ADDR_MMIO PPC_BITMASK(16, 63)
+#define PHB_PAPR_ERR_INJ_MASK 0x2c0
+#define PHB_PAPR_ERR_INJ_MASK_CFG PPC_BITMASK(4, 11)
+#define PHB_PAPR_ERR_INJ_MASK_MMIO PPC_BITMASK(16, 63)
+#define PHB_ETU_ERR_SUMMARY 0x2c8
+
+/* UTL registers */
+#define UTL_SYS_BUS_CONTROL 0x400
+#define UTL_STATUS 0x408
+#define UTL_SYS_BUS_AGENT_STATUS 0x410
+#define UTL_SYS_BUS_AGENT_ERR_SEVERITY 0x418
+#define UTL_SYS_BUS_AGENT_IRQ_EN 0x420
+#define UTL_SYS_BUS_BURST_SZ_CONF 0x440
+#define UTL_REVISION_ID 0x448
+#define UTL_BCLK_DOMAIN_DBG1 0x460
+#define UTL_BCLK_DOMAIN_DBG2 0x468
+#define UTL_BCLK_DOMAIN_DBG3 0x470
+#define UTL_BCLK_DOMAIN_DBG4 0x478
+#define UTL_BCLK_DOMAIN_DBG5 0x480
+#define UTL_BCLK_DOMAIN_DBG6 0x488
+#define UTL_OUT_POST_HDR_BUF_ALLOC 0x4c0
+#define UTL_OUT_POST_DAT_BUF_ALLOC 0x4d0
+#define UTL_IN_POST_HDR_BUF_ALLOC 0x4e0
+#define UTL_IN_POST_DAT_BUF_ALLOC 0x4f0
+#define UTL_OUT_NP_BUF_ALLOC 0x500
+#define UTL_IN_NP_BUF_ALLOC 0x510
+#define UTL_PCIE_TAGS_ALLOC 0x520
+#define UTL_GBIF_READ_TAGS_ALLOC 0x530
+#define UTL_PCIE_PORT_CONTROL 0x540
+#define UTL_PCIE_PORT_STATUS 0x548
+#define UTL_PCIE_PORT_ERROR_SEV 0x550
+#define UTL_PCIE_PORT_IRQ_EN 0x558
+#define UTL_RC_STATUS 0x560
+#define UTL_RC_ERR_SEVERITY 0x568
+#define UTL_RC_IRQ_EN 0x570
+#define UTL_EP_STATUS 0x578
+#define UTL_EP_ERR_SEVERITY 0x580
+#define UTL_EP_ERR_IRQ_EN 0x588
+#define UTL_PCI_PM_CTRL1 0x590
+#define UTL_PCI_PM_CTRL2 0x598
+#define UTL_GP_CTL1 0x5a0
+#define UTL_GP_CTL2 0x5a8
+#define UTL_PCLK_DOMAIN_DBG1 0x5b0
+#define UTL_PCLK_DOMAIN_DBG2 0x5b8
+#define UTL_PCLK_DOMAIN_DBG3 0x5c0
+#define UTL_PCLK_DOMAIN_DBG4 0x5c8
+
+/* PCI-E Stack registers */
+#define PHB_PCIE_SYSTEM_CONFIG 0x600
+#define PHB_PCIE_BUS_NUMBER 0x608
+#define PHB_PCIE_SYSTEM_TEST 0x618
+#define PHB_PCIE_LINK_MANAGEMENT 0x630
+#define PHB_PCIE_LM_LINK_ACTIVE PPC_BIT(8)
+#define PHB_PCIE_DLP_TRAIN_CTL 0x640
+#define PHB_PCIE_DLP_TCTX_DISABLE PPC_BIT(1)
+#define PHB_PCIE_DLP_TCRX_DISABLED PPC_BIT(16)
+#define PHB_PCIE_DLP_INBAND_PRESENCE PPC_BIT(19)
+#define PHB_PCIE_DLP_TC_DL_LINKUP PPC_BIT(21)
+#define PHB_PCIE_DLP_TC_DL_PGRESET PPC_BIT(22)
+#define PHB_PCIE_DLP_TC_DL_LINKACT PPC_BIT(23)
+#define PHB_PCIE_SLOP_LOOPBACK_STATUS 0x648
+#define PHB_PCIE_SYS_LINK_INIT 0x668
+#define PHB_PCIE_UTL_CONFIG 0x670
+#define PHB_PCIE_DLP_CONTROL 0x678
+#define PHB_PCIE_UTL_ERRLOG1 0x680
+#define PHB_PCIE_UTL_ERRLOG2 0x688
+#define PHB_PCIE_UTL_ERRLOG3 0x690
+#define PHB_PCIE_UTL_ERRLOG4 0x698
+#define PHB_PCIE_DLP_ERRLOG1 0x6a0
+#define PHB_PCIE_DLP_ERRLOG2 0x6a8
+#define PHB_PCIE_DLP_ERR_STATUS 0x6b0
+#define PHB_PCIE_DLP_ERR_COUNTERS 0x6b8
+#define PHB_PCIE_UTL_ERR_INJECT 0x6c0
+#define PHB_PCIE_TLDLP_ERR_INJECT 0x6c8
+#define PHB_PCIE_LANE_EQ_CNTL0 0x6d0
+#define PHB_PCIE_LANE_EQ_CNTL1 0x6d8
+#define PHB_PCIE_LANE_EQ_CNTL2 0x6e0
+#define PHB_PCIE_LANE_EQ_CNTL3 0x6e8
+#define PHB_PCIE_STRAPPING 0x700
+
+/* Fundamental register set B */
+#define PHB_VERSION 0x800
+#define PHB_RESET 0x808
+#define PHB_CONTROL 0x810
+#define PHB_CTRL_IVE_128_BYTES PPC_BIT(24)
+#define PHB_AIB_RX_CRED_INIT_TIMER 0x818
+#define PHB_AIB_RX_CMD_CRED 0x820
+#define PHB_AIB_RX_DATA_CRED 0x828
+#define PHB_AIB_TX_CMD_CRED 0x830
+#define PHB_AIB_TX_DATA_CRED 0x838
+#define PHB_AIB_TX_CHAN_MAPPING 0x840
+#define PHB_AIB_TAG_ENABLE 0x858
+#define PHB_AIB_FENCE_CTRL 0x860
+#define PHB_TCE_TAG_ENABLE 0x868
+#define PHB_TCE_WATERMARK 0x870
+#define PHB_TIMEOUT_CTRL1 0x878
+#define PHB_TIMEOUT_CTRL2 0x880
+#define PHB_Q_DMA_R 0x888
+#define PHB_Q_DMA_R_QUIESCE_DMA PPC_BIT(0)
+#define PHB_Q_DMA_R_AUTORESET PPC_BIT(1)
+#define PHB_Q_DMA_R_DMA_RESP_STATUS PPC_BIT(4)
+#define PHB_Q_DMA_R_MMIO_RESP_STATUS PPC_BIT(5)
+#define PHB_Q_DMA_R_TCE_RESP_STATUS PPC_BIT(6)
+#define PHB_AIB_TAG_STATUS 0x900
+#define PHB_TCE_TAG_STATUS 0x908
+
+/* FIR & Error registers */
+#define PHB_LEM_FIR_ACCUM 0xc00
+#define PHB_LEM_FIR_AND_MASK 0xc08
+#define PHB_LEM_FIR_OR_MASK 0xc10
+#define PHB_LEM_ERROR_MASK 0xc18
+#define PHB_LEM_ERROR_AND_MASK 0xc20
+#define PHB_LEM_ERROR_OR_MASK 0xc28
+#define PHB_LEM_ACTION0 0xc30
+#define PHB_LEM_ACTION1 0xc38
+#define PHB_LEM_WOF 0xc40
+#define PHB_ERR_STATUS 0xc80
+#define PHB_ERR1_STATUS 0xc88
+#define PHB_ERR_INJECT 0xc90
+#define PHB_ERR_LEM_ENABLE 0xc98
+#define PHB_ERR_IRQ_ENABLE 0xca0
+#define PHB_ERR_FREEZE_ENABLE 0xca8
+#define PHB_ERR_AIB_FENCE_ENABLE 0xcb0
+#define PHB_ERR_LOG_0 0xcc0
+#define PHB_ERR_LOG_1 0xcc8
+#define PHB_ERR_STATUS_MASK 0xcd0
+#define PHB_ERR1_STATUS_MASK 0xcd8
+
+#define PHB_OUT_ERR_STATUS 0xd00
+#define PHB_OUT_ERR1_STATUS 0xd08
+#define PHB_OUT_ERR_INJECT 0xd10
+#define PHB_OUT_ERR_LEM_ENABLE 0xd18
+#define PHB_OUT_ERR_IRQ_ENABLE 0xd20
+#define PHB_OUT_ERR_FREEZE_ENABLE 0xd28
+#define PHB_OUT_ERR_AIB_FENCE_ENABLE 0xd30
+#define PHB_OUT_ERR_LOG_0 0xd40
+#define PHB_OUT_ERR_LOG_1 0xd48
+#define PHB_OUT_ERR_STATUS_MASK 0xd50
+#define PHB_OUT_ERR1_STATUS_MASK 0xd58
+
+#define PHB_INA_ERR_STATUS 0xd80
+#define PHB_INA_ERR1_STATUS 0xd88
+#define PHB_INA_ERR_INJECT 0xd90
+#define PHB_INA_ERR_LEM_ENABLE 0xd98
+#define PHB_INA_ERR_IRQ_ENABLE 0xda0
+#define PHB_INA_ERR_FREEZE_ENABLE 0xda8
+#define PHB_INA_ERR_AIB_FENCE_ENABLE 0xdb0
+#define PHB_INA_ERR_LOG_0 0xdc0
+#define PHB_INA_ERR_LOG_1 0xdc8
+#define PHB_INA_ERR_STATUS_MASK 0xdd0
+#define PHB_INA_ERR1_STATUS_MASK 0xdd8
+
+#define PHB_INB_ERR_STATUS 0xe00
+#define PHB_INB_ERR1_STATUS 0xe08
+#define PHB_INB_ERR_INJECT 0xe10
+#define PHB_INB_ERR_LEM_ENABLE 0xe18
+#define PHB_INB_ERR_IRQ_ENABLE 0xe20
+#define PHB_INB_ERR_FREEZE_ENABLE 0xe28
+#define PHB_INB_ERR_AIB_FENCE_ENABLE 0xe30
+#define PHB_INB_ERR_LOG_0 0xe40
+#define PHB_INB_ERR_LOG_1 0xe48
+#define PHB_INB_ERR_STATUS_MASK 0xe50
+#define PHB_INB_ERR1_STATUS_MASK 0xe58
+
+/* Performance monitor & Debug registers */
+#define PHB_TRACE_CONTROL 0xf80
+#define PHB_PERFMON_CONFIG 0xf88
+#define PHB_PERFMON_CTR0 0xf90
+#define PHB_PERFMON_CTR1 0xf98
+#define PHB_PERFMON_CTR2 0xfa0
+#define PHB_PERFMON_CTR3 0xfa8
+#define PHB_HOTPLUG_OVERRIDE 0xfb0
+#define PHB_HPOVR_FORCE_RESAMPLE PPC_BIT(9)
+#define PHB_HPOVR_PRESENCE_A PPC_BIT(10)
+#define PHB_HPOVR_PRESENCE_B PPC_BIT(11)
+#define PHB_HPOVR_LINK_ACTIVE PPC_BIT(12)
+#define PHB_HPOVR_LINK_BIFURCATED PPC_BIT(13)
+#define PHB_HPOVR_LINK_LANE_SWAPPED PPC_BIT(14)
+
+/*
+ * IODA2 on-chip tables
+ */
+
+#define IODA2_TBL_LIST 1
+#define IODA2_TBL_LXIVT 2
+#define IODA2_TBL_IVC_CAM 3
+#define IODA2_TBL_RBA 4
+#define IODA2_TBL_RCAM 5
+#define IODA2_TBL_MRT 6
+#define IODA2_TBL_PESTA 7
+#define IODA2_TBL_PESTB 8
+#define IODA2_TBL_TVT 9
+#define IODA2_TBL_TCAM 10
+#define IODA2_TBL_TDR 11
+#define IODA2_TBL_M64BT 16
+#define IODA2_TBL_M32DT 17
+#define IODA2_TBL_PEEV 20
+
+/* LXIVT */
+#define IODA2_LXIVT_SERVER PPC_BITMASK(8, 23)
+#define IODA2_LXIVT_PRIORITY PPC_BITMASK(24, 31)
+#define IODA2_LXIVT_NODE_ID PPC_BITMASK(56, 63)
+
+/* IVT */
+#define IODA2_IVT_SERVER PPC_BITMASK(0, 23)
+#define IODA2_IVT_PRIORITY PPC_BITMASK(24, 31)
+#define IODA2_IVT_GEN PPC_BITMASK(37, 38)
+#define IODA2_IVT_P PPC_BITMASK(39, 39)
+#define IODA2_IVT_Q PPC_BITMASK(47, 47)
+#define IODA2_IVT_PE PPC_BITMASK(48, 63)
+
+/* TVT */
+#define IODA2_TVT_TABLE_ADDR PPC_BITMASK(0, 47)
+#define IODA2_TVT_NUM_LEVELS PPC_BITMASK(48, 50)
+#define IODA2_TVE_1_LEVEL 0
+#define IODA2_TVE_2_LEVELS 1
+#define IODA2_TVE_3_LEVELS 2
+#define IODA2_TVE_4_LEVELS 3
+#define IODA2_TVE_5_LEVELS 4
+#define IODA2_TVT_TCE_TABLE_SIZE PPC_BITMASK(51, 55)
+#define IODA2_TVT_IO_PSIZE PPC_BITMASK(59, 63)
+
+/* PESTA */
+#define IODA2_PESTA_MMIO_FROZEN PPC_BIT(0)
+
+/* PESTB */
+#define IODA2_PESTB_DMA_STOPPED PPC_BIT(0)
+
+/* M32DT */
+#define IODA2_M32DT_PE PPC_BITMASK(8, 15)
+
+/* M64BT */
+#define IODA2_M64BT_ENABLE PPC_BIT(0)
+#define IODA2_M64BT_SINGLE_PE PPC_BIT(1)
+#define IODA2_M64BT_BASE PPC_BITMASK(2, 31)
+#define IODA2_M64BT_MASK PPC_BITMASK(34, 63)
+#define IODA2_M64BT_SINGLE_BASE PPC_BITMASK(2, 26)
+#define IODA2_M64BT_PE_HI PPC_BITMASK(27, 31)
+#define IODA2_M64BT_SINGLE_MASK PPC_BITMASK(34, 58)
+#define IODA2_M64BT_PE_LOW PPC_BITMASK(59, 63)
+
+/*
+ * IODA2 in-memory tables
+ */
+
+/*
+ * PEST
+ *
+ * 2x8 bytes entries, PEST0 and PEST1
+ */
+
+#define IODA2_PEST0_MMIO_CAUSE PPC_BIT(2)
+#define IODA2_PEST0_CFG_READ PPC_BIT(3)
+#define IODA2_PEST0_CFG_WRITE PPC_BIT(4)
+#define IODA2_PEST0_TTYPE PPC_BITMASK(5, 7)
+#define PEST_TTYPE_DMA_WRITE 0
+#define PEST_TTYPE_MSI 1
+#define PEST_TTYPE_DMA_READ 2
+#define PEST_TTYPE_DMA_READ_RESP 3
+#define PEST_TTYPE_MMIO_LOAD 4
+#define PEST_TTYPE_MMIO_STORE 5
+#define PEST_TTYPE_OTHER 7
+#define IODA2_PEST0_CA_RETURN PPC_BIT(8)
+#define IODA2_PEST0_UTL_RTOS_TIMEOUT PPC_BIT(8) /* Same bit as CA return */
+#define IODA2_PEST0_UR_RETURN PPC_BIT(9)
+#define IODA2_PEST0_UTL_NONFATAL PPC_BIT(10)
+#define IODA2_PEST0_UTL_FATAL PPC_BIT(11)
+#define IODA2_PEST0_PARITY_UE PPC_BIT(13)
+#define IODA2_PEST0_UTL_CORRECTABLE PPC_BIT(14)
+#define IODA2_PEST0_UTL_INTERRUPT PPC_BIT(15)
+#define IODA2_PEST0_MMIO_XLATE PPC_BIT(16)
+#define IODA2_PEST0_IODA2_ERROR PPC_BIT(16) /* Same bit as MMIO xlate */
+#define IODA2_PEST0_TCE_PAGE_FAULT PPC_BIT(18)
+#define IODA2_PEST0_TCE_ACCESS_FAULT PPC_BIT(19)
+#define IODA2_PEST0_DMA_RESP_TIMEOUT PPC_BIT(20)
+#define IODA2_PEST0_AIB_SIZE_INVALID PPC_BIT(21)
+#define IODA2_PEST0_LEM_BIT PPC_BITMASK(26, 31)
+#define IODA2_PEST0_RID PPC_BITMASK(32, 47)
+#define IODA2_PEST0_MSI_DATA PPC_BITMASK(48, 63)
+
+#define IODA2_PEST1_FAIL_ADDR PPC_BITMASK(3, 63)
+
+
+#endif /* PCI_HOST_PNV_PHB3_REGS_H */
diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h
new file mode 100644
index 000000000..27556ae53
--- /dev/null
+++ b/include/hw/pci-host/pnv_phb4.h
@@ -0,0 +1,224 @@
+/*
+ * QEMU PowerPC PowerNV (POWER9) PHB4 model
+ *
+ * Copyright (c) 2018-2020, IBM Corporation.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+
+#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/ppc/xive.h"
+#include "qom/object.h"
+
+typedef struct PnvPhb4PecStack PnvPhb4PecStack;
+typedef struct PnvPHB4 PnvPHB4;
+typedef struct PnvChip PnvChip;
+
+/*
+ * We have one such address space wrapper per possible device under
+ * the PHB since they need to be assigned statically at qemu device
+ * creation time. The relationship to a PE is done later
+ * dynamically. This means we can potentially create a lot of these
+ * guys. Q35 stores them as some kind of radix tree but we never
+ * really need to do fast lookups so instead we simply keep a QLIST of
+ * them for now, we can add the radix if needed later on.
+ *
+ * We do cache the PE number to speed things up a bit though.
+ */
+typedef struct PnvPhb4DMASpace {
+ PCIBus *bus;
+ uint8_t devfn;
+ int pe_num; /* Cached PE number */
+#define PHB_INVALID_PE (-1)
+ PnvPHB4 *phb;
+ AddressSpace dma_as;
+ IOMMUMemoryRegion dma_mr;
+ MemoryRegion msi32_mr;
+ MemoryRegion msi64_mr;
+ QLIST_ENTRY(PnvPhb4DMASpace) list;
+} PnvPhb4DMASpace;
+
+/*
+ * PHB4 PCIe Root port
+ */
+#define TYPE_PNV_PHB4_ROOT_BUS "pnv-phb4-root-bus"
+#define TYPE_PNV_PHB4_ROOT_PORT "pnv-phb4-root-port"
+
+typedef struct PnvPHB4RootPort {
+ PCIESlot parent_obj;
+} PnvPHB4RootPort;
+
+/*
+ * PHB4 PCIe Host Bridge for PowerNV machines (POWER9)
+ */
+#define TYPE_PNV_PHB4 "pnv-phb4"
+OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB4, PNV_PHB4)
+
+#define PNV_PHB4_MAX_LSIs 8
+#define PNV_PHB4_MAX_INTs 4096
+#define PNV_PHB4_MAX_MIST (PNV_PHB4_MAX_INTs >> 2)
+#define PNV_PHB4_MAX_MMIO_WINDOWS 32
+#define PNV_PHB4_MIN_MMIO_WINDOWS 16
+#define PNV_PHB4_NUM_REGS (0x3000 >> 3)
+#define PNV_PHB4_MAX_PEs 512
+#define PNV_PHB4_MAX_TVEs (PNV_PHB4_MAX_PEs * 2)
+#define PNV_PHB4_MAX_PEEVs (PNV_PHB4_MAX_PEs / 64)
+#define PNV_PHB4_MAX_MBEs (PNV_PHB4_MAX_MMIO_WINDOWS * 2)
+
+#define PNV_PHB4_VERSION 0x000000a400000002ull
+#define PNV_PHB4_DEVICE_ID 0x04c1
+
+#define PCI_MMIO_TOTAL_SIZE (0x1ull << 60)
+
+struct PnvPHB4 {
+ PCIExpressHost parent_obj;
+
+ PnvPHB4RootPort root;
+
+ uint32_t chip_id;
+ uint32_t phb_id;
+
+ uint64_t version;
+ uint16_t device_id;
+
+ char bus_path[8];
+
+ /* Main register images */
+ uint64_t regs[PNV_PHB4_NUM_REGS];
+ MemoryRegion mr_regs;
+
+ /* Extra SCOM-only register */
+ uint64_t scom_hv_ind_addr_reg;
+
+ /*
+ * Geometry of the PHB. There are two types, small and big PHBs, a
+ * number of resources (number of PEs, windows etc...) are doubled
+ * for a big PHB
+ */
+ bool big_phb;
+
+ /* Memory regions for MMIO space */
+ MemoryRegion mr_mmio[PNV_PHB4_MAX_MMIO_WINDOWS];
+
+ /* PCI side space */
+ MemoryRegion pci_mmio;
+ MemoryRegion pci_io;
+
+ /* On-chip IODA tables */
+ uint64_t ioda_LIST[PNV_PHB4_MAX_LSIs];
+ uint64_t ioda_MIST[PNV_PHB4_MAX_MIST];
+ uint64_t ioda_TVT[PNV_PHB4_MAX_TVEs];
+ uint64_t ioda_MBT[PNV_PHB4_MAX_MBEs];
+ uint64_t ioda_MDT[PNV_PHB4_MAX_PEs];
+ uint64_t ioda_PEEV[PNV_PHB4_MAX_PEEVs];
+
+ /*
+ * The internal PESTA/B is 2 bits per PE split into two tables, we
+ * store them in a single array here to avoid wasting space.
+ */
+ uint8_t ioda_PEST_AB[PNV_PHB4_MAX_PEs];
+
+ /* P9 Interrupt generation */
+ 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);
+extern const MemoryRegionOps pnv_phb4_xscom_ops;
+
+/*
+ * PHB4 PEC (PCI Express Controller)
+ */
+#define TYPE_PNV_PHB4_PEC "pnv-phb4-pec"
+OBJECT_DECLARE_TYPE(PnvPhb4PecState, PnvPhb4PecClass, PNV_PHB4_PEC)
+
+#define TYPE_PNV_PHB4_PEC_STACK "pnv-phb4-pec-stack"
+OBJECT_DECLARE_SIMPLE_TYPE(PnvPhb4PecStack, 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;
+};
+
+struct PnvPhb4PecState {
+ DeviceState parent;
+
+ /* PEC number in chip */
+ 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
+ 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];
+};
+
+
+struct PnvPhb4PecClass {
+ DeviceClass parent_class;
+
+ uint32_t (*xscom_nest_base)(PnvPhb4PecState *pec);
+ uint32_t xscom_nest_size;
+ uint32_t (*xscom_pci_base)(PnvPhb4PecState *pec);
+ uint32_t xscom_pci_size;
+ const char *compat;
+ int compat_size;
+ const char *stk_compat;
+ int stk_compat_size;
+};
+
+#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
new file mode 100644
index 000000000..55df2c3e5
--- /dev/null
+++ b/include/hw/pci-host/pnv_phb4_regs.h
@@ -0,0 +1,553 @@
+/*
+ * QEMU PowerPC PowerNV (POWER9) PHB4 model
+ *
+ * Copyright (c) 2013-2020, IBM Corporation.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+
+#ifndef PCI_HOST_PNV_PHB4_REGS_H
+#define PCI_HOST_PNV_PHB4_REGS_H
+
+/*
+ * PEC XSCOM registers
+ *
+ * There a 3 PECs in P9. Each PEC can have several PHBs. Each PEC has some
+ * "global" registers and some "per-stack" (per-PHB) registers. Those are
+ * organized in two XSCOM ranges, the "Nest" range and the "PCI" range, each
+ * range contains both some "PEC" registers and some "per-stack" registers.
+ *
+ * Finally the PCI range also contains an additional range per stack that
+ * passes through to some of the PHB own registers.
+ *
+ * PEC0 can contain 1 PHB (PHB0)
+ * PEC1 can contain 2 PHBs (PHB1 and PHB2)
+ * PEC2 can contain 3 PHBs (PHB3, PHB4 and PHB5)
+ */
+
+/*
+ * This is the "stack" offset, it's the offset from a given range base
+ * to the first "per-stack" registers and also the stride between
+ * stacks, thus for PEC2, the global registers are at offset 0, the
+ * PHB3 registers at offset 0x40, the PHB4 at offset 0x80 etc....
+ *
+ * It is *also* the offset to the pass-through SCOM region but in this case
+ * it is 0 based, ie PHB3 is at 0x100 PHB4 is a 0x140 etc..
+ */
+#define PEC_STACK_OFFSET 0x40
+
+/* XSCOM Nest global registers */
+#define PEC_NEST_PBCQ_HW_CONFIG 0x00
+#define PEC_NEST_DROP_PRIO_CTRL 0x01
+#define PEC_NEST_PBCQ_ERR_INJECT 0x02
+#define PEC_NEST_PCI_NEST_CLK_TRACE_CTL 0x03
+#define PEC_NEST_PBCQ_PMON_CTRL 0x04
+#define PEC_NEST_PBCQ_PBUS_ADDR_EXT 0x05
+#define PEC_NEST_PBCQ_PRED_VEC_TIMEOUT 0x06
+#define PEC_NEST_CAPP_CTRL 0x07
+#define PEC_NEST_PBCQ_READ_STK_OVR 0x08
+#define PEC_NEST_PBCQ_WRITE_STK_OVR 0x09
+#define PEC_NEST_PBCQ_STORE_STK_OVR 0x0a
+#define PEC_NEST_PBCQ_RETRY_BKOFF_CTRL 0x0b
+
+/* XSCOM Nest per-stack registers */
+#define PEC_NEST_STK_PCI_NEST_FIR 0x00
+#define PEC_NEST_STK_PCI_NEST_FIR_CLR 0x01
+#define PEC_NEST_STK_PCI_NEST_FIR_SET 0x02
+#define PEC_NEST_STK_PCI_NEST_FIR_MSK 0x03
+#define PEC_NEST_STK_PCI_NEST_FIR_MSKC 0x04
+#define PEC_NEST_STK_PCI_NEST_FIR_MSKS 0x05
+#define PEC_NEST_STK_PCI_NEST_FIR_ACT0 0x06
+#define PEC_NEST_STK_PCI_NEST_FIR_ACT1 0x07
+#define PEC_NEST_STK_PCI_NEST_FIR_WOF 0x08
+#define PEC_NEST_STK_ERR_REPORT_0 0x0a
+#define PEC_NEST_STK_ERR_REPORT_1 0x0b
+#define PEC_NEST_STK_PBCQ_GNRL_STATUS 0x0c
+#define PEC_NEST_STK_PBCQ_MODE 0x0d
+#define PEC_NEST_STK_MMIO_BAR0 0x0e
+#define PEC_NEST_STK_MMIO_BAR0_MASK 0x0f
+#define PEC_NEST_STK_MMIO_BAR1 0x10
+#define PEC_NEST_STK_MMIO_BAR1_MASK 0x11
+#define PEC_NEST_STK_PHB_REGS_BAR 0x12
+#define PEC_NEST_STK_INT_BAR 0x13
+#define PEC_NEST_STK_BAR_EN 0x14
+#define PEC_NEST_STK_BAR_EN_MMIO0 PPC_BIT(0)
+#define PEC_NEST_STK_BAR_EN_MMIO1 PPC_BIT(1)
+#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
+
+/* XSCOM PCI global registers */
+#define PEC_PCI_PBAIB_HW_CONFIG 0x00
+#define PEC_PCI_PBAIB_READ_STK_OVR 0x02
+
+/* XSCOM PCI per-stack registers */
+#define PEC_PCI_STK_PCI_FIR 0x00
+#define PEC_PCI_STK_PCI_FIR_CLR 0x01
+#define PEC_PCI_STK_PCI_FIR_SET 0x02
+#define PEC_PCI_STK_PCI_FIR_MSK 0x03
+#define PEC_PCI_STK_PCI_FIR_MSKC 0x04
+#define PEC_PCI_STK_PCI_FIR_MSKS 0x05
+#define PEC_PCI_STK_PCI_FIR_ACT0 0x06
+#define PEC_PCI_STK_PCI_FIR_ACT1 0x07
+#define PEC_PCI_STK_PCI_FIR_WOF 0x08
+#define PEC_PCI_STK_ETU_RESET 0x0a
+#define PEC_PCI_STK_PBAIB_ERR_REPORT 0x0b
+#define PEC_PCI_STK_PBAIB_TX_CMD_CRED 0x0d
+#define PEC_PCI_STK_PBAIB_TX_DAT_CRED 0x0e
+
+/*
+ * PHB "SCOM" registers. This is accessed via the above window
+ * and provides a backdoor to the PHB when the AIB bus is not
+ * functional. Some of these directly map some of the PHB MMIO
+ * registers, some are specific and allow indirect access to a
+ * wider range of PHB registers
+ */
+#define PHB_SCOM_HV_IND_ADDR 0x00
+#define PHB_SCOM_HV_IND_ADDR_VALID PPC_BIT(0)
+#define PHB_SCOM_HV_IND_ADDR_4B PPC_BIT(1)
+#define PHB_SCOM_HV_IND_ADDR_AUTOINC PPC_BIT(2)
+#define PHB_SCOM_HV_IND_ADDR_ADDR PPC_BITMASK(51, 63)
+#define PHB_SCOM_HV_IND_DATA 0x01
+#define PHB_SCOM_ETU_LEM_FIR 0x08
+#define PHB_SCOM_ETU_LEM_FIR_AND 0x09
+#define PHB_SCOM_ETU_LEM_FIR_OR 0x0a
+#define PHB_SCOM_ETU_LEM_FIR_MSK 0x0b
+#define PHB_SCOM_ETU_LEM_ERR_MSK_AND 0x0c
+#define PHB_SCOM_ETU_LEM_ERR_MSK_OR 0x0d
+#define PHB_SCOM_ETU_LEM_ACT0 0x0e
+#define PHB_SCOM_ETU_LEM_ACT1 0x0f
+#define PHB_SCOM_ETU_LEM_WOF 0x10
+#define PHB_SCOM_ETU_PMON_CONFIG 0x17
+#define PHB_SCOM_ETU_PMON_CTR0 0x18
+#define PHB_SCOM_ETU_PMON_CTR1 0x19
+#define PHB_SCOM_ETU_PMON_CTR2 0x1a
+#define PHB_SCOM_ETU_PMON_CTR3 0x1b
+
+
+/*
+ * PHB MMIO registers
+ */
+
+/* PHB Fundamental register set A */
+#define PHB_LSI_SOURCE_ID 0x100
+#define PHB_LSI_SRC_ID PPC_BITMASK(4, 12)
+#define PHB_DMA_CHAN_STATUS 0x110
+#define PHB_DMA_CHAN_ANY_ERR PPC_BIT(27)
+#define PHB_DMA_CHAN_ANY_ERR1 PPC_BIT(28)
+#define PHB_DMA_CHAN_ANY_FREEZE PPC_BIT(29)
+#define PHB_CPU_LOADSTORE_STATUS 0x120
+#define PHB_CPU_LS_ANY_ERR PPC_BIT(27)
+#define PHB_CPU_LS_ANY_ERR1 PPC_BIT(28)
+#define PHB_CPU_LS_ANY_FREEZE PPC_BIT(29)
+#define PHB_CONFIG_DATA 0x130
+#define PHB_LOCK0 0x138
+#define PHB_CONFIG_ADDRESS 0x140
+#define PHB_CA_ENABLE PPC_BIT(0)
+#define PHB_CA_STATUS PPC_BITMASK(1, 3)
+#define PHB_CA_STATUS_GOOD 0
+#define PHB_CA_STATUS_UR 1
+#define PHB_CA_STATUS_CRS 2
+#define PHB_CA_STATUS_CA 4
+#define PHB_CA_BUS PPC_BITMASK(4, 11)
+#define PHB_CA_DEV PPC_BITMASK(12, 16)
+#define PHB_CA_FUNC PPC_BITMASK(17, 19)
+#define PHB_CA_BDFN PPC_BITMASK(4, 19) /* bus,dev,func */
+#define PHB_CA_REG PPC_BITMASK(20, 31)
+#define PHB_CA_PE PPC_BITMASK(39, 47)
+#define PHB_LOCK1 0x148
+#define PHB_PHB4_CONFIG 0x160
+#define PHB_PHB4C_32BIT_MSI_EN PPC_BIT(8)
+#define PHB_PHB4C_64BIT_MSI_EN PPC_BIT(14)
+#define PHB_RTT_BAR 0x168
+#define PHB_RTT_BAR_ENABLE PPC_BIT(0)
+#define PHB_RTT_BASE_ADDRESS_MASK PPC_BITMASK(8, 46)
+#define PHB_PELTV_BAR 0x188
+#define PHB_PELTV_BAR_ENABLE PPC_BIT(0)
+#define PHB_PELTV_BASE_ADDRESS PPC_BITMASK(8, 50)
+#define PHB_M32_START_ADDR 0x1a0
+#define PHB_PEST_BAR 0x1a8
+#define PHB_PEST_BAR_ENABLE PPC_BIT(0)
+#define PHB_PEST_BASE_ADDRESS PPC_BITMASK(8, 51)
+#define PHB_ASN_CMPM 0x1C0
+#define PHB_ASN_CMPM_ENABLE PPC_BIT(63)
+#define PHB_CAPI_CMPM 0x1C8
+#define PHB_CAPI_CMPM_ENABLE PPC_BIT(63)
+#define PHB_M64_AOMASK 0x1d0
+#define PHB_M64_UPPER_BITS 0x1f0
+#define PHB_NXLATE_PREFIX 0x1f8
+#define PHB_DMARD_SYNC 0x200
+#define PHB_DMARD_SYNC_START PPC_BIT(0)
+#define PHB_DMARD_SYNC_COMPLETE PPC_BIT(1)
+#define PHB_RTC_INVALIDATE 0x208
+#define PHB_RTC_INVALIDATE_ALL PPC_BIT(0)
+#define PHB_RTC_INVALIDATE_RID PPC_BITMASK(16, 31)
+#define PHB_TCE_KILL 0x210
+#define PHB_TCE_KILL_ALL PPC_BIT(0)
+#define PHB_TCE_KILL_PE PPC_BIT(1)
+#define PHB_TCE_KILL_ONE PPC_BIT(2)
+#define PHB_TCE_KILL_PSEL PPC_BIT(3)
+#define PHB_TCE_KILL_64K 0x1000 /* Address override */
+#define PHB_TCE_KILL_2M 0x2000 /* Address override */
+#define PHB_TCE_KILL_1G 0x3000 /* Address override */
+#define PHB_TCE_KILL_PENUM PPC_BITMASK(55, 63)
+#define PHB_TCE_SPEC_CTL 0x218
+#define PHB_IODA_ADDR 0x220
+#define PHB_IODA_AD_AUTOINC PPC_BIT(0)
+#define PHB_IODA_AD_TSEL PPC_BITMASK(11, 15)
+#define PHB_IODA_AD_MIST_PWV PPC_BITMASK(28, 31)
+#define PHB_IODA_AD_TADR PPC_BITMASK(54, 63)
+#define PHB_IODA_DATA0 0x228
+#define PHB_PHB4_GEN_CAP 0x250
+#define PHB_PHB4_TCE_CAP 0x258
+#define PHB_PHB4_IRQ_CAP 0x260
+#define PHB_PHB4_EEH_CAP 0x268
+#define PHB_PAPR_ERR_INJ_CTL 0x2b0
+#define PHB_PAPR_ERR_INJ_CTL_INB PPC_BIT(0)
+#define PHB_PAPR_ERR_INJ_CTL_OUTB PPC_BIT(1)
+#define PHB_PAPR_ERR_INJ_CTL_STICKY PPC_BIT(2)
+#define PHB_PAPR_ERR_INJ_CTL_CFG PPC_BIT(3)
+#define PHB_PAPR_ERR_INJ_CTL_RD PPC_BIT(4)
+#define PHB_PAPR_ERR_INJ_CTL_WR PPC_BIT(5)
+#define PHB_PAPR_ERR_INJ_CTL_FREEZE PPC_BIT(6)
+#define PHB_PAPR_ERR_INJ_ADDR 0x2b8
+#define PHB_PAPR_ERR_INJ_ADDR_MMIO PPC_BITMASK(16, 63)
+#define PHB_PAPR_ERR_INJ_MASK 0x2c0
+#define PHB_PAPR_ERR_INJ_MASK_CFG PPC_BITMASK(4, 11)
+#define PHB_PAPR_ERR_INJ_MASK_CFG_ALL PPC_BITMASK(4, 19)
+#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_INDEX 0x308
+
+/* Fundamental register set B */
+#define PHB_VERSION 0x800
+#define PHB_CTRLR 0x810
+#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)
+#define PHB_CTRLR_MMIO_EEH_DISABLE PPC_BIT(14)
+#define PHB_CTRLR_CFG_EEH_BLOCK PPC_BIT(15)
+#define PHB_CTRLR_FENCE_LNKILL_DIS PPC_BIT(16)
+#define PHB_CTRLR_TVT_ADDR_SEL PPC_BITMASK(17, 19)
+#define TVT_DD1_1_PER_PE 0
+#define TVT_DD1_2_PER_PE 1
+#define TVT_DD1_4_PER_PE 2
+#define TVT_DD1_8_PER_PE 3
+#define TVT_DD1_16_PER_PE 4
+#define TVT_2_PER_PE 0
+#define TVT_4_PER_PE 1
+#define TVT_8_PER_PE 2
+#define TVT_16_PER_PE 3
+#define PHB_CTRLR_DMA_RD_SPACING PPC_BITMASK(28, 31)
+#define PHB_AIB_FENCE_CTRL 0x860
+#define PHB_TCE_TAG_ENABLE 0x868
+#define PHB_TCE_WATERMARK 0x870
+#define PHB_TIMEOUT_CTRL1 0x878
+#define PHB_TIMEOUT_CTRL2 0x880
+#define PHB_Q_DMA_R 0x888
+#define PHB_Q_DMA_R_QUIESCE_DMA PPC_BIT(0)
+#define PHB_Q_DMA_R_AUTORESET PPC_BIT(1)
+#define PHB_Q_DMA_R_DMA_RESP_STATUS PPC_BIT(4)
+#define PHB_Q_DMA_R_MMIO_RESP_STATUS PPC_BIT(5)
+#define PHB_Q_DMA_R_TCE_RESP_STATUS PPC_BIT(6)
+#define PHB_Q_DMA_R_TCE_KILL_STATUS PPC_BIT(7)
+#define PHB_TCE_TAG_STATUS 0x908
+
+/* FIR & Error registers */
+#define PHB_LEM_FIR_ACCUM 0xc00
+#define PHB_LEM_FIR_AND_MASK 0xc08
+#define PHB_LEM_FIR_OR_MASK 0xc10
+#define PHB_LEM_ERROR_MASK 0xc18
+#define PHB_LEM_ERROR_AND_MASK 0xc20
+#define PHB_LEM_ERROR_OR_MASK 0xc28
+#define PHB_LEM_ACTION0 0xc30
+#define PHB_LEM_ACTION1 0xc38
+#define PHB_LEM_WOF 0xc40
+#define PHB_ERR_STATUS 0xc80
+#define PHB_ERR1_STATUS 0xc88
+#define PHB_ERR_INJECT 0xc90
+#define PHB_ERR_LEM_ENABLE 0xc98
+#define PHB_ERR_IRQ_ENABLE 0xca0
+#define PHB_ERR_FREEZE_ENABLE 0xca8
+#define PHB_ERR_AIB_FENCE_ENABLE 0xcb0
+#define PHB_ERR_LOG_0 0xcc0
+#define PHB_ERR_LOG_1 0xcc8
+#define PHB_ERR_STATUS_MASK 0xcd0
+#define PHB_ERR1_STATUS_MASK 0xcd8
+
+#define PHB_TXE_ERR_STATUS 0xd00
+#define PHB_TXE_ERR1_STATUS 0xd08
+#define PHB_TXE_ERR_INJECT 0xd10
+#define PHB_TXE_ERR_LEM_ENABLE 0xd18
+#define PHB_TXE_ERR_IRQ_ENABLE 0xd20
+#define PHB_TXE_ERR_FREEZE_ENABLE 0xd28
+#define PHB_TXE_ERR_AIB_FENCE_ENABLE 0xd30
+#define PHB_TXE_ERR_LOG_0 0xd40
+#define PHB_TXE_ERR_LOG_1 0xd48
+#define PHB_TXE_ERR_STATUS_MASK 0xd50
+#define PHB_TXE_ERR1_STATUS_MASK 0xd58
+
+#define PHB_RXE_ARB_ERR_STATUS 0xd80
+#define PHB_RXE_ARB_ERR1_STATUS 0xd88
+#define PHB_RXE_ARB_ERR_INJECT 0xd90
+#define PHB_RXE_ARB_ERR_LEM_ENABLE 0xd98
+#define PHB_RXE_ARB_ERR_IRQ_ENABLE 0xda0
+#define PHB_RXE_ARB_ERR_FREEZE_ENABLE 0xda8
+#define PHB_RXE_ARB_ERR_AIB_FENCE_ENABLE 0xdb0
+#define PHB_RXE_ARB_ERR_LOG_0 0xdc0
+#define PHB_RXE_ARB_ERR_LOG_1 0xdc8
+#define PHB_RXE_ARB_ERR_STATUS_MASK 0xdd0
+#define PHB_RXE_ARB_ERR1_STATUS_MASK 0xdd8
+
+#define PHB_RXE_MRG_ERR_STATUS 0xe00
+#define PHB_RXE_MRG_ERR1_STATUS 0xe08
+#define PHB_RXE_MRG_ERR_INJECT 0xe10
+#define PHB_RXE_MRG_ERR_LEM_ENABLE 0xe18
+#define PHB_RXE_MRG_ERR_IRQ_ENABLE 0xe20
+#define PHB_RXE_MRG_ERR_FREEZE_ENABLE 0xe28
+#define PHB_RXE_MRG_ERR_AIB_FENCE_ENABLE 0xe30
+#define PHB_RXE_MRG_ERR_LOG_0 0xe40
+#define PHB_RXE_MRG_ERR_LOG_1 0xe48
+#define PHB_RXE_MRG_ERR_STATUS_MASK 0xe50
+#define PHB_RXE_MRG_ERR1_STATUS_MASK 0xe58
+
+#define PHB_RXE_TCE_ERR_STATUS 0xe80
+#define PHB_RXE_TCE_ERR1_STATUS 0xe88
+#define PHB_RXE_TCE_ERR_INJECT 0xe90
+#define PHB_RXE_TCE_ERR_LEM_ENABLE 0xe98
+#define PHB_RXE_TCE_ERR_IRQ_ENABLE 0xea0
+#define PHB_RXE_TCE_ERR_FREEZE_ENABLE 0xea8
+#define PHB_RXE_TCE_ERR_AIB_FENCE_ENABLE 0xeb0
+#define PHB_RXE_TCE_ERR_LOG_0 0xec0
+#define PHB_RXE_TCE_ERR_LOG_1 0xec8
+#define PHB_RXE_TCE_ERR_STATUS_MASK 0xed0
+#define PHB_RXE_TCE_ERR1_STATUS_MASK 0xed8
+
+/* Performance monitor & Debug registers */
+#define PHB_TRACE_CONTROL 0xf80
+#define PHB_PERFMON_CONFIG 0xf88
+#define PHB_PERFMON_CTR0 0xf90
+#define PHB_PERFMON_CTR1 0xf98
+#define PHB_PERFMON_CTR2 0xfa0
+#define PHB_PERFMON_CTR3 0xfa8
+
+/* Root complex config space memory mapped */
+#define PHB_RC_CONFIG_BASE 0x1000
+#define PHB_RC_CONFIG_SIZE 0x800
+
+/* PHB4 REGB registers */
+
+/* PBL core */
+#define PHB_PBL_CONTROL 0x1800
+#define PHB_PBL_TIMEOUT_CTRL 0x1810
+#define PHB_PBL_NPTAG_ENABLE 0x1820
+#define PHB_PBL_NBW_CMP_MASK 0x1830
+#define PHB_PBL_NBW_MASK_ENABLE PPC_BIT(63)
+#define PHB_PBL_SYS_LINK_INIT 0x1838
+#define PHB_PBL_BUF_STATUS 0x1840
+#define PHB_PBL_ERR_STATUS 0x1900
+#define PHB_PBL_ERR1_STATUS 0x1908
+#define PHB_PBL_ERR_INJECT 0x1910
+#define PHB_PBL_ERR_INF_ENABLE 0x1920
+#define PHB_PBL_ERR_ERC_ENABLE 0x1928
+#define PHB_PBL_ERR_FAT_ENABLE 0x1930
+#define PHB_PBL_ERR_LOG_0 0x1940
+#define PHB_PBL_ERR_LOG_1 0x1948
+#define PHB_PBL_ERR_STATUS_MASK 0x1950
+#define PHB_PBL_ERR1_STATUS_MASK 0x1958
+
+/* PCI-E stack */
+#define PHB_PCIE_SCR 0x1A00
+#define PHB_PCIE_SCR_SLOT_CAP PPC_BIT(15)
+#define PHB_PCIE_SCR_MAXLINKSPEED PPC_BITMASK(32, 35)
+
+
+#define PHB_PCIE_CRESET 0x1A10
+#define PHB_PCIE_CRESET_CFG_CORE PPC_BIT(0)
+#define PHB_PCIE_CRESET_TLDLP PPC_BIT(1)
+#define PHB_PCIE_CRESET_PBL PPC_BIT(2)
+#define PHB_PCIE_CRESET_PERST_N PPC_BIT(3)
+#define PHB_PCIE_CRESET_PIPE_N PPC_BIT(4)
+
+
+#define PHB_PCIE_HOTPLUG_STATUS 0x1A20
+#define PHB_PCIE_HPSTAT_PRESENCE PPC_BIT(10)
+
+#define PHB_PCIE_DLP_TRAIN_CTL 0x1A40
+#define PHB_PCIE_DLP_LINK_WIDTH PPC_BITMASK(30, 35)
+#define PHB_PCIE_DLP_LINK_SPEED PPC_BITMASK(36, 39)
+#define PHB_PCIE_DLP_LTSSM_TRC PPC_BITMASK(24, 27)
+#define PHB_PCIE_DLP_LTSSM_RESET 0
+#define PHB_PCIE_DLP_LTSSM_DETECT 1
+#define PHB_PCIE_DLP_LTSSM_POLLING 2
+#define PHB_PCIE_DLP_LTSSM_CONFIG 3
+#define PHB_PCIE_DLP_LTSSM_L0 4
+#define PHB_PCIE_DLP_LTSSM_REC 5
+#define PHB_PCIE_DLP_LTSSM_L1 6
+#define PHB_PCIE_DLP_LTSSM_L2 7
+#define PHB_PCIE_DLP_LTSSM_HOTRESET 8
+#define PHB_PCIE_DLP_LTSSM_DISABLED 9
+#define PHB_PCIE_DLP_LTSSM_LOOPBACK 10
+#define PHB_PCIE_DLP_TL_LINKACT PPC_BIT(23)
+#define PHB_PCIE_DLP_DL_PGRESET PPC_BIT(22)
+#define PHB_PCIE_DLP_TRAINING PPC_BIT(20)
+#define PHB_PCIE_DLP_INBAND_PRESENCE PPC_BIT(19)
+
+#define PHB_PCIE_DLP_CTL 0x1A78
+#define PHB_PCIE_DLP_CTL_BYPASS_PH2 PPC_BIT(4)
+#define PHB_PCIE_DLP_CTL_BYPASS_PH3 PPC_BIT(5)
+
+#define PHB_PCIE_DLP_TRWCTL 0x1A80
+#define PHB_PCIE_DLP_TRWCTL_EN PPC_BIT(0)
+
+#define PHB_PCIE_DLP_ERRLOG1 0x1AA0
+#define PHB_PCIE_DLP_ERRLOG2 0x1AA8
+#define PHB_PCIE_DLP_ERR_STATUS 0x1AB0
+#define PHB_PCIE_DLP_ERR_COUNTERS 0x1AB8
+
+#define PHB_PCIE_LANE_EQ_CNTL0 0x1AD0
+#define PHB_PCIE_LANE_EQ_CNTL1 0x1AD8
+#define PHB_PCIE_LANE_EQ_CNTL2 0x1AE0
+#define PHB_PCIE_LANE_EQ_CNTL3 0x1AE8
+#define PHB_PCIE_LANE_EQ_CNTL20 0x1AF0
+#define PHB_PCIE_LANE_EQ_CNTL21 0x1AF8
+#define PHB_PCIE_LANE_EQ_CNTL22 0x1B00 /* DD1 only */
+#define PHB_PCIE_LANE_EQ_CNTL23 0x1B08 /* DD1 only */
+#define PHB_PCIE_TRACE_CTRL 0x1B20
+#define PHB_PCIE_MISC_STRAP 0x1B30
+
+/* Error */
+#define PHB_REGB_ERR_STATUS 0x1C00
+#define PHB_REGB_ERR1_STATUS 0x1C08
+#define PHB_REGB_ERR_INJECT 0x1C10
+#define PHB_REGB_ERR_INF_ENABLE 0x1C20
+#define PHB_REGB_ERR_ERC_ENABLE 0x1C28
+#define PHB_REGB_ERR_FAT_ENABLE 0x1C30
+#define PHB_REGB_ERR_LOG_0 0x1C40
+#define PHB_REGB_ERR_LOG_1 0x1C48
+#define PHB_REGB_ERR_STATUS_MASK 0x1C50
+#define PHB_REGB_ERR1_STATUS_MASK 0x1C58
+
+/*
+ * IODA3 on-chip tables
+ */
+
+#define IODA3_TBL_LIST 1
+#define IODA3_TBL_MIST 2
+#define IODA3_TBL_RCAM 5
+#define IODA3_TBL_MRT 6
+#define IODA3_TBL_PESTA 7
+#define IODA3_TBL_PESTB 8
+#define IODA3_TBL_TVT 9
+#define IODA3_TBL_TCR 10
+#define IODA3_TBL_TDR 11
+#define IODA3_TBL_MBT 16
+#define IODA3_TBL_MDT 17
+#define IODA3_TBL_PEEV 20
+
+/* LIST */
+#define IODA3_LIST_P PPC_BIT(6)
+#define IODA3_LIST_Q PPC_BIT(7)
+#define IODA3_LIST_STATE PPC_BIT(14)
+
+/* MIST */
+#define IODA3_MIST_P3 PPC_BIT(48 + 0)
+#define IODA3_MIST_Q3 PPC_BIT(48 + 1)
+#define IODA3_MIST_PE3 PPC_BITMASK(48 + 4, 48 + 15)
+
+/* TVT */
+#define IODA3_TVT_TABLE_ADDR PPC_BITMASK(0, 47)
+#define IODA3_TVT_NUM_LEVELS PPC_BITMASK(48, 50)
+#define IODA3_TVE_1_LEVEL 0
+#define IODA3_TVE_2_LEVELS 1
+#define IODA3_TVE_3_LEVELS 2
+#define IODA3_TVE_4_LEVELS 3
+#define IODA3_TVE_5_LEVELS 4
+#define IODA3_TVT_TCE_TABLE_SIZE PPC_BITMASK(51, 55)
+#define IODA3_TVT_NON_TRANSLATE_50 PPC_BIT(56)
+#define IODA3_TVT_IO_PSIZE PPC_BITMASK(59, 63)
+
+/* PESTA */
+#define IODA3_PESTA_MMIO_FROZEN PPC_BIT(0)
+#define IODA3_PESTA_TRANS_TYPE PPC_BITMASK(5, 7)
+#define IODA3_PESTA_TRANS_TYPE_MMIOLOAD 0x4
+#define IODA3_PESTA_CA_CMPLT_TMT PPC_BIT(8)
+#define IODA3_PESTA_UR PPC_BIT(9)
+
+/* PESTB */
+#define IODA3_PESTB_DMA_STOPPED PPC_BIT(0)
+
+/* MDT */
+/* FIXME: check this field with Eric and add a B, C and D */
+#define IODA3_MDT_PE_A PPC_BITMASK(0, 15)
+#define IODA3_MDT_PE_B PPC_BITMASK(16, 31)
+#define IODA3_MDT_PE_C PPC_BITMASK(32, 47)
+#define IODA3_MDT_PE_D PPC_BITMASK(48, 63)
+
+/* MBT */
+#define IODA3_MBT0_ENABLE PPC_BIT(0)
+#define IODA3_MBT0_TYPE PPC_BIT(1)
+#define IODA3_MBT0_TYPE_M32 IODA3_MBT0_TYPE
+#define IODA3_MBT0_TYPE_M64 0
+#define IODA3_MBT0_MODE PPC_BITMASK(2, 3)
+#define IODA3_MBT0_MODE_PE_SEG 0
+#define IODA3_MBT0_MODE_MDT 1
+#define IODA3_MBT0_MODE_SINGLE_PE 2
+#define IODA3_MBT0_SEG_DIV PPC_BITMASK(4, 5)
+#define IODA3_MBT0_SEG_DIV_MAX 0
+#define IODA3_MBT0_SEG_DIV_128 1
+#define IODA3_MBT0_SEG_DIV_64 2
+#define IODA3_MBT0_SEG_DIV_8 3
+#define IODA3_MBT0_MDT_COLUMN PPC_BITMASK(4, 5)
+#define IODA3_MBT0_BASE_ADDR PPC_BITMASK(8, 51)
+
+#define IODA3_MBT1_ENABLE PPC_BIT(0)
+#define IODA3_MBT1_MASK PPC_BITMASK(8, 51)
+#define IODA3_MBT1_SEG_BASE PPC_BITMASK(55, 63)
+#define IODA3_MBT1_SINGLE_PE_NUM PPC_BITMASK(55, 63)
+
+/*
+ * IODA3 in-memory tables
+ */
+
+/*
+ * PEST
+ *
+ * 2x8 bytes entries, PEST0 and PEST1
+ */
+
+#define IODA3_PEST0_MMIO_CAUSE PPC_BIT(2)
+#define IODA3_PEST0_CFG_READ PPC_BIT(3)
+#define IODA3_PEST0_CFG_WRITE PPC_BIT(4)
+#define IODA3_PEST0_TTYPE PPC_BITMASK(5, 7)
+#define PEST_TTYPE_DMA_WRITE 0
+#define PEST_TTYPE_MSI 1
+#define PEST_TTYPE_DMA_READ 2
+#define PEST_TTYPE_DMA_READ_RESP 3
+#define PEST_TTYPE_MMIO_LOAD 4
+#define PEST_TTYPE_MMIO_STORE 5
+#define PEST_TTYPE_OTHER 7
+#define IODA3_PEST0_CA_RETURN PPC_BIT(8)
+#define IODA3_PEST0_UR_RETURN PPC_BIT(9)
+#define IODA3_PEST0_PCIE_NONFATAL PPC_BIT(10)
+#define IODA3_PEST0_PCIE_FATAL PPC_BIT(11)
+#define IODA3_PEST0_PARITY_UE PPC_BIT(13)
+#define IODA3_PEST0_PCIE_CORRECTABLE PPC_BIT(14)
+#define IODA3_PEST0_PCIE_INTERRUPT PPC_BIT(15)
+#define IODA3_PEST0_MMIO_XLATE PPC_BIT(16)
+#define IODA3_PEST0_IODA3_ERROR PPC_BIT(16) /* Same bit as MMIO xlate */
+#define IODA3_PEST0_TCE_PAGE_FAULT PPC_BIT(18)
+#define IODA3_PEST0_TCE_ACCESS_FAULT PPC_BIT(19)
+#define IODA3_PEST0_DMA_RESP_TIMEOUT PPC_BIT(20)
+#define IODA3_PEST0_AIB_SIZE_INVALID PPC_BIT(21)
+#define IODA3_PEST0_LEM_BIT PPC_BITMASK(26, 31)
+#define IODA3_PEST0_RID PPC_BITMASK(32, 47)
+#define IODA3_PEST0_MSI_DATA PPC_BITMASK(48, 63)
+
+#define IODA3_PEST1_FAIL_ADDR PPC_BITMASK(3, 63)
+
+
+#endif /* PCI_HOST_PNV_PHB4_REGS_H */
diff --git a/include/hw/pci-host/ppce500.h b/include/hw/pci-host/ppce500.h
new file mode 100644
index 000000000..e3a374230
--- /dev/null
+++ b/include/hw/pci-host/ppce500.h
@@ -0,0 +1,9 @@
+#ifndef PCI_HOST_PPCE500_H
+#define PCI_HOST_PPCE500_H
+
+static inline int ppce500_pci_map_irq_slot(int devno, int irq_num)
+{
+ return (devno + irq_num) % 4;
+}
+
+#endif
diff --git a/include/hw/pci-host/q35.h b/include/hw/pci-host/q35.h
new file mode 100644
index 000000000..ab989698e
--- /dev/null
+++ b/include/hw/pci-host/q35.h
@@ -0,0 +1,199 @@
+/*
+ * q35.h
+ *
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ * Copyright (C) 2012 Jason Baron <jbaron@redhat.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_Q35_H
+#define HW_Q35_H
+
+#include "hw/pci/pci.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"
+OBJECT_DECLARE_SIMPLE_TYPE(Q35PCIHost, Q35_HOST_DEVICE)
+
+#define TYPE_MCH_PCI_DEVICE "mch"
+OBJECT_DECLARE_SIMPLE_TYPE(MCHPCIState, MCH_PCI_DEVICE)
+
+struct MCHPCIState {
+ /*< private >*/
+ PCIDevice parent_obj;
+ /*< public >*/
+
+ MemoryRegion *ram_memory;
+ MemoryRegion *pci_address_space;
+ MemoryRegion *system_memory;
+ MemoryRegion *address_space_io;
+ 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;
+ 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;
+};
+
+struct Q35PCIHost {
+ /*< private >*/
+ PCIExpressHost parent_obj;
+ /*< public >*/
+
+ bool pci_hole64_fix;
+ MCHPCIState mch;
+};
+
+#define Q35_MASK(bit, ms_bit, ls_bit) \
+((uint##bit##_t)(((1ULL << ((ms_bit) + 1)) - 1) & ~((1ULL << ls_bit) - 1)))
+
+/*
+ * 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"
+
+#define MCH_HOST_BRIDGE_CONFIG_ADDR 0xcf8
+#define MCH_HOST_BRIDGE_CONFIG_DATA 0xcfc
+
+/* D0:F0 configuration space */
+#define MCH_HOST_BRIDGE_REVISION_DEFAULT 0x0
+
+#define MCH_HOST_BRIDGE_EXT_TSEG_MBYTES 0x50
+#define MCH_HOST_BRIDGE_EXT_TSEG_MBYTES_SIZE 2
+#define MCH_HOST_BRIDGE_EXT_TSEG_MBYTES_QUERY 0xffff
+#define MCH_HOST_BRIDGE_EXT_TSEG_MBYTES_MAX 0xfff
+
+#define MCH_HOST_BRIDGE_SMBASE_SIZE (128 * KiB)
+#define MCH_HOST_BRIDGE_SMBASE_ADDR 0x30000
+#define MCH_HOST_BRIDGE_F_SMBASE 0x9c
+#define MCH_HOST_BRIDGE_F_SMBASE_QUERY 0xff
+#define MCH_HOST_BRIDGE_F_SMBASE_IN_RAM 0x01
+#define MCH_HOST_BRIDGE_F_SMBASE_LCK 0x02
+
+#define MCH_HOST_BRIDGE_PCIEXBAR 0x60 /* 64bit register */
+#define MCH_HOST_BRIDGE_PCIEXBAR_SIZE 8 /* 64bit register */
+#define MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT 0xb0000000
+#define MCH_HOST_BRIDGE_PCIEXBAR_MAX (0x10000000) /* 256M */
+#define MCH_HOST_BRIDGE_PCIEXBAR_ADMSK Q35_MASK(64, 35, 28)
+#define MCH_HOST_BRIDGE_PCIEXBAR_128ADMSK ((uint64_t)(1 << 26))
+#define MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK ((uint64_t)(1 << 25))
+#define MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_MASK ((uint64_t)(0x3 << 1))
+#define MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_256M ((uint64_t)(0x0 << 1))
+#define MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_128M ((uint64_t)(0x1 << 1))
+#define MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_64M ((uint64_t)(0x2 << 1))
+#define MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_RVD ((uint64_t)(0x3 << 1))
+#define MCH_HOST_BRIDGE_PCIEXBAREN ((uint64_t)1)
+
+#define MCH_HOST_BRIDGE_PAM_NB 7
+#define MCH_HOST_BRIDGE_PAM_SIZE 7
+#define MCH_HOST_BRIDGE_PAM0 0x90
+#define MCH_HOST_BRIDGE_PAM_BIOS_AREA 0xf0000
+#define MCH_HOST_BRIDGE_PAM_AREA_SIZE 0x10000 /* 16KB */
+#define MCH_HOST_BRIDGE_PAM1 0x91
+#define MCH_HOST_BRIDGE_PAM_EXPAN_AREA 0xc0000
+#define MCH_HOST_BRIDGE_PAM_EXPAN_SIZE 0x04000
+#define MCH_HOST_BRIDGE_PAM2 0x92
+#define MCH_HOST_BRIDGE_PAM3 0x93
+#define MCH_HOST_BRIDGE_PAM4 0x94
+#define MCH_HOST_BRIDGE_PAM_EXBIOS_AREA 0xe0000
+#define MCH_HOST_BRIDGE_PAM_EXBIOS_SIZE 0x04000
+#define MCH_HOST_BRIDGE_PAM5 0x95
+#define MCH_HOST_BRIDGE_PAM6 0x96
+#define MCH_HOST_BRIDGE_PAM_WE_HI ((uint8_t)(0x2 << 4))
+#define MCH_HOST_BRIDGE_PAM_RE_HI ((uint8_t)(0x1 << 4))
+#define MCH_HOST_BRIDGE_PAM_HI_MASK ((uint8_t)(0x3 << 4))
+#define MCH_HOST_BRIDGE_PAM_WE_LO ((uint8_t)0x2)
+#define MCH_HOST_BRIDGE_PAM_RE_LO ((uint8_t)0x1)
+#define MCH_HOST_BRIDGE_PAM_LO_MASK ((uint8_t)0x3)
+#define MCH_HOST_BRIDGE_PAM_WE ((uint8_t)0x2)
+#define MCH_HOST_BRIDGE_PAM_RE ((uint8_t)0x1)
+#define MCH_HOST_BRIDGE_PAM_MASK ((uint8_t)0x3)
+
+#define MCH_HOST_BRIDGE_SMRAM 0x9d
+#define MCH_HOST_BRIDGE_SMRAM_SIZE 2
+#define MCH_HOST_BRIDGE_SMRAM_D_OPEN ((uint8_t)(1 << 6))
+#define MCH_HOST_BRIDGE_SMRAM_D_CLS ((uint8_t)(1 << 5))
+#define MCH_HOST_BRIDGE_SMRAM_D_LCK ((uint8_t)(1 << 4))
+#define MCH_HOST_BRIDGE_SMRAM_G_SMRAME ((uint8_t)(1 << 3))
+#define MCH_HOST_BRIDGE_SMRAM_C_BASE_SEG_MASK ((uint8_t)0x7)
+#define MCH_HOST_BRIDGE_SMRAM_C_BASE_SEG ((uint8_t)0x2) /* hardwired to b010 */
+#define MCH_HOST_BRIDGE_SMRAM_C_BASE 0xa0000
+#define MCH_HOST_BRIDGE_SMRAM_C_END 0xc0000
+#define MCH_HOST_BRIDGE_SMRAM_C_SIZE 0x20000
+#define MCH_HOST_BRIDGE_UPPER_SYSTEM_BIOS_END 0x100000
+#define MCH_HOST_BRIDGE_SMRAM_DEFAULT \
+ MCH_HOST_BRIDGE_SMRAM_C_BASE_SEG
+#define MCH_HOST_BRIDGE_SMRAM_WMASK \
+ (MCH_HOST_BRIDGE_SMRAM_D_OPEN | \
+ MCH_HOST_BRIDGE_SMRAM_D_CLS | \
+ MCH_HOST_BRIDGE_SMRAM_D_LCK | \
+ MCH_HOST_BRIDGE_SMRAM_G_SMRAME)
+#define MCH_HOST_BRIDGE_SMRAM_WMASK_LCK \
+ MCH_HOST_BRIDGE_SMRAM_D_CLS
+
+#define MCH_HOST_BRIDGE_ESMRAMC 0x9e
+#define MCH_HOST_BRIDGE_ESMRAMC_H_SMRAME ((uint8_t)(1 << 7))
+#define MCH_HOST_BRIDGE_ESMRAMC_E_SMERR ((uint8_t)(1 << 6))
+#define MCH_HOST_BRIDGE_ESMRAMC_SM_CACHE ((uint8_t)(1 << 5))
+#define MCH_HOST_BRIDGE_ESMRAMC_SM_L1 ((uint8_t)(1 << 4))
+#define MCH_HOST_BRIDGE_ESMRAMC_SM_L2 ((uint8_t)(1 << 3))
+#define MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_MASK ((uint8_t)(0x3 << 1))
+#define MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_1MB ((uint8_t)(0x0 << 1))
+#define MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_2MB ((uint8_t)(0x1 << 1))
+#define MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_8MB ((uint8_t)(0x2 << 1))
+#define MCH_HOST_BRIDGE_ESMRAMC_T_EN ((uint8_t)1)
+#define MCH_HOST_BRIDGE_ESMRAMC_DEFAULT \
+ (MCH_HOST_BRIDGE_ESMRAMC_SM_CACHE | \
+ MCH_HOST_BRIDGE_ESMRAMC_SM_L1 | \
+ MCH_HOST_BRIDGE_ESMRAMC_SM_L2)
+#define MCH_HOST_BRIDGE_ESMRAMC_WMASK \
+ (MCH_HOST_BRIDGE_ESMRAMC_H_SMRAME | \
+ MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_MASK | \
+ MCH_HOST_BRIDGE_ESMRAMC_T_EN)
+#define MCH_HOST_BRIDGE_ESMRAMC_WMASK_LCK 0
+
+/* D1:F0 PCIE* port*/
+#define MCH_PCIE_DEV 1
+#define MCH_PCIE_FUNC 0
+
+uint64_t mch_mcfg_base(void);
+
+/*
+ * Arbitrary but unique BNF number for IOAPIC device.
+ *
+ * TODO: make sure there would have no conflict with real PCI bus
+ */
+#define Q35_PSEUDO_BUS_PLATFORM (0xff)
+#define Q35_PSEUDO_DEVFN_IOAPIC (0x00)
+
+#endif /* HW_Q35_H */
diff --git a/include/hw/pci-host/remote.h b/include/hw/pci-host/remote.h
new file mode 100644
index 000000000..3dcf6aa51
--- /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 REMOTE_PCIHOST_H
+#define REMOTE_PCIHOST_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
new file mode 100644
index 000000000..01190241b
--- /dev/null
+++ b/include/hw/pci-host/sabre.h
@@ -0,0 +1,53 @@
+#ifndef HW_PCI_HOST_SABRE_H
+#define HW_PCI_HOST_SABRE_H
+
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "hw/sparc/sun4u_iommu.h"
+#include "qom/object.h"
+
+#define MAX_IVEC 0x40
+
+/* OBIO IVEC IRQs */
+#define OBIO_HDD_IRQ 0x20
+#define OBIO_NIC_IRQ 0x21
+#define OBIO_LPT_IRQ 0x22
+#define OBIO_FDD_IRQ 0x27
+#define OBIO_KBD_IRQ 0x29
+#define OBIO_MSE_IRQ 0x2a
+#define OBIO_SER_IRQ 0x2b
+
+struct SabrePCIState {
+ PCIDevice parent_obj;
+};
+
+#define TYPE_SABRE_PCI_DEVICE "sabre-pci"
+OBJECT_DECLARE_SIMPLE_TYPE(SabrePCIState, SABRE_PCI_DEVICE)
+
+struct SabreState {
+ PCIHostState parent_obj;
+
+ hwaddr special_base;
+ hwaddr mem_base;
+ MemoryRegion sabre_config;
+ MemoryRegion pci_config;
+ MemoryRegion pci_mmio;
+ MemoryRegion pci_ioport;
+ uint64_t pci_irq_in;
+ IOMMUState *iommu;
+ PCIBridge *bridgeA;
+ PCIBridge *bridgeB;
+ uint32_t pci_control[16];
+ uint32_t pci_irq_map[8];
+ uint32_t pci_err_irq_map[4];
+ uint32_t obio_irq_map[32];
+ qemu_irq ivec_irqs[MAX_IVEC];
+ unsigned int irq_request;
+ uint32_t reset_control;
+ unsigned int nr_resets;
+};
+
+#define TYPE_SABRE "sabre"
+OBJECT_DECLARE_SIMPLE_TYPE(SabreState, SABRE)
+
+#endif
diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
new file mode 100644
index 000000000..5b03a7b0e
--- /dev/null
+++ b/include/hw/pci-host/spapr.h
@@ -0,0 +1,215 @@
+/*
+ * QEMU SPAPR PCI BUS definitions
+ *
+ * Copyright (c) 2011 Alexey Kardashevskiy <aik@au1.ibm.com>
+ *
+ * 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 PCI_HOST_SPAPR_H
+#define PCI_HOST_SPAPR_H
+
+#include "hw/ppc/spapr.h"
+#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"
+
+OBJECT_DECLARE_SIMPLE_TYPE(SpaprPhbState, SPAPR_PCI_HOST_BRIDGE)
+
+#define SPAPR_PCI_DMA_MAX_WINDOWS 2
+
+
+typedef struct SpaprPciMsi {
+ uint32_t first_irq;
+ uint32_t num;
+} SpaprPciMsi;
+
+typedef struct SpaprPciMsiMig {
+ uint32_t key;
+ SpaprPciMsi value;
+} SpaprPciMsiMig;
+
+typedef struct SpaprPciLsi {
+ uint32_t irq;
+} SpaprPciLsi;
+
+typedef struct SpaprPhbPciNvGpuConfig SpaprPhbPciNvGpuConfig;
+
+struct SpaprPhbState {
+ PCIHostState parent_obj;
+
+ uint32_t index;
+ uint64_t buid;
+ char *dtbusname;
+ bool dr_enabled;
+
+ MemoryRegion memspace, iospace;
+ hwaddr mem_win_addr, mem_win_size, mem64_win_addr, mem64_win_size;
+ uint64_t mem64_win_pciaddr;
+ hwaddr io_win_addr, io_win_size;
+ MemoryRegion mem32window, mem64window, iowindow, msiwindow;
+
+ uint32_t dma_liobn[SPAPR_PCI_DMA_MAX_WINDOWS];
+ hwaddr dma_win_addr, dma_win_size;
+ AddressSpace iommu_as;
+ MemoryRegion iommu_root;
+
+ SpaprPciLsi lsi_table[PCI_NUM_PINS];
+
+ GHashTable *msi;
+ /* Temporary cache for migration purposes */
+ int32_t msi_devs_num;
+ SpaprPciMsiMig *msi_devs;
+
+ QLIST_ENTRY(SpaprPhbState) list;
+
+ bool ddw_enabled;
+ uint64_t page_size_mask;
+ uint64_t dma64_win_addr;
+
+ uint32_t numa_node;
+
+ bool pcie_ecs; /* Allow access to PCIe extended config space? */
+
+ /* Fields for migration compatibility hacks */
+ bool pre_2_8_migration;
+ 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;
+};
+
+#define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL
+#define SPAPR_PCI_MEM32_WIN_SIZE \
+ ((1ULL << 32) - SPAPR_PCI_MEM_WIN_BUS_OFFSET)
+#define SPAPR_PCI_MEM64_WIN_SIZE 0x10000000000ULL /* 1 TiB */
+
+/* All PCI outbound windows will be within this range */
+#define SPAPR_PCI_BASE (1ULL << 45) /* 32 TiB */
+#define SPAPR_PCI_LIMIT (1ULL << 46) /* 64 TiB */
+
+#define SPAPR_MAX_PHBS ((SPAPR_PCI_LIMIT - SPAPR_PCI_BASE) / \
+ SPAPR_PCI_MEM64_WIN_SIZE - 1)
+
+#define SPAPR_PCI_IO_WIN_SIZE 0x10000
+
+#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 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);
+
+void spapr_pci_rtas_init(void);
+
+SpaprPhbState *spapr_pci_find_phb(SpaprMachineState *spapr, uint64_t buid);
+PCIDevice *spapr_pci_find_dev(SpaprMachineState *spapr, uint64_t buid,
+ uint32_t config_addr);
+
+/* DRC callbacks */
+void spapr_phb_remove_pci_device_cb(DeviceState *dev);
+int spapr_pci_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
+ void *fdt, int *fdt_start_offset, Error **errp);
+
+/* VFIO EEH hooks */
+#ifdef CONFIG_LINUX
+bool spapr_phb_eeh_available(SpaprPhbState *sphb);
+int spapr_phb_vfio_eeh_set_option(SpaprPhbState *sphb,
+ unsigned int addr, int option);
+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)
+{
+ return false;
+}
+static inline int spapr_phb_vfio_eeh_set_option(SpaprPhbState *sphb,
+ unsigned int addr, int option)
+{
+ return RTAS_OUT_HW_ERROR;
+}
+static inline int spapr_phb_vfio_eeh_get_state(SpaprPhbState *sphb,
+ int *state)
+{
+ return RTAS_OUT_HW_ERROR;
+}
+static inline int spapr_phb_vfio_eeh_reset(SpaprPhbState *sphb, int option)
+{
+ return RTAS_OUT_HW_ERROR;
+}
+static inline int spapr_phb_vfio_eeh_configure(SpaprPhbState *sphb)
+{
+ return RTAS_OUT_HW_ERROR;
+}
+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);
+
+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
new file mode 100644
index 000000000..62bd81e72
--- /dev/null
+++ b/include/hw/pci-host/uninorth.h
@@ -0,0 +1,68 @@
+/*
+ * QEMU Uninorth PCI host (for all Mac99 and newer machines)
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * 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 UNINORTH_H
+#define UNINORTH_H
+
+#include "hw/pci/pci_host.h"
+#include "qom/object.h"
+
+/* UniNorth version */
+#define UNINORTH_VERSION_10A 0x7
+
+#define TYPE_UNI_NORTH_PCI_HOST_BRIDGE "uni-north-pci-pcihost"
+#define TYPE_UNI_NORTH_AGP_HOST_BRIDGE "uni-north-agp-pcihost"
+#define TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE "uni-north-internal-pci-pcihost"
+#define TYPE_U3_AGP_HOST_BRIDGE "u3-agp-pcihost"
+
+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)
+
+struct UNINHostState {
+ PCIHostState parent_obj;
+
+ uint32_t ofw_addr;
+ qemu_irq irqs[4];
+ MemoryRegion pci_mmio;
+ MemoryRegion pci_hole;
+ MemoryRegion pci_io;
+};
+
+struct UNINState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion mem;
+};
+
+#define TYPE_UNI_NORTH "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
new file mode 100644
index 000000000..89be88d87
--- /dev/null
+++ b/include/hw/pci-host/xilinx-pcie.h
@@ -0,0 +1,66 @@
+/*
+ * Xilinx PCIe host controller emulation.
+ *
+ * Copyright (c) 2016 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.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 HW_XILINX_PCIE_H
+#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"
+OBJECT_DECLARE_SIMPLE_TYPE(XilinxPCIEHost, XILINX_PCIE_HOST)
+
+#define TYPE_XILINX_PCIE_ROOT "xilinx-pcie-root"
+OBJECT_DECLARE_SIMPLE_TYPE(XilinxPCIERoot, XILINX_PCIE_ROOT)
+
+struct XilinxPCIERoot {
+ PCIBridge parent_obj;
+};
+
+typedef struct XilinxPCIEInt {
+ uint32_t fifo_reg1;
+ uint32_t fifo_reg2;
+} XilinxPCIEInt;
+
+struct XilinxPCIEHost {
+ PCIExpressHost parent_obj;
+
+ char name[16];
+
+ uint32_t bus_nr;
+ uint64_t cfg_base, cfg_size;
+ uint64_t mmio_base, mmio_size;
+ bool link_up;
+ qemu_irq irq;
+
+ MemoryRegion mmio, io;
+
+ XilinxPCIERoot root;
+
+ uint32_t intr;
+ uint32_t intr_mask;
+ XilinxPCIEInt intr_fifo[16];
+ unsigned int intr_fifo_r, intr_fifo_w;
+ uint32_t rpscr;
+};
+
+#endif /* HW_XILINX_PCIE_H */
diff --git a/include/hw/pci/msi.h b/include/hw/pci/msi.h
new file mode 100644
index 000000000..408768848
--- /dev/null
+++ b/include/hw/pci/msi.h
@@ -0,0 +1,52 @@
+/*
+ * msi.h
+ *
+ * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * 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 QEMU_MSI_H
+#define QEMU_MSI_H
+
+#include "hw/pci/pci.h"
+
+struct MSIMessage {
+ uint64_t address;
+ uint32_t data;
+};
+
+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);
+int msi_init(struct PCIDevice *dev, uint8_t offset,
+ unsigned int nr_vectors, bool msi64bit,
+ bool msi_per_vector_mask, Error **errp);
+void msi_uninit(struct PCIDevice *dev);
+void msi_reset(PCIDevice *dev);
+bool msi_is_masked(const PCIDevice *dev, unsigned int vector);
+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);
+
+static inline bool msi_present(const PCIDevice *dev)
+{
+ return dev->cap_present & QEMU_PCI_CAP_MSI;
+}
+
+#endif /* QEMU_MSI_H */
diff --git a/include/hw/pci/msix.h b/include/hw/pci/msix.h
new file mode 100644
index 000000000..4c4a60c73
--- /dev/null
+++ b/include/hw/pci/msix.h
@@ -0,0 +1,64 @@
+#ifndef QEMU_MSIX_H
+#define QEMU_MSIX_H
+
+#include "hw/pci/pci.h"
+
+#define MSIX_CAP_LENGTH 12
+
+void msix_set_message(PCIDevice *dev, int vector, MSIMessage msg);
+MSIMessage msix_get_message(PCIDevice *dev, unsigned int vector);
+int msix_init(PCIDevice *dev, unsigned short nentries,
+ MemoryRegion *table_bar, uint8_t table_bar_nr,
+ unsigned table_offset, MemoryRegion *pba_bar,
+ uint8_t pba_bar_nr, unsigned pba_offset, uint8_t cap_pos,
+ Error **errp);
+int msix_init_exclusive_bar(PCIDevice *dev, unsigned short nentries,
+ uint8_t bar_nr, Error **errp);
+
+void msix_write_config(PCIDevice *dev, uint32_t address, uint32_t val, int len);
+
+void msix_uninit(PCIDevice *dev, MemoryRegion *table_bar,
+ MemoryRegion *pba_bar);
+void msix_uninit_exclusive_bar(PCIDevice *dev);
+
+unsigned int msix_nr_vectors_allocated(const PCIDevice *dev);
+
+void msix_save(PCIDevice *dev, QEMUFile *f);
+void msix_load(PCIDevice *dev, QEMUFile *f);
+
+int msix_enabled(PCIDevice *dev);
+int msix_present(PCIDevice *dev);
+
+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_unuse(PCIDevice *dev, unsigned vector);
+void msix_unuse_all_vectors(PCIDevice *dev);
+
+void msix_notify(PCIDevice *dev, unsigned vector);
+
+void msix_reset(PCIDevice *dev);
+
+int msix_set_vector_notifiers(PCIDevice *dev,
+ MSIVectorUseNotifier use_notifier,
+ MSIVectorReleaseNotifier release_notifier,
+ MSIVectorPollNotifier poll_notifier);
+void msix_unset_vector_notifiers(PCIDevice *dev);
+
+extern const VMStateDescription vmstate_msix;
+
+#define VMSTATE_MSIX_TEST(_field, _state, _test) { \
+ .name = (stringify(_field)), \
+ .size = sizeof(PCIDevice), \
+ .vmsd = &vmstate_msix, \
+ .flags = VMS_STRUCT, \
+ .offset = vmstate_offset_value(_state, _field, PCIDevice), \
+ .field_exists = (_test) \
+}
+
+#define VMSTATE_MSIX(_f, _s) \
+ VMSTATE_MSIX_TEST(_f, _s, NULL)
+
+#endif
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
new file mode 100644
index 000000000..e7cdf2d5e
--- /dev/null
+++ b/include/hw/pci/pci.h
@@ -0,0 +1,914 @@
+#ifndef QEMU_PCI_H
+#define QEMU_PCI_H
+
+#include "exec/memory.h"
+#include "sysemu/dma.h"
+
+/* PCI includes legacy ISA access. */
+#include "hw/isa/isa.h"
+
+#include "hw/pci/pcie.h"
+#include "qom/object.h"
+
+extern bool pci_available;
+
+/* PCI bus */
+
+#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
+#define PCI_BUS_NUM(x) (((x) >> 8) & 0xff)
+#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
+#define PCI_FUNC(devfn) ((devfn) & 0x07)
+#define PCI_BUILD_BDF(bus, devfn) ((bus << 8) | (devfn))
+#define PCI_BUS_MAX 256
+#define PCI_DEVFN_MAX 256
+#define PCI_SLOT_MAX 32
+#define PCI_FUNC_MAX 8
+
+/* Class, Vendor and Device IDs from Linux's pci_ids.h */
+#include "hw/pci/pci_ids.h"
+
+/* QEMU-specific Vendor and Device ID definitions */
+
+/* IBM (0x1014) */
+#define PCI_DEVICE_ID_IBM_440GX 0x027f
+#define PCI_DEVICE_ID_IBM_OPENPIC2 0xffff
+
+/* Hitachi (0x1054) */
+#define PCI_VENDOR_ID_HITACHI 0x1054
+#define PCI_DEVICE_ID_HITACHI_SH7751R 0x350e
+
+/* Apple (0x106b) */
+#define PCI_DEVICE_ID_APPLE_343S1201 0x0010
+#define PCI_DEVICE_ID_APPLE_UNI_N_I_PCI 0x001e
+#define PCI_DEVICE_ID_APPLE_UNI_N_PCI 0x001f
+#define PCI_DEVICE_ID_APPLE_UNI_N_KEYL 0x0022
+#define PCI_DEVICE_ID_APPLE_IPID_USB 0x003f
+
+/* Realtek (0x10ec) */
+#define PCI_DEVICE_ID_REALTEK_8029 0x8029
+
+/* Xilinx (0x10ee) */
+#define PCI_DEVICE_ID_XILINX_XC2VP30 0x0300
+
+/* Marvell (0x11ab) */
+#define PCI_DEVICE_ID_MARVELL_GT6412X 0x4620
+
+/* QEMU/Bochs VGA (0x1234) */
+#define PCI_VENDOR_ID_QEMU 0x1234
+#define PCI_DEVICE_ID_QEMU_VGA 0x1111
+#define PCI_DEVICE_ID_QEMU_IPMI 0x1112
+
+/* VMWare (0x15ad) */
+#define PCI_VENDOR_ID_VMWARE 0x15ad
+#define PCI_DEVICE_ID_VMWARE_SVGA2 0x0405
+#define PCI_DEVICE_ID_VMWARE_SVGA 0x0710
+#define PCI_DEVICE_ID_VMWARE_NET 0x0720
+#define PCI_DEVICE_ID_VMWARE_SCSI 0x0730
+#define PCI_DEVICE_ID_VMWARE_PVSCSI 0x07C0
+#define PCI_DEVICE_ID_VMWARE_IDE 0x1729
+#define PCI_DEVICE_ID_VMWARE_VMXNET3 0x07B0
+
+/* Intel (0x8086) */
+#define PCI_DEVICE_ID_INTEL_82551IT 0x1209
+#define PCI_DEVICE_ID_INTEL_82557 0x1229
+#define PCI_DEVICE_ID_INTEL_82801IR 0x2922
+
+/* Red Hat / Qumranet (for QEMU) -- see pci-ids.txt */
+#define PCI_VENDOR_ID_REDHAT_QUMRANET 0x1af4
+#define PCI_SUBVENDOR_ID_REDHAT_QUMRANET 0x1af4
+#define PCI_SUBDEVICE_ID_QEMU 0x1100
+
+#define PCI_DEVICE_ID_VIRTIO_NET 0x1000
+#define PCI_DEVICE_ID_VIRTIO_BLOCK 0x1001
+#define PCI_DEVICE_ID_VIRTIO_BALLOON 0x1002
+#define PCI_DEVICE_ID_VIRTIO_CONSOLE 0x1003
+#define PCI_DEVICE_ID_VIRTIO_SCSI 0x1004
+#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
+
+#define PCI_VENDOR_ID_REDHAT 0x1b36
+#define PCI_DEVICE_ID_REDHAT_BRIDGE 0x0001
+#define PCI_DEVICE_ID_REDHAT_SERIAL 0x0002
+#define PCI_DEVICE_ID_REDHAT_SERIAL2 0x0003
+#define PCI_DEVICE_ID_REDHAT_SERIAL4 0x0004
+#define PCI_DEVICE_ID_REDHAT_TEST 0x0005
+#define PCI_DEVICE_ID_REDHAT_ROCKER 0x0006
+#define PCI_DEVICE_ID_REDHAT_SDHCI 0x0007
+#define PCI_DEVICE_ID_REDHAT_PCIE_HOST 0x0008
+#define PCI_DEVICE_ID_REDHAT_PXB 0x0009
+#define PCI_DEVICE_ID_REDHAT_BRIDGE_SEAT 0x000a
+#define PCI_DEVICE_ID_REDHAT_PXB_PCIE 0x000b
+#define PCI_DEVICE_ID_REDHAT_PCIE_RP 0x000c
+#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_QXL 0x0100
+
+#define FMT_PCIBUS PRIx64
+
+typedef uint64_t pcibus_t;
+
+struct PCIHostDeviceAddress {
+ unsigned int domain;
+ unsigned int bus;
+ unsigned int slot;
+ unsigned int function;
+};
+
+typedef void PCIConfigWriteFunc(PCIDevice *pci_dev,
+ uint32_t address, uint32_t data, int len);
+typedef uint32_t PCIConfigReadFunc(PCIDevice *pci_dev,
+ uint32_t address, int len);
+typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num,
+ pcibus_t addr, pcibus_t size, int type);
+typedef void PCIUnregisterFunc(PCIDevice *pci_dev);
+
+typedef struct PCIIORegion {
+ pcibus_t addr; /* current PCI mapping address. -1 means not mapped */
+#define PCI_BAR_UNMAPPED (~(pcibus_t)0)
+ pcibus_t size;
+ uint8_t type;
+ MemoryRegion *memory;
+ MemoryRegion *address_space;
+} PCIIORegion;
+
+#define PCI_ROM_SLOT 6
+#define PCI_NUM_REGIONS 7
+
+enum {
+ QEMU_PCI_VGA_MEM,
+ QEMU_PCI_VGA_IO_LO,
+ QEMU_PCI_VGA_IO_HI,
+ QEMU_PCI_VGA_NUM_REGIONS,
+};
+
+#define QEMU_PCI_VGA_MEM_BASE 0xa0000
+#define QEMU_PCI_VGA_MEM_SIZE 0x20000
+#define QEMU_PCI_VGA_IO_LO_BASE 0x3b0
+#define QEMU_PCI_VGA_IO_LO_SIZE 0xc
+#define QEMU_PCI_VGA_IO_HI_BASE 0x3c0
+#define QEMU_PCI_VGA_IO_HI_SIZE 0x20
+
+#include "hw/pci/pci_regs.h"
+
+/* PCI HEADER_TYPE */
+#define PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
+
+/* Size of the standard PCI config header */
+#define PCI_CONFIG_HEADER_SIZE 0x40
+/* Size of the standard PCI config space */
+#define PCI_CONFIG_SPACE_SIZE 0x100
+/* Size of the standard PCIe config space: 4KB */
+#define PCIE_CONFIG_SPACE_SIZE 0x1000
+
+#define PCI_NUM_PINS 4 /* A-D */
+
+/* Bits in cap_present field. */
+enum {
+ QEMU_PCI_CAP_MSI = 0x1,
+ QEMU_PCI_CAP_MSIX = 0x2,
+ QEMU_PCI_CAP_EXPRESS = 0x4,
+
+ /* multifunction capable device */
+#define QEMU_PCI_CAP_MULTIFUNCTION_BITNR 3
+ QEMU_PCI_CAP_MULTIFUNCTION = (1 << QEMU_PCI_CAP_MULTIFUNCTION_BITNR),
+
+ /* command register SERR bit enabled - unused since QEMU v5.0 */
+#define QEMU_PCI_CAP_SERR_BITNR 4
+ QEMU_PCI_CAP_SERR = (1 << QEMU_PCI_CAP_SERR_BITNR),
+ /* Standard hot plug controller. */
+#define QEMU_PCI_SHPC_BITNR 5
+ QEMU_PCI_CAP_SHPC = (1 << QEMU_PCI_SHPC_BITNR),
+#define QEMU_PCI_SLOTID_BITNR 6
+ QEMU_PCI_CAP_SLOTID = (1 << QEMU_PCI_SLOTID_BITNR),
+ /* PCI Express capability - Power Controller Present */
+#define QEMU_PCIE_SLTCAP_PCP_BITNR 7
+ QEMU_PCIE_SLTCAP_PCP = (1 << QEMU_PCIE_SLTCAP_PCP_BITNR),
+ /* Link active status in endpoint capability is always set */
+#define QEMU_PCIE_LNKSTA_DLLLA_BITNR 8
+ 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 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 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,
+ PCI_INTX_INVERTED,
+ PCI_INTX_DISABLED,
+ } mode;
+ int irq;
+} PCIINTxRoute;
+
+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;
+};
+
+typedef void (*PCIINTxRoutingNotifier)(PCIDevice *dev);
+typedef int (*MSIVectorUseNotifier)(PCIDevice *dev, unsigned int vector,
+ MSIMessage msg);
+typedef void (*MSIVectorReleaseNotifier)(PCIDevice *dev, unsigned int vector);
+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;
+ 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;
+ /* 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;
+};
+
+void pci_register_bar(PCIDevice *pci_dev, int region_num,
+ uint8_t attr, MemoryRegion *memory);
+void pci_register_vga(PCIDevice *pci_dev, MemoryRegion *mem,
+ MemoryRegion *io_lo, MemoryRegion *io_hi);
+void pci_unregister_vga(PCIDevice *pci_dev);
+pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num);
+
+int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
+ uint8_t offset, uint8_t size,
+ Error **errp);
+
+void pci_del_capability(PCIDevice *pci_dev, uint8_t cap_id, uint8_t cap_size);
+
+uint8_t pci_find_capability(PCIDevice *pci_dev, uint8_t cap_id);
+
+
+uint32_t pci_default_read_config(PCIDevice *d,
+ uint32_t address, int len);
+void pci_default_write_config(PCIDevice *d,
+ uint32_t address, uint32_t val, int len);
+void pci_device_save(PCIDevice *s, QEMUFile *f);
+int pci_device_load(PCIDevice *s, QEMUFile *f);
+MemoryRegion *pci_address_space(PCIDevice *dev);
+MemoryRegion *pci_address_space_io(PCIDevice *dev);
+
+/*
+ * Should not normally be used by devices. For use by sPAPR target
+ * where QEMU emulates firmware.
+ */
+int pci_bar(PCIDevice *d, int reg);
+
+typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level);
+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"
+OBJECT_DECLARE_TYPE(PCIBus, PCIBusClass, PCI_BUS)
+#define TYPE_PCIE_BUS "PCIE"
+
+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);
+
+void pci_root_bus_init(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);
+PCIBus *pci_root_bus_new(DeviceState *parent, const char *name,
+ MemoryRegion *address_space_mem,
+ MemoryRegion *address_space_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 *irq_opaque, int nirq);
+void pci_bus_irqs_cleanup(PCIBus *bus);
+int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
+/* 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD */
+static inline int pci_swizzle(int slot, int pin)
+{
+ return (slot + pin) % PCI_NUM_PINS;
+}
+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,
+ uint8_t devfn_min, int nirq,
+ const char *typename);
+void pci_unregister_root_bus(PCIBus *bus);
+void pci_bus_set_route_irq_fn(PCIBus *, pci_route_irq_fn);
+PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin);
+bool pci_intx_route_changed(PCIINTxRoute *old, PCIINTxRoute *new);
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus);
+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);
+
+PCIDevice *pci_vga_init(PCIBus *bus);
+
+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));
+}
+
+int pci_bus_numa_node(PCIBus *bus);
+void pci_for_each_device(PCIBus *bus, int bus_num,
+ pci_bus_dev_fn fn,
+ void *opaque);
+void pci_for_each_device_reverse(PCIBus *bus, int bus_num,
+ pci_bus_dev_fn fn,
+ void *opaque);
+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, 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);
+
+AddressSpace *pci_device_iommu_address_space(PCIDevice *dev);
+void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque);
+
+static inline void
+pci_set_byte(uint8_t *config, uint8_t val)
+{
+ *config = val;
+}
+
+static inline uint8_t
+pci_get_byte(const uint8_t *config)
+{
+ return *config;
+}
+
+static inline void
+pci_set_word(uint8_t *config, uint16_t val)
+{
+ stw_le_p(config, val);
+}
+
+static inline uint16_t
+pci_get_word(const uint8_t *config)
+{
+ return lduw_le_p(config);
+}
+
+static inline void
+pci_set_long(uint8_t *config, uint32_t val)
+{
+ stl_le_p(config, val);
+}
+
+static inline uint32_t
+pci_get_long(const uint8_t *config)
+{
+ return ldl_le_p(config);
+}
+
+/*
+ * PCI capabilities and/or their fields
+ * are generally DWORD aligned only so
+ * mechanism used by pci_set/get_quad()
+ * must be tolerant to unaligned pointers
+ *
+ */
+static inline void
+pci_set_quad(uint8_t *config, uint64_t val)
+{
+ stq_le_p(config, val);
+}
+
+static inline uint64_t
+pci_get_quad(const uint8_t *config)
+{
+ return ldq_le_p(config);
+}
+
+static inline void
+pci_config_set_vendor_id(uint8_t *pci_config, uint16_t val)
+{
+ pci_set_word(&pci_config[PCI_VENDOR_ID], val);
+}
+
+static inline void
+pci_config_set_device_id(uint8_t *pci_config, uint16_t val)
+{
+ pci_set_word(&pci_config[PCI_DEVICE_ID], val);
+}
+
+static inline void
+pci_config_set_revision(uint8_t *pci_config, uint8_t val)
+{
+ pci_set_byte(&pci_config[PCI_REVISION_ID], val);
+}
+
+static inline void
+pci_config_set_class(uint8_t *pci_config, uint16_t val)
+{
+ pci_set_word(&pci_config[PCI_CLASS_DEVICE], val);
+}
+
+static inline void
+pci_config_set_prog_interface(uint8_t *pci_config, uint8_t val)
+{
+ pci_set_byte(&pci_config[PCI_CLASS_PROG], val);
+}
+
+static inline void
+pci_config_set_interrupt_pin(uint8_t *pci_config, uint8_t val)
+{
+ pci_set_byte(&pci_config[PCI_INTERRUPT_PIN], val);
+}
+
+/*
+ * helper functions to do bit mask operation on configuration space.
+ * Just to set bit, use test-and-set and discard returned value.
+ * Just to clear bit, use test-and-clear and discard returned value.
+ * NOTE: They aren't atomic.
+ */
+static inline uint8_t
+pci_byte_test_and_clear_mask(uint8_t *config, uint8_t mask)
+{
+ uint8_t val = pci_get_byte(config);
+ pci_set_byte(config, val & ~mask);
+ return val & mask;
+}
+
+static inline uint8_t
+pci_byte_test_and_set_mask(uint8_t *config, uint8_t mask)
+{
+ uint8_t val = pci_get_byte(config);
+ pci_set_byte(config, val | mask);
+ return val & mask;
+}
+
+static inline uint16_t
+pci_word_test_and_clear_mask(uint8_t *config, uint16_t mask)
+{
+ uint16_t val = pci_get_word(config);
+ pci_set_word(config, val & ~mask);
+ return val & mask;
+}
+
+static inline uint16_t
+pci_word_test_and_set_mask(uint8_t *config, uint16_t mask)
+{
+ uint16_t val = pci_get_word(config);
+ pci_set_word(config, val | mask);
+ return val & mask;
+}
+
+static inline uint32_t
+pci_long_test_and_clear_mask(uint8_t *config, uint32_t mask)
+{
+ uint32_t val = pci_get_long(config);
+ pci_set_long(config, val & ~mask);
+ return val & mask;
+}
+
+static inline uint32_t
+pci_long_test_and_set_mask(uint8_t *config, uint32_t mask)
+{
+ uint32_t val = pci_get_long(config);
+ pci_set_long(config, val | mask);
+ return val & mask;
+}
+
+static inline uint64_t
+pci_quad_test_and_clear_mask(uint8_t *config, uint64_t mask)
+{
+ uint64_t val = pci_get_quad(config);
+ pci_set_quad(config, val & ~mask);
+ return val & mask;
+}
+
+static inline uint64_t
+pci_quad_test_and_set_mask(uint8_t *config, uint64_t mask)
+{
+ uint64_t val = pci_get_quad(config);
+ pci_set_quad(config, val | mask);
+ return val & mask;
+}
+
+/* Access a register specified by a mask */
+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));
+}
+
+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);
+}
+
+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));
+}
+
+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);
+}
+
+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));
+}
+
+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);
+}
+
+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));
+}
+
+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);
+}
+
+PCIDevice *pci_new_multifunction(int devfn, bool multifunction,
+ 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);
+
+void lsi53c8xx_handle_legacy_cmdline(DeviceState *lsi_dev);
+
+qemu_irq pci_allocate_irq(PCIDevice *pci_dev);
+void pci_set_irq(PCIDevice *pci_dev, int level);
+
+static inline void pci_irq_assert(PCIDevice *pci_dev)
+{
+ pci_set_irq(pci_dev, 1);
+}
+
+static inline void pci_irq_deassert(PCIDevice *pci_dev)
+{
+ pci_set_irq(pci_dev, 0);
+}
+
+/*
+ * FIXME: PCI does not work this way.
+ * All the callers to this method should be fixed.
+ */
+static inline void pci_irq_pulse(PCIDevice *pci_dev)
+{
+ pci_irq_assert(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;
+}
+
+/**
+ * pci_dma_rw: Read from or write to an address space from PCI device.
+ *
+ * Return a MemTxResult indicating whether the operation succeeded
+ * or failed (eg unassigned memory, device rejected the transaction,
+ * IOMMU fault).
+ *
+ * @dev: #PCIDevice doing the memory access
+ * @addr: address within the #PCIDevice address space
+ * @buf: buffer with the data transferred
+ * @len: the number of bytes to read or write
+ * @dir: indicates the transfer direction
+ */
+static inline MemTxResult pci_dma_rw(PCIDevice *dev, dma_addr_t addr,
+ void *buf, dma_addr_t len,
+ DMADirection dir)
+{
+ return dma_memory_rw(pci_get_address_space(dev), addr, buf, len, dir);
+}
+
+/**
+ * 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);
+}
+
+/**
+ * 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);
+}
+
+#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
new file mode 100644
index 000000000..a94d35003
--- /dev/null
+++ b/include/hw/pci/pci_bridge.h
@@ -0,0 +1,158 @@
+/*
+ * QEMU PCI bridge
+ *
+ * Copyright (c) 2004 Fabrice Bellard
+ *
+ * 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, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * split out pci bus specific stuff from pci.[hc] to pci_bridge.[hc]
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ */
+
+#ifndef QEMU_PCI_BRIDGE_H
+#define QEMU_PCI_BRIDGE_H
+
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
+#include "qom/object.h"
+
+typedef struct PCIBridgeWindows PCIBridgeWindows;
+
+/*
+ * Aliases for each of the address space windows that the bridge
+ * can forward. Mapped into the bridge's parent's address space,
+ * as subregions.
+ */
+struct PCIBridgeWindows {
+ MemoryRegion alias_pref_mem;
+ MemoryRegion alias_mem;
+ MemoryRegion alias_io;
+ /*
+ * When bridge control VGA forwarding is enabled, bridges will
+ * provide positive decode on the PCI VGA defined I/O port and
+ * MMIO ranges. When enabled forwarding is only qualified on the
+ * I/O and memory enable bits in the bridge command register.
+ */
+ MemoryRegion alias_vga[QEMU_PCI_VGA_NUM_REGIONS];
+};
+
+#define TYPE_PCI_BRIDGE "base-pci-bridge"
+OBJECT_DECLARE_SIMPLE_TYPE(PCIBridge, PCI_BRIDGE)
+
+struct PCIBridge {
+ /*< private >*/
+ PCIDevice parent_obj;
+ /*< public >*/
+
+ /* private member */
+ PCIBus sec_bus;
+ /*
+ * Memory regions for the bridge's address spaces. These regions are not
+ * directly added to system_memory/system_io or its descendants.
+ * Bridge's secondary bus points to these, so that devices
+ * under the bridge see these regions as its address spaces.
+ * The regions are as large as the entire address space -
+ * they don't take into account any windows.
+ */
+ MemoryRegion address_space_mem;
+ MemoryRegion address_space_io;
+
+ PCIBridgeWindows *windows;
+
+ pci_map_irq_fn map_irq;
+ const char *bus_name;
+};
+
+#define PCI_BRIDGE_DEV_PROP_CHASSIS_NR "chassis_nr"
+#define PCI_BRIDGE_DEV_PROP_MSI "msi"
+#define PCI_BRIDGE_DEV_PROP_SHPC "shpc"
+
+int pci_bridge_ssvid_init(PCIDevice *dev, uint8_t offset,
+ uint16_t svid, uint16_t ssid,
+ Error **errp);
+
+PCIDevice *pci_bridge_get_device(PCIBus *bus);
+PCIBus *pci_bridge_get_sec_bus(PCIBridge *br);
+
+pcibus_t pci_bridge_get_base(const PCIDevice *bridge, uint8_t type);
+pcibus_t pci_bridge_get_limit(const PCIDevice *bridge, uint8_t type);
+
+void pci_bridge_update_mappings(PCIBridge *br);
+void pci_bridge_write_config(PCIDevice *d,
+ uint32_t address, uint32_t val, int len);
+void pci_bridge_disable_base_limit(PCIDevice *dev);
+void pci_bridge_reset(DeviceState *qdev);
+
+void pci_bridge_initfn(PCIDevice *pci_dev, const char *typename);
+void pci_bridge_exitfn(PCIDevice *pci_dev);
+
+void pci_bridge_dev_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+ Error **errp);
+void pci_bridge_dev_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+ Error **errp);
+void pci_bridge_dev_unplug_request_cb(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp);
+
+/*
+ * before qdev initialization(qdev_init()), this function sets bus_name and
+ * map_irq callback which are necessary for pci_bridge_initfn() to
+ * initialize bus.
+ */
+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 */
+
+typedef struct PCIBridgeQemuCap {
+ uint8_t id; /* Standard PCI capability header field */
+ uint8_t next; /* Standard PCI capability header field */
+ uint8_t len; /* Standard PCI vendor-specific capability header field */
+ uint8_t type; /* Red Hat vendor-specific capability type.
+ Types are defined with REDHAT_PCI_CAP_ prefix */
+
+ uint32_t bus_res; /* Minimum number of buses to reserve */
+ uint64_t io; /* IO space to reserve */
+ uint32_t mem; /* Non-prefetchable memory to reserve */
+ /* At most one of the following two fields may be set to a value
+ * different from -1 */
+ uint32_t mem_pref_32; /* Prefetchable memory to reserve (32-bit MMIO) */
+ uint64_t mem_pref_64; /* Prefetchable memory to reserve (64-bit MMIO) */
+} PCIBridgeQemuCap;
+
+#define REDHAT_PCI_CAP_RESOURCE_RESERVE 1
+
+/*
+ * PCI BUS/IO/MEM/PREFMEM additional resources recorded as a
+ * capability in PCI configuration space to reserve on firmware init.
+ */
+typedef struct PCIResReserve {
+ uint32_t bus;
+ uint64_t io;
+ uint64_t mem_non_pref;
+ uint64_t mem_pref_32;
+ uint64_t mem_pref_64;
+} PCIResReserve;
+
+int pci_bridge_qemu_reserve_cap_init(PCIDevice *dev, int cap_offset,
+ PCIResReserve res_reserve, Error **errp);
+
+#endif /* QEMU_PCI_BRIDGE_H */
diff --git a/include/hw/pci/pci_bus.h b/include/hw/pci/pci_bus.h
new file mode 100644
index 000000000..347440d42
--- /dev/null
+++ b/include/hw/pci/pci_bus.h
@@ -0,0 +1,66 @@
+#ifndef QEMU_PCI_BUS_H
+#define QEMU_PCI_BUS_H
+
+#include "hw/pci/pci.h"
+
+/*
+ * PCI Bus datastructures.
+ *
+ * Do not access the following members directly;
+ * use accessor functions in pci.h
+ */
+
+struct PCIBusClass {
+ /*< private >*/
+ BusClass parent_class;
+ /*< public >*/
+
+ int (*bus_num)(PCIBus *bus);
+ uint16_t (*numa_node)(PCIBus *bus);
+};
+
+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,
+};
+
+struct PCIBus {
+ BusState qbus;
+ enum PCIBusFlags flags;
+ PCIIOMMUFunc iommu_fn;
+ void *iommu_opaque;
+ uint8_t devfn_min;
+ uint32_t slot_reserved_mask;
+ pci_set_irq_fn set_irq;
+ pci_map_irq_fn map_irq;
+ pci_route_irq_fn route_intx_to_irq;
+ void *irq_opaque;
+ PCIDevice *devices[PCI_SLOT_MAX * PCI_FUNC_MAX];
+ PCIDevice *parent_dev;
+ MemoryRegion *address_space_mem;
+ MemoryRegion *address_space_io;
+
+ QLIST_HEAD(, PCIBus) child; /* this will be replaced by qdev later */
+ QLIST_ENTRY(PCIBus) sibling;/* this will be replaced by qdev later */
+
+ /* The bus IRQ state is the logical OR of the connected devices.
+ Keep a count of the number of devices with raised IRQs. */
+ int nirq;
+ int *irq_count;
+
+ Notifier machine_done;
+};
+
+static inline bool pci_bus_is_root(PCIBus *bus)
+{
+ return !!(bus->flags & PCI_BUS_IS_ROOT);
+}
+
+static inline bool pci_bus_allows_extended_config_space(PCIBus *bus)
+{
+ return !!(bus->flags & PCI_BUS_EXTENDED_CONFIG_SPACE);
+}
+
+#endif /* QEMU_PCI_BUS_H */
diff --git a/include/hw/pci/pci_host.h b/include/hw/pci/pci_host.h
new file mode 100644
index 000000000..c6f4eb458
--- /dev/null
+++ b/include/hw/pci/pci_host.h
@@ -0,0 +1,71 @@
+/*
+ * QEMU Common PCI Host bridge configuration data space access routines.
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * 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.
+ */
+
+/* Worker routines for a PCI host controller that uses an {address,data}
+ register pair to access PCI configuration space. */
+
+#ifndef PCI_HOST_H
+#define PCI_HOST_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_PCI_HOST_BRIDGE "pci-host-bridge"
+OBJECT_DECLARE_TYPE(PCIHostState, PCIHostBridgeClass, PCI_HOST_BRIDGE)
+
+struct PCIHostState {
+ SysBusDevice busdev;
+
+ MemoryRegion conf_mem;
+ MemoryRegion data_mem;
+ MemoryRegion mmcfg;
+ uint32_t config_reg;
+ bool mig_enabled;
+ PCIBus *bus;
+ bool bypass_iommu;
+
+ QLIST_ENTRY(PCIHostState) next;
+};
+
+struct PCIHostBridgeClass {
+ SysBusDeviceClass parent_class;
+
+ const char *(*root_bus_path)(PCIHostState *, PCIBus *);
+};
+
+/* common internal helpers for PCI/PCIe hosts, cut off overflows */
+void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr,
+ uint32_t limit, uint32_t val, uint32_t len);
+uint32_t pci_host_config_read_common(PCIDevice *pci_dev, uint32_t addr,
+ uint32_t limit, uint32_t len);
+
+void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, unsigned len);
+uint32_t pci_data_read(PCIBus *s, uint32_t addr, unsigned len);
+
+extern const MemoryRegionOps pci_host_conf_le_ops;
+extern const MemoryRegionOps pci_host_conf_be_ops;
+extern const MemoryRegionOps pci_host_data_le_ops;
+extern const MemoryRegionOps pci_host_data_be_ops;
+
+#endif /* PCI_HOST_H */
diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h
new file mode 100644
index 000000000..11abe22d4
--- /dev/null
+++ b/include/hw/pci/pci_ids.h
@@ -0,0 +1,286 @@
+/*
+ * PCI Class, Vendor and Device IDs
+ *
+ * Please keep sorted.
+ *
+ * Abbreviated version of linux/pci_ids.h
+ *
+ * QEMU-specific definitions belong in pci.h
+ */
+
+#ifndef HW_PCI_IDS_H
+#define HW_PCI_IDS_H
+
+/* Device classes and subclasses */
+
+#define PCI_CLASS_NOT_DEFINED 0x0000
+#define PCI_CLASS_NOT_DEFINED_VGA 0x0001
+
+#define PCI_BASE_CLASS_STORAGE 0x01
+#define PCI_CLASS_STORAGE_SCSI 0x0100
+#define PCI_CLASS_STORAGE_IDE 0x0101
+#define PCI_CLASS_STORAGE_FLOPPY 0x0102
+#define PCI_CLASS_STORAGE_IPI 0x0103
+#define PCI_CLASS_STORAGE_RAID 0x0104
+#define PCI_CLASS_STORAGE_ATA 0x0105
+#define PCI_CLASS_STORAGE_SATA 0x0106
+#define PCI_CLASS_STORAGE_SAS 0x0107
+#define PCI_CLASS_STORAGE_EXPRESS 0x0108
+#define PCI_CLASS_STORAGE_OTHER 0x0180
+
+#define PCI_BASE_CLASS_NETWORK 0x02
+#define PCI_CLASS_NETWORK_ETHERNET 0x0200
+#define PCI_CLASS_NETWORK_TOKEN_RING 0x0201
+#define PCI_CLASS_NETWORK_FDDI 0x0202
+#define PCI_CLASS_NETWORK_ATM 0x0203
+#define PCI_CLASS_NETWORK_ISDN 0x0204
+#define PCI_CLASS_NETWORK_WORLDFIP 0x0205
+#define PCI_CLASS_NETWORK_PICMG214 0x0206
+#define PCI_CLASS_NETWORK_OTHER 0x0280
+
+#define PCI_BASE_CLASS_DISPLAY 0x03
+#define PCI_CLASS_DISPLAY_VGA 0x0300
+#define PCI_CLASS_DISPLAY_XGA 0x0301
+#define PCI_CLASS_DISPLAY_3D 0x0302
+#define PCI_CLASS_DISPLAY_OTHER 0x0380
+
+#define PCI_BASE_CLASS_MULTIMEDIA 0x04
+#define PCI_CLASS_MULTIMEDIA_VIDEO 0x0400
+#define PCI_CLASS_MULTIMEDIA_AUDIO 0x0401
+#define PCI_CLASS_MULTIMEDIA_PHONE 0x0402
+#define PCI_CLASS_MULTIMEDIA_OTHER 0x0480
+
+#define PCI_BASE_CLASS_MEMORY 0x05
+#define PCI_CLASS_MEMORY_RAM 0x0500
+#define PCI_CLASS_MEMORY_FLASH 0x0501
+#define PCI_CLASS_MEMORY_OTHER 0x0580
+
+#define PCI_BASE_CLASS_BRIDGE 0x06
+#define PCI_CLASS_BRIDGE_HOST 0x0600
+#define PCI_CLASS_BRIDGE_ISA 0x0601
+#define PCI_CLASS_BRIDGE_EISA 0x0602
+#define PCI_CLASS_BRIDGE_MC 0x0603
+#define PCI_CLASS_BRIDGE_PCI 0x0604
+#define PCI_CLASS_BRIDGE_PCI_INF_SUB 0x01
+#define PCI_CLASS_BRIDGE_PCMCIA 0x0605
+#define PCI_CLASS_BRIDGE_NUBUS 0x0606
+#define PCI_CLASS_BRIDGE_CARDBUS 0x0607
+#define PCI_CLASS_BRIDGE_RACEWAY 0x0608
+#define PCI_CLASS_BRIDGE_PCI_SEMITP 0x0609
+#define PCI_CLASS_BRIDGE_IB_PCI 0x060a
+#define PCI_CLASS_BRIDGE_OTHER 0x0680
+
+#define PCI_BASE_CLASS_COMMUNICATION 0x07
+#define PCI_CLASS_COMMUNICATION_SERIAL 0x0700
+#define PCI_CLASS_COMMUNICATION_PARALLEL 0x0701
+#define PCI_CLASS_COMMUNICATION_MULTISERIAL 0x0702
+#define PCI_CLASS_COMMUNICATION_MODEM 0x0703
+#define PCI_CLASS_COMMUNICATION_GPIB 0x0704
+#define PCI_CLASS_COMMUNICATION_SC 0x0705
+#define PCI_CLASS_COMMUNICATION_OTHER 0x0780
+
+#define PCI_BASE_CLASS_SYSTEM 0x08
+#define PCI_CLASS_SYSTEM_PIC 0x0800
+#define PCI_CLASS_SYSTEM_PIC_IOAPIC 0x080010
+#define PCI_CLASS_SYSTEM_PIC_IOXAPIC 0x080020
+#define PCI_CLASS_SYSTEM_DMA 0x0801
+#define PCI_CLASS_SYSTEM_TIMER 0x0802
+#define PCI_CLASS_SYSTEM_RTC 0x0803
+#define PCI_CLASS_SYSTEM_PCI_HOTPLUG 0x0804
+#define PCI_CLASS_SYSTEM_SDHCI 0x0805
+#define PCI_CLASS_SYSTEM_OTHER 0x0880
+
+#define PCI_BASE_CLASS_INPUT 0x09
+#define PCI_CLASS_INPUT_KEYBOARD 0x0900
+#define PCI_CLASS_INPUT_PEN 0x0901
+#define PCI_CLASS_INPUT_MOUSE 0x0902
+#define PCI_CLASS_INPUT_SCANNER 0x0903
+#define PCI_CLASS_INPUT_GAMEPORT 0x0904
+#define PCI_CLASS_INPUT_OTHER 0x0980
+
+#define PCI_BASE_CLASS_DOCKING 0x0a
+#define PCI_CLASS_DOCKING_GENERIC 0x0a00
+#define PCI_CLASS_DOCKING_OTHER 0x0a80
+
+#define PCI_BASE_CLASS_PROCESSOR 0x0b
+#define PCI_CLASS_PROCESSOR_PENTIUM 0x0b02
+#define PCI_CLASS_PROCESSOR_POWERPC 0x0b20
+#define PCI_CLASS_PROCESSOR_MIPS 0x0b30
+#define PCI_CLASS_PROCESSOR_CO 0x0b40
+
+#define PCI_BASE_CLASS_SERIAL 0x0c
+#define PCI_CLASS_SERIAL_FIREWIRE 0x0c00
+#define PCI_CLASS_SERIAL_ACCESS 0x0c01
+#define PCI_CLASS_SERIAL_SSA 0x0c02
+#define PCI_CLASS_SERIAL_USB 0x0c03
+#define PCI_CLASS_SERIAL_USB_UHCI 0x0c0300
+#define PCI_CLASS_SERIAL_USB_OHCI 0x0c0310
+#define PCI_CLASS_SERIAL_USB_EHCI 0x0c0320
+#define PCI_CLASS_SERIAL_USB_XHCI 0x0c0330
+#define PCI_CLASS_SERIAL_USB_UNKNOWN 0x0c0380
+#define PCI_CLASS_SERIAL_USB_DEVICE 0x0c03fe
+#define PCI_CLASS_SERIAL_FIBER 0x0c04
+#define PCI_CLASS_SERIAL_SMBUS 0x0c05
+#define PCI_CLASS_SERIAL_IB 0x0c06
+#define PCI_CLASS_SERIAL_IPMI 0x0c07
+#define PCI_CLASS_SERIAL_SERCOS 0x0c08
+#define PCI_CLASS_SERIAL_CANBUS 0x0c09
+
+#define PCI_BASE_CLASS_WIRELESS 0x0d
+#define PCI_CLASS_WIRELESS_IRDA 0x0d00
+#define PCI_CLASS_WIRELESS_CIR 0x0d01
+#define PCI_CLASS_WIRELESS_RF_CONTROLLER 0x0d10
+#define PCI_CLASS_WIRELESS_BLUETOOTH 0x0d11
+#define PCI_CLASS_WIRELESS_BROADBAND 0x0d12
+#define PCI_CLASS_WIRELESS_OTHER 0x0d80
+
+#define PCI_BASE_CLASS_SATELLITE 0x0f
+#define PCI_CLASS_SATELLITE_TV 0x0f00
+#define PCI_CLASS_SATELLITE_AUDIO 0x0f01
+#define PCI_CLASS_SATELLITE_VOICE 0x0f03
+#define PCI_CLASS_SATELLITE_DATA 0x0f04
+
+#define PCI_BASE_CLASS_CRYPT 0x10
+#define PCI_CLASS_CRYPT_NETWORK 0x1000
+#define PCI_CLASS_CRYPT_ENTERTAINMENT 0x1001
+#define PCI_CLASS_CRYPT_OTHER 0x1080
+
+#define PCI_BASE_CLASS_SIGNAL_PROCESSING 0x11
+#define PCI_CLASS_SP_DPIO 0x1100
+#define PCI_CLASS_SP_PERF 0x1101
+#define PCI_CLASS_SP_SYNCH 0x1110
+#define PCI_CLASS_SP_MANAGEMENT 0x1120
+#define PCI_CLASS_SP_OTHER 0x1180
+
+#define PCI_CLASS_OTHERS 0xff
+
+/* Vendors and devices. Sort key: vendor first, device next. */
+
+#define PCI_VENDOR_ID_LSI_LOGIC 0x1000
+#define PCI_DEVICE_ID_LSI_53C810 0x0001
+#define PCI_DEVICE_ID_LSI_53C895A 0x0012
+#define PCI_DEVICE_ID_LSI_SAS1068 0x0054
+#define PCI_DEVICE_ID_LSI_SAS1078 0x0060
+#define PCI_DEVICE_ID_LSI_SAS0079 0x0079
+
+#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
+
+#define PCI_VENDOR_ID_IBM 0x1014
+
+#define PCI_VENDOR_ID_AMD 0x1022
+#define PCI_DEVICE_ID_AMD_LANCE 0x2000
+#define PCI_DEVICE_ID_AMD_SCSI 0x2020
+
+#define PCI_VENDOR_ID_TI 0x104c
+
+#define PCI_VENDOR_ID_MOTOROLA 0x1057
+#define PCI_DEVICE_ID_MOTOROLA_MPC106 0x0002
+#define PCI_DEVICE_ID_MOTOROLA_RAVEN 0x4801
+
+#define PCI_VENDOR_ID_APPLE 0x106b
+#define PCI_DEVICE_ID_APPLE_UNI_N_AGP 0x0020
+#define PCI_DEVICE_ID_APPLE_U3_AGP 0x004b
+#define PCI_DEVICE_ID_APPLE_UNI_N_GMAC 0x0021
+
+#define PCI_VENDOR_ID_SUN 0x108e
+#define PCI_DEVICE_ID_SUN_EBUS 0x1000
+#define PCI_DEVICE_ID_SUN_HME 0x1001
+#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
+
+#define PCI_VENDOR_ID_REALTEK 0x10ec
+#define PCI_DEVICE_ID_REALTEK_8139 0x8139
+
+#define PCI_VENDOR_ID_XILINX 0x10ee
+
+#define PCI_VENDOR_ID_VIA 0x1106
+#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_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
+
+#define PCI_VENDOR_ID_ENSONIQ 0x1274
+#define PCI_DEVICE_ID_ENSONIQ_ES1370 0x5000
+
+#define PCI_VENDOR_ID_CHELSIO 0x1425
+
+#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
+#define PCI_DEVICE_ID_INTEL_82801AA_5 0x2415
+#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_82371SB_0 0x7000
+#define PCI_DEVICE_ID_INTEL_82371SB_1 0x7010
+#define PCI_DEVICE_ID_INTEL_82371SB_2 0x7020
+#define PCI_DEVICE_ID_INTEL_82371AB_0 0x7110
+#define PCI_DEVICE_ID_INTEL_82371AB 0x7111
+#define PCI_DEVICE_ID_INTEL_82371AB_2 0x7112
+#define PCI_DEVICE_ID_INTEL_82371AB_3 0x7113
+
+#define PCI_DEVICE_ID_INTEL_ICH9_0 0x2910
+#define PCI_DEVICE_ID_INTEL_ICH9_1 0x2917
+#define PCI_DEVICE_ID_INTEL_ICH9_2 0x2912
+#define PCI_DEVICE_ID_INTEL_ICH9_3 0x2913
+#define PCI_DEVICE_ID_INTEL_ICH9_4 0x2914
+#define PCI_DEVICE_ID_INTEL_ICH9_5 0x2919
+#define PCI_DEVICE_ID_INTEL_ICH9_6 0x2930
+#define PCI_DEVICE_ID_INTEL_ICH9_7 0x2916
+#define PCI_DEVICE_ID_INTEL_ICH9_8 0x2918
+
+#define PCI_DEVICE_ID_INTEL_82801I_UHCI1 0x2934
+#define PCI_DEVICE_ID_INTEL_82801I_UHCI2 0x2935
+#define PCI_DEVICE_ID_INTEL_82801I_UHCI3 0x2936
+#define PCI_DEVICE_ID_INTEL_82801I_UHCI4 0x2937
+#define PCI_DEVICE_ID_INTEL_82801I_UHCI5 0x2938
+#define PCI_DEVICE_ID_INTEL_82801I_UHCI6 0x2939
+#define PCI_DEVICE_ID_INTEL_82801I_EHCI1 0x293a
+#define PCI_DEVICE_ID_INTEL_82801I_EHCI2 0x293c
+#define PCI_DEVICE_ID_INTEL_82599_SFP_VF 0x10ed
+
+#define PCI_DEVICE_ID_INTEL_P35_MCH 0x29c0
+
+#define PCI_VENDOR_ID_XEN 0x5853
+#define PCI_DEVICE_ID_XEN_PLATFORM 0x0001
+
+#define PCI_VENDOR_ID_NEC 0x1033
+#define PCI_DEVICE_ID_NEC_UPD720200 0x0194
+
+#define PCI_VENDOR_ID_TEWS 0x1498
+#define PCI_DEVICE_ID_TEWS_TPCI200 0x30C8
+
+#define PCI_VENDOR_ID_VMWARE 0x15ad
+#define PCI_DEVICE_ID_VMWARE_PVRDMA 0x0820
+
+#define PCI_VENDOR_ID_SYNOPSYS 0x16C3
+
+#define PCI_VENDOR_ID_NVIDIA 0x10de
+
+#endif
diff --git a/include/hw/pci/pci_regs.h b/include/hw/pci/pci_regs.h
new file mode 100644
index 000000000..77ba64b93
--- /dev/null
+++ b/include/hw/pci/pci_regs.h
@@ -0,0 +1,8 @@
+#ifndef HW_PCI_PCI_REGS_H
+#define HW_PCI_PCI_REGS_H
+
+#include "standard-headers/linux/pci_regs.h"
+
+#define PCI_PM_CAP_VER_1_1 0x0002 /* PCI PM spec ver. 1.1 */
+
+#endif
diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h
new file mode 100644
index 000000000..6063bee0e
--- /dev/null
+++ b/include/hw/pci/pcie.h
@@ -0,0 +1,150 @@
+/*
+ * pcie.h
+ *
+ * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * 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 QEMU_PCIE_H
+#define QEMU_PCIE_H
+
+#include "hw/pci/pci_regs.h"
+#include "hw/pci/pcie_regs.h"
+#include "hw/pci/pcie_aer.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
+ *
+ * Not all the bits of slot control register match with the ones of
+ * slot status. Not some bits of slot status register is used to
+ * show status, not to report event occurrence.
+ * So such bits must be masked out when checking the software
+ * notification condition.
+ */
+ PCI_EXP_HP_EV_ABP = PCI_EXP_SLTCTL_ABPE,
+ /* attention button pressed */
+ PCI_EXP_HP_EV_PDC = PCI_EXP_SLTCTL_PDCE,
+ /* presence detect changed */
+ PCI_EXP_HP_EV_CCI = PCI_EXP_SLTCTL_CCIE,
+ /* command completed */
+
+ PCI_EXP_HP_EV_SUPPORTED = PCI_EXP_HP_EV_ABP |
+ PCI_EXP_HP_EV_PDC |
+ PCI_EXP_HP_EV_CCI,
+ /* supported event mask */
+
+ /* events not listed aren't supported */
+} PCIExpressHotPlugEvent;
+
+struct PCIExpressDevice {
+ /* Offset of express capability in config space */
+ uint8_t exp_cap;
+ /* Offset of Power Management capability in config space */
+ uint8_t pm_cap;
+
+ /* SLOT */
+ bool hpev_notified; /* Logical AND of conditions for hot plug event.
+ Following 6.7.3.4:
+ Software Notification of Hot-Plug Events, an interrupt
+ is sent whenever the logical and of these conditions
+ transitions from false to true. */
+
+ /* AER */
+ uint16_t aer_cap;
+ PCIEAERLog aer_log;
+
+ /* Offset of ATS capability in config space */
+ uint16_t ats_cap;
+
+ /* ACS */
+ uint16_t acs_cap;
+};
+
+#define COMPAT_PROP_PCP "power_controller_present"
+
+/* PCI express capability helper functions */
+int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type,
+ uint8_t port, Error **errp);
+int pcie_cap_v1_init(PCIDevice *dev, uint8_t offset,
+ uint8_t type, uint8_t port);
+int pcie_endpoint_cap_init(PCIDevice *dev, uint8_t offset);
+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);
+void pcie_cap_flags_set_vector(PCIDevice *dev, uint8_t vector);
+uint8_t pcie_cap_flags_get_vector(PCIDevice *dev);
+
+void pcie_cap_deverr_init(PCIDevice *dev);
+void pcie_cap_deverr_reset(PCIDevice *dev);
+
+void pcie_cap_lnkctl_init(PCIDevice *dev);
+void pcie_cap_lnkctl_reset(PCIDevice *dev);
+
+void pcie_cap_slot_init(PCIDevice *dev, PCIESlot *s);
+void pcie_cap_slot_reset(PCIDevice *dev);
+void pcie_cap_slot_get(PCIDevice *dev, uint16_t *slt_ctl, uint16_t *slt_sta);
+void pcie_cap_slot_write_config(PCIDevice *dev,
+ uint16_t old_slt_ctl, uint16_t old_slt_sta,
+ 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_root_init(PCIDevice *dev);
+void pcie_cap_root_reset(PCIDevice *dev);
+
+void pcie_cap_flr_init(PCIDevice *dev);
+void pcie_cap_flr_write_config(PCIDevice *dev,
+ uint32_t addr, uint32_t val, int len);
+
+/* ARI forwarding capability and control */
+void pcie_cap_arifwd_init(PCIDevice *dev);
+void pcie_cap_arifwd_reset(PCIDevice *dev);
+bool pcie_cap_is_arifwd_enabled(const PCIDevice *dev);
+
+/* PCI express extended capability helper functions */
+uint16_t pcie_find_capability(PCIDevice *dev, uint16_t cap_id);
+void pcie_add_capability(PCIDevice *dev,
+ uint16_t cap_id, uint8_t cap_ver,
+ uint16_t offset, uint16_t size);
+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_dev_ser_num_init(PCIDevice *dev, uint16_t offset, uint64_t ser_num);
+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);
+void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+ Error **errp);
+void pcie_cap_slot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+ Error **errp);
+void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp);
+#endif /* QEMU_PCIE_H */
diff --git a/include/hw/pci/pcie_aer.h b/include/hw/pci/pcie_aer.h
new file mode 100644
index 000000000..65e71d98f
--- /dev/null
+++ b/include/hw/pci/pcie_aer.h
@@ -0,0 +1,103 @@
+/*
+ * pcie_aer.h
+ *
+ * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * 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 QEMU_PCIE_AER_H
+#define QEMU_PCIE_AER_H
+
+#include "hw/pci/pci_regs.h"
+
+/* definitions which PCIExpressDevice uses */
+
+/* AER log */
+struct PCIEAERLog {
+ /* This structure is saved/loaded.
+ So explicitly size them instead of unsigned int */
+
+ /* the number of currently recorded log in log member */
+ uint16_t log_num;
+
+ /*
+ * The maximum number of the log. Errors can be logged up to this.
+ *
+ * This is configurable property.
+ * 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?
+ */
+#define PCIE_AER_LOG_MAX_DEFAULT 8
+#define PCIE_AER_LOG_MAX_LIMIT 128
+ uint16_t log_max;
+
+ /* Error log. log_max-sized array */
+ PCIEAERErr *log;
+};
+
+/* aer error message: error signaling message has only error severity and
+ source id. See 2.2.8.3 error signaling messages */
+struct PCIEAERMsg {
+ /*
+ * PCI_ERR_ROOT_CMD_{COR, NONFATAL, FATAL}_EN
+ * = PCI_EXP_DEVCTL_{CERE, NFERE, FERE}
+ */
+ uint32_t severity;
+
+ uint16_t source_id; /* bdf */
+};
+
+static inline bool
+pcie_aer_msg_is_uncor(const PCIEAERMsg *msg)
+{
+ return msg->severity == PCI_ERR_ROOT_CMD_NONFATAL_EN ||
+ msg->severity == PCI_ERR_ROOT_CMD_FATAL_EN;
+}
+
+/* error */
+struct PCIEAERErr {
+ uint32_t status; /* error status bits */
+ uint16_t source_id; /* bdf */
+
+#define PCIE_AER_ERR_IS_CORRECTABLE 0x1 /* correctable/uncorrectable */
+#define PCIE_AER_ERR_MAYBE_ADVISORY 0x2 /* maybe advisory non-fatal */
+#define PCIE_AER_ERR_HEADER_VALID 0x4 /* TLP header is logged */
+#define PCIE_AER_ERR_TLP_PREFIX_PRESENT 0x8 /* TLP Prefix is logged */
+ uint16_t flags;
+
+ uint32_t header[4]; /* TLP header */
+ uint32_t prefix[4]; /* TLP header prefix */
+};
+
+extern const VMStateDescription vmstate_pcie_aer_log;
+
+int pcie_aer_init(PCIDevice *dev, uint8_t cap_ver, uint16_t offset,
+ uint16_t size, Error **errp);
+void pcie_aer_exit(PCIDevice *dev);
+void pcie_aer_write_config(PCIDevice *dev,
+ uint32_t addr, uint32_t val, int len);
+
+/* aer root port */
+void pcie_aer_root_set_vector(PCIDevice *dev, unsigned int vector);
+void pcie_aer_root_init(PCIDevice *dev);
+void pcie_aer_root_reset(PCIDevice *dev);
+void pcie_aer_root_write_config(PCIDevice *dev,
+ uint32_t addr, uint32_t val, int len,
+ uint32_t root_cmd_prev);
+
+#endif /* QEMU_PCIE_AER_H */
diff --git a/include/hw/pci/pcie_host.h b/include/hw/pci/pcie_host.h
new file mode 100644
index 000000000..076457b27
--- /dev/null
+++ b/include/hw/pci/pcie_host.h
@@ -0,0 +1,81 @@
+/*
+ * pcie_host.h
+ *
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * 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 PCIE_HOST_H
+#define PCIE_HOST_H
+
+#include "hw/pci/pci_host.h"
+#include "exec/memory.h"
+#include "qom/object.h"
+
+#define TYPE_PCIE_HOST_BRIDGE "pcie-host-bridge"
+OBJECT_DECLARE_SIMPLE_TYPE(PCIExpressHost, PCIE_HOST_BRIDGE)
+
+#define PCIE_HOST_MCFG_BASE "MCFG"
+#define PCIE_HOST_MCFG_SIZE "mcfg_size"
+
+/* pcie_host::base_addr == PCIE_BASE_ADDR_UNMAPPED when it isn't mapped. */
+#define PCIE_BASE_ADDR_UNMAPPED ((hwaddr)-1ULL)
+
+struct PCIExpressHost {
+ PCIHostState pci;
+
+ /* express part */
+
+ /* base address where MMCONFIG area is mapped. */
+ hwaddr base_addr;
+
+ /* the size of MMCONFIG area. It's host bridge dependent */
+ hwaddr size;
+
+ /* MMCONFIG mmio area */
+ MemoryRegion mmio;
+};
+
+void pcie_host_mmcfg_unmap(PCIExpressHost *e);
+void pcie_host_mmcfg_init(PCIExpressHost *e, uint32_t size);
+void pcie_host_mmcfg_map(PCIExpressHost *e, hwaddr addr, uint32_t size);
+void pcie_host_mmcfg_update(PCIExpressHost *e,
+ int enable,
+ hwaddr addr,
+ uint32_t size);
+
+/*
+ * PCI express ECAM (Enhanced Configuration Address Mapping) format.
+ * AKA mmcfg address
+ * bit 20 - 28: 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_MIN (1ULL << 20)
+#define PCIE_MMCFG_BUS_BIT 20
+#define PCIE_MMCFG_BUS_MASK 0x1ff
+#define PCIE_MMCFG_DEVFN_BIT 12
+#define PCIE_MMCFG_DEVFN_MASK 0xff
+#define PCIE_MMCFG_CONFOFFSET_MASK 0xfff
+#define PCIE_MMCFG_BUS(addr) (((addr) >> PCIE_MMCFG_BUS_BIT) & \
+ PCIE_MMCFG_BUS_MASK)
+#define PCIE_MMCFG_DEVFN(addr) (((addr) >> PCIE_MMCFG_DEVFN_BIT) & \
+ PCIE_MMCFG_DEVFN_MASK)
+#define PCIE_MMCFG_CONFOFFSET(addr) ((addr) & PCIE_MMCFG_CONFOFFSET_MASK)
+
+#endif /* PCIE_HOST_H */
diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h
new file mode 100644
index 000000000..e25b289ce
--- /dev/null
+++ b/include/hw/pci/pcie_port.h
@@ -0,0 +1,94 @@
+/*
+ * pcie_port.h
+ *
+ * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * 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 QEMU_PCIE_PORT_H
+#define QEMU_PCIE_PORT_H
+
+#include "hw/pci/pci_bridge.h"
+#include "hw/pci/pci_bus.h"
+#include "qom/object.h"
+
+#define TYPE_PCIE_PORT "pcie-port"
+OBJECT_DECLARE_SIMPLE_TYPE(PCIEPort, PCIE_PORT)
+
+struct PCIEPort {
+ /*< private >*/
+ PCIBridge parent_obj;
+ /*< public >*/
+
+ /* pci express switch port */
+ uint8_t port;
+};
+
+void pcie_port_init_reg(PCIDevice *d);
+
+#define TYPE_PCIE_SLOT "pcie-slot"
+OBJECT_DECLARE_SIMPLE_TYPE(PCIESlot, PCIE_SLOT)
+
+struct PCIESlot {
+ /*< private >*/
+ PCIEPort parent_obj;
+ /*< public >*/
+
+ /* pci express switch port with slot */
+ uint8_t chassis;
+ uint16_t slot;
+
+ PCIExpLinkSpeed speed;
+ PCIExpLinkWidth width;
+
+ /* Disable ACS (really for a pcie_root_port) */
+ bool disable_acs;
+
+ /* Indicates whether any type of hot-plug is allowed on the slot */
+ bool hotplug;
+
+ bool native_hotplug;
+
+ QLIST_ENTRY(PCIESlot) next;
+};
+
+void pcie_chassis_create(uint8_t chassis_number);
+PCIESlot *pcie_chassis_find_slot(uint8_t chassis, uint16_t slot);
+int pcie_chassis_add_slot(struct PCIESlot *slot);
+void pcie_chassis_del_slot(PCIESlot *s);
+
+#define TYPE_PCIE_ROOT_PORT "pcie-root-port-base"
+typedef struct PCIERootPortClass PCIERootPortClass;
+DECLARE_CLASS_CHECKERS(PCIERootPortClass, PCIE_ROOT_PORT,
+ TYPE_PCIE_ROOT_PORT)
+
+struct PCIERootPortClass {
+ PCIDeviceClass parent_class;
+ DeviceRealize parent_realize;
+ DeviceReset parent_reset;
+
+ uint8_t (*aer_vector)(const PCIDevice *dev);
+ int (*interrupts_init)(PCIDevice *dev, Error **errp);
+ void (*interrupts_uninit)(PCIDevice *dev);
+
+ int exp_offset;
+ int aer_offset;
+ int ssvid_offset;
+ int acs_offset; /* If nonzero, optional ACS capability offset */
+ int ssid;
+};
+
+#endif /* QEMU_PCIE_PORT_H */
diff --git a/include/hw/pci/pcie_regs.h b/include/hw/pci/pcie_regs.h
new file mode 100644
index 000000000..1db86b0ec
--- /dev/null
+++ b/include/hw/pci/pcie_regs.h
@@ -0,0 +1,182 @@
+/*
+ * constants for pcie configurations space from pci express spec.
+ *
+ * TODO:
+ * Those constants and macros should go to Linux pci_regs.h
+ * Once they're merged, they will go away.
+ */
+#ifndef QEMU_PCIE_REGS_H
+#define QEMU_PCIE_REGS_H
+
+
+/* express capability */
+
+#define PCI_EXP_VER1_SIZEOF 0x14 /* express capability of ver. 1 */
+#define PCI_EXP_VER2_SIZEOF 0x3c /* express capability of ver. 2 */
+#define PCI_EXT_CAP_VER_SHIFT 16
+#define PCI_EXT_CAP_NEXT_SHIFT 20
+#define PCI_EXT_CAP_NEXT_MASK (0xffc << PCI_EXT_CAP_NEXT_SHIFT)
+
+#define PCI_EXT_CAP(id, ver, next) \
+ ((id) | \
+ ((ver) << PCI_EXT_CAP_VER_SHIFT) | \
+ ((next) << PCI_EXT_CAP_NEXT_SHIFT))
+
+#define PCI_EXT_CAP_ALIGN 4
+#define PCI_EXT_CAP_ALIGNUP(x) \
+ (((x) + PCI_EXT_CAP_ALIGN - 1) & ~(PCI_EXT_CAP_ALIGN - 1))
+
+/* PCI_EXP_FLAGS */
+#define PCI_EXP_FLAGS_VER1 1
+#define PCI_EXP_FLAGS_VER2 2
+#define PCI_EXP_FLAGS_IRQ_SHIFT ctz32(PCI_EXP_FLAGS_IRQ)
+#define PCI_EXP_FLAGS_TYPE_SHIFT ctz32(PCI_EXP_FLAGS_TYPE)
+
+/* PCI_EXP_LINK{CAP, STA} */
+/* link speed */
+typedef enum PCIExpLinkSpeed {
+ QEMU_PCI_EXP_LNK_2_5GT = 1,
+ QEMU_PCI_EXP_LNK_5GT,
+ QEMU_PCI_EXP_LNK_8GT,
+ QEMU_PCI_EXP_LNK_16GT,
+} PCIExpLinkSpeed;
+
+#define QEMU_PCI_EXP_LNKCAP_MLS(speed) (speed)
+#define QEMU_PCI_EXP_LNKSTA_CLS QEMU_PCI_EXP_LNKCAP_MLS
+
+typedef enum PCIExpLinkWidth {
+ QEMU_PCI_EXP_LNK_X1 = 1,
+ QEMU_PCI_EXP_LNK_X2 = 2,
+ QEMU_PCI_EXP_LNK_X4 = 4,
+ QEMU_PCI_EXP_LNK_X8 = 8,
+ QEMU_PCI_EXP_LNK_X12 = 12,
+ QEMU_PCI_EXP_LNK_X16 = 16,
+ QEMU_PCI_EXP_LNK_X32 = 32,
+} PCIExpLinkWidth;
+
+#define PCI_EXP_LNK_MLW_SHIFT ctz32(PCI_EXP_LNKCAP_MLW)
+#define QEMU_PCI_EXP_LNKCAP_MLW(width) (width << PCI_EXP_LNK_MLW_SHIFT)
+#define QEMU_PCI_EXP_LNKSTA_NLW QEMU_PCI_EXP_LNKCAP_MLW
+
+/* PCI_EXP_LINKCAP */
+#define PCI_EXP_LNKCAP_ASPMS_SHIFT ctz32(PCI_EXP_LNKCAP_ASPMS)
+#define PCI_EXP_LNKCAP_ASPMS_0S (1 << PCI_EXP_LNKCAP_ASPMS_SHIFT)
+
+#define PCI_EXP_LNKCAP_PN_SHIFT ctz32(PCI_EXP_LNKCAP_PN)
+
+#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 | \
+ PCI_EXP_SLTCTL_CCIE | \
+ PCI_EXP_SLTCTL_HPIE | \
+ PCI_EXP_SLTCTL_AIC | \
+ PCI_EXP_SLTCTL_PCC | \
+ PCI_EXP_SLTCTL_EIC)
+
+#define PCI_EXP_DEVCAP2_EFF 0x100000
+#define PCI_EXP_DEVCAP2_EETLPP 0x200000
+
+#define PCI_EXP_DEVCTL2_EETLPPB 0x8000
+
+/* ARI */
+#define PCI_ARI_VER 1
+#define PCI_ARI_SIZEOF 8
+
+/* AER */
+#define PCI_ERR_VER 2
+#define PCI_ERR_SIZEOF 0x48
+
+#define PCI_ERR_UNC_SDN 0x00000020 /* surprise down */
+#define PCI_ERR_UNC_ACSV 0x00200000 /* ACS Violation */
+#define PCI_ERR_UNC_INTN 0x00400000 /* Internal Error */
+#define PCI_ERR_UNC_MCBTLP 0x00800000 /* MC Blcoked TLP */
+#define PCI_ERR_UNC_ATOP_EBLOCKED 0x01000000 /* atomic op egress blocked */
+#define PCI_ERR_UNC_TLP_PRF_BLOCKED 0x02000000 /* TLP Prefix Blocked */
+#define PCI_ERR_COR_ADV_NONFATAL 0x00002000 /* Advisory Non-Fatal */
+#define PCI_ERR_COR_INTERNAL 0x00004000 /* Corrected Internal */
+#define PCI_ERR_COR_HL_OVERFLOW 0x00008000 /* Header Long Overflow */
+#define PCI_ERR_CAP_FEP_MASK 0x0000001f
+#define PCI_ERR_CAP_MHRC 0x00000200
+#define PCI_ERR_CAP_MHRE 0x00000400
+#define PCI_ERR_CAP_TLP 0x00000800
+
+#define PCI_ERR_HEADER_LOG_SIZE 16
+#define PCI_ERR_TLP_PREFIX_LOG 0x38
+#define PCI_ERR_TLP_PREFIX_LOG_SIZE 16
+
+#define PCI_SEC_STATUS_RCV_SYSTEM_ERROR 0x4000
+
+/* aer root error command/status */
+#define PCI_ERR_ROOT_CMD_EN_MASK (PCI_ERR_ROOT_CMD_COR_EN | \
+ PCI_ERR_ROOT_CMD_NONFATAL_EN | \
+ PCI_ERR_ROOT_CMD_FATAL_EN)
+
+#define PCI_ERR_ROOT_IRQ_MAX 32
+#define PCI_ERR_ROOT_IRQ 0xf8000000
+#define PCI_ERR_ROOT_IRQ_SHIFT ctz32(PCI_ERR_ROOT_IRQ)
+#define PCI_ERR_ROOT_STATUS_REPORT_MASK (PCI_ERR_ROOT_COR_RCV | \
+ PCI_ERR_ROOT_MULTI_COR_RCV | \
+ PCI_ERR_ROOT_UNCOR_RCV | \
+ PCI_ERR_ROOT_MULTI_UNCOR_RCV | \
+ PCI_ERR_ROOT_FIRST_FATAL | \
+ PCI_ERR_ROOT_NONFATAL_RCV | \
+ PCI_ERR_ROOT_FATAL_RCV)
+
+#define PCI_ERR_UNC_SUPPORTED (PCI_ERR_UNC_DLP | \
+ PCI_ERR_UNC_SDN | \
+ PCI_ERR_UNC_POISON_TLP | \
+ PCI_ERR_UNC_FCP | \
+ PCI_ERR_UNC_COMP_TIME | \
+ PCI_ERR_UNC_COMP_ABORT | \
+ PCI_ERR_UNC_UNX_COMP | \
+ PCI_ERR_UNC_RX_OVER | \
+ PCI_ERR_UNC_MALF_TLP | \
+ PCI_ERR_UNC_ECRC | \
+ PCI_ERR_UNC_UNSUP | \
+ PCI_ERR_UNC_ACSV | \
+ PCI_ERR_UNC_INTN | \
+ PCI_ERR_UNC_MCBTLP | \
+ PCI_ERR_UNC_ATOP_EBLOCKED | \
+ PCI_ERR_UNC_TLP_PRF_BLOCKED)
+
+#define PCI_ERR_UNC_SEVERITY_DEFAULT (PCI_ERR_UNC_DLP | \
+ PCI_ERR_UNC_SDN | \
+ PCI_ERR_UNC_FCP | \
+ PCI_ERR_UNC_RX_OVER | \
+ PCI_ERR_UNC_MALF_TLP | \
+ PCI_ERR_UNC_INTN)
+
+#define PCI_ERR_COR_SUPPORTED (PCI_ERR_COR_RCVR | \
+ PCI_ERR_COR_BAD_TLP | \
+ PCI_ERR_COR_BAD_DLLP | \
+ PCI_ERR_COR_REP_ROLL | \
+ PCI_ERR_COR_REP_TIMER | \
+ PCI_ERR_COR_ADV_NONFATAL | \
+ PCI_ERR_COR_INTERNAL | \
+ PCI_ERR_COR_HL_OVERFLOW)
+
+#define PCI_ERR_COR_MASK_DEFAULT (PCI_ERR_COR_ADV_NONFATAL | \
+ PCI_ERR_COR_INTERNAL | \
+ PCI_ERR_COR_HL_OVERFLOW)
+
+/* ACS */
+#define PCI_ACS_VER 0x1
+#define PCI_ACS_SIZEOF 8
+
+#endif /* QEMU_PCIE_REGS_H */
diff --git a/include/hw/pci/shpc.h b/include/hw/pci/shpc.h
new file mode 100644
index 000000000..d5683b739
--- /dev/null
+++ b/include/hw/pci/shpc.h
@@ -0,0 +1,65 @@
+#ifndef SHPC_H
+#define SHPC_H
+
+#include "exec/memory.h"
+#include "hw/hotplug.h"
+#include "hw/pci/pci.h"
+#include "migration/vmstate.h"
+
+struct SHPCDevice {
+ /* Capability offset in device's config space */
+ int cap;
+
+ /* # of hot-pluggable slots */
+ int nslots;
+
+ /* SHPC WRS: working register set */
+ uint8_t *config;
+
+ /* Used to enable 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;
+
+ /* MMIO for the SHPC BAR */
+ MemoryRegion mmio;
+
+ /* Bus controlled by this SHPC */
+ PCIBus *sec_bus;
+
+ /* MSI already requested for this event */
+ int msi_requested;
+};
+
+void shpc_reset(PCIDevice *d);
+int shpc_bar_size(PCIDevice *dev);
+int shpc_init(PCIDevice *dev, PCIBus *sec_bus, MemoryRegion *bar,
+ unsigned off, Error **errp);
+void shpc_cleanup(PCIDevice *dev, MemoryRegion *bar);
+void shpc_free(PCIDevice *dev);
+void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len);
+
+
+void shpc_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+ Error **errp);
+void shpc_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+ Error **errp);
+void shpc_device_unplug_request_cb(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp);
+
+extern VMStateInfo shpc_vmstate_info;
+#define SHPC_VMSTATE(_field, _type, _test) \
+ VMSTATE_BUFFER_UNSAFE_INFO_TEST(_field, _type, _test, 0, \
+ shpc_vmstate_info, 0)
+
+static inline bool shpc_present(const PCIDevice *dev)
+{
+ return dev->cap_present & QEMU_PCI_CAP_SHPC;
+}
+
+#endif
diff --git a/include/hw/pci/slotid_cap.h b/include/hw/pci/slotid_cap.h
new file mode 100644
index 000000000..8b4dc0ce8
--- /dev/null
+++ b/include/hw/pci/slotid_cap.h
@@ -0,0 +1,11 @@
+#ifndef PCI_SLOTID_CAP_H
+#define PCI_SLOTID_CAP_H
+
+
+int slotid_cap_init(PCIDevice *dev, int nslots,
+ uint8_t chassis,
+ unsigned offset,
+ Error **errp);
+void slotid_cap_cleanup(PCIDevice *dev);
+
+#endif
diff --git a/include/hw/pcmcia.h b/include/hw/pcmcia.h
new file mode 100644
index 000000000..e3ba44e0b
--- /dev/null
+++ b/include/hw/pcmcia.h
@@ -0,0 +1,66 @@
+#ifndef HW_PCMCIA_H
+#define HW_PCMCIA_H
+
+/* PCMCIA/Cardbus */
+
+#include "hw/qdev-core.h"
+#include "qom/object.h"
+
+typedef struct PCMCIASocket {
+ qemu_irq irq;
+ bool attached;
+} PCMCIASocket;
+
+#define TYPE_PCMCIA_CARD "pcmcia-card"
+OBJECT_DECLARE_TYPE(PCMCIACardState, PCMCIACardClass, PCMCIA_CARD)
+
+struct PCMCIACardState {
+ /*< private >*/
+ DeviceState parent_obj;
+ /*< public >*/
+
+ PCMCIASocket *slot;
+};
+
+struct PCMCIACardClass {
+ /*< private >*/
+ DeviceClass parent_class;
+ /*< public >*/
+
+ int (*attach)(PCMCIACardState *state);
+ int (*detach)(PCMCIACardState *state);
+
+ const uint8_t *cis;
+ int cis_len;
+
+ /* Only valid if attached */
+ uint8_t (*attr_read)(PCMCIACardState *card, uint32_t address);
+ void (*attr_write)(PCMCIACardState *card, uint32_t address, uint8_t value);
+ uint16_t (*common_read)(PCMCIACardState *card, uint32_t address);
+ void (*common_write)(PCMCIACardState *card,
+ uint32_t address, uint16_t value);
+ uint16_t (*io_read)(PCMCIACardState *card, uint32_t address);
+ void (*io_write)(PCMCIACardState *card, uint32_t address, uint16_t value);
+};
+
+#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);
+
+#endif
diff --git a/include/hw/platform-bus.h b/include/hw/platform-bus.h
new file mode 100644
index 000000000..44f30c535
--- /dev/null
+++ b/include/hw/platform-bus.h
@@ -0,0 +1,52 @@
+#ifndef HW_PLATFORM_BUS_H
+#define HW_PLATFORM_BUS_H
+
+/*
+ * Platform Bus device to support dynamic Sysbus devices
+ *
+ * Copyright (C) 2014 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Alexander Graf, <agraf@suse.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.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/>.
+ */
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+
+#define TYPE_PLATFORM_BUS_DEVICE "platform-bus-device"
+OBJECT_DECLARE_SIMPLE_TYPE(PlatformBusDevice, PLATFORM_BUS_DEVICE)
+
+struct PlatformBusDevice {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ uint32_t mmio_size;
+ MemoryRegion mmio;
+
+ uint32_t num_irqs;
+ qemu_irq *irqs;
+ unsigned long *used_irqs;
+};
+
+int platform_bus_get_irqn(PlatformBusDevice *platform_bus, SysBusDevice *sbdev,
+ int n);
+hwaddr platform_bus_get_mmio_addr(PlatformBusDevice *pbus, SysBusDevice *sbdev,
+ int n);
+
+void platform_bus_link_device(PlatformBusDevice *pbus, SysBusDevice *sbdev);
+
+#endif /* HW_PLATFORM_BUS_H */
diff --git a/include/hw/ppc/fdt.h b/include/hw/ppc/fdt.h
new file mode 100644
index 000000000..a8cd85069
--- /dev/null
+++ b/include/hw/ppc/fdt.h
@@ -0,0 +1,29 @@
+/*
+ * QEMU PowerPC helper routines for the device tree.
+ *
+ * Copyright (C) 2016 IBM Corp.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+
+#ifndef PPC_FDT_H
+#define PPC_FDT_H
+
+#include "qemu/error-report.h"
+#include "target/ppc/cpu-qom.h"
+
+#define _FDT(exp) \
+ do { \
+ int ret = (exp); \
+ if (ret < 0) { \
+ error_report("error creating device tree: %s: %s", \
+ #exp, fdt_strerror(ret)); \
+ exit(1); \
+ } \
+ } while (0)
+
+size_t ppc_create_page_sizes_prop(PowerPCCPU *cpu, uint32_t *prop,
+ size_t maxsize);
+
+#endif /* PPC_FDT_H */
diff --git a/include/hw/ppc/mac_dbdma.h b/include/hw/ppc/mac_dbdma.h
new file mode 100644
index 000000000..4a3f64451
--- /dev/null
+++ b/include/hw/ppc/mac_dbdma.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2009 Laurent Vivier
+ *
+ * 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_MAC_DBDMA_H
+#define HW_MAC_DBDMA_H
+
+#include "exec/memory.h"
+#include "qemu/iov.h"
+#include "sysemu/dma.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+typedef struct DBDMA_io DBDMA_io;
+
+typedef void (*DBDMA_flush)(DBDMA_io *io);
+typedef void (*DBDMA_rw)(DBDMA_io *io);
+typedef void (*DBDMA_end)(DBDMA_io *io);
+struct DBDMA_io {
+ void *opaque;
+ void *channel;
+ hwaddr addr;
+ int len;
+ int is_last;
+ int is_dma_out;
+ DBDMA_end dma_end;
+ /* DMA is in progress, don't start another one */
+ bool processing;
+ /* DMA request */
+ void *dma_mem;
+ dma_addr_t dma_len;
+ DMADirection dir;
+};
+
+/*
+ * DBDMA control/status registers. All little-endian.
+ */
+
+#define DBDMA_CONTROL 0x00
+#define DBDMA_STATUS 0x01
+#define DBDMA_CMDPTR_HI 0x02
+#define DBDMA_CMDPTR_LO 0x03
+#define DBDMA_INTR_SEL 0x04
+#define DBDMA_BRANCH_SEL 0x05
+#define DBDMA_WAIT_SEL 0x06
+#define DBDMA_XFER_MODE 0x07
+#define DBDMA_DATA2PTR_HI 0x08
+#define DBDMA_DATA2PTR_LO 0x09
+#define DBDMA_RES1 0x0A
+#define DBDMA_ADDRESS_HI 0x0B
+#define DBDMA_BRANCH_ADDR_HI 0x0C
+#define DBDMA_RES2 0x0D
+#define DBDMA_RES3 0x0E
+#define DBDMA_RES4 0x0F
+
+#define DBDMA_REGS 16
+#define DBDMA_SIZE (DBDMA_REGS * sizeof(uint32_t))
+
+#define DBDMA_CHANNEL_SHIFT 7
+#define DBDMA_CHANNEL_SIZE (1 << DBDMA_CHANNEL_SHIFT)
+
+#define DBDMA_CHANNELS (0x1000 >> DBDMA_CHANNEL_SHIFT)
+
+/* Bits in control and status registers */
+
+#define RUN 0x8000
+#define PAUSE 0x4000
+#define FLUSH 0x2000
+#define WAKE 0x1000
+#define DEAD 0x0800
+#define ACTIVE 0x0400
+#define BT 0x0100
+#define DEVSTAT 0x00ff
+
+/*
+ * DBDMA command structure. These fields are all little-endian!
+ */
+
+typedef struct dbdma_cmd {
+ uint16_t req_count; /* requested byte transfer count */
+ uint16_t command; /* command word (has bit-fields) */
+ uint32_t phy_addr; /* physical data address */
+ uint32_t cmd_dep; /* command-dependent field */
+ uint16_t res_count; /* residual count after completion */
+ uint16_t xfer_status; /* transfer status */
+} dbdma_cmd;
+
+/* DBDMA command values in command field */
+
+#define COMMAND_MASK 0xf000
+#define OUTPUT_MORE 0x0000 /* transfer memory data to stream */
+#define OUTPUT_LAST 0x1000 /* ditto followed by end marker */
+#define INPUT_MORE 0x2000 /* transfer stream data to memory */
+#define INPUT_LAST 0x3000 /* ditto, expect end marker */
+#define STORE_WORD 0x4000 /* write word (4 bytes) to device reg */
+#define LOAD_WORD 0x5000 /* read word (4 bytes) from device reg */
+#define DBDMA_NOP 0x6000 /* do nothing */
+#define DBDMA_STOP 0x7000 /* suspend processing */
+
+/* Key values in command field */
+
+#define KEY_MASK 0x0700
+#define KEY_STREAM0 0x0000 /* usual data stream */
+#define KEY_STREAM1 0x0100 /* control/status stream */
+#define KEY_STREAM2 0x0200 /* device-dependent stream */
+#define KEY_STREAM3 0x0300 /* device-dependent stream */
+#define KEY_STREAM4 0x0400 /* reserved */
+#define KEY_REGS 0x0500 /* device register space */
+#define KEY_SYSTEM 0x0600 /* system memory-mapped space */
+#define KEY_DEVICE 0x0700 /* device memory-mapped space */
+
+/* Interrupt control values in command field */
+
+#define INTR_MASK 0x0030
+#define INTR_NEVER 0x0000 /* don't interrupt */
+#define INTR_IFSET 0x0010 /* intr if condition bit is 1 */
+#define INTR_IFCLR 0x0020 /* intr if condition bit is 0 */
+#define INTR_ALWAYS 0x0030 /* always interrupt */
+
+/* Branch control values in command field */
+
+#define BR_MASK 0x000c
+#define BR_NEVER 0x0000 /* don't branch */
+#define BR_IFSET 0x0004 /* branch if condition bit is 1 */
+#define BR_IFCLR 0x0008 /* branch if condition bit is 0 */
+#define BR_ALWAYS 0x000c /* always branch */
+
+/* Wait control values in command field */
+
+#define WAIT_MASK 0x0003
+#define WAIT_NEVER 0x0000 /* don't wait */
+#define WAIT_IFSET 0x0001 /* wait if condition bit is 1 */
+#define WAIT_IFCLR 0x0002 /* wait if condition bit is 0 */
+#define WAIT_ALWAYS 0x0003 /* always wait */
+
+typedef struct DBDMA_channel {
+ int channel;
+ uint32_t regs[DBDMA_REGS];
+ qemu_irq irq;
+ DBDMA_io io;
+ DBDMA_rw rw;
+ DBDMA_flush flush;
+ dbdma_cmd current;
+} DBDMA_channel;
+
+struct DBDMAState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion mem;
+ DBDMA_channel channels[DBDMA_CHANNELS];
+ QEMUBH *bh;
+};
+typedef struct DBDMAState DBDMAState;
+
+/* Externally callable functions */
+
+void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq,
+ DBDMA_rw rw, DBDMA_flush flush,
+ void *opaque);
+void DBDMA_kick(DBDMAState *dbdma);
+
+#define TYPE_MAC_DBDMA "mac-dbdma"
+OBJECT_DECLARE_SIMPLE_TYPE(DBDMAState, MAC_DBDMA)
+
+#endif
diff --git a/include/hw/ppc/openpic.h b/include/hw/ppc/openpic.h
new file mode 100644
index 000000000..ebdaf8a49
--- /dev/null
+++ b/include/hw/ppc/openpic.h
@@ -0,0 +1,176 @@
+#ifndef OPENPIC_H
+#define OPENPIC_H
+
+#include "hw/sysbus.h"
+#include "hw/core/cpu.h"
+#include "qom/object.h"
+
+#define MAX_CPU 32
+#define MAX_MSI 8
+#define VID 0x03 /* MPIC version ID */
+
+/* OpenPIC have 5 outputs per CPU connected and one IRQ out single output */
+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_RESET, /* Core reset event */
+ OPENPIC_OUTPUT_NB,
+};
+
+typedef struct IrqLines { qemu_irq irq[OPENPIC_OUTPUT_NB]; } IrqLines;
+
+#define OPENPIC_MODEL_FSL_MPIC_20 1
+#define OPENPIC_MODEL_FSL_MPIC_42 2
+#define OPENPIC_MODEL_KEYLARGO 3
+
+#define OPENPIC_MAX_SRC 256
+#define OPENPIC_MAX_TMR 4
+#define OPENPIC_MAX_IPI 4
+#define OPENPIC_MAX_IRQ (OPENPIC_MAX_SRC + OPENPIC_MAX_IPI + \
+ OPENPIC_MAX_TMR)
+
+/* KeyLargo */
+#define KEYLARGO_MAX_CPU 4
+#define KEYLARGO_MAX_EXT 64
+#define KEYLARGO_MAX_IPI 4
+#define KEYLARGO_MAX_IRQ (64 + KEYLARGO_MAX_IPI)
+#define KEYLARGO_MAX_TMR 0
+#define KEYLARGO_IPI_IRQ (KEYLARGO_MAX_EXT) /* First IPI IRQ */
+/* Timers don't exist but this makes the code happy... */
+#define KEYLARGO_TMR_IRQ (KEYLARGO_IPI_IRQ + KEYLARGO_MAX_IPI)
+
+typedef struct FslMpicInfo {
+ int max_ext;
+} FslMpicInfo;
+
+typedef enum IRQType {
+ IRQ_TYPE_NORMAL = 0,
+ IRQ_TYPE_FSLINT, /* FSL internal interrupt -- level only */
+ IRQ_TYPE_FSLSPECIAL, /* FSL timer/IPI interrupt, edge, no polarity */
+} IRQType;
+
+/*
+ * 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)
+
+typedef struct IRQQueue {
+ unsigned long *queue;
+ int32_t queue_size; /* Only used for VMSTATE_BITMAP */
+ int next;
+ int priority;
+} IRQQueue;
+
+typedef struct IRQSource {
+ uint32_t ivpr; /* IRQ vector/priority register */
+ uint32_t idr; /* IRQ destination register */
+ uint32_t destmask; /* bitmap of CPU destinations */
+ int last_cpu;
+ int output; /* IRQ level, e.g. OPENPIC_OUTPUT_INT */
+ int pending; /* TRUE if IRQ is pending */
+ IRQType type;
+ bool level:1; /* level-triggered */
+ bool nomask:1; /* critical interrupts ignore mask on some FSL MPICs */
+} IRQSource;
+
+#define IVPR_MASK_SHIFT 31
+#define IVPR_MASK_MASK (1U << IVPR_MASK_SHIFT)
+#define IVPR_ACTIVITY_SHIFT 30
+#define IVPR_ACTIVITY_MASK (1U << IVPR_ACTIVITY_SHIFT)
+#define IVPR_MODE_SHIFT 29
+#define IVPR_MODE_MASK (1U << IVPR_MODE_SHIFT)
+#define IVPR_POLARITY_SHIFT 23
+#define IVPR_POLARITY_MASK (1U << IVPR_POLARITY_SHIFT)
+#define IVPR_SENSE_SHIFT 22
+#define IVPR_SENSE_MASK (1U << IVPR_SENSE_SHIFT)
+
+#define IVPR_PRIORITY_MASK (0xFU << 16)
+#define IVPR_PRIORITY(_ivprr_) ((int)(((_ivprr_) & IVPR_PRIORITY_MASK) >> 16))
+#define IVPR_VECTOR(opp, _ivprr_) ((_ivprr_) & (opp)->vector_mask)
+
+/* IDR[EP/CI] are only for FSL MPIC prior to v4.0 */
+#define IDR_EP 0x80000000 /* external pin */
+#define IDR_CI 0x40000000 /* critical interrupt */
+
+typedef struct OpenPICTimer {
+ uint32_t tccr; /* Global timer current count register */
+ uint32_t tbcr; /* Global timer base count register */
+ int n_IRQ;
+ 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.
+ */
+ uint64_t origin_time;
+} OpenPICTimer;
+
+typedef struct OpenPICMSI {
+ uint32_t msir; /* Shared Message Signaled Interrupt Register */
+} OpenPICMSI;
+
+typedef struct IRQDest {
+ int32_t ctpr; /* CPU current task priority */
+ IRQQueue raised;
+ IRQQueue servicing;
+ qemu_irq *irqs;
+
+ /* Count of IRQ sources asserting on non-INT outputs */
+ uint32_t outputs_active[OPENPIC_OUTPUT_NB];
+} IRQDest;
+
+#define TYPE_OPENPIC "openpic"
+OBJECT_DECLARE_SIMPLE_TYPE(OpenPICState, OPENPIC)
+
+struct OpenPICState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ MemoryRegion mem;
+
+ /* Behavior control */
+ FslMpicInfo *fsl;
+ uint32_t model;
+ uint32_t flags;
+ uint32_t nb_irqs;
+ uint32_t vid;
+ uint32_t vir; /* Vendor identification register */
+ uint32_t vector_mask;
+ uint32_t tfrr_reset;
+ uint32_t ivpr_reset;
+ uint32_t idr_reset;
+ uint32_t brr1;
+ uint32_t mpic_mode_mask;
+
+ /* Sub-regions */
+ MemoryRegion sub_io_mem[6];
+
+ /* Global registers */
+ uint32_t frr; /* Feature reporting register */
+ uint32_t gcr; /* Global configuration register */
+ uint32_t pir; /* Processor initialization register */
+ uint32_t spve; /* Spurious vector register */
+ uint32_t tfrr; /* Timer frequency reporting register */
+ /* Source registers */
+ IRQSource src[OPENPIC_MAX_IRQ];
+ /* Local registers per output pin */
+ IRQDest dst[MAX_CPU];
+ uint32_t nb_cpus;
+ /* Timer registers */
+ OpenPICTimer timers[OPENPIC_MAX_TMR];
+ uint32_t max_tmr;
+
+ /* Shared MSI registers */
+ OpenPICMSI msi[MAX_MSI];
+ uint32_t max_irq;
+ uint32_t irq_ipi0;
+ uint32_t irq_tim0;
+ uint32_t irq_msi;
+};
+
+#endif /* OPENPIC_H */
diff --git a/include/hw/ppc/openpic_kvm.h b/include/hw/ppc/openpic_kvm.h
new file mode 100644
index 000000000..9ef421525
--- /dev/null
+++ b/include/hw/ppc/openpic_kvm.h
@@ -0,0 +1,7 @@
+#ifndef OPENPIC_KVM_H
+#define OPENPIC_KVM_H
+
+#define TYPE_KVM_OPENPIC "kvm-openpic"
+int kvm_openpic_connect_vcpu(DeviceState *d, CPUState *cs);
+
+#endif /* OPENPIC_KVM_H */
diff --git a/include/hw/ppc/pef.h b/include/hw/ppc/pef.h
new file mode 100644
index 000000000..707dbe524
--- /dev/null
+++ b/include/hw/ppc/pef.h
@@ -0,0 +1,17 @@
+/*
+ * PEF (Protected Execution Facility) for POWER support
+ *
+ * Copyright Red Hat.
+ *
+ * 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_PPC_PEF_H
+#define HW_PPC_PEF_H
+
+int pef_kvm_init(ConfidentialGuestSupport *cgs, Error **errp);
+int pef_kvm_reset(ConfidentialGuestSupport *cgs, Error **errp);
+
+#endif /* HW_PPC_PEF_H */
diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
new file mode 100644
index 000000000..aa08d79d2
--- /dev/null
+++ b/include/hw/ppc/pnv.h
@@ -0,0 +1,332 @@
+/*
+ * QEMU PowerPC PowerNV various definitions
+ *
+ * Copyright (c) 2014-2016 BenH, 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_H
+#define PPC_PNV_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"
+#include "qom/object.h"
+
+#define TYPE_PNV_CHIP "pnv-chip"
+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_phbs;
+
+ MemoryRegion xscom_mmio;
+ MemoryRegion xscom;
+ AddressSpace xscom_as;
+
+ MemoryRegion *fw_mr;
+ gchar *dt_isa_nodename;
+};
+
+#define TYPE_PNV8_CHIP "pnv8-chip"
+typedef struct Pnv8Chip Pnv8Chip;
+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
+ PnvPHB3 phbs[PNV8_CHIP_PHB3_MAX];
+
+ XICSFabric *xics;
+};
+
+#define TYPE_PNV9_CHIP "pnv9-chip"
+typedef struct Pnv9Chip Pnv9Chip;
+DECLARE_INSTANCE_CHECKER(Pnv9Chip, PNV9_CHIP,
+ TYPE_PNV9_CHIP)
+
+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];
+};
+
+/*
+ * 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"
+typedef struct Pnv10Chip Pnv10Chip;
+DECLARE_INSTANCE_CHECKER(Pnv10Chip, PNV10_CHIP,
+ TYPE_PNV10_CHIP)
+
+struct Pnv10Chip {
+ /*< private >*/
+ PnvChip parent_obj;
+
+ /*< public >*/
+ Pnv9Psi psi;
+ PnvLpcController lpc;
+};
+
+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);
+};
+
+#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")
+DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER8E,
+ TYPE_PNV_CHIP_POWER8E)
+
+#define TYPE_PNV_CHIP_POWER8 PNV_CHIP_TYPE_NAME("power8_v2.0")
+DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER8,
+ TYPE_PNV_CHIP_POWER8)
+
+#define TYPE_PNV_CHIP_POWER8NVL PNV_CHIP_TYPE_NAME("power8nvl_v1.0")
+DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER8NVL,
+ TYPE_PNV_CHIP_POWER8NVL)
+
+#define TYPE_PNV_CHIP_POWER9 PNV_CHIP_TYPE_NAME("power9_v2.0")
+DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER9,
+ TYPE_PNV_CHIP_POWER9)
+
+#define TYPE_PNV_CHIP_POWER10 PNV_CHIP_TYPE_NAME("power10_v2.0")
+DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER10,
+ TYPE_PNV_CHIP_POWER10)
+
+PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir);
+
+#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)
+
+
+struct PnvMachineClass {
+ /*< private >*/
+ MachineClass parent_class;
+
+ /*< public >*/
+ const char *compat;
+ int compat_size;
+
+ void (*dt_power_mgt)(PnvMachineState *pnv, void *fdt);
+};
+
+struct PnvMachineState {
+ /*< private >*/
+ MachineState parent_obj;
+
+ uint32_t initrd_base;
+ long initrd_size;
+
+ uint32_t num_chips;
+ PnvChip **chips;
+
+ ISABus *isa_bus;
+ uint32_t cpld_irqstate;
+
+ IPMIBmc *bmc;
+ Notifier powerdown_notifier;
+
+ PnvPnor *pnor;
+
+ hwaddr fw_load_addr;
+};
+
+#define PNV_FDT_ADDR 0x01000000
+#define PNV_TIMEBASE_FREQ 512000000ULL
+
+/*
+ * BMC helpers
+ */
+void pnv_dt_bmc_sensors(IPMIBmc *bmc, void *fdt);
+void pnv_bmc_powerdown(IPMIBmc *bmc);
+IPMIBmc *pnv_bmc_create(PnvPnor *pnor);
+IPMIBmc *pnv_bmc_find(Error **errp);
+void pnv_bmc_set_pnor(IPMIBmc *bmc, PnvPnor *pnor);
+
+/*
+ * POWER8 MMIO base addresses
+ */
+#define PNV_XSCOM_SIZE 0x800000000ull
+#define PNV_XSCOM_BASE(chip) \
+ (0x0003fc0000000000ull + ((uint64_t)(chip)->chip_id) * PNV_XSCOM_SIZE)
+
+#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((chip)->chip_id))
+
+#define PNV_HOMER_SIZE 0x0000000000400000ull
+#define PNV_HOMER_BASE(chip) \
+ (0x7ffd800000ull + ((uint64_t)(chip)->chip_id) * PNV_HOMER_SIZE)
+
+
+/*
+ * XSCOM 0x20109CA defines the ICP BAR:
+ *
+ * 0:29 : bits 14 to 43 of address to define 1 MB region.
+ * 30 : 1 to enable ICP to receive loads/stores against its BAR region
+ * 31:63 : Constant 0
+ *
+ * Usually defined as :
+ *
+ * 0xffffe00200000000 -> 0x0003ffff80000000
+ * 0xffffe00600000000 -> 0x0003ffff80100000
+ * 0xffffe02200000000 -> 0x0003ffff80800000
+ * 0xffffe02600000000 -> 0x0003ffff80900000
+ */
+#define PNV_ICP_SIZE 0x0000000000100000ull
+#define PNV_ICP_BASE(chip) \
+ (0x0003ffff80000000ull + (uint64_t) (chip)->chip_id * PNV_ICP_SIZE)
+
+
+#define PNV_PSIHB_SIZE 0x0000000000100000ull
+#define PNV_PSIHB_BASE(chip) \
+ (0x0003fffe80000000ull + (uint64_t)(chip)->chip_id * PNV_PSIHB_SIZE)
+
+#define PNV_PSIHB_FSP_SIZE 0x0000000100000000ull
+#define PNV_PSIHB_FSP_BASE(chip) \
+ (0x0003ffe000000000ull + (uint64_t)(chip)->chip_id * \
+ PNV_PSIHB_FSP_SIZE)
+
+/*
+ * POWER9 MMIO base addresses
+ */
+#define PNV9_CHIP_BASE(chip, base) \
+ ((base) + ((uint64_t) (chip)->chip_id << 42))
+
+#define PNV9_XIVE_VC_SIZE 0x0000008000000000ull
+#define PNV9_XIVE_VC_BASE(chip) PNV9_CHIP_BASE(chip, 0x0006010000000000ull)
+
+#define PNV9_XIVE_PC_SIZE 0x0000001000000000ull
+#define PNV9_XIVE_PC_BASE(chip) PNV9_CHIP_BASE(chip, 0x0006018000000000ull)
+
+#define PNV9_LPCM_SIZE 0x0000000100000000ull
+#define PNV9_LPCM_BASE(chip) PNV9_CHIP_BASE(chip, 0x0006030000000000ull)
+
+#define PNV9_PSIHB_SIZE 0x0000000000100000ull
+#define PNV9_PSIHB_BASE(chip) PNV9_CHIP_BASE(chip, 0x0006030203000000ull)
+
+#define PNV9_XIVE_IC_SIZE 0x0000000000080000ull
+#define PNV9_XIVE_IC_BASE(chip) PNV9_CHIP_BASE(chip, 0x0006030203100000ull)
+
+#define PNV9_XIVE_TM_SIZE 0x0000000000040000ull
+#define PNV9_XIVE_TM_BASE(chip) PNV9_CHIP_BASE(chip, 0x0006030203180000ull)
+
+#define PNV9_PSIHB_ESB_SIZE 0x0000000000010000ull
+#define PNV9_PSIHB_ESB_BASE(chip) PNV9_CHIP_BASE(chip, 0x00060302031c0000ull)
+
+#define PNV9_XSCOM_SIZE 0x0000000400000000ull
+#define PNV9_XSCOM_BASE(chip) PNV9_CHIP_BASE(chip, 0x00603fc00000000ull)
+
+#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((chip)->chip_id))
+
+#define PNV9_HOMER_SIZE 0x0000000000400000ull
+#define PNV9_HOMER_BASE(chip) \
+ (0x203ffd800000ull + ((uint64_t)(chip)->chip_id) * PNV9_HOMER_SIZE)
+
+/*
+ * POWER10 MMIO base addresses - 16TB stride per chip
+ */
+#define PNV10_CHIP_BASE(chip, base) \
+ ((base) + ((uint64_t) (chip)->chip_id << 44))
+
+#define PNV10_XSCOM_SIZE 0x0000000400000000ull
+#define PNV10_XSCOM_BASE(chip) PNV10_CHIP_BASE(chip, 0x00603fc00000000ull)
+
+#define PNV10_LPCM_SIZE 0x0000000100000000ull
+#define PNV10_LPCM_BASE(chip) PNV10_CHIP_BASE(chip, 0x0006030000000000ull)
+
+#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)
+
+#endif /* PPC_PNV_H */
diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h
new file mode 100644
index 000000000..c22eab2e1
--- /dev/null
+++ b/include/hw/ppc/pnv_core.h
@@ -0,0 +1,73 @@
+/*
+ * QEMU PowerPC PowerNV CPU Core model
+ *
+ * Copyright (c) 2016, 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_CORE_H
+#define PPC_PNV_CORE_H
+
+#include "hw/cpu/core.h"
+#include "target/ppc/cpu.h"
+#include "qom/object.h"
+
+#define TYPE_PNV_CORE "powernv-cpu-core"
+OBJECT_DECLARE_TYPE(PnvCore, PnvCoreClass,
+ PNV_CORE)
+
+typedef struct PnvChip PnvChip;
+
+struct PnvCore {
+ /*< private >*/
+ CPUCore parent_obj;
+
+ /*< public >*/
+ PowerPCCPU **threads;
+ uint32_t pir;
+ uint64_t hrmor;
+ PnvChip *chip;
+
+ MemoryRegion xscom_regs;
+};
+
+struct PnvCoreClass {
+ DeviceClass parent_class;
+
+ const MemoryRegionOps *xscom_ops;
+};
+
+#define PNV_CORE_TYPE_SUFFIX "-" TYPE_PNV_CORE
+#define PNV_CORE_TYPE_NAME(cpu_model) cpu_model PNV_CORE_TYPE_SUFFIX
+
+typedef struct PnvCPUState {
+ Object *intc;
+} PnvCPUState;
+
+static inline PnvCPUState *pnv_cpu_state(PowerPCCPU *cpu)
+{
+ return (PnvCPUState *)cpu->machine_data;
+}
+
+#define TYPE_PNV_QUAD "powernv-cpu-quad"
+OBJECT_DECLARE_SIMPLE_TYPE(PnvQuad, PNV_QUAD)
+
+struct PnvQuad {
+ DeviceState parent_obj;
+
+ uint32_t quad_id;
+ MemoryRegion xscom_regs;
+};
+#endif /* PPC_PNV_CORE_H */
diff --git a/include/hw/ppc/pnv_homer.h b/include/hw/ppc/pnv_homer.h
new file mode 100644
index 000000000..1889e3083
--- /dev/null
+++ b/include/hw/ppc/pnv_homer.h
@@ -0,0 +1,56 @@
+/*
+ * QEMU PowerPC PowerNV Emulation of a few HOMER related registers
+ *
+ * Copyright (c) 2019, 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_HOMER_H
+#define PPC_PNV_HOMER_H
+
+#include "hw/ppc/pnv.h"
+#include "qom/object.h"
+
+#define TYPE_PNV_HOMER "pnv-homer"
+OBJECT_DECLARE_TYPE(PnvHomer, PnvHomerClass,
+ PNV_HOMER)
+#define TYPE_PNV8_HOMER TYPE_PNV_HOMER "-POWER8"
+DECLARE_INSTANCE_CHECKER(PnvHomer, PNV8_HOMER,
+ TYPE_PNV8_HOMER)
+#define TYPE_PNV9_HOMER TYPE_PNV_HOMER "-POWER9"
+DECLARE_INSTANCE_CHECKER(PnvHomer, PNV9_HOMER,
+ TYPE_PNV9_HOMER)
+
+struct PnvHomer {
+ DeviceState parent;
+
+ struct PnvChip *chip;
+ MemoryRegion pba_regs;
+ MemoryRegion regs;
+};
+
+
+struct PnvHomerClass {
+ DeviceClass parent_class;
+
+ int pba_size;
+ const MemoryRegionOps *pba_ops;
+ int homer_size;
+ const MemoryRegionOps *homer_ops;
+
+ hwaddr core_max_base;
+};
+
+#endif /* PPC_PNV_HOMER_H */
diff --git a/include/hw/ppc/pnv_lpc.h b/include/hw/ppc/pnv_lpc.h
new file mode 100644
index 000000000..e893e763d
--- /dev/null
+++ b/include/hw/ppc/pnv_lpc.h
@@ -0,0 +1,108 @@
+/*
+ * QEMU PowerPC PowerNV LPC controller
+ *
+ * Copyright (c) 2016, 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_LPC_H
+#define PPC_PNV_LPC_H
+
+#include "hw/ppc/pnv_psi.h"
+#include "qom/object.h"
+
+#define TYPE_PNV_LPC "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"
+DECLARE_INSTANCE_CHECKER(PnvLpcController, PNV8_LPC,
+ TYPE_PNV8_LPC)
+
+#define TYPE_PNV9_LPC TYPE_PNV_LPC "-POWER9"
+DECLARE_INSTANCE_CHECKER(PnvLpcController, PNV9_LPC,
+ TYPE_PNV9_LPC)
+
+#define TYPE_PNV10_LPC TYPE_PNV_LPC "-POWER10"
+DECLARE_INSTANCE_CHECKER(PnvLpcController, PNV10_LPC,
+ TYPE_PNV10_LPC)
+
+struct PnvLpcController {
+ DeviceState parent;
+
+ uint64_t eccb_stat_reg;
+ uint32_t eccb_data_reg;
+
+ /* OPB bus */
+ MemoryRegion opb_mr;
+ AddressSpace opb_as;
+
+ /* ISA IO and Memory space */
+ MemoryRegion isa_io;
+ MemoryRegion isa_mem;
+ MemoryRegion isa_fw;
+
+ /* Windows from OPB to ISA (aliases) */
+ MemoryRegion opb_isa_io;
+ MemoryRegion opb_isa_mem;
+ MemoryRegion opb_isa_fw;
+
+ /* Registers */
+ MemoryRegion lpc_hc_regs;
+ MemoryRegion opb_master_regs;
+
+ /* OPB Master LS registers */
+ uint32_t opb_irq_route0;
+ uint32_t opb_irq_route1;
+ uint32_t opb_irq_stat;
+ uint32_t opb_irq_mask;
+ uint32_t opb_irq_pol;
+ uint32_t opb_irq_input;
+
+ /* LPC HC registers */
+ uint32_t lpc_hc_fw_seg_idsel;
+ uint32_t lpc_hc_fw_rd_acc_size;
+ uint32_t lpc_hc_irqser_ctrl;
+ uint32_t lpc_hc_irqmask;
+ uint32_t lpc_hc_irqstat;
+ uint32_t lpc_hc_error_addr;
+
+ /* XSCOM registers */
+ MemoryRegion xscom_regs;
+
+ /* PSI to generate interrupts */
+ PnvPsi *psi;
+};
+
+
+struct PnvLpcClass {
+ DeviceClass parent_class;
+
+ int psi_irq;
+
+ DeviceRealize parent_realize;
+};
+
+/*
+ * 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,
+ uint64_t lpcm_addr, uint64_t lpcm_size);
+
+#endif /* PPC_PNV_LPC_H */
diff --git a/include/hw/ppc/pnv_occ.h b/include/hw/ppc/pnv_occ.h
new file mode 100644
index 000000000..b78185aec
--- /dev/null
+++ b/include/hw/ppc/pnv_occ.h
@@ -0,0 +1,63 @@
+/*
+ * QEMU PowerPC PowerNV Emulation of a few OCC related registers
+ *
+ * Copyright (c) 2015-2017, 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_OCC_H
+#define PPC_PNV_OCC_H
+
+#include "hw/ppc/pnv_psi.h"
+#include "qom/object.h"
+
+#define TYPE_PNV_OCC "pnv-occ"
+OBJECT_DECLARE_TYPE(PnvOCC, PnvOCCClass,
+ PNV_OCC)
+#define TYPE_PNV8_OCC TYPE_PNV_OCC "-POWER8"
+DECLARE_INSTANCE_CHECKER(PnvOCC, PNV8_OCC,
+ TYPE_PNV8_OCC)
+#define TYPE_PNV9_OCC TYPE_PNV_OCC "-POWER9"
+DECLARE_INSTANCE_CHECKER(PnvOCC, PNV9_OCC,
+ TYPE_PNV9_OCC)
+
+#define PNV_OCC_SENSOR_DATA_BLOCK_OFFSET 0x00580000
+#define PNV_OCC_SENSOR_DATA_BLOCK_SIZE 0x00025800
+
+struct PnvOCC {
+ DeviceState xd;
+
+ /* OCC Misc interrupt */
+ uint64_t occmisc;
+
+ PnvPsi *psi;
+
+ MemoryRegion xscom_regs;
+ MemoryRegion sram_regs;
+};
+
+
+struct PnvOCCClass {
+ DeviceClass parent_class;
+
+ int xscom_size;
+ const MemoryRegionOps *xscom_ops;
+ int psi_irq;
+};
+
+#define PNV_OCC_SENSOR_DATA_BLOCK_BASE(i) \
+ (PNV_OCC_SENSOR_DATA_BLOCK_OFFSET + (i) * PNV_OCC_SENSOR_DATA_BLOCK_SIZE)
+
+#endif /* PPC_PNV_OCC_H */
diff --git a/include/hw/ppc/pnv_pnor.h b/include/hw/ppc/pnv_pnor.h
new file mode 100644
index 000000000..99f9a3adf
--- /dev/null
+++ b/include/hw/ppc/pnv_pnor.h
@@ -0,0 +1,31 @@
+/*
+ * QEMU PowerNV PNOR simple model
+ *
+ * Copyright (c) 2019, IBM Corporation.
+ *
+ * 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
+#include "qom/object.h"
+
+/*
+ * PNOR offset on the LPC FW address space
+ */
+#define PNOR_SPI_OFFSET 0x0c000000UL
+
+#define TYPE_PNV_PNOR "pnv-pnor"
+OBJECT_DECLARE_SIMPLE_TYPE(PnvPnor, PNV_PNOR)
+
+struct PnvPnor {
+ SysBusDevice parent_obj;
+
+ BlockBackend *blk;
+
+ uint8_t *storage;
+ int64_t size;
+ MemoryRegion mmio;
+};
+
+#endif /* _PPC_PNV_PNOR_H */
diff --git a/include/hw/ppc/pnv_psi.h b/include/hw/ppc/pnv_psi.h
new file mode 100644
index 000000000..eb841b34a
--- /dev/null
+++ b/include/hw/ppc/pnv_psi.h
@@ -0,0 +1,120 @@
+/*
+ * QEMU PowerPC PowerNV Processor Service Interface (PSI) model
+ *
+ * Copyright (c) 2015-2017, 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_PSI_H
+#define PPC_PNV_PSI_H
+
+#include "hw/sysbus.h"
+#include "hw/ppc/xics.h"
+#include "hw/ppc/xive.h"
+#include "qom/object.h"
+
+#define TYPE_PNV_PSI "pnv-psi"
+OBJECT_DECLARE_TYPE(PnvPsi, PnvPsiClass,
+ PNV_PSI)
+
+#define PSIHB_XSCOM_MAX 0x20
+
+struct PnvPsi {
+ DeviceState parent;
+
+ MemoryRegion regs_mr;
+ uint64_t bar;
+
+ /* FSP region not supported */
+ /* MemoryRegion fsp_mr; */
+ uint64_t fsp_bar;
+
+ /* Interrupt generation */
+ qemu_irq *qirqs;
+
+ /* Registers */
+ uint64_t regs[PSIHB_XSCOM_MAX];
+
+ MemoryRegion xscom_regs;
+};
+
+#define TYPE_PNV8_PSI TYPE_PNV_PSI "-POWER8"
+OBJECT_DECLARE_SIMPLE_TYPE(Pnv8Psi, PNV8_PSI)
+
+struct Pnv8Psi {
+ PnvPsi parent;
+
+ ICSState ics;
+};
+
+#define TYPE_PNV9_PSI TYPE_PNV_PSI "-POWER9"
+OBJECT_DECLARE_SIMPLE_TYPE(Pnv9Psi, PNV9_PSI)
+
+struct Pnv9Psi {
+ PnvPsi parent;
+
+ XiveSource source;
+};
+
+#define TYPE_PNV10_PSI TYPE_PNV_PSI "-POWER10"
+
+
+struct PnvPsiClass {
+ SysBusDeviceClass parent_class;
+
+ uint32_t xscom_pcba;
+ uint32_t xscom_size;
+ uint64_t bar_mask;
+ const char *compat;
+ int compat_size;
+
+ void (*irq_set)(PnvPsi *psi, int, bool state);
+};
+
+/* 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,
+ PSIHB_IRQ_LPC_I2C,
+ PSIHB_IRQ_LOCAL_ERR,
+ PSIHB_IRQ_EXTERNAL,
+} 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
+#define PSIHB9_IRQ_FSI 2
+#define PSIHB9_IRQ_LPCHC 3
+#define PSIHB9_IRQ_LOCAL_ERR 4
+#define PSIHB9_IRQ_GLOBAL_ERR 5
+#define PSIHB9_IRQ_TPM 6
+#define PSIHB9_IRQ_LPC_SIRQ0 7
+#define PSIHB9_IRQ_LPC_SIRQ1 8
+#define PSIHB9_IRQ_LPC_SIRQ2 9
+#define PSIHB9_IRQ_LPC_SIRQ3 10
+#define PSIHB9_IRQ_SBE_I2C 11
+#define PSIHB9_IRQ_DIO 12
+#define PSIHB9_IRQ_PSU 13
+#define PSIHB9_NUM_IRQS 14
+
+void pnv_psi_pic_print_info(Pnv9Psi *psi, Monitor *mon);
+
+#endif /* PPC_PNV_PSI_H */
diff --git a/include/hw/ppc/pnv_xive.h b/include/hw/ppc/pnv_xive.h
new file mode 100644
index 000000000..7928e2796
--- /dev/null
+++ b/include/hw/ppc/pnv_xive.h
@@ -0,0 +1,98 @@
+/*
+ * QEMU PowerPC XIVE interrupt controller model
+ *
+ * Copyright (c) 2017-2019, IBM Corporation.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+
+#ifndef PPC_PNV_XIVE_H
+#define PPC_PNV_XIVE_H
+
+#include "hw/ppc/xive.h"
+#include "qom/object.h"
+
+struct PnvChip;
+
+#define TYPE_PNV_XIVE "pnv-xive"
+OBJECT_DECLARE_TYPE(PnvXive, PnvXiveClass,
+ PNV_XIVE)
+
+#define XIVE_BLOCK_MAX 16
+
+#define XIVE_TABLE_BLK_MAX 16 /* Block Scope Table (0-15) */
+#define XIVE_TABLE_MIG_MAX 16 /* Migration Register Table (1-15) */
+#define XIVE_TABLE_VDT_MAX 16 /* VDT Domain Table (0-15) */
+#define XIVE_TABLE_EDT_MAX 64 /* EDT Domain Table (0-63) */
+
+struct PnvXive {
+ XiveRouter parent_obj;
+
+ /* Owning chip */
+ struct PnvChip *chip;
+
+ /* XSCOM addresses giving access to the controller registers */
+ MemoryRegion xscom_regs;
+
+ /* Main MMIO regions that can be configured by FW */
+ MemoryRegion ic_mmio;
+ MemoryRegion ic_reg_mmio;
+ MemoryRegion ic_notify_mmio;
+ MemoryRegion ic_lsi_mmio;
+ MemoryRegion tm_indirect_mmio;
+ MemoryRegion vc_mmio;
+ MemoryRegion pc_mmio;
+ MemoryRegion tm_mmio;
+
+ /*
+ * IPI and END address spaces modeling the EDT segmentation in the
+ * VC region
+ */
+ AddressSpace ipi_as;
+ MemoryRegion ipi_mmio;
+ MemoryRegion ipi_edt_mmio;
+
+ AddressSpace end_as;
+ MemoryRegion end_mmio;
+ MemoryRegion end_edt_mmio;
+
+ /* Shortcut values for the Main MMIO regions */
+ hwaddr ic_base;
+ uint32_t ic_shift;
+ hwaddr vc_base;
+ uint32_t vc_shift;
+ hwaddr pc_base;
+ uint32_t pc_shift;
+ hwaddr tm_base;
+ uint32_t tm_shift;
+
+ /* Our XIVE source objects for IPIs and ENDs */
+ XiveSource ipi_source;
+ XiveENDSource end_source;
+
+ /* Interrupt controller registers */
+ uint64_t regs[0x300];
+
+ /*
+ * Virtual Structure Descriptor tables : EAT, SBE, ENDT, NVTT, IRQ
+ * These are in a SRAM protected by ECC.
+ */
+ uint64_t vsds[5][XIVE_BLOCK_MAX];
+
+ /* Translation tables */
+ uint64_t blk[XIVE_TABLE_BLK_MAX];
+ uint64_t mig[XIVE_TABLE_MIG_MAX];
+ uint64_t vdt[XIVE_TABLE_VDT_MAX];
+ uint64_t edt[XIVE_TABLE_EDT_MAX];
+};
+
+struct PnvXiveClass {
+ XiveRouterClass parent_class;
+
+ DeviceRealize parent_realize;
+};
+
+void pnv_xive_pic_print_info(PnvXive *xive, Monitor *mon);
+
+#endif /* PPC_PNV_XIVE_H */
diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h
new file mode 100644
index 000000000..2ff9f7a8d
--- /dev/null
+++ b/include/hw/ppc/pnv_xscom.h
@@ -0,0 +1,148 @@
+/*
+ * QEMU PowerPC PowerNV XSCOM bus definitions
+ *
+ * Copyright (c) 2016, 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_XSCOM_H
+#define PPC_PNV_XSCOM_H
+
+#include "qom/object.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)
+typedef struct PnvXScomInterfaceClass PnvXScomInterfaceClass;
+DECLARE_CLASS_CHECKERS(PnvXScomInterfaceClass, PNV_XSCOM_INTERFACE,
+ TYPE_PNV_XSCOM_INTERFACE)
+
+struct PnvXScomInterfaceClass {
+ InterfaceClass parent;
+ int (*dt_xscom)(PnvXScomInterface *dev, void *fdt, int offset);
+};
+
+/*
+ * Layout of the XSCOM PCB addresses of EX core 1 (POWER 8)
+ *
+ * GPIO 0x1100xxxx
+ * SCOM 0x1101xxxx
+ * OHA 0x1102xxxx
+ * CLOCK CTL 0x1103xxxx
+ * FIR 0x1104xxxx
+ * THERM 0x1105xxxx
+ * <reserved> 0x1106xxxx
+ * ..
+ * 0x110Exxxx
+ * PCB SLAVE 0x110Fxxxx
+ */
+
+#define PNV_XSCOM_EX_CORE_BASE 0x10000000ull
+
+#define PNV_XSCOM_EX_BASE(core) \
+ (PNV_XSCOM_EX_CORE_BASE | ((uint64_t)(core) << 24))
+#define PNV_XSCOM_EX_SIZE 0x100000
+
+#define PNV_XSCOM_LPC_BASE 0xb0020
+#define PNV_XSCOM_LPC_SIZE 0x4
+
+#define PNV_XSCOM_PSIHB_BASE 0x2010900
+#define PNV_XSCOM_PSIHB_SIZE 0x20
+
+#define PNV_XSCOM_OCC_BASE 0x0066000
+#define PNV_XSCOM_OCC_SIZE 0x6000
+
+#define PNV_XSCOM_PBA_BASE 0x2013f00
+#define PNV_XSCOM_PBA_SIZE 0x40
+
+#define PNV_XSCOM_PBCQ_NEST_BASE 0x2012000
+#define PNV_XSCOM_PBCQ_NEST_SIZE 0x46
+
+#define PNV_XSCOM_PBCQ_PCI_BASE 0x9012000
+#define PNV_XSCOM_PBCQ_PCI_SIZE 0x15
+
+#define PNV_XSCOM_PBCQ_SPCI_BASE 0x9013c00
+#define PNV_XSCOM_PBCQ_SPCI_SIZE 0x5
+
+/*
+ * Layout of the XSCOM PCB addresses (POWER 9)
+ */
+#define PNV9_XSCOM_EC_BASE(core) \
+ ((uint64_t)(((core) & 0x1F) + 0x20) << 24)
+#define PNV9_XSCOM_EC_SIZE 0x100000
+
+#define PNV9_XSCOM_EQ_BASE(core) \
+ ((uint64_t)(((core) & 0x1C) + 0x40) << 22)
+#define PNV9_XSCOM_EQ_SIZE 0x100000
+
+#define PNV9_XSCOM_OCC_BASE PNV_XSCOM_OCC_BASE
+#define PNV9_XSCOM_OCC_SIZE 0x8000
+
+#define PNV9_XSCOM_PBA_BASE 0x5012b00
+#define PNV9_XSCOM_PBA_SIZE 0x40
+
+#define PNV9_XSCOM_PSIHB_BASE 0x5012900
+#define PNV9_XSCOM_PSIHB_SIZE 0x100
+
+#define PNV9_XSCOM_XIVE_BASE 0x5013000
+#define PNV9_XSCOM_XIVE_SIZE 0x300
+
+#define PNV9_XSCOM_PEC_NEST_BASE 0x4010c00
+#define PNV9_XSCOM_PEC_NEST_SIZE 0x100
+
+#define PNV9_XSCOM_PEC_PCI_BASE 0xd010800
+#define PNV9_XSCOM_PEC_PCI_SIZE 0x200
+
+/* XSCOM PCI "pass-through" window to PHB SCOM */
+#define PNV9_XSCOM_PEC_PCI_STK0 0x100
+#define PNV9_XSCOM_PEC_PCI_STK1 0x140
+#define PNV9_XSCOM_PEC_PCI_STK2 0x180
+
+/*
+ * Layout of the XSCOM PCB addresses (POWER 10)
+ */
+#define PNV10_XSCOM_EQ_CHIPLET(core) (0x20 + ((core) >> 2))
+#define PNV10_XSCOM_EQ(chiplet) ((chiplet) << 24)
+#define PNV10_XSCOM_EC(proc) \
+ ((0x2 << 16) | ((1 << (3 - (proc))) << 12))
+
+#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_EC_BASE(core) \
+ ((uint64_t) PNV10_XSCOM_EQ_BASE(core) | PNV10_XSCOM_EC(core & 0x3))
+#define PNV10_XSCOM_EC_SIZE 0x100000
+
+#define PNV10_XSCOM_PSIHB_BASE 0x3011D00
+#define PNV10_XSCOM_PSIHB_SIZE 0x100
+
+void pnv_xscom_realize(PnvChip *chip, uint64_t size, Error **errp);
+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);
+
+void pnv_xscom_add_subregion(PnvChip *chip, hwaddr offset,
+ MemoryRegion *mr);
+void pnv_xscom_region_init(MemoryRegion *mr,
+ Object *owner,
+ const MemoryRegionOps *ops,
+ void *opaque,
+ const char *name,
+ uint64_t size);
+
+#endif /* PPC_PNV_XSCOM_H */
diff --git a/include/hw/ppc/ppc.h b/include/hw/ppc/ppc.h
new file mode 100644
index 000000000..93e614cff
--- /dev/null
+++ b/include/hw/ppc/ppc.h
@@ -0,0 +1,115 @@
+#ifndef HW_PPC_H
+#define HW_PPC_H
+
+#include "target/ppc/cpu-qom.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);
+
+/* PowerPC hardware exceptions management helpers */
+typedef void (*clk_setup_cb)(void *opaque, uint32_t freq);
+typedef struct clk_setup_t clk_setup_t;
+struct clk_setup_t {
+ clk_setup_cb cb;
+ void *opaque;
+};
+static inline void clk_setup (clk_setup_t *clk, uint32_t freq)
+{
+ if (clk->cb != NULL)
+ (*clk->cb)(clk->opaque, freq);
+}
+
+struct ppc_tb_t {
+ /* Time base management */
+ int64_t tb_offset; /* Compensation */
+ int64_t atb_offset; /* Compensation */
+ int64_t vtb_offset;
+ uint32_t tb_freq; /* TB frequency */
+ /* Decrementer management */
+ uint64_t decr_next; /* Tick for next decr interrupt */
+ uint32_t decr_freq; /* decrementer frequency */
+ QEMUTimer *decr_timer;
+ /* Hypervisor decrementer management */
+ uint64_t hdecr_next; /* Tick for next hdecr interrupt */
+ QEMUTimer *hdecr_timer;
+ int64_t purr_offset;
+ void *opaque;
+ uint32_t flags;
+};
+
+/* PPC Timers flags */
+#define PPC_TIMER_BOOKE (1 << 0) /* Enable Booke support */
+#define PPC_TIMER_E500 (1 << 1) /* Enable e500 support */
+#define PPC_DECR_UNDERFLOW_TRIGGERED (1 << 2) /* Decr interrupt triggered when
+ * the most significant bit
+ * changes from 0 to 1.
+ */
+#define PPC_DECR_ZERO_TRIGGERED (1 << 3) /* Decr interrupt triggered when
+ * the decrementer reaches zero.
+ */
+#define PPC_DECR_UNDERFLOW_LEVEL (1 << 4) /* Decr interrupt active when
+ * the most significant bit is 1.
+ */
+
+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);
+/* 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);
+int ppc_dcr_init (CPUPPCState *env, int (*dcr_read_error)(int dcrn),
+ int (*dcr_write_error)(int dcrn));
+int ppc_dcr_register (CPUPPCState *env, int dcrn, void *opaque,
+ dcr_read_cb drc_read, dcr_write_cb dcr_write);
+clk_setup_cb ppc_40x_timers_init (CPUPPCState *env, uint32_t freq,
+ unsigned int decr_excp);
+
+/* Embedded PowerPC reset */
+void ppc40x_core_reset(PowerPCCPU *cpu);
+void ppc40x_chip_reset(PowerPCCPU *cpu);
+void ppc40x_system_reset(PowerPCCPU *cpu);
+
+#if defined(CONFIG_USER_ONLY)
+static inline void ppc40x_irq_init(PowerPCCPU *cpu) {}
+static inline void ppc6xx_irq_init(PowerPCCPU *cpu) {}
+static inline void ppc970_irq_init(PowerPCCPU *cpu) {}
+static inline void ppcPOWER7_irq_init(PowerPCCPU *cpu) {}
+static inline void ppcPOWER9_irq_init(PowerPCCPU *cpu) {}
+static inline void ppce500_irq_init(PowerPCCPU *cpu) {}
+static inline void ppc_irq_reset(PowerPCCPU *cpu) {}
+#else
+void ppc40x_irq_init(PowerPCCPU *cpu);
+void ppce500_irq_init(PowerPCCPU *cpu);
+void ppc6xx_irq_init(PowerPCCPU *cpu);
+void ppc970_irq_init(PowerPCCPU *cpu);
+void ppcPOWER7_irq_init(PowerPCCPU *cpu);
+void ppcPOWER9_irq_init(PowerPCCPU *cpu);
+void ppc_irq_reset(PowerPCCPU *cpu);
+#endif
+
+/* PPC machines for OpenBIOS */
+enum {
+ ARCH_PREP = 0,
+ ARCH_MAC99,
+ ARCH_HEATHROW,
+ 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_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)
+#define FW_CFG_PPC_NVRAM_ADDR (FW_CFG_ARCH_LOCAL + 0x08)
+#define FW_CFG_PPC_BUSFREQ (FW_CFG_ARCH_LOCAL + 0x09)
+#define FW_CFG_PPC_NVRAM_FLAT (FW_CFG_ARCH_LOCAL + 0x0a)
+#define FW_CFG_PPC_VIACONFIG (FW_CFG_ARCH_LOCAL + 0x0b)
+
+#define PPC_SERIAL_MM_BAUDBASE 399193
+
+/* ppc_booke.c */
+void ppc_booke_timers_init(PowerPCCPU *cpu, uint32_t freq, uint32_t flags);
+#endif
diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h
new file mode 100644
index 000000000..980f964b5
--- /dev/null
+++ b/include/hw/ppc/ppc4xx.h
@@ -0,0 +1,52 @@
+/*
+ * QEMU PowerPC 4xx emulation shared definitions
+ *
+ * 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 PPC4XX_H
+#define PPC4XX_H
+
+#include "hw/ppc/ppc.h"
+#include "exec/memory.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);
+
+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_init (CPUPPCState *env, qemu_irq irq, int nbanks,
+ MemoryRegion ram_memories[],
+ hwaddr *ram_bases,
+ hwaddr *ram_sizes,
+ int do_init);
+
+void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum,
+ qemu_irq irqs[4]);
+
+#define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost"
+
+#endif /* PPC4XX_H */
diff --git a/include/hw/ppc/ppc_e500.h b/include/hw/ppc/ppc_e500.h
new file mode 100644
index 000000000..b66c0e3ee
--- /dev/null
+++ b/include/hw/ppc/ppc_e500.h
@@ -0,0 +1,6 @@
+#ifndef HW_PPC_E500_H
+#define HW_PPC_E500_H
+
+void ppce500_set_mpic_proxy(bool enabled);
+
+#endif
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
new file mode 100644
index 000000000..ee7504b97
--- /dev/null
+++ b/include/hw/ppc/spapr.h
@@ -0,0 +1,991 @@
+#ifndef HW_SPAPR_H
+#define HW_SPAPR_H
+
+#include "qemu/units.h"
+#include "sysemu/dma.h"
+#include "hw/boards.h"
+#include "hw/ppc/spapr_drc.h"
+#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/vof.h"
+
+struct SpaprVioBus;
+struct SpaprPhbState;
+struct SpaprNvram;
+
+typedef struct SpaprEventLogEntry SpaprEventLogEntry;
+typedef struct SpaprEventSource SpaprEventSource;
+typedef struct SpaprPendingHpt SpaprPendingHpt;
+
+#define HPTE64_V_HPTE_DIRTY 0x0000000000000040ULL
+#define SPAPR_ENTRY_POINT 0x100
+
+#define SPAPR_TIMEBASE_FREQ 512000000ULL
+
+#define TYPE_SPAPR_RTC "spapr-rtc"
+
+OBJECT_DECLARE_SIMPLE_TYPE(SpaprRtcState, SPAPR_RTC)
+
+struct SpaprRtcState {
+ /*< private >*/
+ DeviceState parent_obj;
+ int64_t ns_offset;
+};
+
+typedef struct SpaprDimmState SpaprDimmState;
+
+#define TYPE_SPAPR_MACHINE "spapr-machine"
+OBJECT_DECLARE_TYPE(SpaprMachineState, SpaprMachineClass, SPAPR_MACHINE)
+
+typedef enum {
+ SPAPR_RESIZE_HPT_DEFAULT = 0,
+ SPAPR_RESIZE_HPT_DISABLED,
+ SPAPR_RESIZE_HPT_ENABLED,
+ SPAPR_RESIZE_HPT_REQUIRED,
+} SpaprResizeHpt;
+
+/**
+ * Capabilities
+ */
+
+/* Hardware Transactional Memory */
+#define SPAPR_CAP_HTM 0x00
+/* Vector Scalar Extensions */
+#define SPAPR_CAP_VSX 0x01
+/* Decimal Floating Point */
+#define SPAPR_CAP_DFP 0x02
+/* Cache Flush on Privilege Change */
+#define SPAPR_CAP_CFPC 0x03
+/* Speculation Barrier Bounds Checking */
+#define SPAPR_CAP_SBBC 0x04
+/* Indirect Branch Serialisation */
+#define SPAPR_CAP_IBS 0x05
+/* HPT Maximum Page Size (encoded as a shift) */
+#define SPAPR_CAP_HPT_MAXPAGESIZE 0x06
+/* Nested KVM-HV */
+#define SPAPR_CAP_NESTED_KVM_HV 0x07
+/* Large Decrementer */
+#define SPAPR_CAP_LARGE_DECREMENTER 0x08
+/* Count Cache Flush Assist HW Instruction */
+#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
+/* Num Caps */
+#define SPAPR_CAP_NUM (SPAPR_CAP_RPT_INVALIDATE + 1)
+
+/*
+ * Capability Values
+ */
+/* Bool Caps */
+#define SPAPR_CAP_OFF 0x00
+#define SPAPR_CAP_ON 0x01
+
+/* Custom Caps */
+
+/* Generic */
+#define SPAPR_CAP_BROKEN 0x00
+#define SPAPR_CAP_WORKAROUND 0x01
+#define SPAPR_CAP_FIXED 0x02
+/* SPAPR_CAP_IBS (cap-ibs) */
+#define SPAPR_CAP_FIXED_IBS 0x02
+#define SPAPR_CAP_FIXED_CCD 0x03
+#define SPAPR_CAP_FIXED_NA 0x10 /* Lets leave a bit of a gap... */
+
+#define FDT_MAX_SIZE 0x200000
+
+/* Max number of GPUs per system */
+#define NVGPU_MAX_NUM 6
+
+/* Max number of NUMA nodes */
+#define NUMA_NODES_MAX_NUM (MAX_NODES + NVGPU_MAX_NUM)
+
+/*
+ * 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 {
+ uint8_t caps[SPAPR_CAP_NUM];
+};
+
+/**
+ * SpaprMachineClass:
+ */
+struct SpaprMachineClass {
+ /*< private >*/
+ MachineClass parent_class;
+
+ /*< public >*/
+ bool dr_lmb_enabled; /* enable dynamic-reconfig/hotplug of LMBs */
+ bool dr_phb_enabled; /* enable dynamic-reconfig/hotplug of PHBs */
+ bool update_dt_enabled; /* enable KVMPPC_H_UPDATE_DT */
+ bool use_ohci_by_default; /* use USB-OHCI instead of XHCI */
+ bool pre_2_10_has_unused_icps;
+ bool legacy_irq_allocation;
+ uint32_t nr_xirqs;
+ bool broken_host_serial_model; /* present real host info to the guest */
+ bool pre_4_1_migration; /* don't migrate hpt-max-page-size */
+ bool linux_pci_probe;
+ 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;
+
+ 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);
+ SpaprResizeHpt resize_hpt_default;
+ SpaprCapabilities default_caps;
+ SpaprIrq *irq;
+};
+
+/**
+ * SpaprMachineState:
+ */
+struct SpaprMachineState {
+ /*< private >*/
+ MachineState parent_obj;
+
+ struct SpaprVioBus *vio_bus;
+ QLIST_HEAD(, SpaprPhbState) phbs;
+ struct SpaprNvram *nvram;
+ SpaprRtcState rtc;
+
+ SpaprResizeHpt resize_hpt;
+ void *htab;
+ uint32_t htab_shift;
+ uint64_t patb_entry; /* Process tbl registed 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;
+ 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;
+ uint32_t vsmt; /* Virtual SMT mode (KVM's "core stride") */
+
+ Notifier epow_notifier;
+ QTAILQ_HEAD(, SpaprEventLogEntry) pending_events;
+ bool use_hotplug_event_source;
+ SpaprEventSource *event_sources;
+
+ /* ibm,client-architecture-support option negotiation */
+ bool cas_pre_isa3_guest;
+ SpaprOptionVector *ov5; /* QEMU-supported option vectors */
+ SpaprOptionVector *ov5_cas; /* negotiated (via CAS) option vectors */
+ uint32_t max_compat_pvr;
+
+ /* Migration state */
+ int htab_save_index;
+ bool htab_first_pass;
+ int htab_fd;
+
+ /* Pending DIMM unplug cache. It is populated when a LMB
+ * unplug starts. It can be regenerated if a migration
+ * occurs during the unplug process. */
+ QTAILQ_HEAD(, SpaprDimmState) pending_dimm_unplugs;
+
+ /* State related to FWNMI option */
+
+ /* System Reset and Machine Check Notification Routine addresses
+ * registered by "ibm,nmi-register" RTAS call.
+ */
+ target_ulong fwnmi_system_reset_addr;
+ target_ulong fwnmi_machine_check_addr;
+
+ /* Machine Check FWNMI synchronization, fwnmi_machine_check_interlock is
+ * set to -1 if a FWNMI machine check is not in progress, else is set to
+ * the CPU that was delivered the machine check, and is set back to -1
+ * when that CPU makes an "ibm,nmi-interlock" RTAS call. The cond is used
+ * to synchronize other CPUs.
+ */
+ int fwnmi_machine_check_interlock;
+ QemuCond fwnmi_machine_check_interlock_cond;
+
+ /* Set by -boot */
+ char *boot_device;
+
+ /*< public >*/
+ char *kvm_type;
+ char *host_model;
+ char *host_serial;
+
+ int32_t irq_map_nr;
+ unsigned long *irq_map;
+ SpaprIrq *irq;
+ qemu_irq *qirqs;
+ SpaprInterruptController *active_intc;
+ ICSState *ics;
+ SpaprXive *xive;
+
+ 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;
+};
+
+#define H_SUCCESS 0
+#define H_BUSY 1 /* Hardware busy -- retry later */
+#define H_CLOSED 2 /* Resource closed */
+#define H_NOT_AVAILABLE 3
+#define H_CONSTRAINED 4 /* Resource request constrained to max allowed */
+#define H_PARTIAL 5
+#define H_IN_PROGRESS 14 /* Kind of like busy */
+#define H_PAGE_REGISTERED 15
+#define H_PARTIAL_STORE 16
+#define H_PENDING 17 /* returned from H_POLL_PENDING */
+#define H_CONTINUE 18 /* Returned from H_Join on success */
+#define H_LONG_BUSY_START_RANGE 9900 /* Start of long busy range */
+#define H_LONG_BUSY_ORDER_1_MSEC 9900 /* Long busy, hint that 1msec \
+ is a good time to retry */
+#define H_LONG_BUSY_ORDER_10_MSEC 9901 /* Long busy, hint that 10msec \
+ is a good time to retry */
+#define H_LONG_BUSY_ORDER_100_MSEC 9902 /* Long busy, hint that 100msec \
+ is a good time to retry */
+#define H_LONG_BUSY_ORDER_1_SEC 9903 /* Long busy, hint that 1sec \
+ is a good time to retry */
+#define H_LONG_BUSY_ORDER_10_SEC 9904 /* Long busy, hint that 10sec \
+ is a good time to retry */
+#define H_LONG_BUSY_ORDER_100_SEC 9905 /* Long busy, hint that 100sec \
+ is a good time to retry */
+#define H_LONG_BUSY_END_RANGE 9905 /* End of long busy range */
+#define H_HARDWARE -1 /* Hardware error */
+#define H_FUNCTION -2 /* Function not supported */
+#define H_PRIVILEGE -3 /* Caller not privileged */
+#define H_PARAMETER -4 /* Parameter invalid, out-of-range or conflicting */
+#define H_BAD_MODE -5 /* Illegal msr value */
+#define H_PTEG_FULL -6 /* PTEG is full */
+#define H_NOT_FOUND -7 /* PTE was not found" */
+#define H_RESERVED_DABR -8 /* DABR address is reserved by the hypervisor on this processor" */
+#define H_NO_MEM -9
+#define H_AUTHORITY -10
+#define H_PERMISSION -11
+#define H_DROPPED -12
+#define H_SOURCE_PARM -13
+#define H_DEST_PARM -14
+#define H_REMOTE_PARM -15
+#define H_RESOURCE -16
+#define H_ADAPTER_PARM -17
+#define H_RH_PARM -18
+#define H_RCQ_PARM -19
+#define H_SCQ_PARM -20
+#define H_EQ_PARM -21
+#define H_RT_PARM -22
+#define H_ST_PARM -23
+#define H_SIGT_PARM -24
+#define H_TOKEN_PARM -25
+#define H_MLENGTH_PARM -27
+#define H_MEM_PARM -28
+#define H_MEM_ACCESS_PARM -29
+#define H_ATTR_PARM -30
+#define H_PORT_PARM -31
+#define H_MCG_PARM -32
+#define H_VL_PARM -33
+#define H_TSIZE_PARM -34
+#define H_TRACE_PARM -35
+
+#define H_MASK_PARM -37
+#define H_MCG_FULL -38
+#define H_ALIAS_EXIST -39
+#define H_P_COUNTER -40
+#define H_TABLE_FULL -41
+#define H_ALT_TABLE -42
+#define H_MR_CONDITION -43
+#define H_NOT_ENOUGH_RESOURCES -44
+#define H_R_STATE -45
+#define H_RESCINDEND -46
+#define H_P2 -55
+#define H_P3 -56
+#define H_P4 -57
+#define H_P5 -58
+#define H_P6 -59
+#define H_P7 -60
+#define H_P8 -61
+#define H_P9 -62
+#define H_OVERLAP -68
+#define H_UNSUPPORTED_FLAG -256
+#define H_MULTI_THREADS_ACTIVE -9005
+
+
+/* Long Busy is a condition that can be returned by the firmware
+ * when a call cannot be completed now, but the identical call
+ * should be retried later. This prevents calls blocking in the
+ * firmware for long periods of time. Annoyingly the firmware can return
+ * a range of return codes, hinting at how long we should wait before
+ * retrying. If you don't care for the hint, the macro below is a good
+ * way to check for the long_busy return codes
+ */
+#define H_IS_LONG_BUSY(x) ((x >= H_LONG_BUSY_START_RANGE) \
+ && (x <= H_LONG_BUSY_END_RANGE))
+
+/* Flags */
+#define H_LARGE_PAGE (1ULL<<(63-16))
+#define H_EXACT (1ULL<<(63-24)) /* Use exact PTE or return H_PTEG_FULL */
+#define H_R_XLATE (1ULL<<(63-25)) /* include a valid logical page num in the pte if the valid bit is set */
+#define H_READ_4 (1ULL<<(63-26)) /* Return 4 PTEs */
+#define H_PAGE_STATE_CHANGE (1ULL<<(63-28))
+#define H_PAGE_UNUSED ((1ULL<<(63-29)) | (1ULL<<(63-30)))
+#define H_PAGE_SET_UNUSED (H_PAGE_STATE_CHANGE | H_PAGE_UNUSED)
+#define H_PAGE_SET_LOANED (H_PAGE_SET_UNUSED | (1ULL<<(63-31)))
+#define H_PAGE_SET_ACTIVE H_PAGE_STATE_CHANGE
+#define H_AVPN (1ULL<<(63-32)) /* An avpn is provided as a sanity test */
+#define H_ANDCOND (1ULL<<(63-33))
+#define H_ICACHE_INVALIDATE (1ULL<<(63-40)) /* icbi, etc. (ignored for IO pages) */
+#define H_ICACHE_SYNCHRONIZE (1ULL<<(63-41)) /* dcbst, icbi, etc (ignored for IO pages */
+#define H_ZERO_PAGE (1ULL<<(63-48)) /* zero the page before mapping (ignored for IO pages) */
+#define H_COPY_PAGE (1ULL<<(63-49))
+#define H_N (1ULL<<(63-61))
+#define H_PP1 (1ULL<<(63-62))
+#define H_PP2 (1ULL<<(63-63))
+
+/* Values for 2nd argument to H_SET_MODE */
+#define H_SET_MODE_RESOURCE_SET_CIABR 1
+#define H_SET_MODE_RESOURCE_SET_DAWR0 2
+#define H_SET_MODE_RESOURCE_ADDR_TRANS_MODE 3
+#define H_SET_MODE_RESOURCE_LE 4
+
+/* Flags for H_SET_MODE_RESOURCE_LE */
+#define H_SET_MODE_ENDIAN_BIG 0
+#define H_SET_MODE_ENDIAN_LITTLE 1
+
+/* VASI States */
+#define H_VASI_INVALID 0
+#define H_VASI_ENABLED 1
+#define H_VASI_ABORTED 2
+#define H_VASI_SUSPENDING 3
+#define H_VASI_SUSPENDED 4
+#define H_VASI_RESUMED 5
+#define H_VASI_COMPLETED 6
+
+/* DABRX flags */
+#define H_DABRX_HYPERVISOR (1ULL<<(63-61))
+#define H_DABRX_KERNEL (1ULL<<(63-62))
+#define H_DABRX_USER (1ULL<<(63-63))
+
+/* Values for KVM_PPC_GET_CPU_CHAR & H_GET_CPU_CHARACTERISTICS */
+#define H_CPU_CHAR_SPEC_BAR_ORI31 PPC_BIT(0)
+#define H_CPU_CHAR_BCCTRL_SERIALISED PPC_BIT(1)
+#define H_CPU_CHAR_L1D_FLUSH_ORI30 PPC_BIT(2)
+#define H_CPU_CHAR_L1D_FLUSH_TRIG2 PPC_BIT(3)
+#define H_CPU_CHAR_L1D_THREAD_PRIV PPC_BIT(4)
+#define H_CPU_CHAR_HON_BRANCH_HINTS PPC_BIT(5)
+#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
+
+/* pSeries hypervisor opcodes */
+#define H_REMOVE 0x04
+#define H_ENTER 0x08
+#define H_READ 0x0c
+#define H_CLEAR_MOD 0x10
+#define H_CLEAR_REF 0x14
+#define H_PROTECT 0x18
+#define H_GET_TCE 0x1c
+#define H_PUT_TCE 0x20
+#define H_SET_SPRG0 0x24
+#define H_SET_DABR 0x28
+#define H_PAGE_INIT 0x2c
+#define H_SET_ASR 0x30
+#define H_ASR_ON 0x34
+#define H_ASR_OFF 0x38
+#define H_LOGICAL_CI_LOAD 0x3c
+#define H_LOGICAL_CI_STORE 0x40
+#define H_LOGICAL_CACHE_LOAD 0x44
+#define H_LOGICAL_CACHE_STORE 0x48
+#define H_LOGICAL_ICBI 0x4c
+#define H_LOGICAL_DCBF 0x50
+#define H_GET_TERM_CHAR 0x54
+#define H_PUT_TERM_CHAR 0x58
+#define H_REAL_TO_LOGICAL 0x5c
+#define H_HYPERVISOR_DATA 0x60
+#define H_EOI 0x64
+#define H_CPPR 0x68
+#define H_IPI 0x6c
+#define H_IPOLL 0x70
+#define H_XIRR 0x74
+#define H_PERFMON 0x7c
+#define H_MIGRATE_DMA 0x78
+#define H_REGISTER_VPA 0xDC
+#define H_CEDE 0xE0
+#define H_CONFER 0xE4
+#define H_PROD 0xE8
+#define H_GET_PPP 0xEC
+#define H_SET_PPP 0xF0
+#define H_PURR 0xF4
+#define H_PIC 0xF8
+#define H_REG_CRQ 0xFC
+#define H_FREE_CRQ 0x100
+#define H_VIO_SIGNAL 0x104
+#define H_SEND_CRQ 0x108
+#define H_COPY_RDMA 0x110
+#define H_REGISTER_LOGICAL_LAN 0x114
+#define H_FREE_LOGICAL_LAN 0x118
+#define H_ADD_LOGICAL_LAN_BUFFER 0x11C
+#define H_SEND_LOGICAL_LAN 0x120
+#define H_BULK_REMOVE 0x124
+#define H_MULTICAST_CTRL 0x130
+#define H_SET_XDABR 0x134
+#define H_STUFF_TCE 0x138
+#define H_PUT_TCE_INDIRECT 0x13C
+#define H_CHANGE_LOGICAL_LAN_MAC 0x14C
+#define H_VTERM_PARTNER_INFO 0x150
+#define H_REGISTER_VTERM 0x154
+#define H_FREE_VTERM 0x158
+#define H_RESET_EVENTS 0x15C
+#define H_ALLOC_RESOURCE 0x160
+#define H_FREE_RESOURCE 0x164
+#define H_MODIFY_QP 0x168
+#define H_QUERY_QP 0x16C
+#define H_REREGISTER_PMR 0x170
+#define H_REGISTER_SMR 0x174
+#define H_QUERY_MR 0x178
+#define H_QUERY_MW 0x17C
+#define H_QUERY_HCA 0x180
+#define H_QUERY_PORT 0x184
+#define H_MODIFY_PORT 0x188
+#define H_DEFINE_AQP1 0x18C
+#define H_GET_TRACE_BUFFER 0x190
+#define H_DEFINE_AQP0 0x194
+#define H_RESIZE_MR 0x198
+#define H_ATTACH_MCQP 0x19C
+#define H_DETACH_MCQP 0x1A0
+#define H_CREATE_RPT 0x1A4
+#define H_REMOVE_RPT 0x1A8
+#define H_REGISTER_RPAGES 0x1AC
+#define H_DISABLE_AND_GETC 0x1B0
+#define H_ERROR_DATA 0x1B4
+#define H_GET_HCA_INFO 0x1B8
+#define H_GET_PERF_COUNT 0x1BC
+#define H_MANAGE_TRACE 0x1C0
+#define H_GET_CPU_CHARACTERISTICS 0x1C8
+#define H_FREE_LOGICAL_LAN_BUFFER 0x1D4
+#define H_QUERY_INT_STATE 0x1E4
+#define H_POLL_PENDING 0x1D8
+#define H_ILLAN_ATTRIBUTES 0x244
+#define H_MODIFY_HEA_QP 0x250
+#define H_QUERY_HEA_QP 0x254
+#define H_QUERY_HEA 0x258
+#define H_QUERY_HEA_PORT 0x25C
+#define H_MODIFY_HEA_PORT 0x260
+#define H_REG_BCMC 0x264
+#define H_DEREG_BCMC 0x268
+#define H_REGISTER_HEA_RPAGES 0x26C
+#define H_DISABLE_AND_GET_HEA 0x270
+#define H_GET_HEA_INFO 0x274
+#define H_ALLOC_HEA_RESOURCE 0x278
+#define H_ADD_CONN 0x284
+#define H_DEL_CONN 0x288
+#define H_JOIN 0x298
+#define H_VASI_STATE 0x2A4
+#define H_ENABLE_CRQ 0x2B0
+#define H_GET_EM_PARMS 0x2B8
+#define H_SET_MPP 0x2D0
+#define H_GET_MPP 0x2D4
+#define H_HOME_NODE_ASSOCIATIVITY 0x2EC
+#define H_XIRR_X 0x2FC
+#define H_RANDOM 0x300
+#define H_SET_MODE 0x31C
+#define H_RESIZE_HPT_PREPARE 0x36C
+#define H_RESIZE_HPT_COMMIT 0x370
+#define H_CLEAN_SLB 0x374
+#define H_INVALIDATE_PID 0x378
+#define H_REGISTER_PROC_TBL 0x37C
+#define H_SIGNAL_SYS_RESET 0x380
+
+#define H_INT_GET_SOURCE_INFO 0x3A8
+#define H_INT_SET_SOURCE_CONFIG 0x3AC
+#define H_INT_GET_SOURCE_CONFIG 0x3B0
+#define H_INT_GET_QUEUE_INFO 0x3B4
+#define H_INT_SET_QUEUE_CONFIG 0x3B8
+#define H_INT_GET_QUEUE_CONFIG 0x3BC
+#define H_INT_SET_OS_REPORTING_LINE 0x3C0
+#define H_INT_GET_OS_REPORTING_LINE 0x3C4
+#define H_INT_ESB 0x3C8
+#define H_INT_SYNC 0x3CC
+#define H_INT_RESET 0x3D0
+#define H_SCM_READ_METADATA 0x3E4
+#define H_SCM_WRITE_METADATA 0x3E8
+#define H_SCM_BIND_MEM 0x3EC
+#define H_SCM_UNBIND_MEM 0x3F0
+#define H_SCM_UNBIND_ALL 0x3FC
+#define H_SCM_HEALTH 0x400
+#define H_RPT_INVALIDATE 0x448
+
+#define MAX_HCALL_OPCODE H_RPT_INVALIDATE
+
+/* The hcalls above are standardized in PAPR and implemented by pHyp
+ * as well.
+ *
+ * We also need some hcalls which are specific to qemu / KVM-on-POWER.
+ * We put those into the 0xf000-0xfffc range which is reserved by PAPR
+ * for "platform-specific" hcalls.
+ */
+#define KVMPPC_HCALL_BASE 0xf000
+#define KVMPPC_H_RTAS (KVMPPC_HCALL_BASE + 0x0)
+#define KVMPPC_H_LOGICAL_MEMOP (KVMPPC_HCALL_BASE + 0x1)
+/* Client Architecture support */
+#define KVMPPC_H_CAS (KVMPPC_HCALL_BASE + 0x2)
+#define KVMPPC_H_UPDATE_DT (KVMPPC_HCALL_BASE + 0x3)
+/* 0x4 was used for KVMPPC_H_UPDATE_PHANDLE in SLOF */
+#define KVMPPC_H_VOF_CLIENT (KVMPPC_HCALL_BASE + 0x5)
+#define KVMPPC_HCALL_MAX KVMPPC_H_VOF_CLIENT
+
+/*
+ * The hcall range 0xEF00 to 0xEF80 is reserved for use in facilitating
+ * Secure VM mode via an Ultravisor / Protected Execution Facility
+ */
+#define SVM_HCALL_BASE 0xEF00
+#define SVM_H_TPM_COMM 0xEF10
+#define SVM_HCALL_MAX SVM_H_TPM_COMM
+
+
+typedef struct SpaprDeviceTreeUpdateHeader {
+ uint32_t version_id;
+} SpaprDeviceTreeUpdateHeader;
+
+#define hcall_dprintf(fmt, ...) \
+ do { \
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: " fmt, __func__, ## __VA_ARGS__); \
+ } while (0)
+
+typedef target_ulong (*spapr_hcall_fn)(PowerPCCPU *cpu, SpaprMachineState *sm,
+ target_ulong opcode,
+ target_ulong *args);
+
+void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn);
+target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode,
+ target_ulong *args);
+target_ulong softmmu_resize_hpt_prepare(PowerPCCPU *cpu, SpaprMachineState *spapr,
+ target_ulong shift);
+target_ulong softmmu_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
+#define VPA_SIZE_OFFSET 0x4
+#define VPA_SHARED_PROC_OFFSET 0x9
+#define VPA_SHARED_PROC_VAL 0x2
+#define VPA_DISPATCH_COUNTER 0x100
+
+/* ibm,set-eeh-option */
+#define RTAS_EEH_DISABLE 0
+#define RTAS_EEH_ENABLE 1
+#define RTAS_EEH_THAW_IO 2
+#define RTAS_EEH_THAW_DMA 3
+
+/* ibm,get-config-addr-info2 */
+#define RTAS_GET_PE_ADDR 0
+#define RTAS_GET_PE_MODE 1
+#define RTAS_PE_MODE_NONE 0
+#define RTAS_PE_MODE_NOT_SHARED 1
+#define RTAS_PE_MODE_SHARED 2
+
+/* ibm,read-slot-reset-state2 */
+#define RTAS_EEH_PE_STATE_NORMAL 0
+#define RTAS_EEH_PE_STATE_RESET 1
+#define RTAS_EEH_PE_STATE_STOPPED_IO_DMA 2
+#define RTAS_EEH_PE_STATE_STOPPED_DMA 4
+#define RTAS_EEH_PE_STATE_UNAVAIL 5
+#define RTAS_EEH_NOT_SUPPORT 0
+#define RTAS_EEH_SUPPORT 1
+#define RTAS_EEH_PE_UNAVAIL_INFO 1000
+#define RTAS_EEH_PE_RECOVER_INFO 0
+
+/* ibm,set-slot-reset */
+#define RTAS_SLOT_RESET_DEACTIVATE 0
+#define RTAS_SLOT_RESET_HOT 1
+#define RTAS_SLOT_RESET_FUNDAMENTAL 3
+
+/* ibm,slot-error-detail */
+#define RTAS_SLOT_TEMP_ERR_LOG 1
+#define RTAS_SLOT_PERM_ERR_LOG 2
+
+/* RTAS return codes */
+#define RTAS_OUT_SUCCESS 0
+#define RTAS_OUT_NO_ERRORS_FOUND 1
+#define RTAS_OUT_HW_ERROR -1
+#define RTAS_OUT_BUSY -2
+#define RTAS_OUT_PARAM_ERROR -3
+#define RTAS_OUT_NOT_SUPPORTED -3
+#define RTAS_OUT_NO_SUCH_INDICATOR -3
+#define RTAS_OUT_NOT_AUTHORIZED -9002
+#define RTAS_OUT_SYSPARM_PARAM_ERROR -9999
+
+/* DDW pagesize mask values from ibm,query-pe-dma-window */
+#define RTAS_DDW_PGSIZE_4K 0x01
+#define RTAS_DDW_PGSIZE_64K 0x02
+#define RTAS_DDW_PGSIZE_16M 0x04
+#define RTAS_DDW_PGSIZE_32M 0x08
+#define RTAS_DDW_PGSIZE_64M 0x10
+#define RTAS_DDW_PGSIZE_128M 0x20
+#define RTAS_DDW_PGSIZE_256M 0x40
+#define RTAS_DDW_PGSIZE_16G 0x80
+
+/* RTAS tokens */
+#define RTAS_TOKEN_BASE 0x2000
+
+#define RTAS_DISPLAY_CHARACTER (RTAS_TOKEN_BASE + 0x00)
+#define RTAS_GET_TIME_OF_DAY (RTAS_TOKEN_BASE + 0x01)
+#define RTAS_SET_TIME_OF_DAY (RTAS_TOKEN_BASE + 0x02)
+#define RTAS_POWER_OFF (RTAS_TOKEN_BASE + 0x03)
+#define RTAS_SYSTEM_REBOOT (RTAS_TOKEN_BASE + 0x04)
+#define RTAS_QUERY_CPU_STOPPED_STATE (RTAS_TOKEN_BASE + 0x05)
+#define RTAS_START_CPU (RTAS_TOKEN_BASE + 0x06)
+#define RTAS_STOP_SELF (RTAS_TOKEN_BASE + 0x07)
+#define RTAS_IBM_GET_SYSTEM_PARAMETER (RTAS_TOKEN_BASE + 0x08)
+#define RTAS_IBM_SET_SYSTEM_PARAMETER (RTAS_TOKEN_BASE + 0x09)
+#define RTAS_IBM_SET_XIVE (RTAS_TOKEN_BASE + 0x0A)
+#define RTAS_IBM_GET_XIVE (RTAS_TOKEN_BASE + 0x0B)
+#define RTAS_IBM_INT_OFF (RTAS_TOKEN_BASE + 0x0C)
+#define RTAS_IBM_INT_ON (RTAS_TOKEN_BASE + 0x0D)
+#define RTAS_CHECK_EXCEPTION (RTAS_TOKEN_BASE + 0x0E)
+#define RTAS_EVENT_SCAN (RTAS_TOKEN_BASE + 0x0F)
+#define RTAS_IBM_SET_TCE_BYPASS (RTAS_TOKEN_BASE + 0x10)
+#define RTAS_QUIESCE (RTAS_TOKEN_BASE + 0x11)
+#define RTAS_NVRAM_FETCH (RTAS_TOKEN_BASE + 0x12)
+#define RTAS_NVRAM_STORE (RTAS_TOKEN_BASE + 0x13)
+#define RTAS_READ_PCI_CONFIG (RTAS_TOKEN_BASE + 0x14)
+#define RTAS_WRITE_PCI_CONFIG (RTAS_TOKEN_BASE + 0x15)
+#define RTAS_IBM_READ_PCI_CONFIG (RTAS_TOKEN_BASE + 0x16)
+#define RTAS_IBM_WRITE_PCI_CONFIG (RTAS_TOKEN_BASE + 0x17)
+#define RTAS_IBM_QUERY_INTERRUPT_SOURCE_NUMBER (RTAS_TOKEN_BASE + 0x18)
+#define RTAS_IBM_CHANGE_MSI (RTAS_TOKEN_BASE + 0x19)
+#define RTAS_SET_INDICATOR (RTAS_TOKEN_BASE + 0x1A)
+#define RTAS_SET_POWER_LEVEL (RTAS_TOKEN_BASE + 0x1B)
+#define RTAS_GET_POWER_LEVEL (RTAS_TOKEN_BASE + 0x1C)
+#define RTAS_GET_SENSOR_STATE (RTAS_TOKEN_BASE + 0x1D)
+#define RTAS_IBM_CONFIGURE_CONNECTOR (RTAS_TOKEN_BASE + 0x1E)
+#define RTAS_IBM_OS_TERM (RTAS_TOKEN_BASE + 0x1F)
+#define RTAS_IBM_SET_EEH_OPTION (RTAS_TOKEN_BASE + 0x20)
+#define RTAS_IBM_GET_CONFIG_ADDR_INFO2 (RTAS_TOKEN_BASE + 0x21)
+#define RTAS_IBM_READ_SLOT_RESET_STATE2 (RTAS_TOKEN_BASE + 0x22)
+#define RTAS_IBM_SET_SLOT_RESET (RTAS_TOKEN_BASE + 0x23)
+#define RTAS_IBM_CONFIGURE_PE (RTAS_TOKEN_BASE + 0x24)
+#define RTAS_IBM_SLOT_ERROR_DETAIL (RTAS_TOKEN_BASE + 0x25)
+#define RTAS_IBM_QUERY_PE_DMA_WINDOW (RTAS_TOKEN_BASE + 0x26)
+#define RTAS_IBM_CREATE_PE_DMA_WINDOW (RTAS_TOKEN_BASE + 0x27)
+#define RTAS_IBM_REMOVE_PE_DMA_WINDOW (RTAS_TOKEN_BASE + 0x28)
+#define RTAS_IBM_RESET_PE_DMA_WINDOW (RTAS_TOKEN_BASE + 0x29)
+#define RTAS_IBM_SUSPEND_ME (RTAS_TOKEN_BASE + 0x2A)
+#define RTAS_IBM_NMI_REGISTER (RTAS_TOKEN_BASE + 0x2B)
+#define RTAS_IBM_NMI_INTERLOCK (RTAS_TOKEN_BASE + 0x2C)
+
+#define RTAS_TOKEN_MAX (RTAS_TOKEN_BASE + 0x2D)
+
+/* RTAS ibm,get-system-parameter token values */
+#define RTAS_SYSPARM_SPLPAR_CHARACTERISTICS 20
+#define RTAS_SYSPARM_DIAGNOSTICS_RUN_MODE 42
+#define RTAS_SYSPARM_UUID 48
+
+/* RTAS indicator/sensor types
+ *
+ * as defined by PAPR+ 2.7 7.3.5.4, Table 41
+ *
+ * NOTE: currently only DR-related sensors are implemented here
+ */
+#define RTAS_SENSOR_TYPE_ISOLATION_STATE 9001
+#define RTAS_SENSOR_TYPE_DR 9002
+#define RTAS_SENSOR_TYPE_ALLOCATION_STATE 9003
+#define RTAS_SENSOR_TYPE_ENTITY_SENSE RTAS_SENSOR_TYPE_ALLOCATION_STATE
+
+/* Possible values for the platform-processor-diagnostics-run-mode parameter
+ * of the RTAS ibm,get-system-parameter call.
+ */
+#define DIAGNOSTICS_RUN_MODE_DISABLED 0
+#define DIAGNOSTICS_RUN_MODE_STAGGERED 1
+#define DIAGNOSTICS_RUN_MODE_IMMEDIATE 2
+#define DIAGNOSTICS_RUN_MODE_PERIODIC 3
+
+static inline uint64_t ppc64_phys_to_real(uint64_t addr)
+{
+ return addr & ~0xF000000000000000ULL;
+}
+
+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));
+}
+
+static inline uint64_t rtas_ldq(target_ulong phys, int n)
+{
+ return (uint64_t)rtas_ld(phys, n) << 32 | rtas_ld(phys, n + 1);
+}
+
+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);
+}
+
+typedef void (*spapr_rtas_fn)(PowerPCCPU *cpu, SpaprMachineState *sm,
+ uint32_t token,
+ uint32_t nargs, target_ulong args,
+ uint32_t nret, target_ulong rets);
+void spapr_rtas_register(int token, const char *name, spapr_rtas_fn fn);
+target_ulong spapr_rtas_call(PowerPCCPU *cpu, SpaprMachineState *sm,
+ uint32_t token, uint32_t nargs, target_ulong args,
+ uint32_t nret, target_ulong rets);
+void spapr_dt_rtas_tokens(void *fdt, int rtas);
+void spapr_load_rtas(SpaprMachineState *spapr, void *fdt, hwaddr addr);
+
+#define SPAPR_TCE_PAGE_SHIFT 12
+#define SPAPR_TCE_PAGE_SIZE (1ULL << SPAPR_TCE_PAGE_SHIFT)
+#define SPAPR_TCE_PAGE_MASK (SPAPR_TCE_PAGE_SIZE - 1)
+
+#define SPAPR_VIO_BASE_LIOBN 0x00000000
+#define SPAPR_VIO_LIOBN(reg) (0x00000000 | (reg))
+#define SPAPR_PCI_LIOBN(phb_index, window_num) \
+ (0x80000000 | ((phb_index) << 8) | (window_num))
+#define SPAPR_IS_PCI_LIOBN(liobn) (!!((liobn) & 0x80000000))
+#define SPAPR_PCI_DMA_WINDOW_NUM(liobn) ((liobn) & 0xff)
+
+#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 */
+#define RTAS_ERROR_LOG_OFFSET 0x30
+
+#define RTAS_EVENT_SCAN_RATE 1
+
+/* This helper should be used to encode interrupt specifiers when the related
+ * "interrupt-controller" node has its "#interrupt-cells" property set to 2 (ie,
+ * VIO devices, RTAS event sources and PHBs).
+ */
+static inline void spapr_dt_irq(uint32_t *intspec, int irq, bool is_lsi)
+{
+ intspec[0] = cpu_to_be32(irq);
+ intspec[1] = is_lsi ? cpu_to_be32(1) : 0;
+}
+
+
+#define TYPE_SPAPR_TCE_TABLE "spapr-tce-table"
+OBJECT_DECLARE_SIMPLE_TYPE(SpaprTceTable, SPAPR_TCE_TABLE)
+
+#define TYPE_SPAPR_IOMMU_MEMORY_REGION "spapr-iommu-memory-region"
+DECLARE_INSTANCE_CHECKER(IOMMUMemoryRegion, SPAPR_IOMMU_MEMORY_REGION,
+ TYPE_SPAPR_IOMMU_MEMORY_REGION)
+
+struct SpaprTceTable {
+ DeviceState parent;
+ uint32_t liobn;
+ uint32_t nb_table;
+ uint64_t bus_offset;
+ uint32_t page_shift;
+ uint64_t *table;
+ uint32_t mig_nb_table;
+ uint64_t *mig_table;
+ bool bypass;
+ bool need_vfio;
+ bool skipping_replay;
+ int fd;
+ MemoryRegion root;
+ IOMMUMemoryRegion iommu;
+ struct SpaprVioDevice *vdev; /* for @bypass migration compatibility only */
+ QLIST_ENTRY(SpaprTceTable) list;
+};
+
+SpaprTceTable *spapr_tce_find_by_liobn(target_ulong liobn);
+
+struct SpaprEventLogEntry {
+ uint32_t summary;
+ uint32_t extended_length;
+ void *extended_log;
+ QTAILQ_ENTRY(SpaprEventLogEntry) next;
+};
+
+void *spapr_build_fdt(SpaprMachineState *spapr, bool reset, size_t space);
+void spapr_events_init(SpaprMachineState *sm);
+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,
+ uint32_t nb_table);
+void spapr_tce_table_disable(SpaprTceTable *tcet);
+void spapr_tce_set_need_vfio(SpaprTceTable *tcet, bool need_vfio);
+
+MemoryRegion *spapr_tce_get_iommu(SpaprTceTable *tcet);
+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(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,
+ uint32_t count);
+void spapr_hotplug_req_remove_by_count(SpaprDrcType drc_type,
+ uint32_t count);
+void spapr_hotplug_req_add_by_count_indexed(SpaprDrcType drc_type,
+ uint32_t count, uint32_t index);
+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);
+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);
+void spapr_mce_req_event(PowerPCCPU *cpu, bool recovered);
+
+/* DRC callbacks. */
+void spapr_core_release(DeviceState *dev);
+int spapr_core_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
+ void *fdt, int *fdt_start_offset, Error **errp);
+void spapr_lmb_release(DeviceState *dev);
+int spapr_lmb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
+ void *fdt, int *fdt_start_offset, Error **errp);
+void spapr_phb_release(DeviceState *dev);
+int spapr_phb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
+ void *fdt, int *fdt_start_offset, Error **errp);
+
+void spapr_rtc_read(SpaprRtcState *rtc, struct tm *tm, uint32_t *ns);
+int spapr_rtc_import_offset(SpaprRtcState *rtc, int64_t legacy_offset);
+
+#define TYPE_SPAPR_RNG "spapr-rng"
+
+#define SPAPR_MEMORY_BLOCK_SIZE ((hwaddr)1 << 28) /* 256MB */
+
+/*
+ * This defines the maximum number of DIMM slots we can have for sPAPR
+ * guest. This is not defined by sPAPR but we are defining it to 32 slots
+ * based on default number of slots provided by PowerPC kernel.
+ */
+#define SPAPR_MAX_RAM_SLOTS 32
+
+/* 1GB alignment for hotplug memory region */
+#define SPAPR_DEVICE_MEM_ALIGN (1 * GiB)
+
+/*
+ * Number of 32 bit words in each LMB list entry in ibm,dynamic-memory
+ * property under ibm,dynamic-reconfiguration-memory node.
+ */
+#define SPAPR_DR_LMB_LIST_ENTRY_SIZE 6
+
+/*
+ * Defines for flag value in ibm,dynamic-memory property under
+ * ibm,dynamic-reconfiguration-memory node.
+ */
+#define SPAPR_LMB_FLAGS_ASSIGNED 0x00000008
+#define SPAPR_LMB_FLAGS_DRC_INVALID 0x00000020
+#define SPAPR_LMB_FLAGS_RESERVED 0x00000080
+#define SPAPR_LMB_FLAGS_HOTREMOVABLE 0x00000100
+
+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);
+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);
+int spapr_caps_pre_save(void *opaque);
+
+/*
+ * Handling of optional capabilities
+ */
+extern const VMStateDescription vmstate_spapr_cap_htm;
+extern const VMStateDescription vmstate_spapr_cap_vsx;
+extern const VMStateDescription vmstate_spapr_cap_dfp;
+extern const VMStateDescription vmstate_spapr_cap_cfpc;
+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_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;
+
+static inline uint8_t spapr_get_cap(SpaprMachineState *spapr, int cap)
+{
+ return spapr->eff.caps[cap];
+}
+
+void spapr_caps_init(SpaprMachineState *spapr);
+void spapr_caps_apply(SpaprMachineState *spapr);
+void spapr_caps_cpu_apply(SpaprMachineState *spapr, PowerPCCPU *cpu);
+void spapr_caps_add_properties(SpaprMachineClass *smc);
+int spapr_caps_post_migration(SpaprMachineState *spapr);
+
+bool spapr_check_pagesize(SpaprMachineState *spapr, hwaddr pagesize,
+ Error **errp);
+/*
+ * XIVE definitions
+ */
+#define SPAPR_OV5_XIVE_LEGACY 0x0
+#define SPAPR_OV5_XIVE_EXPLOIT 0x40
+#define SPAPR_OV5_XIVE_BOTH 0x80 /* Only to advertise on the platform */
+
+void spapr_set_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);
+
+#endif /* HW_SPAPR_H */
diff --git a/include/hw/ppc/spapr_cpu_core.h b/include/hw/ppc/spapr_cpu_core.h
new file mode 100644
index 000000000..dab3dfc76
--- /dev/null
+++ b/include/hw/ppc/spapr_cpu_core.h
@@ -0,0 +1,58 @@
+/*
+ * sPAPR CPU core device.
+ *
+ * Copyright (C) 2016 Bharata B Rao <bharata@linux.vnet.ibm.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_CPU_CORE_H
+#define HW_SPAPR_CPU_CORE_H
+
+#include "hw/cpu/core.h"
+#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"
+OBJECT_DECLARE_TYPE(SpaprCpuCore, SpaprCpuCoreClass,
+ SPAPR_CPU_CORE)
+
+#define SPAPR_CPU_CORE_TYPE_NAME(model) model "-" TYPE_SPAPR_CPU_CORE
+
+struct SpaprCpuCore {
+ /*< private >*/
+ CPUCore parent_obj;
+
+ /*< public >*/
+ PowerPCCPU **threads;
+ int node_id;
+ bool pre_3_0_migration; /* older machine don't know about SpaprCpuState */
+};
+
+struct SpaprCpuCoreClass {
+ DeviceClass parent_class;
+ const char *cpu_type;
+};
+
+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);
+
+typedef struct SpaprCpuState {
+ uint64_t vpa_addr;
+ uint64_t slb_shadow_addr, slb_shadow_size;
+ uint64_t dtl_addr, dtl_size;
+ bool prod; /* not migrated, only used to improve dispatch latencies */
+ struct ICPState *icp;
+ struct XiveTCTX *tctx;
+} SpaprCpuState;
+
+static inline SpaprCpuState *spapr_cpu_state(PowerPCCPU *cpu)
+{
+ return (SpaprCpuState *)cpu->machine_data;
+}
+
+#endif
diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h
new file mode 100644
index 000000000..02a63b366
--- /dev/null
+++ b/include/hw/ppc/spapr_drc.h
@@ -0,0 +1,259 @@
+/*
+ * QEMU SPAPR Dynamic Reconfiguration Connector Implementation
+ *
+ * Copyright IBM Corp. 2014
+ *
+ * Authors:
+ * Michael Roth <mdroth@linux.vnet.ibm.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_DRC_H
+#define HW_SPAPR_DRC_H
+
+#include <libfdt.h>
+#include "qom/object.h"
+#include "sysemu/runstate.h"
+#include "hw/qdev-core.h"
+#include "qapi/error.h"
+
+#define TYPE_SPAPR_DR_CONNECTOR "spapr-dr-connector"
+#define SPAPR_DR_CONNECTOR_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(SpaprDrcClass, obj, TYPE_SPAPR_DR_CONNECTOR)
+#define SPAPR_DR_CONNECTOR_CLASS(klass) \
+ OBJECT_CLASS_CHECK(SpaprDrcClass, klass, \
+ TYPE_SPAPR_DR_CONNECTOR)
+#define SPAPR_DR_CONNECTOR(obj) OBJECT_CHECK(SpaprDrc, (obj), \
+ TYPE_SPAPR_DR_CONNECTOR)
+
+#define TYPE_SPAPR_DRC_PHYSICAL "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 TYPE_SPAPR_DRC_CPU "spapr-drc-cpu"
+
+#define TYPE_SPAPR_DRC_PCI "spapr-drc-pci"
+
+#define TYPE_SPAPR_DRC_LMB "spapr-drc-lmb"
+
+#define TYPE_SPAPR_DRC_PHB "spapr-drc-phb"
+
+#define TYPE_SPAPR_DRC_PMEM "spapr-drc-pmem"
+
+/*
+ * Various hotplug types managed by SpaprDrc
+ *
+ * these are somewhat arbitrary, but to make things easier
+ * when generating DRC indexes later we've aligned the bit
+ * positions with the values used to assign DRC indexes on
+ * pSeries. we use those values as bit shifts to allow for
+ * the OR'ing of these values in various QEMU routines, but
+ * for values exposed to the guest (via DRC indexes for
+ * instance) we will use the shift amounts.
+ */
+typedef enum {
+ SPAPR_DR_CONNECTOR_TYPE_SHIFT_CPU = 1,
+ SPAPR_DR_CONNECTOR_TYPE_SHIFT_PHB = 2,
+ SPAPR_DR_CONNECTOR_TYPE_SHIFT_VIO = 3,
+ SPAPR_DR_CONNECTOR_TYPE_SHIFT_PCI = 4,
+ SPAPR_DR_CONNECTOR_TYPE_SHIFT_LMB = 8,
+ SPAPR_DR_CONNECTOR_TYPE_SHIFT_PMEM = 9,
+} SpaprDrcTypeShift;
+
+typedef enum {
+ SPAPR_DR_CONNECTOR_TYPE_ANY = ~0,
+ SPAPR_DR_CONNECTOR_TYPE_CPU = 1 << SPAPR_DR_CONNECTOR_TYPE_SHIFT_CPU,
+ SPAPR_DR_CONNECTOR_TYPE_PHB = 1 << SPAPR_DR_CONNECTOR_TYPE_SHIFT_PHB,
+ SPAPR_DR_CONNECTOR_TYPE_VIO = 1 << SPAPR_DR_CONNECTOR_TYPE_SHIFT_VIO,
+ SPAPR_DR_CONNECTOR_TYPE_PCI = 1 << SPAPR_DR_CONNECTOR_TYPE_SHIFT_PCI,
+ SPAPR_DR_CONNECTOR_TYPE_LMB = 1 << SPAPR_DR_CONNECTOR_TYPE_SHIFT_LMB,
+ SPAPR_DR_CONNECTOR_TYPE_PMEM = 1 << SPAPR_DR_CONNECTOR_TYPE_SHIFT_PMEM,
+} SpaprDrcType;
+
+/*
+ * set via set-indicator RTAS calls
+ * as documented by PAPR+ 2.7 13.5.3.4, Table 177
+ *
+ * isolated: put device under firmware control
+ * unisolated: claim OS control of device (may or may not be in use)
+ */
+typedef enum {
+ SPAPR_DR_ISOLATION_STATE_ISOLATED = 0,
+ SPAPR_DR_ISOLATION_STATE_UNISOLATED = 1
+} SpaprDRIsolationState;
+
+/*
+ * set via set-indicator RTAS calls
+ * as documented by PAPR+ 2.7 13.5.3.4, Table 177
+ *
+ * unusable: mark device as unavailable to OS
+ * usable: mark device as available to OS
+ * exchange: (currently unused)
+ * recover: (currently unused)
+ */
+typedef enum {
+ SPAPR_DR_ALLOCATION_STATE_UNUSABLE = 0,
+ SPAPR_DR_ALLOCATION_STATE_USABLE = 1,
+ SPAPR_DR_ALLOCATION_STATE_EXCHANGE = 2,
+ SPAPR_DR_ALLOCATION_STATE_RECOVER = 3
+} SpaprDRAllocationState;
+
+/*
+ * DR-indicator (LED/visual indicator)
+ *
+ * set via set-indicator RTAS calls
+ * as documented by PAPR+ 2.7 13.5.3.4, Table 177,
+ * and PAPR+ 2.7 13.5.4.1, Table 180
+ *
+ * inactive: hotpluggable entity inactive and safely removable
+ * active: hotpluggable entity in use and not safely removable
+ * identify: (currently unused)
+ * action: (currently unused)
+ */
+typedef enum {
+ SPAPR_DR_INDICATOR_INACTIVE = 0,
+ SPAPR_DR_INDICATOR_ACTIVE = 1,
+ SPAPR_DR_INDICATOR_IDENTIFY = 2,
+ SPAPR_DR_INDICATOR_ACTION = 3,
+} SpaprDRIndicatorState;
+
+/*
+ * returned via get-sensor-state RTAS calls
+ * as documented by PAPR+ 2.7 13.5.3.3, Table 175:
+ *
+ * empty: connector slot empty (e.g. empty hotpluggable PCI slot)
+ * present: connector slot populated and device available to OS
+ * unusable: device not currently available to OS
+ * exchange: (currently unused)
+ * recover: (currently unused)
+ */
+typedef enum {
+ SPAPR_DR_ENTITY_SENSE_EMPTY = 0,
+ SPAPR_DR_ENTITY_SENSE_PRESENT = 1,
+ SPAPR_DR_ENTITY_SENSE_UNUSABLE = 2,
+ SPAPR_DR_ENTITY_SENSE_EXCHANGE = 3,
+ SPAPR_DR_ENTITY_SENSE_RECOVER = 4,
+} SpaprDREntitySense;
+
+typedef enum {
+ SPAPR_DR_CC_RESPONSE_NEXT_SIB = 1, /* currently unused */
+ SPAPR_DR_CC_RESPONSE_NEXT_CHILD = 2,
+ SPAPR_DR_CC_RESPONSE_NEXT_PROPERTY = 3,
+ SPAPR_DR_CC_RESPONSE_PREV_PARENT = 4,
+ SPAPR_DR_CC_RESPONSE_SUCCESS = 0,
+ SPAPR_DR_CC_RESPONSE_ERROR = -1,
+ SPAPR_DR_CC_RESPONSE_CONTINUE = -2,
+ SPAPR_DR_CC_RESPONSE_NOT_CONFIGURABLE = -9003,
+} SpaprDRCCResponse;
+
+typedef enum {
+ /*
+ * Values come from Fig. 12 in LoPAPR section 13.4
+ *
+ * These are exposed in the migration stream, so don't change
+ * them.
+ */
+ SPAPR_DRC_STATE_INVALID = 0,
+ SPAPR_DRC_STATE_LOGICAL_UNUSABLE = 1,
+ SPAPR_DRC_STATE_LOGICAL_AVAILABLE = 2,
+ SPAPR_DRC_STATE_LOGICAL_UNISOLATE = 3,
+ SPAPR_DRC_STATE_LOGICAL_CONFIGURED = 4,
+ SPAPR_DRC_STATE_PHYSICAL_AVAILABLE = 5,
+ SPAPR_DRC_STATE_PHYSICAL_POWERON = 6,
+ SPAPR_DRC_STATE_PHYSICAL_UNISOLATE = 7,
+ SPAPR_DRC_STATE_PHYSICAL_CONFIGURED = 8,
+} SpaprDrcState;
+
+typedef struct SpaprDrc {
+ /*< private >*/
+ DeviceState parent;
+
+ uint32_t id;
+ Object *owner;
+
+ uint32_t state;
+
+ /* RTAS ibm,configure-connector state */
+ /* (only valid in UNISOLATE state) */
+ int ccs_offset;
+ int ccs_depth;
+
+ /* device pointer, via link property */
+ DeviceState *dev;
+ bool unplug_requested;
+ void *fdt;
+ int fdt_start_offset;
+} SpaprDrc;
+
+struct SpaprMachineState;
+
+typedef struct SpaprDrcClass {
+ /*< private >*/
+ DeviceClass parent;
+ SpaprDrcState empty_state;
+ SpaprDrcState ready_state;
+
+ /*< public >*/
+ SpaprDrcTypeShift typeshift;
+ const char *typename; /* used in device tree, PAPR 13.5.2.6 & C.6.1 */
+ const char *drc_name_prefix; /* used other places in device tree */
+
+ SpaprDREntitySense (*dr_entity_sense)(SpaprDrc *drc);
+ uint32_t (*isolate)(SpaprDrc *drc);
+ uint32_t (*unisolate)(SpaprDrc *drc);
+ void (*release)(DeviceState *dev);
+
+ int (*dt_populate)(SpaprDrc *drc, struct SpaprMachineState *spapr,
+ void *fdt, int *fdt_start_offset, Error **errp);
+} SpaprDrcClass;
+
+typedef struct SpaprDrcPhysical {
+ /*< private >*/
+ SpaprDrc parent;
+
+ /* DR-indicator */
+ uint32_t dr_indicator;
+} SpaprDrcPhysical;
+
+static inline bool spapr_drc_hotplugged(DeviceState *dev)
+{
+ return dev->hotplugged && !runstate_check(RUN_STATE_INMIGRATE);
+}
+
+/* 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);
+
+SpaprDrc *spapr_dr_connector_new(Object *owner, const char *type,
+ uint32_t id);
+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);
+
+/*
+ * 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);
+
+/*
+ * 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)
+{
+ return drc->unplug_requested;
+}
+
+#endif /* HW_SPAPR_DRC_H */
diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
new file mode 100644
index 000000000..c22a72c9e
--- /dev/null
+++ b/include/hw/ppc/spapr_irq.h
@@ -0,0 +1,117 @@
+/*
+ * QEMU PowerPC sPAPR IRQ backend definitions
+ *
+ * Copyright (c) 2018, IBM Corporation.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+
+#ifndef HW_SPAPR_IRQ_H
+#define HW_SPAPR_IRQ_H
+
+#include "target/ppc/cpu-qom.h"
+#include "qom/object.h"
+
+/*
+ * IRQ range offsets per device type
+ */
+#define SPAPR_IRQ_IPI 0x0
+
+#define SPAPR_XIRQ_BASE XICS_IRQ_BASE /* 0x1000 */
+#define SPAPR_IRQ_EPOW (SPAPR_XIRQ_BASE + 0x0000)
+#define SPAPR_IRQ_HOTPLUG (SPAPR_XIRQ_BASE + 0x0001)
+#define SPAPR_IRQ_VIO (SPAPR_XIRQ_BASE + 0x0100) /* 256 VIO devices */
+#define SPAPR_IRQ_PCI_LSI (SPAPR_XIRQ_BASE + 0x0200) /* 32+ PHBs devices */
+
+/* Offset of the dynamic range covered by the bitmap allocator */
+#define SPAPR_IRQ_MSI (SPAPR_XIRQ_BASE + 0x0300)
+
+#define SPAPR_NR_XIRQS 0x1000
+
+struct SpaprMachineState;
+
+typedef struct SpaprInterruptController SpaprInterruptController;
+
+#define TYPE_SPAPR_INTC "spapr-interrupt-controller"
+#define SPAPR_INTC(obj) \
+ INTERFACE_CHECK(SpaprInterruptController, (obj), TYPE_SPAPR_INTC)
+typedef struct SpaprInterruptControllerClass SpaprInterruptControllerClass;
+DECLARE_CLASS_CHECKERS(SpaprInterruptControllerClass, SPAPR_INTC,
+ TYPE_SPAPR_INTC)
+
+struct SpaprInterruptControllerClass {
+ InterfaceClass parent;
+
+ int (*activate)(SpaprInterruptController *intc, uint32_t nr_servers,
+ Error **errp);
+ void (*deactivate)(SpaprInterruptController *intc);
+
+ /*
+ * These methods will typically be called on all intcs, active and
+ * inactive
+ */
+ int (*cpu_intc_create)(SpaprInterruptController *intc,
+ PowerPCCPU *cpu, Error **errp);
+ void (*cpu_intc_reset)(SpaprInterruptController *intc, PowerPCCPU *cpu);
+ void (*cpu_intc_destroy)(SpaprInterruptController *intc, PowerPCCPU *cpu);
+ int (*claim_irq)(SpaprInterruptController *intc, int irq, bool lsi,
+ Error **errp);
+ void (*free_irq)(SpaprInterruptController *intc, int irq);
+
+ /* These methods should only be called on the active intc */
+ void (*set_irq)(SpaprInterruptController *intc, int irq, int val);
+ void (*print_info)(SpaprInterruptController *intc, Monitor *mon);
+ void (*dt)(SpaprInterruptController *intc, uint32_t nr_servers,
+ void *fdt, uint32_t phandle);
+ int (*post_load)(SpaprInterruptController *intc, int version_id);
+};
+
+void spapr_irq_update_active_intc(struct SpaprMachineState *spapr);
+
+int spapr_irq_cpu_intc_create(struct SpaprMachineState *spapr,
+ PowerPCCPU *cpu, Error **errp);
+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(struct SpaprMachineState *spapr);
+int spapr_irq_msi_alloc(struct SpaprMachineState *spapr, uint32_t num, bool align,
+ Error **errp);
+void spapr_irq_msi_free(struct SpaprMachineState *spapr, int irq, uint32_t num);
+
+typedef struct SpaprIrq {
+ bool xics;
+ bool xive;
+} SpaprIrq;
+
+extern SpaprIrq spapr_irq_xics;
+extern SpaprIrq spapr_irq_xics_legacy;
+extern SpaprIrq spapr_irq_xive;
+extern SpaprIrq spapr_irq_dual;
+
+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 **);
+
+int spapr_irq_init_kvm(SpaprInterruptControllerInitKvm fn,
+ SpaprInterruptController *intc,
+ uint32_t nr_servers,
+ Error **errp);
+
+/*
+ * XICS legacy routines
+ */
+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_numa.h b/include/hw/ppc/spapr_numa.h
new file mode 100644
index 000000000..7cb336740
--- /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
new file mode 100644
index 000000000..764f999f5
--- /dev/null
+++ b/include/hw/ppc/spapr_nvdimm.h
@@ -0,0 +1,25 @@
+/*
+ * QEMU PowerPC PAPR SCM backend definitions
+ *
+ * Copyright (c) 2020, IBM Corporation.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+
+#ifndef HW_SPAPR_NVDIMM_H
+#define HW_SPAPR_NVDIMM_H
+
+#include "hw/mem/nvdimm.h"
+
+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);
+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);
+
+#endif
diff --git a/include/hw/ppc/spapr_ovec.h b/include/hw/ppc/spapr_ovec.h
new file mode 100644
index 000000000..c3e8b98e7
--- /dev/null
+++ b/include/hw/ppc/spapr_ovec.h
@@ -0,0 +1,83 @@
+/*
+ * QEMU SPAPR Option/Architecture Vector Definitions
+ *
+ * Each architecture option is organized/documented by the following
+ * in LoPAPR 1.1, Table 244:
+ *
+ * <vector number>: the bit-vector in which the option is located
+ * <vector byte>: the byte offset of the vector entry
+ * <vector bit>: the bit offset within the vector entry
+ *
+ * where each vector entry can be one or more bytes.
+ *
+ * Firmware expects a somewhat literal encoding of this bit-vector
+ * structure, where each entry is stored in little-endian so that the
+ * byte ordering reflects that of the documentation, but where each bit
+ * offset is from "left-to-right" in the traditional representation of
+ * a byte value where the MSB is the left-most bit. Thus, each
+ * individual byte encodes the option bits in reverse order of the
+ * documented bit.
+ *
+ * These definitions/helpers attempt to abstract away this internal
+ * representation so that we can define/set/test for individual option
+ * bits using only the documented values. This is done mainly by relying
+ * on a bitmap to approximate the documented "bit-vector" structure and
+ * handling conversations to-from the internal representation under the
+ * covers.
+ *
+ * Copyright IBM Corp. 2016
+ *
+ * Authors:
+ * Michael Roth <mdroth@linux.vnet.ibm.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 SPAPR_OVEC_H
+#define SPAPR_OVEC_H
+
+#include "cpu.h"
+
+typedef struct SpaprOptionVector SpaprOptionVector;
+
+#define OV_BIT(byte, bit) ((byte - 1) * BITS_PER_BYTE + bit)
+
+/* option vector 1 */
+#define OV1_PPC_3_00 OV_BIT(3, 0) /* guest supports PowerPC 3.00? */
+
+/* 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)
+#define OV5_XIVE_BOTH OV_BIT(23, 0)
+#define OV5_XIVE_EXPLOIT OV_BIT(23, 1) /* 1=exploitation 0=legacy */
+
+/* ISA 3.00 MMU features: */
+#define OV5_MMU_BOTH OV_BIT(24, 0) /* Radix and hash */
+#define OV5_MMU_RADIX_300 OV_BIT(24, 1) /* 1=Radix only, 0=Hash only */
+#define OV5_MMU_RADIX_GTSE OV_BIT(26, 1) /* Radix GTSE */
+
+/* interfaces */
+SpaprOptionVector *spapr_ovec_new(void);
+SpaprOptionVector *spapr_ovec_clone(SpaprOptionVector *ov_orig);
+void spapr_ovec_intersect(SpaprOptionVector *ov,
+ SpaprOptionVector *ov1,
+ SpaprOptionVector *ov2);
+bool spapr_ovec_subset(SpaprOptionVector *ov1, SpaprOptionVector *ov2);
+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);
+
+/* migration */
+extern const VMStateDescription vmstate_spapr_ovec;
+
+#endif /* SPAPR_OVEC_H */
diff --git a/include/hw/ppc/spapr_rtas.h b/include/hw/ppc/spapr_rtas.h
new file mode 100644
index 000000000..383611f10
--- /dev/null
+++ b/include/hw/ppc/spapr_rtas.h
@@ -0,0 +1,10 @@
+#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
new file mode 100644
index 000000000..96d2a9697
--- /dev/null
+++ b/include/hw/ppc/spapr_tpm_proxy.h
@@ -0,0 +1,30 @@
+/*
+ * SPAPR TPM Proxy/Hypercall
+ *
+ * Copyright IBM Corp. 2019
+ *
+ * Authors:
+ * Michael Roth <mdroth@linux.vnet.ibm.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_TPM_PROXY_H
+#define HW_SPAPR_TPM_PROXY_H
+
+#include "qom/object.h"
+#include "hw/qdev-core.h"
+
+#define TYPE_SPAPR_TPM_PROXY "spapr-tpm-proxy"
+OBJECT_DECLARE_SIMPLE_TYPE(SpaprTpmProxy, SPAPR_TPM_PROXY)
+
+struct SpaprTpmProxy {
+ /*< private >*/
+ DeviceState parent;
+
+ char *host_path;
+ int host_fd;
+};
+
+#endif /* HW_SPAPR_TPM_PROXY_H */
diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h
new file mode 100644
index 000000000..4bea87f39
--- /dev/null
+++ b/include/hw/ppc/spapr_vio.h
@@ -0,0 +1,141 @@
+#ifndef HW_SPAPR_VIO_H
+#define HW_SPAPR_VIO_H
+
+/*
+ * QEMU sPAPR VIO bus definitions
+ *
+ * Copyright (c) 2010 David Gibson, IBM Corporation <david@gibson.dropbear.id.au>
+ * Based on the s390 virtio bus definitions:
+ * Copyright (c) 2009 Alexander Graf <agraf@suse.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.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/>.
+ */
+
+#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"
+OBJECT_DECLARE_TYPE(SpaprVioDevice, SpaprVioDeviceClass,
+ VIO_SPAPR_DEVICE)
+
+#define TYPE_SPAPR_VIO_BUS "spapr-vio-bus"
+OBJECT_DECLARE_SIMPLE_TYPE(SpaprVioBus, SPAPR_VIO_BUS)
+
+#define TYPE_SPAPR_VIO_BRIDGE "spapr-vio-bridge"
+
+typedef struct SpaprVioCrq {
+ uint64_t qladdr;
+ uint32_t qsize;
+ uint32_t qnext;
+ int(*SendFunc)(struct SpaprVioDevice *vdev, uint8_t *crq);
+} SpaprVioCrq;
+
+
+struct SpaprVioDeviceClass {
+ DeviceClass parent_class;
+
+ const char *dt_name, *dt_type, *dt_compatible;
+ target_ulong signal_mask;
+ uint32_t rtce_window_size;
+ void (*realize)(SpaprVioDevice *dev, Error **errp);
+ void (*reset)(SpaprVioDevice *dev);
+ int (*devnode)(SpaprVioDevice *dev, void *fdt, int node_off);
+ const char *(*get_dt_compatible)(SpaprVioDevice *dev);
+};
+
+struct SpaprVioDevice {
+ DeviceState qdev;
+ uint32_t reg;
+ uint32_t irq;
+ uint64_t signal_state;
+ SpaprVioCrq crq;
+ AddressSpace as;
+ MemoryRegion mrroot;
+ MemoryRegion mrbypass;
+ SpaprTceTable *tcet;
+};
+
+#define DEFINE_SPAPR_PROPERTIES(type, field) \
+ DEFINE_PROP_UINT32("reg", type, field.reg, -1)
+
+struct SpaprVioBus {
+ BusState bus;
+ uint32_t next_reg;
+};
+
+SpaprVioBus *spapr_vio_bus_init(void);
+SpaprVioDevice *spapr_vio_find_by_reg(SpaprVioBus *bus, uint32_t reg);
+void spapr_dt_vdevice(SpaprVioBus *bus, void *fdt);
+gchar *spapr_vio_stdout_path(SpaprVioBus *bus);
+
+static inline void spapr_vio_irq_pulse(SpaprVioDevice *dev)
+{
+ SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
+
+ qemu_irq_pulse(spapr_qirq(spapr, dev->irq));
+}
+
+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);
+}
+
+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) ?
+ 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) ?
+ 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) ?
+ 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)))
+
+int spapr_vio_send_crq(SpaprVioDevice *dev, uint8_t *crq);
+
+SpaprVioDevice *vty_lookup(SpaprMachineState *spapr, target_ulong reg);
+void vty_putchars(SpaprVioDevice *sdev, uint8_t *buf, int len);
+void spapr_vty_create(SpaprVioBus *bus, Chardev *chardev);
+void spapr_vlan_create(SpaprVioBus *bus, NICInfo *nd);
+void spapr_vscsi_create(SpaprVioBus *bus);
+
+SpaprVioDevice *spapr_vty_get_default(SpaprVioBus *bus);
+
+extern const VMStateDescription vmstate_spapr_vio;
+
+#define VMSTATE_SPAPR_VIO(_f, _s) \
+ VMSTATE_STRUCT(_f, _s, 0, vmstate_spapr_vio, SpaprVioDevice)
+
+void spapr_vio_set_bypass(SpaprVioDevice *dev, bool bypass);
+
+#endif /* HW_SPAPR_VIO_H */
diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h
new file mode 100644
index 000000000..b282960ad
--- /dev/null
+++ b/include/hw/ppc/spapr_xive.h
@@ -0,0 +1,99 @@
+/*
+ * QEMU PowerPC sPAPR XIVE interrupt controller model
+ *
+ * Copyright (c) 2017-2018, IBM Corporation.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+
+#ifndef PPC_SPAPR_XIVE_H
+#define PPC_SPAPR_XIVE_H
+
+#include "hw/ppc/spapr_irq.h"
+#include "hw/ppc/xive.h"
+
+#define TYPE_SPAPR_XIVE "spapr-xive"
+#define SPAPR_XIVE(obj) OBJECT_CHECK(SpaprXive, (obj), TYPE_SPAPR_XIVE)
+#define SPAPR_XIVE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(SpaprXiveClass, (klass), TYPE_SPAPR_XIVE)
+#define SPAPR_XIVE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(SpaprXiveClass, (obj), TYPE_SPAPR_XIVE)
+
+typedef struct SpaprXive {
+ XiveRouter parent;
+
+ /* Internal interrupt source for IPIs and virtual devices */
+ XiveSource source;
+ hwaddr vc_base;
+
+ /* END ESB MMIOs */
+ XiveENDSource end_source;
+ hwaddr end_base;
+
+ /* DT */
+ gchar *nodename;
+
+ /* Routing table */
+ XiveEAS *eat;
+ uint32_t nr_irqs;
+ XiveEND *endt;
+ uint32_t nr_ends;
+
+ /* TIMA mapping address */
+ hwaddr tm_base;
+ MemoryRegion tm_mmio;
+
+ /* KVM support */
+ int fd;
+ void *tm_mmap;
+ MemoryRegion tm_mmio_kvm;
+ VMChangeStateEntry *change;
+
+ uint8_t hv_prio;
+} SpaprXive;
+
+typedef struct SpaprXiveClass {
+ XiveRouterClass parent;
+
+ DeviceRealize parent_realize;
+} SpaprXiveClass;
+
+/*
+ * The sPAPR machine has a unique XIVE IC device. Assign a fixed value
+ * to the controller block id value. It can nevertheless be changed
+ * for testing purpose.
+ */
+#define SPAPR_XIVE_BLOCK_ID 0x0
+
+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);
+
+int spapr_xive_end_to_target(uint8_t end_blk, uint32_t end_idx,
+ uint32_t *out_server, uint8_t *out_prio);
+
+/*
+ * KVM XIVE device helpers
+ */
+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);
+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);
+int kvmppc_xive_set_queue_config(SpaprXive *xive, uint8_t end_blk,
+ uint32_t end_idx, XiveEND *end,
+ Error **errp);
+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);
+int kvmppc_xive_pre_save(SpaprXive *xive);
+int kvmppc_xive_post_load(SpaprXive *xive, int version_id);
+
+#endif /* PPC_SPAPR_XIVE_H */
diff --git a/include/hw/ppc/vof.h b/include/hw/ppc/vof.h
new file mode 100644
index 000000000..97fdef758
--- /dev/null
+++ b/include/hw/ppc/vof.h
@@ -0,0 +1,60 @@
+/*
+ * Virtual Open Firmware
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef HW_VOF_H
+#define HW_VOF_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
new file mode 100644
index 000000000..00b80b08c
--- /dev/null
+++ b/include/hw/ppc/xics.h
@@ -0,0 +1,196 @@
+/*
+ * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
+ *
+ * PAPR Virtualized Interrupt System, aka ICS/ICP aka xics
+ *
+ * Copyright (c) 2010,2011 David Gibson, IBM Corporation.
+ *
+ * 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 XICS_H
+#define XICS_H
+
+#include "exec/memory.h"
+#include "hw/qdev-core.h"
+#include "qom/object.h"
+
+#define XICS_IPI 0x2
+#define XICS_BUID 0x1
+#define XICS_IRQ_BASE (XICS_BUID << 12)
+
+/*
+ * We currently only support one BUID which is our interrupt base
+ * (the kernel implementation supports more but we don't exploit
+ * that yet)
+ */
+typedef struct PnvICPState PnvICPState;
+typedef struct ICSStateClass ICSStateClass;
+typedef struct ICSState ICSState;
+typedef struct ICSIRQState ICSIRQState;
+typedef struct XICSFabric XICSFabric;
+
+#define TYPE_ICP "icp"
+OBJECT_DECLARE_TYPE(ICPState, ICPStateClass,
+ ICP)
+
+#define TYPE_PNV_ICP "pnv-icp"
+DECLARE_INSTANCE_CHECKER(PnvICPState, PNV_ICP,
+ TYPE_PNV_ICP)
+
+
+struct ICPStateClass {
+ DeviceClass parent_class;
+
+ DeviceRealize parent_realize;
+};
+
+struct ICPState {
+ /*< private >*/
+ DeviceState parent_obj;
+ /*< public >*/
+ CPUState *cs;
+ ICSState *xirr_owner;
+ uint32_t xirr;
+ uint8_t pending_priority;
+ uint8_t mfrr;
+ qemu_irq output;
+
+ XICSFabric *xics;
+};
+
+#define ICP_PROP_XICS "xics"
+#define ICP_PROP_CPU "cpu"
+
+struct PnvICPState {
+ ICPState parent_obj;
+
+ MemoryRegion mmio;
+ uint32_t links[3];
+};
+
+#define TYPE_ICS "ics"
+DECLARE_OBJ_CHECKERS(ICSState, ICSStateClass,
+ ICS, TYPE_ICS)
+
+
+struct ICSStateClass {
+ DeviceClass parent_class;
+
+ DeviceRealize parent_realize;
+ DeviceReset parent_reset;
+
+ void (*reject)(ICSState *s, uint32_t irq);
+ void (*resend)(ICSState *s);
+};
+
+struct ICSState {
+ /*< private >*/
+ DeviceState parent_obj;
+ /*< public >*/
+ uint32_t nr_irqs;
+ uint32_t offset;
+ ICSIRQState *irqs;
+ XICSFabric *xics;
+};
+
+#define ICS_PROP_XICS "xics"
+
+static inline bool ics_valid_irq(ICSState *ics, uint32_t nr)
+{
+ return (nr >= ics->offset) && (nr < (ics->offset + ics->nr_irqs));
+}
+
+struct ICSIRQState {
+ uint32_t server;
+ uint8_t priority;
+ uint8_t saved_priority;
+#define XICS_STATUS_ASSERTED 0x1
+#define XICS_STATUS_SENT 0x2
+#define XICS_STATUS_REJECTED 0x4
+#define XICS_STATUS_MASKED_PENDING 0x8
+#define XICS_STATUS_PRESENTED 0x10
+#define XICS_STATUS_QUEUED 0x20
+ uint8_t status;
+/* (flags & XICS_FLAGS_IRQ_MASK) == 0 means the interrupt is not allocated */
+#define XICS_FLAGS_IRQ_LSI 0x1
+#define XICS_FLAGS_IRQ_MSI 0x2
+#define XICS_FLAGS_IRQ_MASK 0x3
+ uint8_t flags;
+};
+
+#define TYPE_XICS_FABRIC "xics-fabric"
+#define XICS_FABRIC(obj) \
+ INTERFACE_CHECK(XICSFabric, (obj), TYPE_XICS_FABRIC)
+typedef struct XICSFabricClass XICSFabricClass;
+DECLARE_CLASS_CHECKERS(XICSFabricClass, XICS_FABRIC,
+ TYPE_XICS_FABRIC)
+
+struct XICSFabricClass {
+ InterfaceClass parent;
+ ICSState *(*ics_get)(XICSFabric *xi, int irq);
+ void (*ics_resend)(XICSFabric *xi);
+ ICPState *(*icp_get)(XICSFabric *xi, int server);
+};
+
+ICPState *xics_icp_get(XICSFabric *xi, int server);
+
+/* Internal XICS interfaces */
+void icp_set_cppr(ICPState *icp, uint8_t cppr);
+void icp_set_mfrr(ICPState *icp, uint8_t mfrr);
+uint32_t icp_accept(ICPState *ss);
+uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr);
+void icp_eoi(ICPState *icp, uint32_t xirr);
+void icp_irq(ICSState *ics, int server, int nr, uint8_t priority);
+void icp_reset(ICPState *icp);
+
+void ics_write_xive(ICSState *ics, int nr, int server,
+ uint8_t priority, uint8_t saved_priority);
+void ics_set_irq(void *opaque, int srcno, int val);
+
+static inline bool ics_irq_free(ICSState *ics, uint32_t srcno)
+{
+ return !(ics->irqs[srcno].flags & XICS_FLAGS_IRQ_MASK);
+}
+
+void ics_set_irq_type(ICSState *ics, int srcno, bool lsi);
+void icp_pic_print_info(ICPState *icp, Monitor *mon);
+void ics_pic_print_info(ICSState *ics, Monitor *mon);
+
+void ics_resend(ICSState *ics);
+void icp_resend(ICPState *ss);
+
+Object *icp_create(Object *cpu, const char *type, XICSFabric *xi,
+ Error **errp);
+void icp_destroy(ICPState *icp);
+
+/* KVM */
+void icp_get_kvm_state(ICPState *icp);
+int icp_set_kvm_state(ICPState *icp, Error **errp);
+void icp_synchronize_state(ICPState *icp);
+void icp_kvm_realize(DeviceState *dev, Error **errp);
+
+void ics_get_kvm_state(ICSState *ics);
+int ics_set_kvm_state_one(ICSState *ics, int srcno, Error **errp);
+int ics_set_kvm_state(ICSState *ics, Error **errp);
+void ics_synchronize_state(ICSState *ics);
+void ics_kvm_set_irq(ICSState *ics, int srcno, int val);
+
+#endif /* XICS_H */
diff --git a/include/hw/ppc/xics_spapr.h b/include/hw/ppc/xics_spapr.h
new file mode 100644
index 000000000..de752c0d2
--- /dev/null
+++ b/include/hw/ppc/xics_spapr.h
@@ -0,0 +1,43 @@
+/*
+ * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
+ *
+ * PAPR Virtualized Interrupt System, aka ICS/ICP aka xics
+ *
+ * Copyright (c) 2010, 2011 David Gibson, IBM Corporation.
+ *
+ * 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 XICS_SPAPR_H
+#define XICS_SPAPR_H
+
+#include "hw/ppc/spapr.h"
+#include "qom/object.h"
+
+#define TYPE_ICS_SPAPR "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(void);
+
+#endif /* XICS_SPAPR_H */
diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h
new file mode 100644
index 000000000..b8ab0bf74
--- /dev/null
+++ b/include/hw/ppc/xive.h
@@ -0,0 +1,536 @@
+/*
+ * QEMU PowerPC XIVE interrupt controller model
+ *
+ *
+ * The POWER9 processor comes with a new interrupt controller, called
+ * XIVE as "eXternal Interrupt Virtualization Engine".
+ *
+ * = Overall architecture
+ *
+ *
+ * XIVE Interrupt Controller
+ * +------------------------------------+ IPIs
+ * | +---------+ +---------+ +--------+ | +-------+
+ * | |VC | |CQ | |PC |----> | CORES |
+ * | | esb | | | | |----> | |
+ * | | eas | | Bridge | | tctx |----> | |
+ * | |SC end | | | | nvt | | | |
+ * +------+ | +---------+ +----+----+ +--------+ | +-+-+-+-+
+ * | RAM | +------------------|-----------------+ | | |
+ * | | | | | |
+ * | | | | | |
+ * | | +--------------------v------------------------v-v-v--+ other
+ * | <--+ Power Bus +--> chips
+ * | esb | +---------+-----------------------+------------------+
+ * | eas | | |
+ * | end | +--|------+ |
+ * | nvt | +----+----+ | +----+----+
+ * +------+ |SC | | |SC |
+ * | | | | |
+ * | PQ-bits | | | PQ-bits |
+ * | local |-+ | in VC |
+ * +---------+ +---------+
+ * PCIe NX,NPU,CAPI
+ *
+ * SC: Source Controller (aka. IVSE)
+ * VC: Virtualization Controller (aka. IVRE)
+ * PC: Presentation Controller (aka. IVPE)
+ * CQ: Common Queue (Bridge)
+ *
+ * PQ-bits: 2 bits source state machine (P:pending Q:queued)
+ * esb: Event State Buffer (Array of PQ bits in an IVSE)
+ * eas: Event Assignment Structure
+ * end: Event Notification Descriptor
+ * nvt: Notification Virtual Target
+ * tctx: Thread interrupt Context
+ *
+ *
+ * The XIVE IC is composed of three sub-engines :
+ *
+ * - Interrupt Virtualization Source Engine (IVSE), or Source
+ * Controller (SC). These are found in PCI PHBs, in the PSI host
+ * bridge controller, but also inside the main controller for the
+ * core IPIs and other sub-chips (NX, CAP, NPU) of the
+ * chip/processor. They are configured to feed the IVRE with events.
+ *
+ * - Interrupt Virtualization Routing Engine (IVRE) or Virtualization
+ * Controller (VC). Its job is to match an event source with an
+ * Event Notification Descriptor (END).
+ *
+ * - Interrupt Virtualization Presentation Engine (IVPE) or
+ * Presentation Controller (PC). It maintains the interrupt context
+ * state of each thread and handles the delivery of the external
+ * exception to the thread.
+ *
+ * In XIVE 1.0, the sub-engines used to be referred as:
+ *
+ * SC Source Controller
+ * VC Virtualization Controller
+ * PC Presentation Controller
+ * CQ Common Queue (PowerBUS Bridge)
+ *
+ *
+ * = XIVE internal tables
+ *
+ * Each of the sub-engines uses a set of tables to redirect exceptions
+ * from event sources to CPU threads.
+ *
+ * +-------+
+ * User or OS | EQ |
+ * or +------>|entries|
+ * Hypervisor | | .. |
+ * Memory | +-------+
+ * | ^
+ * | |
+ * +-------------------------------------------------+
+ * | |
+ * Hypervisor +------+ +---+--+ +---+--+ +------+
+ * Memory | ESB | | EAT | | ENDT | | NVTT |
+ * (skiboot) +----+-+ +----+-+ +----+-+ +------+
+ * ^ | ^ | ^ | ^
+ * | | | | | | |
+ * +-------------------------------------------------+
+ * | | | | | | |
+ * | | | | | | |
+ * +----|--|--------|--|--------|--|-+ +-|-----+ +------+
+ * | | | | | | | | | | tctx| |Thread|
+ * IPI or --> | + v + v + v |---| + .. |-----> |
+ * HW events --> | | | | | |
+ * IVSE | IVRE | | IVPE | +------+
+ * +---------------------------------+ +-------+
+ *
+ *
+ *
+ * The IVSE have a 2-bits state machine, P for pending and Q for queued,
+ * for each source that allows events to be triggered. They are stored in
+ * an Event State Buffer (ESB) array and can be controlled by MMIOs.
+ *
+ * If the event is let through, the IVRE looks up in the Event Assignment
+ * Structure (EAS) table for an Event Notification Descriptor (END)
+ * configured for the source. Each Event Notification Descriptor defines
+ * a notification path to a CPU and an in-memory Event Queue, in which
+ * will be enqueued an EQ data for the OS to pull.
+ *
+ * The IVPE determines if a Notification Virtual Target (NVT) can
+ * handle the event by scanning the thread contexts of the VCPUs
+ * dispatched on the processor HW threads. It maintains the state of
+ * the thread interrupt context (TCTX) of each thread in a NVT table.
+ *
+ * = Acronyms
+ *
+ * Description In XIVE 1.0, used to be referred as
+ *
+ * EAS Event Assignment Structure IVE Interrupt Virt. Entry
+ * EAT Event Assignment Table IVT Interrupt Virt. Table
+ * ENDT Event Notif. Descriptor Table EQDT Event Queue Desc. Table
+ * EQ Event Queue same
+ * ESB Event State Buffer SBE State Bit Entry
+ * NVT Notif. Virtual Target VPD Virtual Processor Desc.
+ * NVTT Notif. Virtual Target Table VPDT Virtual Processor Desc. Table
+ * TCTX Thread interrupt Context
+ *
+ *
+ * Copyright (c) 2017-2018, IBM Corporation.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef PPC_XIVE_H
+#define PPC_XIVE_H
+
+#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)
+ */
+
+typedef struct XiveNotifier XiveNotifier;
+
+#define TYPE_XIVE_NOTIFIER "xive-notifier"
+#define XIVE_NOTIFIER(obj) \
+ INTERFACE_CHECK(XiveNotifier, (obj), TYPE_XIVE_NOTIFIER)
+typedef struct XiveNotifierClass XiveNotifierClass;
+DECLARE_CLASS_CHECKERS(XiveNotifierClass, XIVE_NOTIFIER,
+ TYPE_XIVE_NOTIFIER)
+
+struct XiveNotifierClass {
+ InterfaceClass parent;
+ void (*notify)(XiveNotifier *xn, uint32_t lisn);
+};
+
+/*
+ * XIVE Interrupt Source
+ */
+
+#define TYPE_XIVE_SOURCE "xive-source"
+OBJECT_DECLARE_SIMPLE_TYPE(XiveSource, XIVE_SOURCE)
+
+/*
+ * XIVE Interrupt Source characteristics, which define how the ESB are
+ * controlled.
+ */
+#define XIVE_SRC_H_INT_ESB 0x1 /* ESB managed with hcall H_INT_ESB */
+#define XIVE_SRC_STORE_EOI 0x2 /* Store EOI supported */
+
+struct XiveSource {
+ DeviceState parent;
+
+ /* IRQs */
+ uint32_t nr_irqs;
+ unsigned long *lsi_map;
+
+ /* PQ bits and LSI assertion bit */
+ uint8_t *status;
+
+ /* 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;
+};
+
+/*
+ * ESB MMIO setting. Can be one page, for both source triggering and
+ * source management, or two different pages. See below for magic
+ * values.
+ */
+#define XIVE_ESB_4K 12 /* PSI HB only */
+#define XIVE_ESB_4K_2PAGE 13
+#define XIVE_ESB_64K 16
+#define XIVE_ESB_64K_2PAGE 17
+
+static inline bool xive_source_esb_has_2page(XiveSource *xsrc)
+{
+ return xsrc->esb_shift == XIVE_ESB_64K_2PAGE ||
+ 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)
+{
+ assert(srcno < xsrc->nr_irqs);
+ return (1ull << xsrc->esb_shift) * srcno;
+}
+
+/* In a two pages ESB MMIO setting, the odd page is for management */
+static inline hwaddr xive_source_esb_mgmt(XiveSource *xsrc, int srcno)
+{
+ hwaddr addr = xive_source_esb_page(xsrc, srcno);
+
+ if (xive_source_esb_has_2page(xsrc)) {
+ addr += (1 << (xsrc->esb_shift - 1));
+ }
+
+ return addr;
+}
+
+/*
+ * Each interrupt source has a 2-bit state machine which can be
+ * controlled by MMIO. P indicates that an interrupt is pending (has
+ * been sent to a queue and is waiting for an EOI). Q indicates that
+ * the interrupt has been triggered while pending.
+ *
+ * This acts as a coalescing mechanism in order to guarantee that a
+ * given interrupt only occurs at most once in a queue.
+ *
+ * When doing an EOI, the Q bit will indicate if the interrupt
+ * needs to be re-triggered.
+ */
+#define XIVE_STATUS_ASSERTED 0x4 /* Extra bit for LSI */
+#define XIVE_ESB_VAL_P 0x2
+#define XIVE_ESB_VAL_Q 0x1
+
+#define XIVE_ESB_RESET 0x0
+#define XIVE_ESB_PENDING XIVE_ESB_VAL_P
+#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.
+ *
+ * The following offsets into the ESB MMIO allow to read or manipulate
+ * the PQ bits. They must be used with an 8-byte load instruction.
+ * They all return the previous state of the interrupt (atomically).
+ *
+ * Additionally, some ESB pages support doing an EOI via a store and
+ * some ESBs support doing a trigger via a separate trigger page.
+ */
+#define XIVE_ESB_STORE_EOI 0x400 /* Store */
+#define XIVE_ESB_LOAD_EOI 0x000 /* Load */
+#define XIVE_ESB_GET 0x800 /* Load */
+#define XIVE_ESB_SET_PQ_00 0xc00 /* Load */
+#define XIVE_ESB_SET_PQ_01 0xd00 /* Load */
+#define XIVE_ESB_SET_PQ_10 0xe00 /* Load */
+#define XIVE_ESB_SET_PQ_11 0xf00 /* Load */
+
+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);
+
+static inline bool xive_source_irq_is_lsi(XiveSource *xsrc, uint32_t srcno)
+{
+ assert(srcno < xsrc->nr_irqs);
+ return test_bit(srcno, xsrc->lsi_map);
+}
+
+static inline void xive_source_irq_set_lsi(XiveSource *xsrc, uint32_t srcno)
+{
+ assert(srcno < xsrc->nr_irqs);
+ bitmap_set(xsrc->lsi_map, srcno, 1);
+}
+
+void xive_source_set_irq(void *opaque, int srcno, int val);
+
+/*
+ * XIVE Thread interrupt Management (TM) context
+ */
+
+#define TYPE_XIVE_TCTX "xive-tctx"
+OBJECT_DECLARE_SIMPLE_TYPE(XiveTCTX, XIVE_TCTX)
+
+/*
+ * XIVE Thread interrupt Management register rings :
+ *
+ * QW-0 User event-based exception state
+ * QW-1 O/S OS context for priority management, interrupt acks
+ * QW-2 Pool hypervisor pool context for virtual processors dispatched
+ * QW-3 Physical physical thread context and security context
+ */
+#define XIVE_TM_RING_COUNT 4
+#define XIVE_TM_RING_SIZE 0x10
+
+typedef struct XivePresenter XivePresenter;
+
+struct XiveTCTX {
+ DeviceState parent_obj;
+
+ CPUState *cs;
+ qemu_irq hv_output;
+ qemu_irq os_output;
+
+ uint8_t regs[XIVE_TM_RING_COUNT * XIVE_TM_RING_SIZE];
+
+ XivePresenter *xptr;
+};
+
+static inline uint32_t xive_tctx_word2(uint8_t *ring)
+{
+ return *((uint32_t *) &ring[TM_WORD2]);
+}
+
+/*
+ * XIVE Router
+ */
+typedef struct XiveFabric XiveFabric;
+
+struct XiveRouter {
+ SysBusDevice parent;
+
+ XiveFabric *xfb;
+};
+
+#define TYPE_XIVE_ROUTER "xive-router"
+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_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,
+ XiveEND *end, uint8_t word_number);
+ int (*get_nvt)(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx,
+ XiveNVT *nvt);
+ 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);
+};
+
+int xive_router_get_eas(XiveRouter *xrtr, uint8_t eas_blk, uint32_t eas_idx,
+ XiveEAS *eas);
+int xive_router_get_end(XiveRouter *xrtr, uint8_t end_blk, uint32_t end_idx,
+ XiveEND *end);
+int xive_router_write_end(XiveRouter *xrtr, uint8_t end_blk, uint32_t end_idx,
+ XiveEND *end, uint8_t word_number);
+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);
+
+/*
+ * XIVE Presenter
+ */
+
+typedef struct XiveTCTXMatch {
+ XiveTCTX *tctx;
+ uint8_t ring;
+} XiveTCTXMatch;
+
+#define TYPE_XIVE_PRESENTER "xive-presenter"
+#define XIVE_PRESENTER(obj) \
+ INTERFACE_CHECK(XivePresenter, (obj), TYPE_XIVE_PRESENTER)
+typedef struct XivePresenterClass XivePresenterClass;
+DECLARE_CLASS_CHECKERS(XivePresenterClass, XIVE_PRESENTER,
+ TYPE_XIVE_PRESENTER)
+
+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);
+ bool (*in_kernel)(const 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)
+ */
+
+#define TYPE_XIVE_FABRIC "xive-fabric"
+#define XIVE_FABRIC(obj) \
+ INTERFACE_CHECK(XiveFabric, (obj), TYPE_XIVE_FABRIC)
+typedef struct XiveFabricClass XiveFabricClass;
+DECLARE_CLASS_CHECKERS(XiveFabricClass, XIVE_FABRIC,
+ TYPE_XIVE_FABRIC)
+
+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);
+};
+
+/*
+ * XIVE END ESBs
+ */
+
+#define TYPE_XIVE_END_SOURCE "xive-end-source"
+OBJECT_DECLARE_SIMPLE_TYPE(XiveENDSource, XIVE_END_SOURCE)
+
+struct XiveENDSource {
+ DeviceState parent;
+
+ uint32_t nr_ends;
+
+ /* ESB memory region */
+ uint32_t esb_shift;
+ MemoryRegion esb_mmio;
+
+ XiveRouter *xrtr;
+};
+
+/*
+ * For legacy compatibility, the exceptions define up to 256 different
+ * priorities. P9 implements only 9 levels : 8 active levels [0 - 7]
+ * and the least favored level 0xFF.
+ */
+#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
+ * management context. It is four page wide, each page providing a
+ * different view of the registers. The page with the lower offset is
+ * the most privileged and gives access to the entire context.
+ */
+#define XIVE_TM_HW_PAGE 0x0
+#define XIVE_TM_HV_PAGE 0x1
+#define XIVE_TM_OS_PAGE 0x2
+#define XIVE_TM_USER_PAGE 0x3
+
+void xive_tctx_tm_write(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset,
+ uint64_t value, unsigned size);
+uint64_t xive_tctx_tm_read(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset,
+ unsigned size);
+
+void xive_tctx_pic_print_info(XiveTCTX *tctx, Monitor *mon);
+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);
+
+/*
+ * KVM XIVE device helpers
+ */
+
+int kvmppc_xive_source_reset_one(XiveSource *xsrc, int srcno, Error **errp);
+void kvmppc_xive_source_set_irq(void *opaque, int srcno, int val);
+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/xive_regs.h b/include/hw/ppc/xive_regs.h
new file mode 100644
index 000000000..b7fde2354
--- /dev/null
+++ b/include/hw/ppc/xive_regs.h
@@ -0,0 +1,301 @@
+/*
+ * QEMU PowerPC XIVE internal structure definitions
+ *
+ *
+ * The XIVE structures are accessed by the HW and their format is
+ * architected to be big-endian. Some macros are provided to ease
+ * access to the different fields.
+ *
+ *
+ * Copyright (c) 2016-2018, IBM Corporation.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+
+#ifndef PPC_XIVE_REGS_H
+#define PPC_XIVE_REGS_H
+
+#include "qemu/bswap.h"
+#include "qemu/host-utils.h"
+
+/*
+ * Interrupt source number encoding on PowerBUS
+ */
+/*
+ * Trigger data definition
+ *
+ * The trigger definition is used for triggers both for HW source
+ * interrupts (PHB, PSI), as well as for rerouting interrupts between
+ * Interrupt Controller.
+ *
+ * HW source controllers set bit0 of word0 to ‘0’ as they provide EAS
+ * information (EAS block + EAS index) in the 8 byte data and not END
+ * information, which is use for rerouting interrupts.
+ *
+ * bit1 of word0 to ‘1’ signals that the state bit check has been
+ * performed.
+ */
+#define XIVE_TRIGGER_END PPC_BIT(0)
+#define XIVE_TRIGGER_PQ PPC_BIT(1)
+
+/*
+ * QEMU macros to manipulate the trigger payload in native endian
+ */
+#define XIVE_EAS_BLOCK(n) (((n) >> 28) & 0xf)
+#define XIVE_EAS_INDEX(n) ((n) & 0x0fffffff)
+#define XIVE_EAS(blk, idx) ((uint32_t)(blk) << 28 | (idx))
+
+#define TM_SHIFT 16
+
+/* TM register offsets */
+#define TM_QW0_USER 0x000 /* All rings */
+#define TM_QW1_OS 0x010 /* Ring 0..2 */
+#define TM_QW2_HV_POOL 0x020 /* Ring 0..1 */
+#define TM_QW3_HV_PHYS 0x030 /* Ring 0..1 */
+
+/* Byte offsets inside a QW QW0 QW1 QW2 QW3 */
+#define TM_NSR 0x0 /* + + - + */
+#define TM_CPPR 0x1 /* - + - + */
+#define TM_IPB 0x2 /* - + + + */
+#define TM_LSMFB 0x3 /* - + + + */
+#define TM_ACK_CNT 0x4 /* - + - - */
+#define TM_INC 0x5 /* - + - + */
+#define TM_AGE 0x6 /* - + - + */
+#define TM_PIPR 0x7 /* - + - + */
+
+#define TM_WORD0 0x0
+#define TM_WORD1 0x4
+
+/*
+ * QW word 2 contains the valid bit at the top and other fields
+ * depending on the QW.
+ */
+#define TM_WORD2 0x8
+#define TM_QW0W2_VU PPC_BIT32(0)
+#define TM_QW0W2_LOGIC_SERV PPC_BITMASK32(1, 31) /* XX 2,31 ? */
+#define TM_QW1W2_VO PPC_BIT32(0)
+#define TM_QW1W2_OS_CAM PPC_BITMASK32(8, 31)
+#define TM_QW2W2_VP PPC_BIT32(0)
+#define TM_QW2W2_POOL_CAM PPC_BITMASK32(8, 31)
+#define TM_QW3W2_VT PPC_BIT32(0)
+#define TM_QW3W2_LP PPC_BIT32(6)
+#define TM_QW3W2_LE PPC_BIT32(7)
+#define TM_QW3W2_T PPC_BIT32(31)
+
+/*
+ * In addition to normal loads to "peek" and writes (only when invalid)
+ * using 4 and 8 bytes accesses, the above registers support these
+ * "special" byte operations:
+ *
+ * - Byte load from QW0[NSR] - User level NSR (EBB)
+ * - Byte store to QW0[NSR] - User level NSR (EBB)
+ * - Byte load/store to QW1[CPPR] and QW3[CPPR] - CPPR access
+ * - Byte load from QW3[TM_WORD2] - Read VT||00000||LP||LE on thrd 0
+ * otherwise VT||0000000
+ * - Byte store to QW3[TM_WORD2] - Set VT bit (and LP/LE if present)
+ *
+ * Then we have all these "special" CI ops at these offset that trigger
+ * all sorts of side effects:
+ */
+#define TM_SPC_ACK_EBB 0x800 /* Load8 ack EBB to reg*/
+#define TM_SPC_ACK_OS_REG 0x810 /* Load16 ack OS irq to reg */
+#define TM_SPC_PUSH_USR_CTX 0x808 /* Store32 Push/Validate user context */
+#define TM_SPC_PULL_USR_CTX 0x808 /* Load32 Pull/Invalidate user
+ * context */
+#define TM_SPC_SET_OS_PENDING 0x812 /* Store8 Set OS irq pending bit */
+#define TM_SPC_PULL_OS_CTX 0x818 /* Load32/Load64 Pull/Invalidate OS
+ * context to reg */
+#define TM_SPC_PULL_POOL_CTX 0x828 /* Load32/Load64 Pull/Invalidate Pool
+ * context to reg*/
+#define TM_SPC_ACK_HV_REG 0x830 /* Load16 ack HV irq to reg */
+#define TM_SPC_PULL_USR_CTX_OL 0xc08 /* Store8 Pull/Inval usr ctx to odd
+ * line */
+#define TM_SPC_ACK_OS_EL 0xc10 /* Store8 ack OS irq to even line */
+#define TM_SPC_ACK_HV_POOL_EL 0xc20 /* Store8 ack HV evt pool to even
+ * line */
+#define TM_SPC_ACK_HV_EL 0xc30 /* Store8 ack HV irq to even line */
+/* XXX more... */
+
+/* NSR fields for the various QW ack types */
+#define TM_QW0_NSR_EB PPC_BIT8(0)
+#define TM_QW1_NSR_EO PPC_BIT8(0)
+#define TM_QW3_NSR_HE PPC_BITMASK8(0, 1)
+#define TM_QW3_NSR_HE_NONE 0
+#define TM_QW3_NSR_HE_POOL 1
+#define TM_QW3_NSR_HE_PHYS 2
+#define TM_QW3_NSR_HE_LSI 3
+#define TM_QW3_NSR_I PPC_BIT8(2)
+#define TM_QW3_NSR_GRP_LVL PPC_BIT8(3, 7)
+
+/*
+ * EAS (Event Assignment Structure)
+ *
+ * One per interrupt source. Targets an interrupt to a given Event
+ * Notification Descriptor (END) and provides the corresponding
+ * logical interrupt number (END data)
+ */
+typedef struct XiveEAS {
+ /*
+ * Use a single 64-bit definition to make it easier to perform
+ * atomic updates
+ */
+ uint64_t w;
+#define EAS_VALID PPC_BIT(0)
+#define EAS_END_BLOCK PPC_BITMASK(4, 7) /* Destination END block# */
+#define EAS_END_INDEX PPC_BITMASK(8, 31) /* Destination END index */
+#define EAS_MASKED PPC_BIT(32) /* Masked */
+#define EAS_END_DATA PPC_BITMASK(33, 63) /* Data written to the END */
+} XiveEAS;
+
+#define xive_eas_is_valid(eas) (be64_to_cpu((eas)->w) & EAS_VALID)
+#define xive_eas_is_masked(eas) (be64_to_cpu((eas)->w) & EAS_MASKED)
+
+void xive_eas_pic_print_info(XiveEAS *eas, uint32_t lisn, Monitor *mon);
+
+static inline uint64_t xive_get_field64(uint64_t mask, uint64_t word)
+{
+ return (be64_to_cpu(word) & mask) >> ctz64(mask);
+}
+
+static inline uint64_t xive_set_field64(uint64_t mask, uint64_t word,
+ uint64_t value)
+{
+ uint64_t tmp =
+ (be64_to_cpu(word) & ~mask) | ((value << ctz64(mask)) & mask);
+ return cpu_to_be64(tmp);
+}
+
+static inline uint32_t xive_get_field32(uint32_t mask, uint32_t word)
+{
+ return (be32_to_cpu(word) & mask) >> ctz32(mask);
+}
+
+static inline uint32_t xive_set_field32(uint32_t mask, uint32_t word,
+ uint32_t value)
+{
+ uint32_t tmp =
+ (be32_to_cpu(word) & ~mask) | ((value << ctz32(mask)) & mask);
+ return cpu_to_be32(tmp);
+}
+
+/* Event Notification Descriptor (END) */
+typedef struct XiveEND {
+ uint32_t w0;
+#define END_W0_VALID PPC_BIT32(0) /* "v" bit */
+#define END_W0_ENQUEUE PPC_BIT32(1) /* "q" bit */
+#define END_W0_UCOND_NOTIFY PPC_BIT32(2) /* "n" bit */
+#define END_W0_BACKLOG PPC_BIT32(3) /* "b" bit */
+#define END_W0_PRECL_ESC_CTL PPC_BIT32(4) /* "p" bit */
+#define END_W0_ESCALATE_CTL PPC_BIT32(5) /* "e" bit */
+#define END_W0_UNCOND_ESCALATE PPC_BIT32(6) /* "u" bit - DD2.0 */
+#define END_W0_SILENT_ESCALATE PPC_BIT32(7) /* "s" bit - DD2.0 */
+#define END_W0_QSIZE PPC_BITMASK32(12, 15)
+#define END_W0_SW0 PPC_BIT32(16)
+#define END_W0_FIRMWARE END_W0_SW0 /* Owned by FW */
+#define END_QSIZE_4K 0
+#define END_QSIZE_64K 4
+#define END_W0_HWDEP PPC_BITMASK32(24, 31)
+ uint32_t w1;
+#define END_W1_ESn PPC_BITMASK32(0, 1)
+#define END_W1_ESn_P PPC_BIT32(0)
+#define END_W1_ESn_Q PPC_BIT32(1)
+#define END_W1_ESe PPC_BITMASK32(2, 3)
+#define END_W1_ESe_P PPC_BIT32(2)
+#define END_W1_ESe_Q PPC_BIT32(3)
+#define END_W1_GENERATION PPC_BIT32(9)
+#define END_W1_PAGE_OFF PPC_BITMASK32(10, 31)
+ uint32_t w2;
+#define END_W2_MIGRATION_REG PPC_BITMASK32(0, 3)
+#define END_W2_OP_DESC_HI PPC_BITMASK32(4, 31)
+ uint32_t w3;
+#define END_W3_OP_DESC_LO PPC_BITMASK32(0, 31)
+ uint32_t w4;
+#define END_W4_ESC_END_BLOCK PPC_BITMASK32(4, 7)
+#define END_W4_ESC_END_INDEX PPC_BITMASK32(8, 31)
+ uint32_t w5;
+#define END_W5_ESC_END_DATA PPC_BITMASK32(1, 31)
+ uint32_t w6;
+#define END_W6_FORMAT_BIT PPC_BIT32(8)
+#define END_W6_NVT_BLOCK PPC_BITMASK32(9, 12)
+#define END_W6_NVT_INDEX PPC_BITMASK32(13, 31)
+ uint32_t w7;
+#define END_W7_F0_IGNORE PPC_BIT32(0)
+#define END_W7_F0_BLK_GROUPING PPC_BIT32(1)
+#define END_W7_F0_PRIORITY PPC_BITMASK32(8, 15)
+#define END_W7_F1_WAKEZ PPC_BIT32(0)
+#define END_W7_F1_LOG_SERVER_ID PPC_BITMASK32(1, 31)
+} XiveEND;
+
+#define xive_end_is_valid(end) (be32_to_cpu((end)->w0) & END_W0_VALID)
+#define xive_end_is_enqueue(end) (be32_to_cpu((end)->w0) & END_W0_ENQUEUE)
+#define xive_end_is_notify(end) (be32_to_cpu((end)->w0) & END_W0_UCOND_NOTIFY)
+#define xive_end_is_backlog(end) (be32_to_cpu((end)->w0) & END_W0_BACKLOG)
+#define xive_end_is_escalate(end) (be32_to_cpu((end)->w0) & END_W0_ESCALATE_CTL)
+#define xive_end_is_uncond_escalation(end) \
+ (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)
+{
+ return ((uint64_t) be32_to_cpu(end->w2) & 0x0fffffff) << 32 |
+ be32_to_cpu(end->w3);
+}
+
+void xive_end_pic_print_info(XiveEND *end, uint32_t end_idx, Monitor *mon);
+void xive_end_queue_pic_print_info(XiveEND *end, uint32_t width, Monitor *mon);
+void xive_end_eas_pic_print_info(XiveEND *end, uint32_t end_idx, Monitor *mon);
+
+/* Notification Virtual Target (NVT) */
+typedef struct XiveNVT {
+ uint32_t w0;
+#define NVT_W0_VALID PPC_BIT32(0)
+ uint32_t w1;
+#define NVT_W1_EQ_BLOCK PPC_BITMASK32(0, 3)
+#define NVT_W1_EQ_INDEX PPC_BITMASK32(4, 31)
+ uint32_t w2;
+ uint32_t w3;
+ uint32_t w4;
+#define NVT_W4_IPB PPC_BITMASK32(16, 23)
+ uint32_t w5;
+ uint32_t w6;
+ uint32_t w7;
+ uint32_t w8;
+#define NVT_W8_GRP_VALID PPC_BIT32(0)
+ uint32_t w9;
+ uint32_t wa;
+ uint32_t wb;
+ uint32_t wc;
+ uint32_t wd;
+ uint32_t we;
+ uint32_t wf;
+} XiveNVT;
+
+#define xive_nvt_is_valid(nvt) (be32_to_cpu((nvt)->w0) & NVT_W0_VALID)
+
+/*
+ * The VP number space in a block is defined by the END_W6_NVT_INDEX
+ * field of the XIVE END
+ */
+#define XIVE_NVT_SHIFT 19
+#define XIVE_NVT_COUNT (1 << XIVE_NVT_SHIFT)
+
+static inline uint32_t xive_nvt_cam_line(uint8_t nvt_blk, uint32_t nvt_idx)
+{
+ return (nvt_blk << XIVE_NVT_SHIFT) | nvt_idx;
+}
+
+static inline uint32_t xive_nvt_idx(uint32_t cam_line)
+{
+ return cam_line & ((1 << XIVE_NVT_SHIFT) - 1);
+}
+
+static inline uint32_t xive_nvt_blk(uint32_t cam_line)
+{
+ return (cam_line >> XIVE_NVT_SHIFT) & 0xf;
+}
+
+#endif /* PPC_XIVE_REGS_H */
diff --git a/include/hw/ptimer.h b/include/hw/ptimer.h
new file mode 100644
index 000000000..c44321847
--- /dev/null
+++ b/include/hw/ptimer.h
@@ -0,0 +1,301 @@
+/*
+ * General purpose implementation of a simple periodic countdown timer.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ *
+ * This code is licensed under the GNU LGPL.
+ */
+#ifndef PTIMER_H
+#define PTIMER_H
+
+#include "qemu/timer.h"
+
+/*
+ * The ptimer API implements a simple periodic countdown timer.
+ * The countdown timer has a value (which can be read and written via
+ * ptimer_get_count() and ptimer_set_count()). When it is enabled
+ * using ptimer_run(), the value will count downwards at the frequency
+ * which has been configured using ptimer_set_period() or ptimer_set_freq().
+ * When it reaches zero it will trigger a callback function, and
+ * can be set to either reload itself from a specified limit value
+ * and keep counting down, or to stop (as a one-shot timer).
+ *
+ * A transaction-based API is used for modifying ptimer state: all calls
+ * to functions which modify ptimer state must be between matched calls to
+ * ptimer_transaction_begin() and ptimer_transaction_commit().
+ * When ptimer_transaction_commit() is called it will evaluate the state
+ * of the timer after all the changes in the transaction, and call the
+ * callback if necessary. (See the ptimer_init() documentation for the full
+ * list of state-modifying functions and detailed semantics of the callback.)
+ *
+ * Forgetting to set the period/frequency (or setting it to zero) is a
+ * bug in the QEMU device and will cause warning messages to be printed
+ * 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 rough edges of the default policy:
+ * - Starting to run with a period = 0 emits error message and stops the
+ * timer without a trigger.
+ *
+ * - Setting period to 0 of the running timer emits error message and
+ * stops the timer without a trigger.
+ *
+ * - Starting to run with counter = 0 or setting it to "0" while timer
+ * is running causes a trigger and reloads counter with a limit value.
+ * If limit = 0, ptimer emits error message and stops the timer.
+ *
+ * - Counter value of the running timer is one less than the actual value.
+ *
+ * - Changing period/frequency of the running timer loses time elapsed
+ * 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
+
+/* Periodic timer counter stays with "0" for a one period before wrapping
+ * around. */
+#define PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD (1 << 0)
+
+/* Running periodic timer that has counter = limit = 0 would continuously
+ * re-trigger every period. */
+#define PTIMER_POLICY_CONTINUOUS_TRIGGER (1 << 1)
+
+/* Starting to run with/setting counter to "0" won't trigger immediately,
+ * but after a one period for both oneshot and periodic modes. */
+#define PTIMER_POLICY_NO_IMMEDIATE_TRIGGER (1 << 2)
+
+/* Starting to run with/setting counter to "0" won't re-load counter
+ * immediately, but after a one period. */
+#define PTIMER_POLICY_NO_IMMEDIATE_RELOAD (1 << 3)
+
+/* Make counter value of the running timer represent the actual value and
+ * not the one less. */
+#define PTIMER_POLICY_NO_COUNTER_ROUND_DOWN (1 << 4)
+
+/*
+ * Starting to run with a zero counter, or setting the counter to "0" via
+ * ptimer_set_count() or ptimer_set_limit() will not trigger the timer
+ * (though it will cause a reload). Only a counter decrement to "0"
+ * will cause a trigger. Not compatible with NO_IMMEDIATE_TRIGGER;
+ * ptimer_init() will assert() that you don't set both.
+ */
+#define PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT (1 << 5)
+
+/* ptimer.c */
+typedef struct ptimer_state ptimer_state;
+typedef void (*ptimer_cb)(void *opaque);
+
+/**
+ * ptimer_init - Allocate and return a new ptimer
+ * @callback: function to call on ptimer expiry
+ * @callback_opaque: opaque pointer passed to @callback
+ * @policy: PTIMER_POLICY_* bits specifying behaviour
+ *
+ * The ptimer returned must be freed using ptimer_free().
+ *
+ * If a ptimer is created using this API then will use the
+ * transaction-based API for modifying ptimer state: all calls
+ * to functions which modify ptimer state:
+ * - ptimer_set_period()
+ * - ptimer_set_freq()
+ * - ptimer_set_limit()
+ * - ptimer_set_count()
+ * - ptimer_run()
+ * - ptimer_stop()
+ * must be between matched calls to ptimer_transaction_begin()
+ * and ptimer_transaction_commit(). When ptimer_transaction_commit()
+ * is called it will evaluate the state of the timer after all the
+ * changes in the transaction, and call the callback if necessary.
+ *
+ * The callback function is always called from within a transaction
+ * begin/commit block, so the callback should not call the
+ * ptimer_transaction_begin() function itself. If the callback changes
+ * the ptimer state such that another ptimer expiry is triggered, then
+ * the callback will be called a second time after the first call returns.
+ */
+ptimer_state *ptimer_init(ptimer_cb callback,
+ void *callback_opaque,
+ uint8_t policy_mask);
+
+/**
+ * ptimer_free - Free a ptimer
+ * @s: timer to free
+ *
+ * Free a ptimer created using ptimer_init().
+ */
+void ptimer_free(ptimer_state *s);
+
+/**
+ * ptimer_transaction_begin() - Start a ptimer modification transaction
+ *
+ * This function must be called before making any calls to functions
+ * which modify the ptimer's state (see the ptimer_init() documentation
+ * for a list of these), and must always have a matched call to
+ * ptimer_transaction_commit().
+ * It is an error to call this function for a BH-based ptimer;
+ * attempting to do this will trigger an assert.
+ */
+void ptimer_transaction_begin(ptimer_state *s);
+
+/**
+ * ptimer_transaction_commit() - Commit a ptimer modification transaction
+ *
+ * This function must be called after calls to functions which modify
+ * the ptimer's state, and completes the update of the ptimer. If the
+ * ptimer state now means that we should trigger the timer expiry
+ * callback, it will be called directly.
+ */
+void ptimer_transaction_commit(ptimer_state *s);
+
+/**
+ * ptimer_set_period - Set counter increment interval in nanoseconds
+ * @s: ptimer to configure
+ * @period: period of the counter in nanoseconds
+ *
+ * Note that if your counter behaviour is specified as having a
+ * particular frequency rather than a period then ptimer_set_freq()
+ * may be more appropriate.
+ *
+ * This function will assert if it is called outside a
+ * ptimer_transaction_begin/commit block.
+ */
+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
+ *
+ * This does the same thing as ptimer_set_period(), so you only
+ * need to call one of them. If the counter behaviour is specified
+ * as setting the frequency then this function is more appropriate,
+ * because it allows specifying an effective period which is
+ * precise to fractions of a nanosecond, avoiding rounding errors.
+ *
+ * This function will assert if it is called outside a
+ * ptimer_transaction_begin/commit block.
+ */
+void ptimer_set_freq(ptimer_state *s, uint32_t freq);
+
+/**
+ * ptimer_get_limit - Get the configured limit of the ptimer
+ * @s: ptimer to query
+ *
+ * This function returns the current limit (reload) value
+ * of the down-counter; that is, the value which it will be
+ * reset to when it hits zero.
+ *
+ * Generally timer devices using ptimers should be able to keep
+ * their reload register state inside the ptimer using the get
+ * and set limit functions rather than needing to also track it
+ * in their own state structure.
+ */
+uint64_t ptimer_get_limit(ptimer_state *s);
+
+/**
+ * ptimer_set_limit - Set the limit of the ptimer
+ * @s: ptimer
+ * @limit: initial countdown value
+ * @reload: if nonzero, then reset the counter to the new limit
+ *
+ * Set the limit value of the down-counter. The @reload flag can
+ * be used to emulate the behaviour of timers which immediately
+ * reload the counter when their reload register is written to.
+ *
+ * This function will assert if it is called outside a
+ * ptimer_transaction_begin/commit block.
+ */
+void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload);
+
+/**
+ * ptimer_get_count - Get the current value of the ptimer
+ * @s: ptimer
+ *
+ * Return the current value of the down-counter. This will
+ * return the correct value whether the counter is enabled or
+ * disabled.
+ */
+uint64_t ptimer_get_count(ptimer_state *s);
+
+/**
+ * ptimer_set_count - Set the current value of the ptimer
+ * @s: ptimer
+ * @count: count value to set
+ *
+ * Set the value of the down-counter. If the counter is currently
+ * enabled this will arrange for a timer callback at the appropriate
+ * point in the future.
+ *
+ * This function will assert if it is called outside a
+ * ptimer_transaction_begin/commit block.
+ */
+void ptimer_set_count(ptimer_state *s, uint64_t count);
+
+/**
+ * ptimer_run - Start a ptimer counting
+ * @s: ptimer
+ * @oneshot: non-zero if this timer should only count down once
+ *
+ * Start a ptimer counting down; when it reaches zero the callback function
+ * passed to ptimer_init() will be invoked.
+ * If the @oneshot argument is zero,
+ * the counter value will then be reloaded from the limit and it will
+ * start counting down again. If @oneshot is non-zero, then the counter
+ * will disable itself when it reaches zero.
+ *
+ * This function will assert if it is called outside a
+ * ptimer_transaction_begin/commit block.
+ */
+void ptimer_run(ptimer_state *s, int oneshot);
+
+/**
+ * ptimer_stop - Stop a ptimer counting
+ * @s: ptimer
+ *
+ * Pause a timer (the count stays at its current value until ptimer_run()
+ * is called to start it counting again).
+ *
+ * Note that this can cause it to "lose" time, even if it is immediately
+ * restarted.
+ *
+ * This function will assert if it is called outside a
+ * ptimer_transaction_begin/commit block.
+ */
+void ptimer_stop(ptimer_state *s);
+
+extern const VMStateDescription vmstate_ptimer;
+
+#define VMSTATE_PTIMER(_field, _state) \
+ VMSTATE_STRUCT_POINTER_V(_field, _state, 1, vmstate_ptimer, ptimer_state)
+
+#define VMSTATE_PTIMER_ARRAY(_f, _s, _n) \
+ VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(_f, _s, _n, 0, \
+ vmstate_ptimer, ptimer_state)
+
+#endif
diff --git a/include/hw/qdev-clock.h b/include/hw/qdev-clock.h
new file mode 100644
index 000000000..ffa0f7ba0
--- /dev/null
+++ b/include/hw/qdev-clock.h
@@ -0,0 +1,164 @@
+/*
+ * Device's clock input and output
+ *
+ * Copyright GreenSocs 2016-2020
+ *
+ * Authors:
+ * Frederic Konrad
+ * Damien Hedde
+ *
+ * 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 QDEV_CLOCK_H
+#define QDEV_CLOCK_H
+
+#include "hw/clock.h"
+
+/**
+ * qdev_init_clock_in:
+ * @dev: the device to add an input clock to
+ * @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.
+ * This adds a child<> property.
+ * The callback will be called with @opaque as opaque parameter.
+ */
+Clock *qdev_init_clock_in(DeviceState *dev, const char *name,
+ ClockCallback *callback, void *opaque,
+ unsigned int events);
+
+/**
+ * qdev_init_clock_out:
+ * @dev: the device to add an output clock to
+ * @name: the name of the clock (can't be NULL).
+ * @returns: a pointer to the newly added clock
+ *
+ * Add an output clock to device @dev as a clock named @name.
+ * This adds a child<> property.
+ */
+Clock *qdev_init_clock_out(DeviceState *dev, const char *name);
+
+/**
+ * qdev_get_clock_in:
+ * @dev: the device which has the clock
+ * @name: the name of the clock (can't be NULL).
+ * @returns: a pointer to the clock
+ *
+ * Get the input clock @name from @dev or NULL if does not exist.
+ */
+Clock *qdev_get_clock_in(DeviceState *dev, const char *name);
+
+/**
+ * qdev_get_clock_out:
+ * @dev: the device which has the clock
+ * @name: the name of the clock (can't be NULL).
+ * @returns: a pointer to the clock
+ *
+ * Get the output clock @name from @dev or NULL if does not exist.
+ */
+Clock *qdev_get_clock_out(DeviceState *dev, const char *name);
+
+/**
+ * qdev_connect_clock_in:
+ * @dev: a device
+ * @name: the name of an input clock in @dev
+ * @source: the source clock (an output clock of another device for example)
+ *
+ * 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.
+ */
+void qdev_connect_clock_in(DeviceState *dev, const char *name, Clock *source);
+
+/**
+ * qdev_alias_clock:
+ * @dev: the device which has the clock
+ * @name: the name of the clock in @dev (can't be NULL)
+ * @alias_dev: the device to add the clock
+ * @alias_name: the name of the clock in @container
+ * @returns: a pointer to the clock
+ *
+ * Add a clock @alias_name in @alias_dev which is an alias of the clock @name
+ * in @dev. The direction _in_ or _out_ will the same as the original.
+ * An alias clock must not be modified or used by @alias_dev and should
+ * typically be only only for device composition purpose.
+ */
+Clock *qdev_alias_clock(DeviceState *dev, const char *name,
+ DeviceState *alias_dev, const char *alias_name);
+
+/**
+ * qdev_finalize_clocklist:
+ * @dev: the device being finalized
+ *
+ * Clear the clocklist from @dev. Only used internally in qdev.
+ */
+void qdev_finalize_clocklist(DeviceState *dev);
+
+/**
+ * ClockPortInitElem:
+ * @name: name of the clock (can't be NULL)
+ * @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)
+ */
+struct ClockPortInitElem {
+ const char *name;
+ bool is_output;
+ ClockCallback *callback;
+ unsigned int callback_events;
+ size_t offset;
+};
+
+#define clock_offset_value(devstate, field) \
+ (offsetof(devstate, field) + \
+ type_check(Clock *, typeof_field(devstate, field)))
+
+#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), \
+}
+
+/**
+ * QDEV_CLOCK_(IN|OUT):
+ * @devstate: structure type. @dev argument of qdev_init_clocks below must be
+ * a pointer to that same type.
+ * @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, cbevents) \
+ QDEV_CLOCK(false, devstate, field, callback, cbevents)
+
+#define QDEV_CLOCK_OUT(devstate, field) \
+ QDEV_CLOCK(true, devstate, field, NULL, 0)
+
+#define QDEV_CLOCK_END { .name = NULL }
+
+typedef struct ClockPortInitElem ClockPortInitArray[];
+
+/**
+ * qdev_init_clocks:
+ * @dev: the device to add clocks to
+ * @clocks: a QDEV_CLOCK_END-terminated array which contains the
+ * clocks information.
+ */
+void qdev_init_clocks(DeviceState *dev, const ClockPortInitArray clocks);
+
+#endif /* QDEV_CLOCK_H */
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
new file mode 100644
index 000000000..20d306659
--- /dev/null
+++ b/include/hw/qdev-core.h
@@ -0,0 +1,881 @@
+#ifndef QDEV_CORE_H
+#define QDEV_CORE_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"
+
+enum {
+ DEV_NVECTORS_UNSPECIFIED = -1,
+};
+
+#define TYPE_DEVICE "device"
+OBJECT_DECLARE_TYPE(DeviceState, DeviceClass, DEVICE)
+
+typedef enum DeviceCategory {
+ DEVICE_CATEGORY_BRIDGE,
+ DEVICE_CATEGORY_USB,
+ DEVICE_CATEGORY_STORAGE,
+ DEVICE_CATEGORY_NETWORK,
+ DEVICE_CATEGORY_INPUT,
+ DEVICE_CATEGORY_DISPLAY,
+ DEVICE_CATEGORY_SOUND,
+ DEVICE_CATEGORY_MISC,
+ DEVICE_CATEGORY_CPU,
+ DEVICE_CATEGORY_WATCHDOG,
+ DEVICE_CATEGORY_MAX
+} DeviceCategory;
+
+typedef void (*DeviceRealize)(DeviceState *dev, Error **errp);
+typedef void (*DeviceUnrealize)(DeviceState *dev);
+typedef void (*DeviceReset)(DeviceState *dev);
+typedef void (*BusRealize)(BusState *bus, Error **errp);
+typedef void (*BusUnrealize)(BusState *bus);
+
+/**
+ * DeviceClass:
+ * @props: Properties accessing state fields.
+ * @realize: Callback function invoked when the #DeviceState:realized
+ * property is changed to %true.
+ * @unrealize: Callback function invoked when the #DeviceState:realized
+ * property is changed to %false.
+ * @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 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.
+ *
+ */
+struct DeviceClass {
+ /*< private >*/
+ ObjectClass parent_class;
+ /*< public >*/
+
+ DECLARE_BITMAP(categories, DEVICE_CATEGORY_MAX);
+ const char *fw_name;
+ 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.
+ */
+ Property *props_;
+
+ /*
+ * Can this device be instantiated 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.
+ * Others instantiate, but don't work. Exposing users to such
+ * 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.
+ * TODO: remove once every reset callback is unused
+ */
+ DeviceReset reset;
+ DeviceRealize realize;
+ DeviceUnrealize unrealize;
+
+ /* device state */
+ const VMStateDescription *vmsd;
+
+ /* Private to qdev / bus. */
+ const char *bus_type;
+};
+
+typedef struct NamedGPIOList NamedGPIOList;
+
+struct NamedGPIOList {
+ char *name;
+ qemu_irq *in;
+ int num_in;
+ int num_out;
+ QLIST_ENTRY(NamedGPIOList) node;
+};
+
+typedef struct Clock Clock;
+typedef struct NamedClockList NamedClockList;
+
+struct NamedClockList {
+ char *name;
+ Clock *clock;
+ bool output;
+ bool alias;
+ QLIST_ENTRY(NamedClockList) node;
+};
+
+/**
+ * DeviceState:
+ * @realized: Indicates whether the device has been fully constructed.
+ * When accessed outside big qemu lock, must be accessed with
+ * qatomic_load_acquire()
+ * @reset: ResettableState for the device; handled by Resettable interface.
+ *
+ * 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 >*/
+ Object parent_obj;
+ /*< public >*/
+
+ char *id;
+ char *canonical_path;
+ bool realized;
+ bool pending_deleted_event;
+ int64_t pending_deleted_expires_ms;
+ QDict *opts;
+ int hotplugged;
+ bool allow_unplug_during_migration;
+ BusState *parent_bus;
+ QLIST_HEAD(, NamedGPIOList) gpios;
+ QLIST_HEAD(, NamedClockList) clocks;
+ QLIST_HEAD(, BusState) child_bus;
+ int num_child_bus;
+ int instance_id_alias;
+ int alias_required_for_version;
+ ResettableState reset;
+};
+
+struct DeviceListener {
+ void (*realize)(DeviceListener *listener, DeviceState *dev);
+ void (*unrealize)(DeviceListener *listener, DeviceState *dev);
+ /*
+ * 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.
+ */
+ bool (*hide_device)(DeviceListener *listener, const QDict *device_opts,
+ bool from_json, Error **errp);
+ QTAILQ_ENTRY(DeviceListener) link;
+};
+
+#define TYPE_BUS "bus"
+DECLARE_OBJ_CHECKERS(BusState, BusClass,
+ BUS, TYPE_BUS)
+
+struct BusClass {
+ ObjectClass parent_class;
+
+ /* 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;
+
+ /* maximum devices allowed on the bus, 0: no limit. */
+ int max_dev;
+ /* number of automatically allocated bus ids (e.g. ide.0) */
+ int automatic_ids;
+};
+
+typedef struct BusChild {
+ struct rcu_head rcu;
+ DeviceState *child;
+ int index;
+ QTAILQ_ENTRY(BusChild) sibling;
+} BusChild;
+
+#define QDEV_HOTPLUG_HANDLER_PROPERTY "hotplug-handler"
+
+/**
+ * BusState:
+ * @hotplug_handler: link to a hotplug handler associated with bus.
+ * @reset: ResettableState for the bus; handled by Resettable interface.
+ */
+struct BusState {
+ Object obj;
+ DeviceState *parent;
+ char *name;
+ HotplugHandler *hotplug_handler;
+ int max_index;
+ bool realized;
+ bool full;
+ int num_children;
+
+ /*
+ * children is a RCU QTAILQ, thus readers must use RCU to access it,
+ * and writers must hold the big qemu lock
+ */
+
+ QTAILQ_HEAD(, BusChild) children;
+ QLIST_ENTRY(BusState) sibling;
+ ResettableState reset;
+};
+
+/**
+ * GlobalProperty:
+ * @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.
+ *
+ * An error is fatal for non-hotplugged devices, when the global is applied.
+ */
+typedef struct GlobalProperty {
+ const char *driver;
+ const char *property;
+ const char *value;
+ bool used;
+ bool optional;
+} GlobalProperty;
+
+static inline void
+compat_props_add(GPtrArray *arr,
+ GlobalProperty props[], size_t nelem)
+{
+ int i;
+ for (i = 0; i < nelem; i++) {
+ g_ptr_array_add(arr, (void *)&props[i]);
+ }
+}
+
+/*** Board API. This should go away once we have a machine config file. ***/
+
+/**
+ * qdev_new: Create a device on the heap
+ * @name: device type to create (we assert() that this type exists)
+ *
+ * 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.
+ */
+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.
+ */
+DeviceState *qdev_try_new(const char *name);
+/**
+ * qdev_realize: Realize @dev.
+ * @dev: device to realize
+ * @bus: bus to plug it into (may be NULL)
+ * @errp: pointer to error object
+ *
+ * "Realize" the device, i.e. perform the second phase of device
+ * initialization.
+ * @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.
+ */
+bool qdev_realize(DeviceState *dev, BusState *bus, Error **errp);
+/**
+ * qdev_realize_and_unref: Realize @dev and drop a reference
+ * @dev: device to realize
+ * @bus: bus to plug it into (may be NULL)
+ * @errp: pointer to error object
+ *
+ * Realize @dev and drop a reference.
+ * This is like qdev_realize(), except the caller must hold a
+ * (private) reference, which is dropped on return regardless of
+ * success or failure. Intended use::
+ *
+ * dev = qdev_new();
+ * [...]
+ * qdev_realize_and_unref(dev, bus, errp);
+ *
+ * Now @dev can go away without further ado.
+ *
+ * If you are embedding the device into some other 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
+ * via the child<> property, and so the reference-count-drop done here
+ * would be incorrect. For that use case you want qdev_realize().
+ */
+bool qdev_realize_and_unref(DeviceState *dev, BusState *bus, Error **errp);
+/**
+ * qdev_unrealize: Unrealize a device
+ * @dev: device to unrealize
+ *
+ * This function will "unrealize" a device, which is the first phase
+ * of correctly destroying a device that has been realized. It will:
+ *
+ * - unrealize any child buses by calling qbus_unrealize()
+ * (this will recursively unrealize any devices on those buses)
+ * - call the the unrealize method of @dev
+ *
+ * The device can then be freed by causing its reference count to go
+ * to zero.
+ *
+ * Warning: most devices in QEMU do not expect to be unrealized. Only
+ * devices which are hot-unpluggable should be unrealized (as part of
+ * the unplugging process); all other devices are expected to last for
+ * the life of the simulation and should not be unrealized and freed.
+ */
+void qdev_unrealize(DeviceState *dev);
+void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
+ int required_for_version);
+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.
+ *
+ * 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.
+ */
+HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev);
+void qdev_unplug(DeviceState *dev, Error **errp);
+void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp);
+void qdev_machine_creation_done(void);
+bool qdev_machine_modified(void);
+
+/**
+ * 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)
+ *
+ * Returns the qemu_irq corresponding to an anonymous input GPIO line
+ * (which the device has set up with qdev_init_gpio_in()). The index
+ * @n of the GPIO line must be valid (i.e. be at least 0 and less than
+ * the total number of anonymous input GPIOs the device has); this
+ * function will assert() if passed an invalid index.
+ *
+ * This function is intended to be used by board code or SoC "container"
+ * device models to wire up the GPIO lines; usually the return value
+ * will be passed to qdev_connect_gpio_out() or a similar function to
+ * connect another device's output GPIO line to this input.
+ *
+ * For named input GPIO lines, use qdev_get_gpio_in_named().
+ */
+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
+ * @name: Name of the input GPIO array
+ * @n: Number of the GPIO line in that array (which must be in range)
+ *
+ * Returns the qemu_irq corresponding to a named input GPIO line
+ * (which the device has set up with qdev_init_gpio_in_named()).
+ * The @name string must correspond to an input GPIO array which exists on
+ * the device, and the index @n of the GPIO line must be valid (i.e.
+ * be at least 0 and less than the total number of input GPIOs in that
+ * array); this function will assert() if passed an invalid name or index.
+ *
+ * For anonymous input GPIO lines, use qdev_get_gpio_in().
+ */
+qemu_irq qdev_get_gpio_in_named(DeviceState *dev, const char *name, int n);
+
+/**
+ * qdev_connect_gpio_out: Connect one of a device's anonymous output GPIO lines
+ * @dev: Device whose GPIO to connect
+ * @n: Number of the anonymous output GPIO line (which must be in range)
+ * @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
+ * output GPIO line, the qemu_irq's callback is invoked.
+ * The index @n of the GPIO line must be valid (i.e. be at least 0 and
+ * less than the total number of anonymous output GPIOs the device has
+ * created with qdev_init_gpio_out()); otherwise this function will assert().
+ *
+ * Outbound GPIO lines can be connected to any qemu_irq, but the common
+ * case is connecting them to another device's inbound GPIO line, using
+ * the qemu_irq returned by qdev_get_gpio_in() or qdev_get_gpio_in_named().
+ *
+ * It is not valid to try to connect one outbound GPIO to multiple
+ * 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
+ * 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
+ * gate with multiple inputs and one output.
+ *
+ * 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
+ * @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
+ *
+ * This function connects an anonymous output GPIO line on a device
+ * up to an arbitrary qemu_irq, so that when the device asserts that
+ * output GPIO line, the qemu_irq's callback is invoked.
+ * The @name string must correspond to an output GPIO array which exists on
+ * the device, and the index @n of the GPIO line must be valid (i.e.
+ * be at least 0 and less than the total number of input GPIOs in that
+ * array); this function will assert() if passed an invalid name or index.
+ *
+ * Outbound GPIO lines can be connected to any qemu_irq, but the common
+ * case is connecting them to another device's inbound GPIO line, using
+ * the qemu_irq returned by qdev_get_gpio_in() or qdev_get_gpio_in_named().
+ *
+ * It is not valid to try to connect one outbound GPIO to multiple
+ * 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().
+ */
+void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n,
+ qemu_irq pin);
+/**
+ * qdev_get_gpio_out_connector: Get the qemu_irq connected to an output GPIO
+ * @dev: Device whose output GPIO we are interested in
+ * @name: Name of the output GPIO array
+ * @n: Number of the output GPIO line within that array
+ *
+ * Returns whatever qemu_irq is currently connected to the specified
+ * output GPIO line of @dev. This will be NULL if the output GPIO line
+ * has never been wired up to the anything. Note that the qemu_irq
+ * returned does not belong to @dev -- it will be the input GPIO or
+ * IRQ of whichever device the board code has connected up to @dev's
+ * output GPIO.
+ *
+ * You probably don't need to use this function -- it is used only
+ * by the platform-bus subsystem.
+ */
+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
+ * @icpt: New qemu_irq to connect instead
+ * @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.
+ *
+ * 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.
+ */
+qemu_irq qdev_intercept_gpio_out(DeviceState *dev, qemu_irq icpt,
+ const char *name, int n);
+
+BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
+
+/*** Device API. ***/
+
+/**
+ * qdev_init_gpio_in: create an array of anonymous input GPIO lines
+ * @dev: Device to create input GPIOs for
+ * @handler: Function to call when GPIO line value is set
+ * @n: Number of GPIO lines to create
+ *
+ * Devices should use functions in the qdev_init_gpio_in* family in
+ * their instance_init or realize methods to create any input GPIO
+ * lines they need. There is no functional difference between
+ * anonymous and named GPIO lines. Stylistically, named GPIOs are
+ * preferable (easier to understand at callsites) unless a device
+ * has exactly one uniform kind of GPIO input whose purpose is obvious.
+ * Note that input GPIO lines can serve as 'sinks' for IRQ lines.
+ *
+ * See qdev_get_gpio_in() for how code that uses such a device can get
+ * 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
+ * @pins: Pointer to qemu_irq or qemu_irq array for the GPIO lines
+ * @n: Number of GPIO lines to create
+ *
+ * Devices should use functions in the qdev_init_gpio_out* family
+ * in their instance_init or realize methods to create any output
+ * GPIO lines they need. There is no functional difference between
+ * anonymous and named GPIO lines. Stylistically, named GPIOs are
+ * preferable (easier to understand at callsites) unless a device
+ * has exactly one uniform kind of GPIO output whose purpose is obvious.
+ *
+ * The @pins argument should be a pointer to either a "qemu_irq"
+ * (if @n == 1) or a "qemu_irq []" array (if @n > 1) in the device's
+ * state structure. The device implementation can then raise and
+ * lower the GPIO line by calling qemu_set_irq(). (If anything is
+ * connected to the other end of the GPIO this will cause the handler
+ * function for that input GPIO to be called.)
+ *
+ * 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
+ * @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
+ * @n: Number of GPIO lines to create
+ *
+ * Like qdev_init_gpio_out(), but creates an array of GPIO output lines
+ * with a name. Code using the device can then connect these GPIO lines
+ * using qdev_connect_gpio_out_named().
+ */
+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
+ *
+ * @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
+ * @name: Name of the GPIO input (must be unique for this device)
+ * @n: Number of GPIO lines in this input set
+ */
+void qdev_init_gpio_in_named_with_opaque(DeviceState *dev,
+ qemu_irq_handler handler,
+ void *opaque,
+ const char *name, int n);
+
+/**
+ * qdev_init_gpio_in_named: create an array of input GPIO lines
+ * for the specified device
+ *
+ * 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).
+ */
+static inline void qdev_init_gpio_in_named(DeviceState *dev,
+ qemu_irq_handler handler,
+ const char *name, int n)
+{
+ qdev_init_gpio_in_named_with_opaque(dev, handler, dev, name, n);
+}
+
+/**
+ * qdev_pass_gpios: create GPIO lines on container which pass through to device
+ * @dev: Device which has GPIO lines
+ * @container: Container device which needs to expose them
+ * @name: Name of GPIO array to pass through (NULL for the anonymous GPIO array)
+ *
+ * In QEMU, complicated devices like SoCs are often modelled with a
+ * "container" QOM device which itself contains other QOM devices and
+ * which wires them up appropriately. This function allows the container
+ * to create GPIO arrays on itself which simply pass through to a GPIO
+ * array of one of its internal devices.
+ *
+ * If @dev has both input and output GPIOs named @name then both will
+ * be passed through. It is not possible to pass a subset of the array
+ * with this function.
+ *
+ * To users of the container device, the GPIO array created on @container
+ * behaves exactly like any other.
+ */
+void qdev_pass_gpios(DeviceState *dev, DeviceState *container,
+ const char *name);
+
+BusState *qdev_get_parent_bus(DeviceState *dev);
+
+/*** BUS API. ***/
+
+DeviceState *qdev_find_recursive(BusState *bus, const char *id);
+
+/* Returns 0 to walk children, > 0 to skip walk, < 0 to terminate walk. */
+typedef int (qbus_walkerfn)(BusState *bus, void *opaque);
+typedef int (qdev_walkerfn)(DeviceState *dev, void *opaque);
+
+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);
+
+/* Returns > 0 if either devfn or busfn skip walk somewhere in cursion,
+ * < 0 if either devfn or busfn terminate walk somewhere in cursion,
+ * 0 otherwise. */
+int qbus_walk_children(BusState *bus,
+ qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn,
+ qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
+ void *opaque);
+int qdev_walk_children(DeviceState *dev,
+ qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn,
+ qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
+ 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.
+ *
+ * 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:
+ *
+ * Reset bus @bus and perform a recursive processing using the resettable
+ * interface. It triggers a RESET_TYPE_COLD.
+ */
+void bus_cold_reset(BusState *bus);
+
+/**
+ * device_is_in_reset:
+ * 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.
+ */
+bool bus_is_in_reset(BusState *bus);
+
+/* This should go away once we get rid of the NULL bus hack */
+BusState *sysbus_get_default(void);
+
+char *qdev_get_fw_dev_path(DeviceState *dev);
+char *qdev_get_own_fw_dev_path_from_handler(BusState *bus, DeviceState *dev);
+
+/**
+ * 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:
+ * 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);
+void device_class_set_parent_realize(DeviceClass *dc,
+ DeviceRealize dev_realize,
+ DeviceRealize *parent_realize);
+void device_class_set_parent_unrealize(DeviceClass *dc,
+ DeviceUnrealize dev_unrealize,
+ DeviceUnrealize *parent_unrealize);
+
+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);
+
+/* FIXME: make this a link<> */
+bool qdev_set_parent_bus(DeviceState *dev, BusState *bus, Error **errp);
+
+extern bool qdev_hot_removed;
+
+char *qdev_get_dev_path(DeviceState *dev);
+
+void qbus_set_hotplug_handler(BusState *bus, Object *handler);
+void qbus_set_bus_hotplug_handler(BusState *bus);
+
+static inline bool qbus_is_hotpluggable(BusState *bus)
+{
+ return bus->hotplug_handler;
+}
+
+/**
+ * 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: options QDict
+ * @from_json: true if @opts entries are typed, false for all strings
+ * @errp: pointer to error object
+ *
+ * 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.
+ */
+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,
+
+ /*
+ * 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;
+
+extern bool phase_check(MachineInitPhase phase);
+extern void phase_advance(MachineInitPhase phase);
+
+#endif
diff --git a/include/hw/qdev-dma.h b/include/hw/qdev-dma.h
new file mode 100644
index 000000000..b00391aa0
--- /dev/null
+++ b/include/hw/qdev-dma.h
@@ -0,0 +1,16 @@
+/*
+ * Support for dma_addr_t typed properties
+ *
+ * Copyright (C) 2012 David Gibson, IBM Corporation.
+ *
+ * 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_QDEV_DMA_H
+#define HW_QDEV_DMA_H
+
+#define DEFINE_PROP_DMAADDR(_n, _s, _f, _d) \
+ DEFINE_PROP_UINT64(_n, _s, _f, _d)
+
+#endif
diff --git a/include/hw/qdev-properties-system.h b/include/hw/qdev-properties-system.h
new file mode 100644
index 000000000..0ac327ae6
--- /dev/null
+++ b/include/hw/qdev-properties-system.h
@@ -0,0 +1,77 @@
+#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_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;
+
+#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_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)
+
+
+#endif
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
new file mode 100644
index 000000000..f7925f67d
--- /dev/null
+++ b/include/hw/qdev-properties.h
@@ -0,0 +1,257 @@
+#ifndef QEMU_QDEV_PROPERTIES_H
+#define QEMU_QDEV_PROPERTIES_H
+
+#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;
+ 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_int64;
+extern const PropertyInfo qdev_prop_size;
+extern const PropertyInfo qdev_prop_string;
+extern const PropertyInfo qdev_prop_on_off_auto;
+extern const PropertyInfo qdev_prop_size32;
+extern const PropertyInfo qdev_prop_arraylen;
+extern const PropertyInfo qdev_prop_link;
+
+#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) \
+ DEFINE_PROP(_name, _state, _field, _prop, _type, \
+ .set_default = true, \
+ .defval.i = (_type)_defval)
+
+#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) \
+ 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) \
+ DEFINE_PROP(_name, _state, _field, _prop, _type, \
+ .set_default = true, \
+ .defval.u = (_type)_defval)
+
+#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) \
+ 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) \
+ DEFINE_PROP(_name, _state, _field, qdev_prop_bool, bool, \
+ .set_default = true, \
+ .defval.u = (bool)_defval)
+
+#define PROP_ARRAY_LEN_PREFIX "len-"
+
+/**
+ * DEFINE_PROP_ARRAY:
+ * @_name: name of the array
+ * @_state: name of the device state structure type
+ * @_field: uint32_t field in @_state to hold the array length
+ * @_arrayfield: field in @_state (of type '@_arraytype *') which
+ * will point to the array
+ * @_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.
+ *
+ * When the array length 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.
+ * It is the responsibility of the device deinit code to free the
+ * @_arrayfield memory.
+ */
+#define DEFINE_PROP_ARRAY(_name, _state, _field, \
+ _arrayfield, _arrayprop, _arraytype) \
+ DEFINE_PROP((PROP_ARRAY_LEN_PREFIX _name), \
+ _state, _field, qdev_prop_arraylen, 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) \
+ 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)
+#define DEFINE_PROP_UINT16(_n, _s, _f, _d) \
+ DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, qdev_prop_uint16, uint16_t)
+#define DEFINE_PROP_UINT32(_n, _s, _f, _d) \
+ DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, qdev_prop_uint32, uint32_t)
+#define DEFINE_PROP_INT32(_n, _s, _f, _d) \
+ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_int32, int32_t)
+#define DEFINE_PROP_UINT64(_n, _s, _f, _d) \
+ DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, qdev_prop_uint64, uint64_t)
+#define DEFINE_PROP_INT64(_n, _s, _f, _d) \
+ 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_STRING(_n, _s, _f) \
+ DEFINE_PROP(_n, _s, _f, qdev_prop_string, char*)
+#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_SIZE32(_n, _s, _f, _d) \
+ DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, qdev_prop_size32, uint32_t)
+
+#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);
+
+/*
+ * Set properties between creation and realization.
+ * @value must be valid. Each property may be set at most once.
+ */
+void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value);
+void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value);
+void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value);
+void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value);
+void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value);
+void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value);
+void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value);
+void qdev_prop_set_chr(DeviceState *dev, const char *name, Chardev *value);
+void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value);
+void qdev_prop_set_drive(DeviceState *dev, const char *name,
+ BlockBackend *value);
+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 *object_field_prop_ptr(Object *obj, Property *prop);
+
+void qdev_prop_register_global(GlobalProperty *prop);
+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, Object *obj,
+ const char *name, const char *value);
+
+/**
+ * qdev_property_add_static:
+ * @dev: Device to add the property to.
+ * @prop: The qdev property definition.
+ *
+ * Add a static QOM property to @dev for qdev property @prop.
+ * On error, store error in @errp. Static properties access data in a struct.
+ * The type of the QOM property is derived from prop->info.
+ */
+void qdev_property_add_static(DeviceState *dev, Property *prop);
+
+/**
+ * qdev_alias_all_properties: Create aliases on source for all target properties
+ * @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.
+ *
+ * This is useful when @target is an internal implementation object
+ * owned by @source, and you want to expose all the properties of that
+ * implementation object as properties on the @source object so that users
+ * of @source can set them.
+ */
+void qdev_alias_all_properties(DeviceState *target, Object *source);
+
+/**
+ * @qdev_prop_set_after_realize:
+ * @dev: device
+ * @name: name of property
+ * @errp: indirect pointer to Error to be set
+ * Set the Error object to report that an attempt was made to set a property
+ * on a device after it has already been realized. This is a utility function
+ * which allows property-setter functions to easily report the error in
+ * a friendly format identifying both the device and the property.
+ */
+void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
+ Error **errp);
+
+/**
+ * qdev_prop_allow_set_link_before_realize:
+ *
+ * Set the #Error object if an attempt is made to set the link after realize.
+ * This function should be used as the check() argument to
+ * object_property_add_link().
+ */
+void qdev_prop_allow_set_link_before_realize(const Object *obj,
+ const char *name,
+ Object *val, Error **errp);
+
+#endif
diff --git a/include/hw/rdma/rdma.h b/include/hw/rdma/rdma.h
new file mode 100644
index 000000000..80b2e531c
--- /dev/null
+++ b/include/hw/rdma/rdma.h
@@ -0,0 +1,37 @@
+/*
+ * 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"
+
+typedef struct RdmaProviderClass RdmaProviderClass;
+DECLARE_CLASS_CHECKERS(RdmaProviderClass, RDMA_PROVIDER,
+ INTERFACE_RDMA_PROVIDER)
+#define RDMA_PROVIDER(obj) \
+ INTERFACE_CHECK(RdmaProvider, (obj), \
+ INTERFACE_RDMA_PROVIDER)
+
+typedef struct RdmaProvider RdmaProvider;
+
+struct RdmaProviderClass {
+ InterfaceClass parent;
+
+ void (*format_statistics)(RdmaProvider *obj, GString *buf);
+};
+
+#endif
diff --git a/include/hw/register.h b/include/hw/register.h
new file mode 100644
index 000000000..6a076cfcd
--- /dev/null
+++ b/include/hw/register.h
@@ -0,0 +1,229 @@
+/*
+ * Register Definition API
+ *
+ * Copyright (c) 2016 Xilinx Inc.
+ * Copyright (c) 2013 Peter Crosthwaite <peter.crosthwaite@xilinx.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef REGISTER_H
+#define REGISTER_H
+
+#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;
+typedef struct RegisterInfoArray RegisterInfoArray;
+
+/**
+ * Access description for a register that is part of guest accessible device
+ * state.
+ *
+ * @name: String name of the register
+ * @ro: whether or not the bit is read-only
+ * @w1c: bits with the common write 1 to clear semantic.
+ * @reset: reset value.
+ * @cor: Bits that are clear on read
+ * @rsvd: Bits that are reserved and should not be changed
+ *
+ * @pre_write: Pre write callback. Passed the value that's to be written,
+ * immediately before the actual write. The returned value is what is written,
+ * giving the handler a chance to modify the written value.
+ * @post_write: Post write callback. Passed the written value. Most write side
+ * effects should be implemented here. This is called during device reset.
+ *
+ * @post_read: Post read callback. Passes the value that is about to be returned
+ * for a read. The return value from this function is what is ultimately read,
+ * allowing this function to modify the value before return to the client.
+ */
+
+struct RegisterAccessInfo {
+ const char *name;
+ uint64_t ro;
+ uint64_t w1c;
+ uint64_t reset;
+ uint64_t cor;
+ uint64_t rsvd;
+ uint64_t unimp;
+
+ uint64_t (*pre_write)(RegisterInfo *reg, uint64_t val);
+ void (*post_write)(RegisterInfo *reg, uint64_t val);
+
+ uint64_t (*post_read)(RegisterInfo *reg, uint64_t val);
+
+ hwaddr addr;
+};
+
+/**
+ * A register that is part of guest accessible state
+ * @data: pointer to the register data. Will be cast
+ * to the relevant uint type depending on data_size.
+ * @data_size: Size of the register in bytes. Must be
+ * 1, 2, 4 or 8
+ *
+ * @access: Access description of this register
+ *
+ * @debug: Whether or not verbose debug is enabled
+ * @prefix: String prefix for log and debug messages
+ *
+ * @opaque: Opaque data for the register
+ */
+
+struct RegisterInfo {
+ /* <private> */
+ DeviceState parent_obj;
+
+ /* <public> */
+ void *data;
+ int data_size;
+
+ const RegisterAccessInfo *access;
+
+ void *opaque;
+};
+
+#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
+ * modeled using the RegisterInfo structure.
+ *
+ * @r is an array containing of all the relevant RegisterInfo structures.
+ *
+ * @num_elements is the number of elements in the array r
+ *
+ * @mem: optional Memory region for the register
+ */
+
+struct RegisterInfoArray {
+ MemoryRegion mem;
+
+ int num_elements;
+ RegisterInfo **r;
+
+ bool debug;
+ const char *prefix;
+};
+
+/**
+ * write a value to a register, subject to its restrictions
+ * @reg: register to write to
+ * @val: value to write
+ * @we: write enable mask
+ * @prefix: The device prefix that should be printed before the register name
+ * @debug: Should the write operation debug information be printed?
+ */
+
+void register_write(RegisterInfo *reg, uint64_t val, uint64_t we,
+ const char *prefix, bool debug);
+
+/**
+ * read a value from a register, subject to its restrictions
+ * @reg: register to read from
+ * @re: read enable mask
+ * @prefix: The device prefix that should be printed before the register name
+ * @debug: Should the read operation debug information be printed?
+ * returns: value read
+ */
+
+uint64_t register_read(RegisterInfo *reg, uint64_t re, const char* prefix,
+ bool debug);
+
+/**
+ * Resets a register. This will also call the post_write hook if it exists.
+ * @reg: The register to reset.
+ */
+
+void register_reset(RegisterInfo *reg);
+
+/**
+ * Initialize a register.
+ * @reg: Register to initialize
+ */
+
+void register_init(RegisterInfo *reg);
+
+/**
+ * Memory API MMIO write handler that will write to a Register API register.
+ * @opaque: RegisterInfo to write to
+ * @addr: Address to write
+ * @value: Value to write
+ * @size: Number of bytes to write
+ */
+
+void register_write_memory(void *opaque, hwaddr addr, uint64_t value,
+ unsigned size);
+
+/**
+ * Memory API MMIO read handler that will read from a Register API register.
+ * @opaque: RegisterInfo to read from
+ * @addr: Address to read
+ * @size: Number of bytes to read
+ * returns: Value read from register
+ */
+
+uint64_t register_read_memory(void *opaque, hwaddr addr, unsigned size);
+
+/**
+ * Init a block of registers into a container MemoryRegion. A
+ * number of constant register definitions are parsed to create a corresponding
+ * array of RegisterInfo's.
+ *
+ * @owner: device owning the registers
+ * @rae: Register definitions to init
+ * @num: number of registers to init (length of @rae)
+ * @ri: Register array to init, must already be allocated
+ * @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.
+ */
+
+RegisterInfoArray *register_init_block8(DeviceState *owner,
+ const RegisterAccessInfo *rae,
+ int num, RegisterInfo *ri,
+ uint8_t *data,
+ const MemoryRegionOps *ops,
+ bool debug_enabled,
+ uint64_t memory_size);
+
+RegisterInfoArray *register_init_block32(DeviceState *owner,
+ const RegisterAccessInfo *rae,
+ int num, RegisterInfo *ri,
+ uint32_t *data,
+ const MemoryRegionOps *ops,
+ 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
+ * from the device's instance_finalize function.
+ *
+ * Any memory operations that the device performed that require cleanup (such
+ * as creating subregions) need to be called before calling this function.
+ *
+ * @r_array: A structure containing all of the registers, as returned by
+ * register_init_block32()
+ */
+
+void register_finalize_block(RegisterInfoArray *r_array);
+
+#endif
diff --git a/include/hw/registerfields.h b/include/hw/registerfields.h
new file mode 100644
index 000000000..f2a3c9c41
--- /dev/null
+++ b/include/hw/registerfields.h
@@ -0,0 +1,111 @@
+/*
+ * Register Definition API: field macros
+ *
+ * Copyright (c) 2016 Xilinx Inc.
+ * Copyright (c) 2013 Peter Crosthwaite <peter.crosthwaite@xilinx.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef REGISTERFIELDS_H
+#define REGISTERFIELDS_H
+
+#include "qemu/bitops.h"
+
+/* Define constants for a 32 bit register */
+
+/* This macro will define A_FOO, for the byte address of a register
+ * as well as R_FOO for the uint32_t[] register number (A_FOO / 4).
+ */
+#define REG32(reg, addr) \
+ enum { A_ ## reg = (addr) }; \
+ enum { R_ ## reg = (addr) / 4 };
+
+#define REG8(reg, addr) \
+ enum { A_ ## reg = (addr) }; \
+ enum { R_ ## reg = (addr) };
+
+#define REG16(reg, addr) \
+ 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
+ * constants for field BAR in register FOO.
+ */
+#define FIELD(reg, field, shift, length) \
+ enum { R_ ## reg ## _ ## field ## _SHIFT = (shift)}; \
+ enum { R_ ## reg ## _ ## field ## _LENGTH = (length)}; \
+ enum { R_ ## reg ## _ ## field ## _MASK = \
+ MAKE_64BIT_MASK(shift, length)};
+
+/* Extract a field from a register */
+#define FIELD_EX8(storage, reg, field) \
+ extract8((storage), R_ ## reg ## _ ## field ## _SHIFT, \
+ R_ ## reg ## _ ## field ## _LENGTH)
+#define FIELD_EX16(storage, reg, field) \
+ extract16((storage), R_ ## reg ## _ ## field ## _SHIFT, \
+ R_ ## reg ## _ ## field ## _LENGTH)
+#define FIELD_EX32(storage, reg, field) \
+ extract32((storage), R_ ## reg ## _ ## field ## _SHIFT, \
+ R_ ## reg ## _ ## field ## _LENGTH)
+#define FIELD_EX64(storage, reg, field) \
+ extract64((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
+ * compilation warnings.
+ */
+#define FIELD_DP8(storage, reg, field, val) ({ \
+ struct { \
+ unsigned 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_DP16(storage, reg, field, val) ({ \
+ struct { \
+ unsigned 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_DP32(storage, reg, field, val) ({ \
+ struct { \
+ unsigned 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_DP64(storage, reg, field, val) ({ \
+ struct { \
+ 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; })
+
+/* 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);
+
+#endif
diff --git a/include/hw/remote/iohub.h b/include/hw/remote/iohub.h
new file mode 100644
index 000000000..0bf98e0d7
--- /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.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/machine.h b/include/hw/remote/machine.h
new file mode 100644
index 000000000..2a2a33c4b
--- /dev/null
+++ b/include/hw/remote/machine.h
@@ -0,0 +1,38 @@
+/*
+ * 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;
+};
+
+/* 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 000000000..bc2e30945
--- /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 000000000..4ec091588
--- /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 000000000..c4f3efb92
--- /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 000000000..741def71f
--- /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.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/resettable.h b/include/hw/resettable.h
new file mode 100644
index 000000000..bdcd1276b
--- /dev/null
+++ b/include/hw/resettable.h
@@ -0,0 +1,246 @@
+/*
+ * Resettable interface header.
+ *
+ * Copyright (c) 2019 GreenSocs SAS
+ *
+ * Authors:
+ * Damien Hedde
+ *
+ * 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_RESETTABLE_H
+#define HW_RESETTABLE_H
+
+#include "qom/object.h"
+
+#define TYPE_RESETTABLE_INTERFACE "resettable"
+
+typedef struct ResettableClass ResettableClass;
+DECLARE_CLASS_CHECKERS(ResettableClass, RESETTABLE,
+ TYPE_RESETTABLE_INTERFACE)
+
+
+typedef struct ResettableState ResettableState;
+
+/**
+ * ResetType:
+ * Types of reset.
+ *
+ * + Cold: reset resulting from a power cycle of the object.
+ *
+ * TODO: Support has to be added to handle more types. In particular,
+ * ResettableState structure needs to be expanded.
+ */
+typedef enum ResetType {
+ RESET_TYPE_COLD,
+} ResetType;
+
+/*
+ * ResettableClass:
+ * Interface for resettable objects.
+ *
+ * See docs/devel/reset.rst for more detailed information about how QEMU models
+ * reset. This whole API must only be used when holding the iothread mutex.
+ *
+ * All objects which can be reset must implement this interface;
+ * it is usually provided by a base class such as DeviceClass or BusClass.
+ * Every Resettable object must maintain some state tracking the
+ * progress of a reset operation by providing a ResettableState structure.
+ * The functions defined in this module take care of updating the
+ * state of the reset.
+ * The base class implementation of the interface provides this
+ * state and implements the associated method: get_state.
+ *
+ * Concrete object implementations (typically specific devices
+ * such as a UART model) should provide the functions
+ * for the phases.enter, phases.hold and phases.exit methods, which
+ * they can set in their class init function, either directly or
+ * by calling resettable_class_set_parent_phases().
+ * The phase methods are guaranteed to only only ever be called once
+ * for any reset event, in the order 'enter', 'hold', 'exit'.
+ * An object will always move quickly from 'enter' to 'hold'
+ * but might remain in 'hold' for an arbitrary period of time
+ * before eventually reset is deasserted and the 'exit' phase is called.
+ * Object implementations should be prepared for functions handling
+ * inbound connections from other devices (such as qemu_irq handler
+ * functions) to be called at any point during reset after their
+ * 'enter' method has been called.
+ *
+ * Users of a resettable object should not call these methods
+ * directly, but instead use the function resettable_reset().
+ *
+ * @phases.enter: This phase is called when the object enters reset. It
+ * should reset local state of the object, but it must not do anything that
+ * has a side-effect on other objects, such as raising or lowering a qemu_irq
+ * line or reading or writing guest memory. It takes the reset's type as
+ * argument.
+ *
+ * @phases.hold: This phase is called for entry into reset, once every object
+ * in the system which is being reset has had its @phases.enter method called.
+ * At this point devices can do actions that affect other objects.
+ *
+ * @phases.exit: This phase is called when the object leaves the reset state.
+ * Actions affecting other objects are permitted.
+ *
+ * @get_state: Mandatory method which must return a pointer to a
+ * ResettableState.
+ *
+ * @get_transitional_function: transitional method to handle Resettable objects
+ * not yet fully moved to this interface. It will be removed as soon as it is
+ * not needed anymore. This method is optional and may return a pointer to a
+ * function to be used instead of the phases. If the method exists and returns
+ * a non-NULL function pointer then that function is executed as a replacement
+ * of the 'hold' phase method taking the object as argument. The two other phase
+ * methods are not executed.
+ *
+ * @child_foreach: Executes a given callback on every Resettable child. Child
+ * in this context means a child in the qbus tree, so the children of a qbus
+ * are the devices on it, and the children of a device are all the buses it
+ * owns. This is not the same as the QOM object hierarchy. The function takes
+ * additional opaque and ResetType arguments which must be passed unmodified to
+ * the callback.
+ */
+typedef void (*ResettableEnterPhase)(Object *obj, ResetType type);
+typedef void (*ResettableHoldPhase)(Object *obj);
+typedef void (*ResettableExitPhase)(Object *obj);
+typedef ResettableState * (*ResettableGetState)(Object *obj);
+typedef void (*ResettableTrFunction)(Object *obj);
+typedef ResettableTrFunction (*ResettableGetTrFunction)(Object *obj);
+typedef void (*ResettableChildCallback)(Object *, void *opaque,
+ ResetType type);
+typedef void (*ResettableChildForeach)(Object *obj,
+ ResettableChildCallback cb,
+ void *opaque, ResetType type);
+typedef struct ResettablePhases {
+ ResettableEnterPhase enter;
+ ResettableHoldPhase hold;
+ ResettableExitPhase exit;
+} ResettablePhases;
+struct ResettableClass {
+ InterfaceClass parent_class;
+
+ /* Phase methods */
+ ResettablePhases phases;
+
+ /* State access method */
+ ResettableGetState get_state;
+
+ /* Transitional method for legacy reset compatibility */
+ ResettableGetTrFunction get_transitional_function;
+
+ /* Hierarchy handling method */
+ ResettableChildForeach child_foreach;
+};
+
+/**
+ * ResettableState:
+ * Structure holding reset related state. The fields should not be accessed
+ * directly; the definition is here to allow further inclusion into other
+ * objects.
+ *
+ * @count: Number of reset level the object is into. It is incremented when
+ * the reset operation starts and decremented when it finishes.
+ * @hold_phase_pending: flag which indicates that we need to invoke the 'hold'
+ * phase handler for this object.
+ * @exit_phase_in_progress: true if we are currently in the exit phase
+ */
+struct ResettableState {
+ unsigned count;
+ bool hold_phase_pending;
+ bool exit_phase_in_progress;
+};
+
+/**
+ * resettable_state_clear:
+ * Clear the state. It puts the state to the initial (zeroed) state required
+ * to reuse an object. Typically used in realize step of base classes
+ * implementing the interface.
+ */
+static inline void resettable_state_clear(ResettableState *state)
+{
+ memset(state, 0, sizeof(ResettableState));
+}
+
+/**
+ * resettable_reset:
+ * Trigger a reset on an object @obj of type @type. @obj must implement
+ * Resettable interface.
+ *
+ * Calling this function is equivalent to calling @resettable_assert_reset()
+ * then @resettable_release_reset().
+ */
+void resettable_reset(Object *obj, ResetType type);
+
+/**
+ * resettable_assert_reset:
+ * Put an object @obj into reset. @obj must implement Resettable interface.
+ *
+ * @resettable_release_reset() must eventually be called after this call.
+ * There must be one call to @resettable_release_reset() per call of
+ * @resettable_assert_reset(), with the same type argument.
+ *
+ * NOTE: Until support for migration is added, the @resettable_release_reset()
+ * must not be delayed. It must occur just after @resettable_assert_reset() so
+ * that migration cannot be triggered in between. Prefer using
+ * @resettable_reset() for now.
+ */
+void resettable_assert_reset(Object *obj, ResetType type);
+
+/**
+ * resettable_release_reset:
+ * Release the object @obj from reset. @obj must implement Resettable interface.
+ *
+ * See @resettable_assert_reset() description for details.
+ */
+void resettable_release_reset(Object *obj, ResetType type);
+
+/**
+ * resettable_is_in_reset:
+ * Return true if @obj is under reset.
+ *
+ * @obj must implement Resettable interface.
+ */
+bool resettable_is_in_reset(Object *obj);
+
+/**
+ * resettable_change_parent:
+ * Indicate that the parent of Ressettable @obj is changing from @oldp to @newp.
+ * All 3 objects must implement resettable interface. @oldp or @newp may be
+ * NULL.
+ *
+ * This function will adapt the reset state of @obj so that it is coherent
+ * with the reset state of @newp. It may trigger @resettable_assert_reset()
+ * or @resettable_release_reset(). It will do such things only if the reset
+ * state of @newp and @oldp are different.
+ *
+ * When using this function during reset, it must only be called during
+ * a hold phase method. Calling this during enter or exit phase is an error.
+ */
+void resettable_change_parent(Object *obj, Object *newp, Object *oldp);
+
+/**
+ * resettable_cold_reset_fn:
+ * Helper to call resettable_reset((Object *) opaque, RESET_TYPE_COLD).
+ *
+ * This function is typically useful to register a reset handler with
+ * qemu_register_reset.
+ */
+void resettable_cold_reset_fn(void *opaque);
+
+/**
+ * resettable_class_set_parent_phases:
+ *
+ * Save @rc current reset phases into @parent_phases and override @rc phases
+ * by the given new methods (@enter, @hold and @exit).
+ * Each phase is overridden only if the new one is not NULL allowing to
+ * override a subset of phases.
+ */
+void resettable_class_set_parent_phases(ResettableClass *rc,
+ ResettableEnterPhase enter,
+ ResettableHoldPhase hold,
+ ResettableExitPhase exit,
+ ResettablePhases *parent_phases);
+
+#endif
diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
new file mode 100644
index 000000000..baff11dd8
--- /dev/null
+++ b/include/hw/riscv/boot.h
@@ -0,0 +1,62 @@
+/*
+ * QEMU RISC-V Boot Helper
+ *
+ * Copyright (c) 2017 SiFive, Inc.
+ * Copyright (c) 2019 Alistair Francis <alistair.francis@wdc.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 RISCV_BOOT_H
+#define RISCV_BOOT_H
+
+#include "exec/cpu-defs.h"
+#include "hw/loader.h"
+#include "hw/riscv/riscv_hart.h"
+
+#define RISCV32_BIOS_BIN "opensbi-riscv32-generic-fw_dynamic.bin"
+#define RISCV32_BIOS_ELF "opensbi-riscv32-generic-fw_dynamic.elf"
+#define RISCV64_BIOS_BIN "opensbi-riscv64-generic-fw_dynamic.bin"
+#define RISCV64_BIOS_ELF "opensbi-riscv64-generic-fw_dynamic.elf"
+
+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);
+char *riscv_find_firmware(const char *firmware_filename);
+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 firmware_end_addr,
+ 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(MachineState *machine, RISCVHartArrayState *harts,
+ 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(MachineState *machine, hwaddr rom_base,
+ hwaddr rom_size,
+ uint32_t reset_vec_size,
+ uint64_t kernel_entry);
+
+#endif /* RISCV_BOOT_H */
diff --git a/include/hw/riscv/boot_opensbi.h b/include/hw/riscv/boot_opensbi.h
new file mode 100644
index 000000000..0d5ddd6c3
--- /dev/null
+++ b/include/hw/riscv/boot_opensbi.h
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2019 Western Digital Corporation or its affiliates.
+ *
+ * Based on include/sbi/{fw_dynamic.h,sbi_scratch.h} from the OpenSBI project.
+ */
+#ifndef OPENSBI_H
+#define OPENSBI_H
+
+/** Expected value of info magic ('OSBI' ascii string in hex) */
+#define FW_DYNAMIC_INFO_MAGIC_VALUE 0x4942534f
+
+/** Maximum supported info version */
+#define FW_DYNAMIC_INFO_VERSION 0x2
+
+/** Possible next mode values */
+#define FW_DYNAMIC_INFO_NEXT_MODE_U 0x0
+#define FW_DYNAMIC_INFO_NEXT_MODE_S 0x1
+#define FW_DYNAMIC_INFO_NEXT_MODE_M 0x3
+
+enum sbi_scratch_options {
+ /** Disable prints during boot */
+ SBI_SCRATCH_NO_BOOT_PRINTS = (1 << 0),
+ /** Enable runtime debug prints */
+ SBI_SCRATCH_DEBUG_PRINTS = (1 << 1),
+};
+
+/** Representation dynamic info passed by previous booting stage */
+struct fw_dynamic_info {
+ /** Info magic */
+ target_long magic;
+ /** Info version */
+ target_long version;
+ /** Next booting stage address */
+ target_long next_addr;
+ /** Next booting stage mode */
+ target_long next_mode;
+ /** Options for OpenSBI library */
+ target_long options;
+ /**
+ * Preferred boot HART id
+ *
+ * It is possible that the previous booting stage uses same link
+ * address as the FW_DYNAMIC firmware. In this case, the relocation
+ * lottery mechanism can potentially overwrite the previous booting
+ * stage while other HARTs are still running in the previous booting
+ * stage leading to boot-time crash. To avoid this boot-time crash,
+ * the previous booting stage can specify last HART that will jump
+ * to the FW_DYNAMIC firmware as the preferred boot HART.
+ *
+ * To avoid specifying a preferred boot HART, the previous booting
+ * stage can set it to -1UL which will force the FW_DYNAMIC firmware
+ * to use the relocation lottery mechanism.
+ */
+ target_long boot_hart;
+};
+
+#endif
diff --git a/include/hw/riscv/microchip_pfsoc.h b/include/hw/riscv/microchip_pfsoc.h
new file mode 100644
index 000000000..a0673f5f5
--- /dev/null
+++ b/include/hw/riscv/microchip_pfsoc.h
@@ -0,0 +1,150 @@
+/*
+ * 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/char/mchp_pfsoc_mmuart.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"
+
+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_SYSREG,
+ MICROCHIP_PFSOC_MPUCFG,
+ 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_SPI0,
+ MICROCHIP_PFSOC_SPI1,
+ MICROCHIP_PFSOC_I2C1,
+ MICROCHIP_PFSOC_GEM0,
+ MICROCHIP_PFSOC_GEM1,
+ MICROCHIP_PFSOC_GPIO0,
+ MICROCHIP_PFSOC_GPIO1,
+ MICROCHIP_PFSOC_GPIO2,
+ MICROCHIP_PFSOC_ENVM_CFG,
+ MICROCHIP_PFSOC_ENVM_DATA,
+ MICROCHIP_PFSOC_QSPI_XIP,
+ MICROCHIP_PFSOC_IOSCB,
+ MICROCHIP_PFSOC_EMMC_SD_MUX,
+ 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,
+};
+
+#define MICROCHIP_PFSOC_MANAGEMENT_CPU_COUNT 1
+#define MICROCHIP_PFSOC_COMPUTE_CPU_COUNT 4
+
+#define MICROCHIP_PFSOC_PLIC_NUM_SOURCES 185
+#define MICROCHIP_PFSOC_PLIC_NUM_PRIORITIES 7
+#define MICROCHIP_PFSOC_PLIC_PRIORITY_BASE 0x04
+#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 000000000..fcce942ce
--- /dev/null
+++ b/include/hw/riscv/numa.h
@@ -0,0 +1,113 @@
+/*
+ * 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/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 for given FDT node
+ */
+void riscv_socket_fdt_write_id(const MachineState *ms, void *fdt,
+ 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 FDT for given machine
+ */
+void riscv_socket_fdt_write_distance_matrix(const MachineState *ms, void *fdt);
+
+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
new file mode 100644
index 000000000..eac35ef59
--- /dev/null
+++ b/include/hw/riscv/opentitan.h
@@ -0,0 +1,101 @@
+/*
+ * QEMU RISC-V Board Compatible with OpenTitan FPGA platform
+ *
+ * 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_OPENTITAN_H
+#define HW_OPENTITAN_H
+
+#include "hw/riscv/riscv_hart.h"
+#include "hw/intc/sifive_plic.h"
+#include "hw/char/ibex_uart.h"
+#include "hw/timer/ibex_timer.h"
+#include "qom/object.h"
+
+#define TYPE_RISCV_IBEX_SOC "riscv.lowrisc.ibex.soc"
+OBJECT_DECLARE_SIMPLE_TYPE(LowRISCIbexSoCState, RISCV_IBEX_SOC)
+
+struct LowRISCIbexSoCState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ RISCVHartArrayState cpus;
+ SiFivePLICState plic;
+ IbexUartState uart;
+ IbexTimerState timer;
+
+ MemoryRegion flash_mem;
+ MemoryRegion rom;
+ MemoryRegion flash_alias;
+};
+
+typedef struct OpenTitanState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ LowRISCIbexSoCState soc;
+} OpenTitanState;
+
+enum {
+ IBEX_DEV_ROM,
+ IBEX_DEV_RAM,
+ IBEX_DEV_FLASH,
+ IBEX_DEV_FLASH_VIRTUAL,
+ IBEX_DEV_UART,
+ IBEX_DEV_GPIO,
+ IBEX_DEV_SPI,
+ IBEX_DEV_I2C,
+ IBEX_DEV_PATTGEN,
+ IBEX_DEV_TIMER,
+ IBEX_DEV_SENSOR_CTRL,
+ IBEX_DEV_OTP_CTRL,
+ IBEX_DEV_PWRMGR,
+ IBEX_DEV_RSTMGR,
+ IBEX_DEV_CLKMGR,
+ IBEX_DEV_PINMUX,
+ IBEX_DEV_PADCTRL,
+ 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_NMI_GEN,
+ IBEX_DEV_OTBN,
+ IBEX_DEV_PERI,
+};
+
+enum {
+ IBEX_TIMER_TIMEREXPIRED0_0 = 126,
+ IBEX_UART0_RX_PARITY_ERR_IRQ = 8,
+ IBEX_UART0_RX_TIMEOUT_IRQ = 7,
+ IBEX_UART0_RX_BREAK_ERR_IRQ = 6,
+ IBEX_UART0_RX_FRAME_ERR_IRQ = 5,
+ IBEX_UART0_RX_OVERFLOW_IRQ = 4,
+ IBEX_UART0_TX_EMPTY_IRQ = 3,
+ IBEX_UART0_RX_WATERMARK_IRQ = 2,
+ IBEX_UART0_TX_WATERMARK_IRQ = 1,
+};
+
+#endif
diff --git a/include/hw/riscv/riscv_hart.h b/include/hw/riscv/riscv_hart.h
new file mode 100644
index 000000000..bbc21cdc9
--- /dev/null
+++ b/include/hw/riscv/riscv_hart.h
@@ -0,0 +1,44 @@
+/*
+ * QEMU RISC-V Hart Array interface
+ *
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * Holds the state of a heterogenous 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,
+ * 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_HART_H
+#define HW_RISCV_HART_H
+
+#include "hw/sysbus.h"
+#include "target/riscv/cpu.h"
+#include "qom/object.h"
+
+#define TYPE_RISCV_HART_ARRAY "riscv.hart_array"
+
+OBJECT_DECLARE_SIMPLE_TYPE(RISCVHartArrayState, RISCV_HART_ARRAY)
+
+struct RISCVHartArrayState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ uint32_t num_harts;
+ uint32_t hartid_base;
+ char *cpu_type;
+ uint64_t resetvec;
+ RISCVCPU *harts;
+};
+
+#endif
diff --git a/include/hw/riscv/shakti_c.h b/include/hw/riscv/shakti_c.h
new file mode 100644
index 000000000..50a2b7908
--- /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_H
+#define HW_SHAKTI_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 0x04
+#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_cpu.h b/include/hw/riscv/sifive_cpu.h
new file mode 100644
index 000000000..136799633
--- /dev/null
+++ b/include/hw/riscv/sifive_cpu.h
@@ -0,0 +1,31 @@
+/*
+ * SiFive CPU types
+ *
+ * Copyright (c) 2017 SiFive, Inc.
+ * Copyright (c) 2019 Bin Meng <bmeng.cn@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 HW_SIFIVE_CPU_H
+#define HW_SIFIVE_CPU_H
+
+#if defined(TARGET_RISCV32)
+#define SIFIVE_E_CPU TYPE_RISCV_CPU_SIFIVE_E31
+#define SIFIVE_U_CPU TYPE_RISCV_CPU_SIFIVE_U34
+#elif defined(TARGET_RISCV64)
+#define SIFIVE_E_CPU TYPE_RISCV_CPU_SIFIVE_E51
+#define SIFIVE_U_CPU TYPE_RISCV_CPU_SIFIVE_U54
+#endif
+
+#endif /* HW_SIFIVE_CPU_H */
diff --git a/include/hw/riscv/sifive_e.h b/include/hw/riscv/sifive_e.h
new file mode 100644
index 000000000..83604da80
--- /dev/null
+++ b/include/hw/riscv/sifive_e.h
@@ -0,0 +1,93 @@
+/*
+ * SiFive E series machine interface
+ *
+ * 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_E_H
+#define HW_SIFIVE_E_H
+
+#include "hw/riscv/riscv_hart.h"
+#include "hw/riscv/sifive_cpu.h"
+#include "hw/gpio/sifive_gpio.h"
+
+#define TYPE_RISCV_E_SOC "riscv.sifive.e.soc"
+#define RISCV_E_SOC(obj) \
+ OBJECT_CHECK(SiFiveESoCState, (obj), TYPE_RISCV_E_SOC)
+
+typedef struct SiFiveESoCState {
+ /*< private >*/
+ DeviceState parent_obj;
+
+ /*< public >*/
+ RISCVHartArrayState cpus;
+ DeviceState *plic;
+ SIFIVEGPIOState gpio;
+ MemoryRegion xip_mem;
+ MemoryRegion mask_rom;
+} SiFiveESoCState;
+
+typedef struct SiFiveEState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ SiFiveESoCState soc;
+ bool revb;
+} SiFiveEState;
+
+#define TYPE_RISCV_E_MACHINE MACHINE_TYPE_NAME("sifive_e")
+#define RISCV_E_MACHINE(obj) \
+ OBJECT_CHECK(SiFiveEState, (obj), TYPE_RISCV_E_MACHINE)
+
+enum {
+ 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
+};
+
+#define SIFIVE_E_PLIC_HART_CONFIG "M"
+#define SIFIVE_E_PLIC_NUM_SOURCES 127
+#define SIFIVE_E_PLIC_NUM_PRIORITIES 7
+#define SIFIVE_E_PLIC_PRIORITY_BASE 0x04
+#define SIFIVE_E_PLIC_PENDING_BASE 0x1000
+#define SIFIVE_E_PLIC_ENABLE_BASE 0x2000
+#define SIFIVE_E_PLIC_ENABLE_STRIDE 0x80
+#define SIFIVE_E_PLIC_CONTEXT_BASE 0x200000
+#define SIFIVE_E_PLIC_CONTEXT_STRIDE 0x1000
+
+#endif
diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h
new file mode 100644
index 000000000..8f63a183c
--- /dev/null
+++ b/include/hw/riscv/sifive_u.h
@@ -0,0 +1,168 @@
+/*
+ * SiFive U series machine interface
+ *
+ * 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_U_H
+#define HW_SIFIVE_U_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/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) \
+ OBJECT_CHECK(SiFiveUSoCState, (obj), TYPE_RISCV_U_SOC)
+
+typedef struct SiFiveUSoCState {
+ /*< private >*/
+ DeviceState parent_obj;
+
+ /*< public >*/
+ CPUClusterState e_cluster;
+ CPUClusterState u_cluster;
+ RISCVHartArrayState e_cpus;
+ RISCVHartArrayState u_cpus;
+ DeviceState *plic;
+ 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")
+#define RISCV_U_MACHINE(obj) \
+ OBJECT_CHECK(SiFiveUState, (obj), TYPE_RISCV_U_MACHINE)
+
+typedef struct SiFiveUState {
+ /*< private >*/
+ MachineState parent_obj;
+
+ /*< public >*/
+ SiFiveUSoCState soc;
+
+ void *fdt;
+ int fdt_size;
+
+ bool start_in_flash;
+ uint32_t msel;
+ uint32_t serial;
+} SiFiveUState;
+
+enum {
+ 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,
+ SIFIVE_U_GPIO_IRQ3 = 10,
+ SIFIVE_U_GPIO_IRQ4 = 11,
+ SIFIVE_U_GPIO_IRQ5 = 12,
+ SIFIVE_U_GPIO_IRQ6 = 13,
+ SIFIVE_U_GPIO_IRQ7 = 14,
+ SIFIVE_U_GPIO_IRQ8 = 15,
+ SIFIVE_U_GPIO_IRQ9 = 16,
+ SIFIVE_U_GPIO_IRQ10 = 17,
+ SIFIVE_U_GPIO_IRQ11 = 18,
+ SIFIVE_U_GPIO_IRQ12 = 19,
+ SIFIVE_U_GPIO_IRQ13 = 20,
+ SIFIVE_U_GPIO_IRQ14 = 21,
+ SIFIVE_U_GPIO_IRQ15 = 22,
+ 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 {
+ SIFIVE_U_HFCLK_FREQ = 33333333,
+ SIFIVE_U_RTCCLK_FREQ = 1000000
+};
+
+enum {
+ MSEL_MEMMAP_QSPI0_FLASH = 1,
+ MSEL_L2LIM_QSPI0_FLASH = 6,
+ MSEL_L2LIM_QSPI2_SD = 11
+};
+
+#define SIFIVE_U_MANAGEMENT_CPU_COUNT 1
+#define SIFIVE_U_COMPUTE_CPU_COUNT 4
+
+#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_PENDING_BASE 0x1000
+#define SIFIVE_U_PLIC_ENABLE_BASE 0x2000
+#define SIFIVE_U_PLIC_ENABLE_STRIDE 0x80
+#define SIFIVE_U_PLIC_CONTEXT_BASE 0x200000
+#define SIFIVE_U_PLIC_CONTEXT_STRIDE 0x1000
+
+#endif
diff --git a/include/hw/riscv/spike.h b/include/hw/riscv/spike.h
new file mode 100644
index 000000000..cdd1a1301
--- /dev/null
+++ b/include/hw/riscv/spike.h
@@ -0,0 +1,50 @@
+/*
+ * Spike machine interface
+ *
+ * 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_RISCV_SPIKE_H
+#define HW_RISCV_SPIKE_H
+
+#include "hw/riscv/riscv_hart.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#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 >*/
+ MachineState parent;
+
+ /*< public >*/
+ RISCVHartArrayState soc[SPIKE_SOCKETS_MAX];
+ void *fdt;
+ int fdt_size;
+};
+
+enum {
+ SPIKE_MROM,
+ SPIKE_CLINT,
+ SPIKE_DRAM
+};
+
+#endif
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
new file mode 100644
index 000000000..b8ef99f34
--- /dev/null
+++ b/include/hw/riscv/virt.h
@@ -0,0 +1,94 @@
+/*
+ * QEMU RISC-V VirtIO machine interface
+ *
+ * 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_RISCV_VIRT_H
+#define HW_RISCV_VIRT_H
+
+#include "hw/riscv/riscv_hart.h"
+#include "hw/sysbus.h"
+#include "hw/block/flash.h"
+#include "qom/object.h"
+
+#define VIRT_CPUS_MAX 8
+#define VIRT_SOCKETS_MAX 8
+
+#define TYPE_RISCV_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
+typedef struct RISCVVirtState RISCVVirtState;
+DECLARE_INSTANCE_CHECKER(RISCVVirtState, RISCV_VIRT_MACHINE,
+ TYPE_RISCV_VIRT_MACHINE)
+
+struct RISCVVirtState {
+ /*< private >*/
+ MachineState parent;
+
+ /*< public >*/
+ RISCVHartArrayState soc[VIRT_SOCKETS_MAX];
+ DeviceState *plic[VIRT_SOCKETS_MAX];
+ PFlashCFI01 *flash[2];
+ FWCfgState *fw_cfg;
+
+ int fdt_size;
+ bool have_aclint;
+};
+
+enum {
+ VIRT_DEBUG,
+ VIRT_MROM,
+ VIRT_TEST,
+ VIRT_RTC,
+ VIRT_CLINT,
+ VIRT_ACLINT_SSWI,
+ VIRT_PLIC,
+ VIRT_UART0,
+ VIRT_VIRTIO,
+ VIRT_FW_CFG,
+ VIRT_FLASH,
+ VIRT_DRAM,
+ VIRT_PCIE_MMIO,
+ VIRT_PCIE_PIO,
+ VIRT_PCIE_ECAM
+};
+
+enum {
+ UART0_IRQ = 10,
+ RTC_IRQ = 11,
+ VIRTIO_IRQ = 1, /* 1 to 8 */
+ VIRTIO_COUNT = 8,
+ PCIE_IRQ = 0x20, /* 32 to 35 */
+ VIRTIO_NDEV = 0x35 /* Arbitrary maximum number of interrupts */
+};
+
+#define VIRT_PLIC_NUM_SOURCES 127
+#define VIRT_PLIC_NUM_PRIORITIES 7
+#define VIRT_PLIC_PRIORITY_BASE 0x04
+#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)
+
+#endif
diff --git a/include/hw/rtc/allwinner-rtc.h b/include/hw/rtc/allwinner-rtc.h
new file mode 100644
index 000000000..bf415431c
--- /dev/null
+++ b/include/hw/rtc/allwinner-rtc.h
@@ -0,0 +1,129 @@
+/*
+ * Allwinner Real Time Clock emulation
+ *
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.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_RTC_H
+#define HW_MISC_ALLWINNER_RTC_H
+
+#include "qom/object.h"
+#include "hw/sysbus.h"
+
+/**
+ * Constants
+ * @{
+ */
+
+/** Highest register address used by RTC device */
+#define AW_RTC_REGS_MAXADDR (0x200)
+
+/** Total number of known registers */
+#define AW_RTC_REGS_NUM (AW_RTC_REGS_MAXADDR / sizeof(uint32_t))
+
+/** @} */
+
+/**
+ * Object model types
+ * @{
+ */
+
+/** Generic Allwinner RTC device (abstract) */
+#define TYPE_AW_RTC "allwinner-rtc"
+
+/** Allwinner RTC sun4i family (A10, A12) */
+#define TYPE_AW_RTC_SUN4I TYPE_AW_RTC "-sun4i"
+
+/** Allwinner RTC sun6i family and newer (A31, H2+, H3, etc) */
+#define TYPE_AW_RTC_SUN6I TYPE_AW_RTC "-sun6i"
+
+/** Allwinner RTC sun7i family (A20) */
+#define TYPE_AW_RTC_SUN7I TYPE_AW_RTC "-sun7i"
+
+/** @} */
+
+/**
+ * Object model macros
+ * @{
+ */
+
+OBJECT_DECLARE_TYPE(AwRtcState, AwRtcClass, AW_RTC)
+
+/** @} */
+
+/**
+ * Allwinner RTC per-object instance state.
+ */
+struct AwRtcState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ /**
+ * Actual year represented by the device when year counter is zero
+ *
+ * Can be overridden by the user using the corresponding 'base-year'
+ * property. The base year used by the target OS driver can vary, for
+ * example the Linux driver for sun6i uses 1970 while NetBSD uses 2000.
+ */
+ int base_year;
+
+ /** Maps I/O registers in physical memory */
+ MemoryRegion iomem;
+
+ /** Array of hardware registers */
+ uint32_t regs[AW_RTC_REGS_NUM];
+
+};
+
+/**
+ * Allwinner RTC 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 AwRtcClass {
+ /*< 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)(AwRtcState *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)(AwRtcState *s, uint32_t offset, uint32_t data);
+
+};
+
+#endif /* HW_MISC_ALLWINNER_RTC_H */
diff --git a/include/hw/rtc/aspeed_rtc.h b/include/hw/rtc/aspeed_rtc.h
new file mode 100644
index 000000000..df61e4605
--- /dev/null
+++ b/include/hw/rtc/aspeed_rtc.h
@@ -0,0 +1,28 @@
+/*
+ * ASPEED Real Time Clock
+ * Joel Stanley <joel@jms.id.au>
+ *
+ * Copyright 2019 IBM Corp
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef HW_RTC_ASPEED_RTC_H
+#define HW_RTC_ASPEED_RTC_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+struct AspeedRtcState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ qemu_irq irq;
+
+ uint32_t reg[0x18];
+ int offset;
+
+};
+
+#define TYPE_ASPEED_RTC "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
new file mode 100644
index 000000000..79ca7daf5
--- /dev/null
+++ b/include/hw/rtc/goldfish_rtc.h
@@ -0,0 +1,47 @@
+/*
+ * Goldfish virtual platform RTC
+ *
+ * Copyright (C) 2019 Western Digital Corporation or its affiliates.
+ *
+ * For more details on Google Goldfish virtual platform refer:
+ * https://android.googlesource.com/platform/external/qemu/+/master/docs/GOLDFISH-VIRTUAL-HARDWARE.TXT
+ *
+ * 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_RTC_GOLDFISH_RTC_H
+#define HW_RTC_GOLDFISH_RTC_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_GOLDFISH_RTC "goldfish_rtc"
+OBJECT_DECLARE_SIMPLE_TYPE(GoldfishRTCState, GOLDFISH_RTC)
+
+struct GoldfishRTCState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ QEMUTimer *timer;
+ qemu_irq irq;
+
+ uint64_t tick_offset;
+ uint64_t tick_offset_vmstate;
+ uint64_t alarm_next;
+ uint32_t alarm_running;
+ uint32_t irq_pending;
+ uint32_t irq_enabled;
+ uint32_t time_high;
+};
+
+#endif
diff --git a/include/hw/rtc/m48t59.h b/include/hw/rtc/m48t59.h
new file mode 100644
index 000000000..d9b45eb16
--- /dev/null
+++ b/include/hw/rtc/m48t59.h
@@ -0,0 +1,50 @@
+/*
+ * QEMU M48T59 and M48T08 NVRAM emulation
+ *
+ * Copyright (c) 2003-2005, 2007 Jocelyn Mayer
+ * Copyright (c) 2013 Hervé Poussineau
+ *
+ * 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_RTC_M48T59_H
+#define HW_RTC_M48T59_H
+
+#include "exec/hwaddr.h"
+#include "qom/object.h"
+
+#define TYPE_NVRAM "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;
+
+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);
+};
+
+#endif /* HW_M48T59_H */
diff --git a/include/hw/rtc/mc146818rtc.h b/include/hw/rtc/mc146818rtc.h
new file mode 100644
index 000000000..5b45b2292
--- /dev/null
+++ b/include/hw/rtc/mc146818rtc.h
@@ -0,0 +1,58 @@
+/*
+ * QEMU MC146818 RTC emulation
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#ifndef HW_RTC_MC146818RTC_H
+#define HW_RTC_MC146818RTC_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"
+OBJECT_DECLARE_SIMPLE_TYPE(RTCState, MC146818_RTC)
+
+struct RTCState {
+ ISADevice parent_obj;
+
+ MemoryRegion io;
+ MemoryRegion coalesced_io;
+ uint8_t cmos_data[128];
+ uint8_t cmos_index;
+ int32_t base_year;
+ uint64_t base_rtc;
+ uint64_t last_update;
+ int64_t offset;
+ qemu_irq irq;
+ int it_shift;
+ /* periodic timer */
+ QEMUTimer *periodic_timer;
+ int64_t next_periodic_time;
+ /* update-ended timer */
+ QEMUTimer *update_timer;
+ uint64_t next_alarm_time;
+ uint16_t irq_reinject_on_ack_count;
+ uint32_t irq_coalesced;
+ uint32_t period;
+ QEMUTimer *coalesced_timer;
+ Notifier clock_reset_notifier;
+ LostTickPolicy lost_tick_policy;
+ Notifier suspend_notifier;
+ QLIST_ENTRY(RTCState) 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);
+
+#endif /* MC146818RTC_H */
diff --git a/include/hw/rtc/mc146818rtc_regs.h b/include/hw/rtc/mc146818rtc_regs.h
new file mode 100644
index 000000000..12197e055
--- /dev/null
+++ b/include/hw/rtc/mc146818rtc_regs.h
@@ -0,0 +1,89 @@
+/*
+ * QEMU MC146818 RTC emulation
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * 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_RTC_MC146818RTC_REGS_H
+#define HW_RTC_MC146818RTC_REGS_H
+
+#include "qemu/timer.h"
+#include "qemu/host-utils.h"
+
+#define RTC_SECONDS 0
+#define RTC_SECONDS_ALARM 1
+#define RTC_MINUTES 2
+#define RTC_MINUTES_ALARM 3
+#define RTC_HOURS 4
+#define RTC_HOURS_ALARM 5
+#define RTC_ALARM_DONT_CARE 0xC0
+
+#define RTC_DAY_OF_WEEK 6
+#define RTC_DAY_OF_MONTH 7
+#define RTC_MONTH 8
+#define RTC_YEAR 9
+
+#define RTC_REG_A 10
+#define RTC_REG_B 11
+#define RTC_REG_C 12
+#define RTC_REG_D 13
+
+/* PC cmos mappings */
+#define RTC_CENTURY 0x32
+#define RTC_IBM_PS2_CENTURY_BYTE 0x37
+
+#define REG_A_UIP 0x80
+
+#define REG_B_SET 0x80
+#define REG_B_PIE 0x40
+#define REG_B_AIE 0x20
+#define REG_B_UIE 0x10
+#define REG_B_SQWE 0x08
+#define REG_B_DM 0x04
+#define REG_B_24H 0x02
+
+#define REG_C_UF 0x10
+#define REG_C_IRQF 0x80
+#define REG_C_PF 0x40
+#define REG_C_AF 0x20
+#define REG_C_MASK 0x70
+
+static inline uint32_t periodic_period_to_clock(int period_code)
+{
+ if (!period_code) {
+ return 0;
+ }
+
+ if (period_code <= 2) {
+ period_code += 7;
+ }
+ /* period in 32 Khz cycles */
+ return 1 << (period_code - 1);
+}
+
+#define RTC_CLOCK_RATE 32768
+
+static inline int64_t periodic_clock_to_ns(int64_t clocks)
+{
+ return muldiv64(clocks, NANOSECONDS_PER_SECOND, RTC_CLOCK_RATE);
+}
+
+#endif
diff --git a/include/hw/rtc/pl031.h b/include/hw/rtc/pl031.h
new file mode 100644
index 000000000..9fd4be1ab
--- /dev/null
+++ b/include/hw/rtc/pl031.h
@@ -0,0 +1,48 @@
+/*
+ * ARM AMBA PrimeCell PL031 RTC
+ *
+ * Copyright (c) 2007 CodeSourcery
+ *
+ * This file 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.
+ *
+ * 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_RTC_PL031_H
+#define HW_RTC_PL031_H
+
+#include "hw/sysbus.h"
+#include "qemu/timer.h"
+#include "qom/object.h"
+
+#define TYPE_PL031 "pl031"
+OBJECT_DECLARE_SIMPLE_TYPE(PL031State, PL031)
+
+struct PL031State {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ QEMUTimer *timer;
+ qemu_irq irq;
+
+ /*
+ * Needed to preserve the tick_count across migration, even if the
+ * absolute value of the rtc_clock is different on the source and
+ * destination.
+ */
+ uint32_t tick_offset_vmstate;
+ uint32_t tick_offset;
+ bool tick_offset_migrated;
+ bool migrate_tick_offset;
+
+ uint32_t mr;
+ uint32_t lr;
+ uint32_t cr;
+ uint32_t im;
+ uint32_t is;
+};
+
+#endif
diff --git a/include/hw/rtc/sun4v-rtc.h b/include/hw/rtc/sun4v-rtc.h
new file mode 100644
index 000000000..fd868f6ed
--- /dev/null
+++ b/include/hw/rtc/sun4v-rtc.h
@@ -0,0 +1,19 @@
+/*
+ * QEMU sun4v Real Time Clock device
+ *
+ * The sun4v_rtc device (sun4v tod clock)
+ *
+ * Copyright (c) 2016 Artyom Tarasenko
+ *
+ * This code is licensed under the GNU GPL v3 or (at your option) any later
+ * version.
+ */
+
+#ifndef HW_RTC_SUN4V
+#define HW_RTC_SUN4V
+
+#include "exec/hwaddr.h"
+
+void sun4v_rtc_init(hwaddr addr);
+
+#endif
diff --git a/include/hw/rtc/xlnx-zynqmp-rtc.h b/include/hw/rtc/xlnx-zynqmp-rtc.h
new file mode 100644
index 000000000..5f1ad0a94
--- /dev/null
+++ b/include/hw/rtc/xlnx-zynqmp-rtc.h
@@ -0,0 +1,92 @@
+/*
+ * QEMU model of the Xilinx ZynqMP Real Time Clock (RTC).
+ *
+ * Copyright (c) 2017 Xilinx Inc.
+ *
+ * Written-by: Alistair Francis
+ *
+ * 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_RTC_XLNX_ZYNQMP_H
+#define HW_RTC_XLNX_ZYNQMP_H
+
+#include "hw/register.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_XLNX_ZYNQMP_RTC "xlnx-zynmp.rtc"
+
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPRTC, XLNX_ZYNQMP_RTC)
+
+REG32(SET_TIME_WRITE, 0x0)
+REG32(SET_TIME_READ, 0x4)
+REG32(CALIB_WRITE, 0x8)
+ FIELD(CALIB_WRITE, FRACTION_EN, 20, 1)
+ FIELD(CALIB_WRITE, FRACTION_DATA, 16, 4)
+ FIELD(CALIB_WRITE, MAX_TICK, 0, 16)
+REG32(CALIB_READ, 0xc)
+ FIELD(CALIB_READ, FRACTION_EN, 20, 1)
+ FIELD(CALIB_READ, FRACTION_DATA, 16, 4)
+ FIELD(CALIB_READ, MAX_TICK, 0, 16)
+REG32(CURRENT_TIME, 0x10)
+REG32(CURRENT_TICK, 0x14)
+ FIELD(CURRENT_TICK, VALUE, 0, 16)
+REG32(ALARM, 0x18)
+REG32(RTC_INT_STATUS, 0x20)
+ FIELD(RTC_INT_STATUS, ALARM, 1, 1)
+ FIELD(RTC_INT_STATUS, SECONDS, 0, 1)
+REG32(RTC_INT_MASK, 0x24)
+ FIELD(RTC_INT_MASK, ALARM, 1, 1)
+ FIELD(RTC_INT_MASK, SECONDS, 0, 1)
+REG32(RTC_INT_EN, 0x28)
+ FIELD(RTC_INT_EN, ALARM, 1, 1)
+ FIELD(RTC_INT_EN, SECONDS, 0, 1)
+REG32(RTC_INT_DIS, 0x2c)
+ FIELD(RTC_INT_DIS, ALARM, 1, 1)
+ FIELD(RTC_INT_DIS, SECONDS, 0, 1)
+REG32(ADDR_ERROR, 0x30)
+ FIELD(ADDR_ERROR, STATUS, 0, 1)
+REG32(ADDR_ERROR_INT_MASK, 0x34)
+ FIELD(ADDR_ERROR_INT_MASK, MASK, 0, 1)
+REG32(ADDR_ERROR_INT_EN, 0x38)
+ FIELD(ADDR_ERROR_INT_EN, MASK, 0, 1)
+REG32(ADDR_ERROR_INT_DIS, 0x3c)
+ FIELD(ADDR_ERROR_INT_DIS, MASK, 0, 1)
+REG32(CONTROL, 0x40)
+ FIELD(CONTROL, BATTERY_DISABLE, 31, 1)
+ FIELD(CONTROL, OSC_CNTRL, 24, 4)
+ FIELD(CONTROL, SLVERR_ENABLE, 0, 1)
+REG32(SAFETY_CHK, 0x50)
+
+#define XLNX_ZYNQMP_RTC_R_MAX (R_SAFETY_CHK + 1)
+
+struct XlnxZynqMPRTC {
+ SysBusDevice parent_obj;
+ MemoryRegion iomem;
+ qemu_irq irq_rtc_int;
+ qemu_irq irq_addr_error_int;
+
+ uint32_t tick_offset;
+
+ uint32_t regs[XLNX_ZYNQMP_RTC_R_MAX];
+ RegisterInfo regs_info[XLNX_ZYNQMP_RTC_R_MAX];
+};
+
+#endif
diff --git a/include/hw/rx/rx62n.h b/include/hw/rx/rx62n.h
new file mode 100644
index 000000000..3ed80dba0
--- /dev/null
+++ b/include/hw/rx/rx62n.h
@@ -0,0 +1,79 @@
+/*
+ * RX62N MCU Object
+ *
+ * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware
+ * (Rev.1.40 R01UH0033EJ0140)
+ *
+ * Copyright (c) 2019 Yoshinori Sato
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * 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_RX_RX62N_MCU_H
+#define HW_RX_RX62N_MCU_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"
+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"
+
+#define EXT_CS_BASE 0x01000000
+#define VECTOR_TABLE_BASE 0xffffff80
+#define RX62N_CFLASH_BASE 0xfff80000
+
+#define RX62N_NR_TMR 2
+#define RX62N_NR_CMT 2
+#define RX62N_NR_SCI 6
+
+struct RX62NState {
+ /*< private >*/
+ DeviceState parent_obj;
+ /*< public >*/
+
+ RXCPU cpu;
+ RXICUState icu;
+ RTMRState tmr[RX62N_NR_TMR];
+ RCMTState cmt[RX62N_NR_CMT];
+ RSCIState sci[RX62N_NR_SCI];
+
+ MemoryRegion *sysmem;
+ bool kernel;
+
+ MemoryRegion iram;
+ MemoryRegion iomem1;
+ MemoryRegion d_flash;
+ 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;
+};
+
+#endif
diff --git a/include/hw/s390x/3270-ccw.h b/include/hw/s390x/3270-ccw.h
new file mode 100644
index 000000000..143988229
--- /dev/null
+++ b/include/hw/s390x/3270-ccw.h
@@ -0,0 +1,48 @@
+/*
+ * Emulated ccw-attached 3270 definitions
+ *
+ * Copyright 2017 IBM Corp.
+ * Author(s): Yang Chen <bjcyang@linux.vnet.ibm.com>
+ * Jing Liu <liujbjl@linux.vnet.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_S390X_3270_CCW_H
+#define HW_S390X_3270_CCW_H
+
+#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
+
+#define TYPE_EMULATED_CCW_3270 "emulated-ccw-3270"
+
+/* Local Channel Commands */
+#define TC_WRITE 0x01 /* Write */
+#define TC_RDBUF 0x02 /* Read buffer */
+#define TC_EWRITE 0x05 /* Erase write */
+#define TC_READMOD 0x06 /* Read modified */
+#define TC_EWRITEA 0x0d /* Erase write alternate */
+#define TC_WRITESF 0x11 /* Write structured field */
+
+OBJECT_DECLARE_TYPE(EmulatedCcw3270Device, EmulatedCcw3270Class, EMULATED_CCW_3270)
+
+struct EmulatedCcw3270Device {
+ CcwDevice parent_obj;
+};
+
+struct EmulatedCcw3270Class {
+ CCWDeviceClass parent_class;
+
+ void (*init)(EmulatedCcw3270Device *, Error **);
+ int (*read_payload_3270)(EmulatedCcw3270Device *);
+ int (*write_payload_3270)(EmulatedCcw3270Device *, uint8_t);
+};
+
+#endif
diff --git a/include/hw/s390x/adapter.h b/include/hw/s390x/adapter.h
new file mode 100644
index 000000000..7f1703508
--- /dev/null
+++ b/include/hw/s390x/adapter.h
@@ -0,0 +1,23 @@
+/*
+ * s390 adapter definitions
+ *
+ * Copyright 2013,2014 IBM Corp.
+ * Author(s): Cornelia Huck <cornelia.huck@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 S390X_ADAPTER_H
+#define S390X_ADAPTER_H
+
+struct AdapterInfo {
+ uint64_t ind_addr;
+ uint64_t summary_addr;
+ uint64_t ind_offset;
+ uint32_t summary_offset;
+ uint32_t adapter_id;
+};
+
+#endif
diff --git a/include/hw/s390x/ap-bridge.h b/include/hw/s390x/ap-bridge.h
new file mode 100644
index 000000000..470e439a9
--- /dev/null
+++ b/include/hw/s390x/ap-bridge.h
@@ -0,0 +1,19 @@
+/*
+ * ap bridge
+ *
+ * Copyright 2018 IBM Corp.
+ *
+ * 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_S390X_AP_BRIDGE_H
+#define HW_S390X_AP_BRIDGE_H
+
+#define TYPE_AP_BRIDGE "ap-bridge"
+#define TYPE_AP_BUS "ap-bus"
+
+void s390_init_ap(void);
+
+#endif
diff --git a/include/hw/s390x/ap-device.h b/include/hw/s390x/ap-device.h
new file mode 100644
index 000000000..e502745de
--- /dev/null
+++ b/include/hw/s390x/ap-device.h
@@ -0,0 +1,27 @@
+/*
+ * Adjunct Processor (AP) matrix device interfaces
+ *
+ * Copyright 2018 IBM Corp.
+ *
+ * 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_S390X_AP_DEVICE_H
+#define HW_S390X_AP_DEVICE_H
+
+#include "hw/qdev-core.h"
+#include "qom/object.h"
+
+#define TYPE_AP_DEVICE "ap-device"
+
+struct APDevice {
+ DeviceState parent_obj;
+};
+typedef struct APDevice APDevice;
+
+DECLARE_INSTANCE_CHECKER(APDevice, AP_DEVICE,
+ TYPE_AP_DEVICE)
+
+#endif /* HW_S390X_AP_DEVICE_H */
diff --git a/include/hw/s390x/css-bridge.h b/include/hw/s390x/css-bridge.h
new file mode 100644
index 000000000..deb606d71
--- /dev/null
+++ b/include/hw/s390x/css-bridge.h
@@ -0,0 +1,37 @@
+/*
+ * virtual css bridge definition
+ *
+ * Copyright 2012,2016 IBM Corp.
+ * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
+ * Pierre Morel <pmorel@linux.vnet.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_S390X_CSS_BRIDGE_H
+#define HW_S390X_CSS_BRIDGE_H
+
+#include "qom/object.h"
+#include "hw/sysbus.h"
+
+/* virtual css bridge */
+struct VirtualCssBridge {
+ SysBusDevice sysbus_dev;
+ bool css_dev_path;
+};
+
+#define TYPE_VIRTUAL_CSS_BRIDGE "virtual-css-bridge"
+OBJECT_DECLARE_SIMPLE_TYPE(VirtualCssBridge, VIRTUAL_CSS_BRIDGE)
+
+/* virtual css bus type */
+struct VirtualCssBus {
+ BusState parent_obj;
+};
+
+#define TYPE_VIRTUAL_CSS_BUS "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
new file mode 100644
index 000000000..75e538161
--- /dev/null
+++ b/include/hw/s390x/css.h
@@ -0,0 +1,336 @@
+/*
+ * Channel subsystem structures and definitions.
+ *
+ * Copyright 2012 IBM Corp.
+ * Author(s): Cornelia Huck <cornelia.huck@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 CSS_H
+#define CSS_H
+
+#include "hw/s390x/adapter.h"
+#include "hw/s390x/s390_flic.h"
+#include "hw/s390x/ioinst.h"
+#include "sysemu/kvm.h"
+#include "target/s390x/cpu-qom.h"
+
+/* Channel subsystem constants. */
+#define MAX_DEVNO 65535
+#define MAX_SCHID 65535
+#define MAX_SSID 3
+#define MAX_CSSID 255
+#define MAX_CHPID 255
+
+#define MAX_ISC 7
+
+#define MAX_CIWS 62
+
+#define VIRTUAL_CSSID 0xfe
+#define VIRTIO_CCW_CHPID 0 /* used by convention */
+
+typedef struct CIW {
+ uint8_t type;
+ uint8_t command;
+ uint16_t count;
+} QEMU_PACKED CIW;
+
+typedef struct SenseId {
+ /* common part */
+ uint8_t reserved; /* always 0x'FF' */
+ uint16_t cu_type; /* control unit type */
+ uint8_t cu_model; /* control unit model */
+ uint16_t dev_type; /* device type */
+ uint8_t dev_model; /* device model */
+ uint8_t unused; /* padding byte */
+ /* extended part */
+ CIW ciw[MAX_CIWS]; /* variable # of CIWs */
+} SenseId; /* Note: No QEMU_PACKED due to unaligned members */
+
+/* Channel measurements, from linux/drivers/s390/cio/cmf.c. */
+typedef struct CMB {
+ uint16_t ssch_rsch_count;
+ uint16_t sample_count;
+ uint32_t device_connect_time;
+ uint32_t function_pending_time;
+ uint32_t device_disconnect_time;
+ uint32_t control_unit_queuing_time;
+ uint32_t device_active_only_time;
+ uint32_t reserved[2];
+} QEMU_PACKED CMB;
+
+typedef struct CMBE {
+ uint32_t ssch_rsch_count;
+ uint32_t sample_count;
+ uint32_t device_connect_time;
+ uint32_t function_pending_time;
+ uint32_t device_disconnect_time;
+ uint32_t control_unit_queuing_time;
+ uint32_t device_active_only_time;
+ uint32_t device_busy_time;
+ uint32_t initial_command_response_time;
+ uint32_t reserved[7];
+} QEMU_PACKED CMBE;
+
+typedef enum CcwDataStreamOp {
+ CDS_OP_R = 0, /* read, false when used as is_write */
+ CDS_OP_W = 1, /* write, true when used as is_write */
+ CDS_OP_A = 2 /* advance, should not be used as is_write */
+} CcwDataStreamOp;
+
+/* normal usage is via SuchchDev.cds instead of instantiating */
+typedef struct CcwDataStream {
+#define CDS_F_IDA 0x01
+#define CDS_F_MIDA 0x02
+#define CDS_F_I2K 0x04
+#define CDS_F_C64 0x08
+#define CDS_F_FMT 0x10 /* CCW format-1 */
+#define CDS_F_STREAM_BROKEN 0x80
+ uint8_t flags;
+ uint8_t at_idaw;
+ uint16_t at_byte;
+ uint16_t count;
+ uint32_t cda_orig;
+ int (*op_handler)(struct CcwDataStream *cds, void *buff, int len,
+ CcwDataStreamOp op);
+ hwaddr cda;
+ bool do_skip;
+} CcwDataStream;
+
+/*
+ * IO instructions conclude according to this. Currently we have only
+ * cc codes. Valid values are 0, 1, 2, 3 and the generic semantic for
+ * IO instructions is described briefly. For more details consult the PoP.
+ */
+typedef enum IOInstEnding {
+ /* produced expected result */
+ IOINST_CC_EXPECTED = 0,
+ /* status conditions were present or produced alternate result */
+ IOINST_CC_STATUS_PRESENT = 1,
+ /* inst. ineffective because busy with previously initiated function */
+ IOINST_CC_BUSY = 2,
+ /* inst. ineffective because not operational */
+ IOINST_CC_NOT_OPERATIONAL = 3
+} IOInstEnding;
+
+typedef struct SubchDev SubchDev;
+struct SubchDev {
+ /* channel-subsystem related things: */
+ SCHIB curr_status; /* Needs alignment and thus must come first */
+ ORB orb;
+ uint8_t cssid;
+ uint8_t ssid;
+ uint16_t schid;
+ uint16_t devno;
+ uint8_t sense_data[32];
+ hwaddr channel_prog;
+ CCW1 last_cmd;
+ bool last_cmd_valid;
+ bool ccw_fmt_1;
+ bool thinint_active;
+ uint8_t ccw_no_data_cnt;
+ 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_DEVICE_ACTIVE |
+ SCSW_ACTL_SUBCH_ACTIVE);
+ sch->curr_status.scsw.ctrl |= SCSW_STCTL_PRIMARY |
+ SCSW_STCTL_SECONDARY |
+ SCSW_STCTL_ALERT |
+ SCSW_STCTL_STATUS_PEND;
+ sch->curr_status.scsw.cpa = sch->channel_prog + 8;
+ sch->curr_status.scsw.dstat = SCSW_DSTAT_UNIT_EXCEP;
+}
+
+extern const VMStateDescription vmstate_subch_dev;
+
+/*
+ * Identify a device within the channel subsystem.
+ * Note that this can be used to identify either the subchannel or
+ * the attached I/O device, as there's always one I/O device per
+ * subchannel.
+ */
+typedef struct CssDevId {
+ uint8_t cssid;
+ uint8_t ssid;
+ uint16_t devid;
+ bool valid;
+} CssDevId;
+
+extern const PropertyInfo css_devid_propinfo;
+
+#define DEFINE_PROP_CSS_DEV_ID(_n, _s, _f) \
+ DEFINE_PROP(_n, _s, _f, css_devid_propinfo, CssDevId)
+
+typedef struct IndAddr {
+ hwaddr addr;
+ uint64_t map;
+ unsigned long refcnt;
+ int32_t len;
+ QTAILQ_ENTRY(IndAddr) sibling;
+} IndAddr;
+
+extern const VMStateDescription vmstate_ind_addr;
+
+#define VMSTATE_PTR_TO_IND_ADDR(_f, _s) \
+ VMSTATE_STRUCT(_f, _s, 1, vmstate_ind_addr, IndAddr*)
+
+IndAddr *get_indicator(hwaddr ind_addr, int len);
+void release_indicator(AdapterInfo *adapter, IndAddr *indicator);
+int map_indicator(AdapterInfo *adapter, IndAddr *indicator);
+
+typedef SubchDev *(*css_subch_cb_func)(uint8_t m, uint8_t cssid, uint8_t ssid,
+ uint16_t schid);
+int css_create_css_image(uint8_t cssid, bool default_image);
+bool css_devno_used(uint8_t cssid, uint8_t ssid, uint16_t devno);
+void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid,
+ uint16_t devno, SubchDev *sch);
+void css_sch_build_virtual_schib(SubchDev *sch, uint8_t chpid, uint8_t type);
+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);
+void css_crw_add_to_queue(CRW crw);
+void css_queue_crw(uint8_t rsc, uint8_t erc, int solicited,
+ int chain, uint16_t rsid);
+void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid,
+ int hotplugged, int add);
+void css_generate_chp_crws(uint8_t cssid, uint8_t chpid);
+void css_generate_css_crws(uint8_t cssid);
+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);
+IOInstEnding s390_ccw_store(SubchDev *sch);
+
+typedef enum {
+ CSS_IO_ADAPTER_VIRTIO = 0,
+ CSS_IO_ADAPTER_PCI = 1,
+ CSS_IO_ADAPTER_TYPE_NUMS,
+} CssIoAdapterType;
+
+void css_adapter_interrupt(CssIoAdapterType type, uint8_t isc);
+int css_do_sic(CPUS390XState *env, 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_USER_ONLY
+SubchDev *css_find_subch(uint8_t m, uint8_t cssid, uint8_t ssid,
+ uint16_t schid);
+bool css_subch_visible(SubchDev *sch);
+void css_conditional_io_interrupt(SubchDev *sch);
+IOInstEnding css_do_stsch(SubchDev *sch, SCHIB *schib);
+bool css_schid_final(int m, uint8_t cssid, uint8_t ssid, uint16_t schid);
+IOInstEnding css_do_msch(SubchDev *sch, const SCHIB *schib);
+IOInstEnding css_do_xsch(SubchDev *sch);
+IOInstEnding css_do_csch(SubchDev *sch);
+IOInstEnding css_do_hsch(SubchDev *sch);
+IOInstEnding css_do_ssch(SubchDev *sch, ORB *orb);
+int css_do_tsch_get_irb(SubchDev *sch, IRB *irb, int *irb_len);
+void css_do_tsch_update_subch(SubchDev *sch);
+int css_do_stcrw(CRW *crw);
+void css_undo_stcrw(CRW *crw);
+int css_collect_chp_desc(int m, uint8_t cssid, uint8_t f_chpid, uint8_t l_chpid,
+ int rfmt, void *buf);
+void css_do_schm(uint8_t mbk, int update, int dct, uint64_t mbo);
+int css_enable_mcsse(void);
+int css_enable_mss(void);
+IOInstEnding css_do_rsch(SubchDev *sch);
+int css_do_rchp(uint8_t cssid, uint8_t chpid);
+bool css_present(uint8_t cssid);
+#endif
+
+extern const PropertyInfo css_devid_ro_propinfo;
+
+#define DEFINE_PROP_CSS_DEV_ID_RO(_n, _s, _f) \
+ DEFINE_PROP(_n, _s, _f, css_devid_ro_propinfo, CssDevId)
+
+/**
+ * Create a subchannel for the given bus id.
+ *
+ * If @p bus_id is valid, verify that it is not already in use, and find a
+ * free devno for it.
+ * If @p bus_id is not valid find a free subchannel id and device number
+ * across all subchannel sets and all css images starting from the default
+ * css image.
+ *
+ * If either of the former actions succeed, allocate a subchannel structure,
+ * initialise it with the bus id, subchannel id and device number, register
+ * it with the CSS and return it. Otherwise return NULL.
+ *
+ * The caller becomes owner of the returned subchannel structure and
+ * is responsible for unregistering and freeing it.
+ */
+SubchDev *css_create_sch(CssDevId bus_id, Error **errp);
+
+/** Turn on css migration */
+void css_register_vmstate(void);
+
+
+void ccw_dstream_init(CcwDataStream *cds, CCW1 const *ccw, ORB const *orb);
+
+static inline void ccw_dstream_rewind(CcwDataStream *cds)
+{
+ cds->at_byte = 0;
+ cds->at_idaw = 0;
+ cds->cda = cds->cda_orig;
+}
+
+static inline bool ccw_dstream_good(CcwDataStream *cds)
+{
+ return !(cds->flags & CDS_F_STREAM_BROKEN);
+}
+
+static inline uint16_t ccw_dstream_residual_count(CcwDataStream *cds)
+{
+ return cds->count - cds->at_byte;
+}
+
+static inline uint16_t ccw_dstream_avail(CcwDataStream *cds)
+{
+ return ccw_dstream_good(cds) ? ccw_dstream_residual_count(cds) : 0;
+}
+
+static inline int ccw_dstream_advance(CcwDataStream *cds, int len)
+{
+ return cds->op_handler(cds, NULL, len, CDS_OP_A);
+}
+
+static inline int ccw_dstream_write_buf(CcwDataStream *cds, void *buff, int len)
+{
+ return cds->op_handler(cds, buff, len, CDS_OP_W);
+}
+
+static inline int ccw_dstream_read_buf(CcwDataStream *cds, void *buff, int len)
+{
+ return cds->op_handler(cds, buff, len, CDS_OP_R);
+}
+
+#define ccw_dstream_read(cds, v) ccw_dstream_read_buf((cds), &(v), sizeof(v))
+#define ccw_dstream_write(cds, v) ccw_dstream_write_buf((cds), &(v), sizeof(v))
+
+#endif
diff --git a/include/hw/s390x/ebcdic.h b/include/hw/s390x/ebcdic.h
new file mode 100644
index 000000000..69a04cab6
--- /dev/null
+++ b/include/hw/s390x/ebcdic.h
@@ -0,0 +1,104 @@
+/*
+ * EBCDIC/ASCII conversion Support
+ *
+ * Copyright (c) 2011 Alexander Graf
+ * Copyright IBM, Corp. 2013
+ *
+ * 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 EBCDIC_H
+#define EBCDIC_H
+
+/* EBCDIC handling */
+static const uint8_t ebcdic2ascii[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
+ 0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07,
+ 0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07,
+ 0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
+ 0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
+ 0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
+ 0x87, 0xA4, 0x5B, 0x2E, 0x3C, 0x28, 0x2B, 0x21,
+ 0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
+ 0x8D, 0xE1, 0x5D, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
+ 0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F,
+ 0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
+ 0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
+ 0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
+ 0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+ 0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
+ 0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
+ 0x9B, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
+ 0xAB, 0x07, 0xAA, 0x7C, 0x07, 0x07, 0x07, 0x07,
+ 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
+ 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
+ 0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
+ 0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07,
+};
+
+static const uint8_t ascii2ebcdic[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
+ 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,
+ 0x18, 0x19, 0x3F, 0x27, 0x22, 0x1D, 0x1E, 0x1F,
+ 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
+ 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
+ 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+ 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
+ 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
+ 0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D,
+ 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x59, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x90, 0x3F, 0x3F, 0x3F, 0x3F, 0xEA, 0x3F, 0xFF
+};
+
+static inline void ebcdic_put(uint8_t *p, const char *ascii, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ p[i] = ascii2ebcdic[(uint8_t)ascii[i]];
+ }
+}
+
+static inline void ascii_put(uint8_t *p, const char *ebcdic, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ p[i] = ebcdic2ascii[(uint8_t)ebcdic[i]];
+ }
+}
+
+#endif /* EBCDIC_H */
diff --git a/include/hw/s390x/event-facility.h b/include/hw/s390x/event-facility.h
new file mode 100644
index 000000000..3ffd575d8
--- /dev/null
+++ b/include/hw/s390x/event-facility.h
@@ -0,0 +1,208 @@
+/*
+ * SCLP
+ * Event Facility definitions
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ * Heinz Graalfs <graalfs@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_SCLP_EVENT_FACILITY_H
+#define HW_S390_SCLP_EVENT_FACILITY_H
+
+#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
+#define SCLP_EVENT_MESSAGE 0x02
+#define SCLP_EVENT_CONFIG_MGT_DATA 0x04
+#define SCLP_EVENT_PMSGCMD 0x09
+#define SCLP_EVENT_ASCII_CONSOLE_DATA 0x1a
+#define SCLP_EVENT_SIGNAL_QUIESCE 0x1d
+
+/* SCLP event masks */
+#define SCLP_EVMASK(T) (1ULL << (sizeof(sccb_mask_t) * 8 - (T)))
+
+#define SCLP_EVENT_MASK_OP_CMD SCLP_EVMASK(SCLP_EVENT_OPRTNS_COMMAND)
+#define SCLP_EVENT_MASK_MSG SCLP_EVMASK(SCLP_EVENT_MESSAGE)
+#define SCLP_EVENT_MASK_CONFIG_MGT_DATA SCLP_EVMASK(SCLP_EVENT_CONFIG_MGT_DATA)
+#define SCLP_EVENT_MASK_PMSGCMD SCLP_EVMASK(SCLP_EVENT_PMSGCMD)
+#define SCLP_EVENT_MASK_MSG_ASCII SCLP_EVMASK(SCLP_EVENT_ASCII_CONSOLE_DATA)
+#define SCLP_EVENT_MASK_SIGNAL_QUIESCE SCLP_EVMASK(SCLP_EVENT_SIGNAL_QUIESCE)
+
+#define SCLP_UNCONDITIONAL_READ 0x00
+#define SCLP_SELECTIVE_READ 0x01
+
+#define TYPE_SCLP_EVENT "s390-sclp-event-type"
+OBJECT_DECLARE_TYPE(SCLPEvent, SCLPEventClass,
+ SCLP_EVENT)
+
+#define TYPE_SCLP_CPU_HOTPLUG "sclp-cpu-hotplug"
+#define TYPE_SCLP_QUIESCE "sclpquiesce"
+
+#define SCLP_EVENT_MASK_LEN_MAX 1021
+
+typedef struct WriteEventMask {
+ SCCBHeader h;
+ uint16_t _reserved;
+ uint16_t mask_length;
+ uint8_t masks[];
+/*
+ * Layout of the masks is
+ * uint8_t cp_receive_mask[mask_length];
+ * uint8_t cp_send_mask[mask_length];
+ * uint8_t receive_mask[mask_length];
+ * uint8_t send_mask[mask_length];
+ * where 1 <= mask_length <= SCLP_EVENT_MASK_LEN_MAX
+ */
+} QEMU_PACKED WriteEventMask;
+
+#define WEM_CP_RECEIVE_MASK(wem, mask_len) ((wem)->masks)
+#define WEM_CP_SEND_MASK(wem, mask_len) ((wem)->masks + (mask_len))
+#define WEM_RECEIVE_MASK(wem, mask_len) ((wem)->masks + 2 * (mask_len))
+#define WEM_SEND_MASK(wem, mask_len) ((wem)->masks + 3 * (mask_len))
+
+typedef uint64_t sccb_mask_t;
+
+typedef struct EventBufferHeader {
+ uint16_t length;
+ uint8_t type;
+ uint8_t flags;
+ uint16_t _reserved;
+} QEMU_PACKED EventBufferHeader;
+
+typedef struct MdbHeader {
+ uint16_t length;
+ uint16_t type;
+ uint32_t tag;
+ uint32_t revision_code;
+} QEMU_PACKED MdbHeader;
+
+typedef struct MTO {
+ uint16_t line_type_flags;
+ uint8_t alarm_control;
+ uint8_t _reserved[3];
+ char message[];
+} QEMU_PACKED MTO;
+
+typedef struct GO {
+ uint32_t domid;
+ uint8_t hhmmss_time[8];
+ uint8_t th_time[3];
+ uint8_t _reserved_0;
+ uint8_t dddyyyy_date[7];
+ uint8_t _reserved_1;
+ uint16_t general_msg_flags;
+ uint8_t _reserved_2[10];
+ uint8_t originating_system_name[8];
+ uint8_t job_guest_name[8];
+} QEMU_PACKED GO;
+
+#define MESSAGE_TEXT 0x0004
+
+typedef struct MDBO {
+ uint16_t length;
+ uint16_t type;
+ union {
+ GO go;
+ MTO mto;
+ };
+} QEMU_PACKED MDBO;
+
+typedef struct MDB {
+ MdbHeader header;
+ MDBO mdbo[];
+} QEMU_PACKED MDB;
+
+typedef struct SclpMsg {
+ EventBufferHeader header;
+ MDB mdb;
+} QEMU_PACKED SclpMsg;
+
+#define GDS_ID_MDSMU 0x1310
+#define GDS_ID_CPMSU 0x1212
+#define GDS_ID_TEXTCMD 0x1320
+
+typedef struct GdsVector {
+ uint16_t length;
+ uint16_t gds_id;
+} QEMU_PACKED GdsVector;
+
+#define GDS_KEY_SELFDEFTEXTMSG 0x31
+#define GDS_KEY_TEXTMSG 0x30
+
+typedef struct GdsSubvector {
+ uint8_t length;
+ uint8_t key;
+} QEMU_PACKED GdsSubvector;
+
+/* MDS Message Unit */
+typedef struct MDMSU {
+ GdsVector mdmsu;
+ GdsVector cpmsu;
+ GdsVector text_command;
+ GdsSubvector self_def_text_message;
+ GdsSubvector text_message;
+} QEMU_PACKED MDMSU;
+
+typedef struct WriteEventData {
+ SCCBHeader h;
+ EventBufferHeader ebh;
+} QEMU_PACKED WriteEventData;
+
+typedef struct ReadEventData {
+ SCCBHeader h;
+ union {
+ sccb_mask_t mask;
+ EventBufferHeader ebh;
+ };
+} QEMU_PACKED ReadEventData;
+
+struct SCLPEvent {
+ DeviceState qdev;
+ bool event_pending;
+ char *name;
+};
+
+struct SCLPEventClass {
+ DeviceClass parent_class;
+ int (*init)(SCLPEvent *event);
+
+ /* get SCLP's send mask */
+ sccb_mask_t (*get_send_mask)(void);
+
+ /* get SCLP's receive mask */
+ sccb_mask_t (*get_receive_mask)(void);
+
+ int (*read_event_data)(SCLPEvent *event, EventBufferHeader *evt_buf_hdr,
+ int *slen);
+
+ int (*write_event_data)(SCLPEvent *event, EventBufferHeader *evt_buf_hdr);
+
+ /* can we handle this event type? */
+ bool (*can_handle_event)(uint8_t type);
+};
+
+#define TYPE_SCLP_EVENT_FACILITY "s390-sclp-event-facility"
+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);
+};
+
+BusState *sclp_get_event_facility_bus(void);
+
+#endif
diff --git a/include/hw/s390x/ioinst.h b/include/hw/s390x/ioinst.h
new file mode 100644
index 000000000..3771fff9d
--- /dev/null
+++ b/include/hw/s390x/ioinst.h
@@ -0,0 +1,258 @@
+/*
+ * S/390 channel I/O instructions
+ *
+ * Copyright 2012 IBM Corp.
+ * Author(s): Cornelia Huck <cornelia.huck@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 S390X_IOINST_H
+#define S390X_IOINST_H
+
+/*
+ * Channel I/O related definitions, as defined in the Principles
+ * Of Operation (and taken from the Linux implementation).
+ */
+
+/* subchannel status word (command mode only) */
+typedef struct SCSW {
+ uint16_t flags;
+ uint16_t ctrl;
+ uint32_t cpa;
+ uint8_t dstat;
+ uint8_t cstat;
+ uint16_t count;
+} SCSW;
+QEMU_BUILD_BUG_MSG(sizeof(SCSW) != 12, "size of SCSW is wrong");
+
+#define SCSW_FLAGS_MASK_KEY 0xf000
+#define SCSW_FLAGS_MASK_SCTL 0x0800
+#define SCSW_FLAGS_MASK_ESWF 0x0400
+#define SCSW_FLAGS_MASK_CC 0x0300
+#define SCSW_FLAGS_MASK_FMT 0x0080
+#define SCSW_FLAGS_MASK_PFCH 0x0040
+#define SCSW_FLAGS_MASK_ISIC 0x0020
+#define SCSW_FLAGS_MASK_ALCC 0x0010
+#define SCSW_FLAGS_MASK_SSI 0x0008
+#define SCSW_FLAGS_MASK_ZCC 0x0004
+#define SCSW_FLAGS_MASK_ECTL 0x0002
+#define SCSW_FLAGS_MASK_PNO 0x0001
+
+#define SCSW_CTRL_MASK_FCTL 0x7000
+#define SCSW_CTRL_MASK_ACTL 0x0fe0
+#define SCSW_CTRL_MASK_STCTL 0x001f
+
+#define SCSW_FCTL_CLEAR_FUNC 0x1000
+#define SCSW_FCTL_HALT_FUNC 0x2000
+#define SCSW_FCTL_START_FUNC 0x4000
+
+#define SCSW_ACTL_SUSP 0x0020
+#define SCSW_ACTL_DEVICE_ACTIVE 0x0040
+#define SCSW_ACTL_SUBCH_ACTIVE 0x0080
+#define SCSW_ACTL_CLEAR_PEND 0x0100
+#define SCSW_ACTL_HALT_PEND 0x0200
+#define SCSW_ACTL_START_PEND 0x0400
+#define SCSW_ACTL_RESUME_PEND 0x0800
+
+#define SCSW_STCTL_STATUS_PEND 0x0001
+#define SCSW_STCTL_SECONDARY 0x0002
+#define SCSW_STCTL_PRIMARY 0x0004
+#define SCSW_STCTL_INTERMEDIATE 0x0008
+#define SCSW_STCTL_ALERT 0x0010
+
+#define SCSW_DSTAT_ATTENTION 0x80
+#define SCSW_DSTAT_STAT_MOD 0x40
+#define SCSW_DSTAT_CU_END 0x20
+#define SCSW_DSTAT_BUSY 0x10
+#define SCSW_DSTAT_CHANNEL_END 0x08
+#define SCSW_DSTAT_DEVICE_END 0x04
+#define SCSW_DSTAT_UNIT_CHECK 0x02
+#define SCSW_DSTAT_UNIT_EXCEP 0x01
+
+#define SCSW_CSTAT_PCI 0x80
+#define SCSW_CSTAT_INCORR_LEN 0x40
+#define SCSW_CSTAT_PROG_CHECK 0x20
+#define SCSW_CSTAT_PROT_CHECK 0x10
+#define SCSW_CSTAT_DATA_CHECK 0x08
+#define SCSW_CSTAT_CHN_CTRL_CHK 0x04
+#define SCSW_CSTAT_INTF_CTRL_CHK 0x02
+#define SCSW_CSTAT_CHAIN_CHECK 0x01
+
+/* path management control word */
+typedef struct PMCW {
+ uint32_t intparm;
+ uint16_t flags;
+ uint16_t devno;
+ uint8_t lpm;
+ uint8_t pnom;
+ uint8_t lpum;
+ uint8_t pim;
+ uint16_t mbi;
+ uint8_t pom;
+ uint8_t pam;
+ uint8_t chpid[8];
+ uint32_t chars;
+} PMCW;
+QEMU_BUILD_BUG_MSG(sizeof(PMCW) != 28, "size of PMCW is wrong");
+
+#define PMCW_FLAGS_MASK_QF 0x8000
+#define PMCW_FLAGS_MASK_W 0x4000
+#define PMCW_FLAGS_MASK_ISC 0x3800
+#define PMCW_FLAGS_MASK_ENA 0x0080
+#define PMCW_FLAGS_MASK_LM 0x0060
+#define PMCW_FLAGS_MASK_MME 0x0018
+#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_CHARS_MASK_ST 0x00e00000
+#define PMCW_CHARS_MASK_MBFC 0x00000004
+#define PMCW_CHARS_MASK_XMWME 0x00000002
+#define PMCW_CHARS_MASK_CSENSE 0x00000001
+#define PMCW_CHARS_MASK_INVALID 0xff1ffff8
+
+/* subchannel information block */
+typedef struct SCHIB {
+ PMCW pmcw;
+ SCSW scsw;
+ uint64_t mba;
+ 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;
+ ESW esw;
+ uint32_t ecw[8];
+ uint32_t emw[8];
+} IRB;
+QEMU_BUILD_BUG_MSG(sizeof(IRB) != 96, "size of IRB is wrong");
+
+/* operation request block */
+typedef struct ORB {
+ uint32_t intparm;
+ uint16_t ctrl0;
+ uint8_t lpm;
+ uint8_t ctrl1;
+ uint32_t cpa;
+} ORB;
+QEMU_BUILD_BUG_MSG(sizeof(ORB) != 12, "size of ORB is wrong");
+
+#define ORB_CTRL0_MASK_KEY 0xf000
+#define ORB_CTRL0_MASK_SPND 0x0800
+#define ORB_CTRL0_MASK_STR 0x0400
+#define ORB_CTRL0_MASK_MOD 0x0200
+#define ORB_CTRL0_MASK_SYNC 0x0100
+#define ORB_CTRL0_MASK_FMT 0x0080
+#define ORB_CTRL0_MASK_PFCH 0x0040
+#define ORB_CTRL0_MASK_ISIC 0x0020
+#define ORB_CTRL0_MASK_ALCC 0x0010
+#define ORB_CTRL0_MASK_SSIC 0x0008
+#define ORB_CTRL0_MASK_C64 0x0002
+#define ORB_CTRL0_MASK_I2K 0x0001
+#define ORB_CTRL0_MASK_INVALID 0x0004
+
+#define ORB_CTRL1_MASK_ILS 0x80
+#define ORB_CTRL1_MASK_MIDAW 0x40
+#define ORB_CTRL1_MASK_ORBX 0x01
+#define ORB_CTRL1_MASK_INVALID 0x3e
+
+/* channel command word (type 0) */
+typedef struct CCW0 {
+ uint8_t cmd_code;
+ uint8_t cda0;
+ uint16_t cda1;
+ uint8_t flags;
+ uint8_t reserved;
+ uint16_t count;
+} CCW0;
+QEMU_BUILD_BUG_MSG(sizeof(CCW0) != 8, "size of CCW0 is wrong");
+
+/* channel command word (type 1) */
+typedef struct CCW1 {
+ uint8_t cmd_code;
+ uint8_t flags;
+ uint16_t count;
+ uint32_t cda;
+} CCW1;
+QEMU_BUILD_BUG_MSG(sizeof(CCW1) != 8, "size of CCW1 is wrong");
+
+#define CCW_FLAG_DC 0x80
+#define CCW_FLAG_CC 0x40
+#define CCW_FLAG_SLI 0x20
+#define CCW_FLAG_SKIP 0x10
+#define CCW_FLAG_PCI 0x08
+#define CCW_FLAG_IDA 0x04
+#define CCW_FLAG_SUSPEND 0x02
+#define CCW_FLAG_MIDA 0x01
+
+#define CCW_CMD_NOOP 0x03
+#define CCW_CMD_BASIC_SENSE 0x04
+#define CCW_CMD_TIC 0x08
+#define CCW_CMD_SENSE_ID 0xe4
+
+typedef struct CRW {
+ uint16_t flags;
+ uint16_t rsid;
+} CRW;
+QEMU_BUILD_BUG_MSG(sizeof(CRW) != 4, "size of CRW is wrong");
+
+#define CRW_FLAGS_MASK_S 0x4000
+#define CRW_FLAGS_MASK_R 0x2000
+#define CRW_FLAGS_MASK_C 0x1000
+#define CRW_FLAGS_MASK_RSC 0x0f00
+#define CRW_FLAGS_MASK_A 0x0080
+#define CRW_FLAGS_MASK_ERC 0x003f
+
+#define CRW_ERC_EVENT 0x00 /* event information pending */
+#define CRW_ERC_AVAIL 0x01 /* available */
+#define CRW_ERC_INIT 0x02 /* initialized */
+#define CRW_ERC_TERROR 0x03 /* temporary error */
+#define CRW_ERC_IPI 0x04 /* installed parm initialized */
+#define CRW_ERC_TERM 0x05 /* terminal */
+#define CRW_ERC_PERRN 0x06 /* perm. error, facility not init */
+#define CRW_ERC_PERRI 0x07 /* perm. error, facility init */
+#define CRW_ERC_PMOD 0x08 /* installed parameters modified */
+#define CRW_ERC_IPR 0x0A /* installed parameters restored */
+
+#define CRW_RSC_SUBCH 0x3
+#define CRW_RSC_CHP 0x4
+#define CRW_RSC_CSS 0xb
+
+/* I/O interruption code */
+typedef struct IOIntCode {
+ uint32_t subsys_id;
+ uint32_t intparm;
+ uint32_t interrupt_id;
+} QEMU_PACKED IOIntCode;
+
+/* schid disintegration */
+#define IOINST_SCHID_ONE(_schid) ((_schid & 0x00010000) >> 16)
+#define IOINST_SCHID_M(_schid) ((_schid & 0x00080000) >> 19)
+#define IOINST_SCHID_CSSID(_schid) ((_schid & 0xff000000) >> 24)
+#define IOINST_SCHID_SSID(_schid) ((_schid & 0x00060000) >> 17)
+#define IOINST_SCHID_NR(_schid) (_schid & 0x0000ffff)
+
+#define IO_INT_WORD_ISC(_int_word) ((_int_word & 0x38000000) >> 27)
+#define ISC_TO_ISC_BITS(_isc) ((0x80 >> _isc) << 24)
+
+#define IO_INT_WORD_AI 0x80000000
+
+int ioinst_disassemble_sch_ident(uint32_t value, int *m, int *cssid, int *ssid,
+ int *schid);
+
+#endif
diff --git a/include/hw/s390x/pv.h b/include/hw/s390x/pv.h
new file mode 100644
index 000000000..1f1f545bf
--- /dev/null
+++ b/include/hw/s390x/pv.h
@@ -0,0 +1,75 @@
+/*
+ * 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
+
+#include "qapi/error.h"
+#include "sysemu/kvm.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 */
+
+int s390_pv_kvm_init(ConfidentialGuestSupport *cgs, Error **errp);
+static inline int s390_pv_init(ConfidentialGuestSupport *cgs, Error **errp)
+{
+ if (!cgs) {
+ return 0;
+ }
+ if (kvm_enabled()) {
+ return s390_pv_kvm_init(cgs, errp);
+ }
+
+ error_setg(errp, "Protected Virtualization requires KVM");
+ return -1;
+}
+
+#endif /* HW_S390_PV_H */
diff --git a/include/hw/s390x/s390-ccw.h b/include/hw/s390x/s390-ccw.h
new file mode 100644
index 000000000..2c807ee3a
--- /dev/null
+++ b/include/hw/s390x/s390-ccw.h
@@ -0,0 +1,42 @@
+/*
+ * s390 CCW Assignment Support
+ *
+ * Copyright 2017 IBM Corp.
+ * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
+ * Xiao Feng Ren <renxiaof@linux.vnet.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_CCW_H
+#define HW_S390_CCW_H
+
+#include "hw/s390x/ccw-device.h"
+#include "qom/object.h"
+
+#define TYPE_S390_CCW "s390-ccw"
+typedef struct S390CCWDevice S390CCWDevice;
+typedef struct S390CCWDeviceClass S390CCWDeviceClass;
+DECLARE_OBJ_CHECKERS(S390CCWDevice, S390CCWDeviceClass,
+ S390_CCW_DEVICE, TYPE_S390_CCW)
+
+struct S390CCWDevice {
+ CcwDevice parent_obj;
+ CssDevId hostid;
+ char *mdevid;
+ int32_t bootindex;
+};
+
+struct S390CCWDeviceClass {
+ CCWDeviceClass parent_class;
+ void (*realize)(S390CCWDevice *dev, char *sysfsdev, Error **errp);
+ void (*unrealize)(S390CCWDevice *dev);
+ IOInstEnding (*handle_request) (SubchDev *sch);
+ int (*handle_halt) (SubchDev *sch);
+ int (*handle_clear) (SubchDev *sch);
+ IOInstEnding (*handle_store) (SubchDev *sch);
+};
+
+#endif
diff --git a/include/hw/s390x/s390-pci-bus.h b/include/hw/s390x/s390-pci-bus.h
new file mode 100644
index 000000000..aa891c178
--- /dev/null
+++ b/include/hw/s390x/s390-pci-bus.h
@@ -0,0 +1,391 @@
+/*
+ * 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
+
+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
+ * enbaled: 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;
+ 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 0x20
+typedef struct S390PCIGroup {
+ ClpRspQueryPciGrp zpci_group;
+ int id;
+ QTAILQ_ENTRY(S390PCIGroup) link;
+} S390PCIGroup;
+S390PCIGroup *s390_group_create(int id);
+S390PCIGroup *s390_group_find(int 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;
+ S390PCIGroup *pci_group;
+ ClpRspQueryPci zpci_fn;
+ S390MsixInfo msix;
+ AdapterRoutes routes;
+ S390PCIIOMMU *iommu;
+ MemoryRegion msix_notify_mr;
+ IndAddr *summary_ind;
+ IndAddr *indicator;
+ bool pci_unplug_request_processed;
+ bool unplug_requested;
+ 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;
+};
+
+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);
+
+#endif
diff --git a/include/hw/s390x/s390-pci-clp.h b/include/hw/s390x/s390-pci-clp.h
new file mode 100644
index 000000000..96b8e3f13
--- /dev/null
+++ b/include/hw/s390x/s390-pci-clp.h
@@ -0,0 +1,215 @@
+/*
+ * 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
+#define HW_S390_PCI_CLP
+
+/* 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;
+ uint64_t reserved3;
+ 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 000000000..a55c448aa
--- /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-vfio.h b/include/hw/s390x/s390-pci-vfio.h
new file mode 100644
index 000000000..ff708aef5
--- /dev/null
+++ b/include/hw/s390x/s390-pci-vfio.h
@@ -0,0 +1,39 @@
+/*
+ * 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);
+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 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
new file mode 100644
index 000000000..3331990e0
--- /dev/null
+++ b/include/hw/s390x/s390-virtio-ccw.h
@@ -0,0 +1,57 @@
+/*
+ * virtio ccw machine definitions
+ *
+ * Copyright 2012, 2016 IBM Corp.
+ * Author(s): Cornelia Huck <cornelia.huck@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_S390X_S390_VIRTIO_CCW_H
+#define HW_S390X_S390_VIRTIO_CCW_H
+
+#include "hw/boards.h"
+#include "qom/object.h"
+
+#define TYPE_S390_CCW_MACHINE "s390-ccw-machine"
+
+OBJECT_DECLARE_TYPE(S390CcwMachineState, S390CcwMachineClass, S390_CCW_MACHINE)
+
+
+struct S390CcwMachineState {
+ /*< private >*/
+ MachineState parent_obj;
+
+ /*< public >*/
+ bool aes_key_wrap;
+ bool dea_key_wrap;
+ bool pv;
+ uint8_t loadparm[8];
+};
+
+struct S390CcwMachineClass {
+ /*< private >*/
+ MachineClass parent_class;
+
+ /*< public >*/
+ bool ri_allowed;
+ bool cpu_model_allowed;
+ bool css_migration_enabled;
+ bool hpage_1m_allowed;
+};
+
+/* runtime-instrumentation allowed by the machine */
+bool ri_allowed(void);
+/* cpu model allowed by the machine */
+bool cpu_model_allowed(void);
+/* 1M huge page mappings allowed by the machine */
+bool hpage_1m_allowed(void);
+
+/**
+ * Returns true if (vmstate based) migration of the channel subsystem
+ * is enabled, false if it is disabled.
+ */
+bool css_migration_enabled(void);
+
+#endif
diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h
new file mode 100644
index 000000000..3907a13d0
--- /dev/null
+++ b/include/hw/s390x/s390_flic.h
@@ -0,0 +1,142 @@
+/*
+ * QEMU S390x floating interrupt controller (flic)
+ *
+ * Copyright 2014 IBM Corp.
+ * Author(s): Jens Freimann <jfrei@linux.vnet.ibm.com>
+ * Cornelia Huck <cornelia.huck@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_FLIC_H
+#define HW_S390_FLIC_H
+
+#include "hw/sysbus.h"
+#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.
+ * If any other user of adapter routes needs more of these,
+ * we need to bump the value; but virtio looks like the
+ * maximum right now.
+ */
+#define ADAPTER_ROUTES_MAX_GSI VIRTIO_QUEUE_MAX
+
+typedef struct AdapterRoutes {
+ AdapterInfo adapter;
+ int num_routes;
+ int gsi[ADAPTER_ROUTES_MAX_GSI];
+} AdapterRoutes;
+
+extern const VMStateDescription vmstate_adapter_routes;
+
+#define VMSTATE_ADAPTER_ROUTES(_f, _s) \
+ VMSTATE_STRUCT(_f, _s, 1, vmstate_adapter_routes, AdapterRoutes)
+
+#define TYPE_S390_FLIC_COMMON "s390-flic"
+OBJECT_DECLARE_TYPE(S390FLICState, S390FLICStateClass,
+ S390_FLIC_COMMON)
+
+struct S390FLICState {
+ SysBusDevice parent_obj;
+ /* to limit AdapterRoutes.num_routes for compat */
+ uint32_t adapter_routes_max_batch;
+ bool ais_supported;
+};
+
+
+struct S390FLICStateClass {
+ DeviceClass parent_class;
+
+ int (*register_io_adapter)(S390FLICState *fs, uint32_t id, uint8_t isc,
+ bool swap, bool maskable, uint8_t flags);
+ int (*io_adapter_map)(S390FLICState *fs, uint32_t id, uint64_t map_addr,
+ bool do_map);
+ int (*add_adapter_routes)(S390FLICState *fs, AdapterRoutes *routes);
+ void (*release_adapter_routes)(S390FLICState *fs, AdapterRoutes *routes);
+ int (*clear_io_irq)(S390FLICState *fs, uint16_t subchannel_id,
+ uint16_t subchannel_nr);
+ int (*modify_ais_mode)(S390FLICState *fs, uint8_t isc, uint16_t mode);
+ int (*inject_airq)(S390FLICState *fs, uint8_t type, uint8_t isc,
+ uint8_t flags);
+ void (*inject_service)(S390FLICState *fs, uint32_t parm);
+ void (*inject_io)(S390FLICState *fs, uint16_t subchannel_id,
+ uint16_t subchannel_nr, uint32_t io_int_parm,
+ uint32_t io_int_word);
+ void (*inject_crw_mchk)(S390FLICState *fs);
+};
+
+#define TYPE_KVM_S390_FLIC "s390-flic-kvm"
+typedef struct KVMS390FLICState KVMS390FLICState;
+DECLARE_INSTANCE_CHECKER(KVMS390FLICState, KVM_S390_FLIC,
+ TYPE_KVM_S390_FLIC)
+
+#define TYPE_QEMU_S390_FLIC "s390-flic-qemu"
+OBJECT_DECLARE_SIMPLE_TYPE(QEMUS390FLICState, QEMU_S390_FLIC)
+
+#define SIC_IRQ_MODE_ALL 0
+#define SIC_IRQ_MODE_SINGLE 1
+#define AIS_MODE_MASK(isc) (0x80 >> isc)
+
+#define ISC_TO_PENDING_IO(_isc) (0x80 >> (_isc))
+#define CR6_TO_PENDING_IO(_cr6) (((_cr6) >> 24) & 0xff)
+
+/* organize the ISC bits so that the macros above work */
+#define FLIC_PENDING_IO_ISC7 (1 << 0)
+#define FLIC_PENDING_IO_ISC6 (1 << 1)
+#define FLIC_PENDING_IO_ISC5 (1 << 2)
+#define FLIC_PENDING_IO_ISC4 (1 << 3)
+#define FLIC_PENDING_IO_ISC3 (1 << 4)
+#define FLIC_PENDING_IO_ISC2 (1 << 5)
+#define FLIC_PENDING_IO_ISC1 (1 << 6)
+#define FLIC_PENDING_IO_ISC0 (1 << 7)
+#define FLIC_PENDING_SERVICE (1 << 8)
+#define FLIC_PENDING_MCHK_CR (1 << 9)
+
+#define FLIC_PENDING_IO (FLIC_PENDING_IO_ISC0 | FLIC_PENDING_IO_ISC1 | \
+ FLIC_PENDING_IO_ISC2 | FLIC_PENDING_IO_ISC3 | \
+ FLIC_PENDING_IO_ISC4 | FLIC_PENDING_IO_ISC5 | \
+ FLIC_PENDING_IO_ISC6 | FLIC_PENDING_IO_ISC7)
+
+typedef struct QEMUS390FlicIO {
+ uint16_t id;
+ uint16_t nr;
+ uint32_t parm;
+ uint32_t word;
+ QLIST_ENTRY(QEMUS390FlicIO) next;
+} QEMUS390FlicIO;
+
+struct QEMUS390FLICState {
+ S390FLICState parent_obj;
+ uint32_t pending;
+ uint32_t service_param;
+ uint8_t simm;
+ uint8_t nimm;
+ QLIST_HEAD(, QEMUS390FlicIO) io[8];
+};
+
+uint32_t qemu_s390_flic_dequeue_service(QEMUS390FLICState *flic);
+QEMUS390FlicIO *qemu_s390_flic_dequeue_io(QEMUS390FLICState *flic,
+ uint64_t cr6);
+void qemu_s390_flic_dequeue_crw_mchk(QEMUS390FLICState *flic);
+bool qemu_s390_flic_has_service(QEMUS390FLICState *flic);
+bool qemu_s390_flic_has_io(QEMUS390FLICState *fs, uint64_t cr6);
+bool qemu_s390_flic_has_crw_mchk(QEMUS390FLICState *flic);
+bool qemu_s390_flic_has_any(QEMUS390FLICState *flic);
+
+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
new file mode 100644
index 000000000..d3ade40a5
--- /dev/null
+++ b/include/hw/s390x/sclp.h
@@ -0,0 +1,232 @@
+/*
+ * SCLP Support
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ * Christian Borntraeger <borntraeger@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_SCLP_H
+#define HW_S390_SCLP_H
+
+#include "hw/sysbus.h"
+#include "target/s390x/cpu-qom.h"
+#include "qom/object.h"
+
+#define SCLP_CMD_CODE_MASK 0xffff00ff
+
+/* SCLP command codes */
+#define SCLP_CMDW_READ_SCP_INFO 0x00020001
+#define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001
+#define SCLP_READ_STORAGE_ELEMENT_INFO 0x00040001
+#define SCLP_ATTACH_STORAGE_ELEMENT 0x00080001
+#define SCLP_ASSIGN_STORAGE 0x000D0001
+#define SCLP_UNASSIGN_STORAGE 0x000C0001
+#define SCLP_CMD_READ_EVENT_DATA 0x00770005
+#define SCLP_CMD_WRITE_EVENT_DATA 0x00760005
+#define SCLP_CMD_WRITE_EVENT_MASK 0x00780005
+
+/* SCLP Memory hotplug codes */
+#define SCLP_FC_ASSIGN_ATTACH_READ_STOR 0xE00000000000ULL
+#define SCLP_STARTING_SUBINCREMENT_ID 0x10001
+#define SCLP_INCREMENT_UNIT 0x10000
+#define MAX_STORAGE_INCREMENTS 1020
+
+/* CPU hotplug SCLP codes */
+#define SCLP_HAS_CPU_INFO 0x0C00000000000000ULL
+#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
+#define SCLP_CMDW_CONFIGURE_IOA 0x001a0001
+#define SCLP_CMDW_DECONFIGURE_IOA 0x001b0001
+#define SCLP_RECONFIG_PCI_ATYPE 2
+
+/* SCLP response codes */
+#define SCLP_RC_NORMAL_READ_COMPLETION 0x0010
+#define SCLP_RC_NORMAL_COMPLETION 0x0020
+#define SCLP_RC_SCCB_BOUNDARY_VIOLATION 0x0100
+#define SCLP_RC_NO_ACTION_REQUIRED 0x0120
+#define SCLP_RC_INVALID_SCLP_COMMAND 0x01f0
+#define SCLP_RC_CONTAINED_EQUIPMENT_CHECK 0x0340
+#define SCLP_RC_INSUFFICIENT_SCCB_LENGTH 0x0300
+#define SCLP_RC_STANDBY_READ_COMPLETION 0x0410
+#define SCLP_RC_ADAPTER_IN_RESERVED_STATE 0x05f0
+#define SCLP_RC_ADAPTER_TYPE_NOT_RECOGNIZED 0x06f0
+#define SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED 0x09f0
+#define SCLP_RC_INVALID_FUNCTION 0x40f0
+#define SCLP_RC_NO_EVENT_BUFFERS_STORED 0x60f0
+#define SCLP_RC_INVALID_SELECTION_MASK 0x70f0
+#define SCLP_RC_INCONSISTENT_LENGTHS 0x72f0
+#define SCLP_RC_EVENT_BUFFER_SYNTAX_ERROR 0x73f0
+#define SCLP_RC_INVALID_MASK_LENGTH 0x74f0
+
+
+/* Service Call Control Block (SCCB) and its elements */
+
+#define SCCB_SIZE 4096
+
+#define SCLP_VARIABLE_LENGTH_RESPONSE 0x80
+#define SCLP_EVENT_BUFFER_ACCEPTED 0x80
+
+#define SCLP_FC_NORMAL_WRITE 0
+
+/*
+ * Normally packed structures are not the right thing to do, since all code
+ * must take care of endianness. We cannot use ldl_phys and friends for two
+ * reasons, though:
+ * - some of the embedded structures below the SCCB can appear multiple times
+ * at different locations, so there is no fixed offset
+ * - 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
+ * So we have to double check that all users of sclp data structures use the
+ * right endianness wrappers.
+ */
+typedef struct SCCBHeader {
+ uint16_t length;
+ uint8_t function_code;
+ uint8_t control_mask[3];
+ uint16_t response_code;
+} QEMU_PACKED SCCBHeader;
+
+#define SCCB_DATA_LEN (SCCB_SIZE - sizeof(SCCBHeader))
+#define SCCB_CPU_FEATURE_LEN 6
+
+/* CPU information */
+typedef struct CPUEntry {
+ uint8_t address;
+ uint8_t reserved0;
+ uint8_t features[SCCB_CPU_FEATURE_LEN];
+ uint8_t reserved2[6];
+ uint8_t type;
+ uint8_t reserved1;
+} QEMU_PACKED CPUEntry;
+
+#define SCLP_READ_SCP_INFO_FIXED_CPU_OFFSET 128
+typedef struct ReadInfo {
+ SCCBHeader h;
+ uint16_t rnmax;
+ uint8_t rnsize;
+ uint8_t _reserved1[16 - 11]; /* 11-15 */
+ uint16_t entries_cpu; /* 16-17 */
+ uint16_t offset_cpu; /* 18-19 */
+ uint8_t _reserved2[24 - 20]; /* 20-23 */
+ uint8_t loadparm[8]; /* 24-31 */
+ uint8_t _reserved3[48 - 32]; /* 32-47 */
+ uint64_t facilities; /* 48-55 */
+ uint8_t _reserved0[76 - 56]; /* 56-75 */
+ uint32_t ibc_val;
+ uint8_t conf_char[99 - 80]; /* 80-98 */
+ uint8_t mha_pow;
+ uint32_t rnsize2;
+ uint64_t rnmax2;
+ uint8_t _reserved6[116 - 112]; /* 112-115 */
+ uint8_t conf_char_ext[120 - 116]; /* 116-119 */
+ 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 {
+ SCCBHeader h;
+ uint16_t nr_configured; /* 8-9 */
+ uint16_t offset_configured; /* 10-11 */
+ uint16_t nr_standby; /* 12-13 */
+ uint16_t offset_standby; /* 14-15 */
+ uint8_t reserved0[24-16]; /* 16-23 */
+ struct CPUEntry entries[];
+} QEMU_PACKED ReadCpuInfo;
+
+typedef struct ReadStorageElementInfo {
+ SCCBHeader h;
+ uint16_t max_id;
+ uint16_t assigned;
+ uint16_t standby;
+ uint8_t _reserved0[16 - 14]; /* 14-15 */
+ uint32_t entries[];
+} QEMU_PACKED ReadStorageElementInfo;
+
+typedef struct AttachStorageElement {
+ SCCBHeader h;
+ uint8_t _reserved0[10 - 8]; /* 8-9 */
+ uint16_t assigned;
+ uint8_t _reserved1[16 - 12]; /* 12-15 */
+ uint32_t entries[];
+} QEMU_PACKED AttachStorageElement;
+
+typedef struct AssignStorage {
+ SCCBHeader h;
+ uint16_t rn;
+} QEMU_PACKED AssignStorage;
+
+typedef struct IoaCfgSccb {
+ SCCBHeader header;
+ uint8_t atype;
+ uint8_t reserved1;
+ uint16_t reserved2;
+ uint32_t aid;
+} QEMU_PACKED IoaCfgSccb;
+
+typedef struct SCCB {
+ SCCBHeader h;
+ char data[];
+ } QEMU_PACKED SCCB;
+
+#define TYPE_SCLP "sclp"
+OBJECT_DECLARE_TYPE(SCLPDevice, SCLPDeviceClass,
+ SCLP)
+
+struct SCLPEventFacility;
+
+struct SCLPDevice {
+ /* private */
+ DeviceState parent_obj;
+ struct SCLPEventFacility *event_facility;
+ int increment_size;
+
+ /* public */
+};
+
+struct SCLPDeviceClass {
+ /* private */
+ DeviceClass parent_class;
+ void (*read_SCP_info)(SCLPDevice *sclp, SCCB *sccb);
+ void (*read_cpu_info)(SCLPDevice *sclp, SCCB *sccb);
+
+ /* public */
+ void (*execute)(SCLPDevice *sclp, SCCB *sccb, uint32_t code);
+ void (*service_interrupt)(SCLPDevice *sclp, uint32_t sccb);
+};
+
+static inline int sccb_data_len(SCCB *sccb)
+{
+ return be16_to_cpu(sccb->h.length) - sizeof(sccb->h);
+}
+
+
+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);
+
+#endif
diff --git a/include/hw/s390x/storage-attributes.h b/include/hw/s390x/storage-attributes.h
new file mode 100644
index 000000000..5239eb538
--- /dev/null
+++ b/include/hw/s390x/storage-attributes.h
@@ -0,0 +1,79 @@
+/*
+ * s390 storage attributes device
+ *
+ * Copyright 2016 IBM Corp.
+ * Author(s): Claudio Imbrenda <imbrenda@linux.vnet.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 S390_STORAGE_ATTRIBUTES_H
+#define S390_STORAGE_ATTRIBUTES_H
+
+#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"
+
+OBJECT_DECLARE_TYPE(S390StAttribState, S390StAttribClass, S390_STATTRIB)
+
+struct S390StAttribState {
+ DeviceState parent_obj;
+ uint64_t migration_cur_gfn;
+ bool migration_enabled;
+};
+
+
+struct S390StAttribClass {
+ DeviceClass parent_class;
+ /* Return value: < 0 on error, or new count */
+ int (*get_stattr)(S390StAttribState *sa, uint64_t *start_gfn,
+ uint32_t count, uint8_t *values);
+ int (*peek_stattr)(S390StAttribState *sa, uint64_t start_gfn,
+ uint32_t count, uint8_t *values);
+ 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 (*get_active)(S390StAttribState *sa);
+ long long (*get_dirtycount)(S390StAttribState *sa);
+};
+
+typedef struct QEMUS390StAttribState QEMUS390StAttribState;
+DECLARE_INSTANCE_CHECKER(QEMUS390StAttribState, QEMU_S390_STATTRIB,
+ TYPE_QEMU_S390_STATTRIB)
+
+struct QEMUS390StAttribState {
+ S390StAttribState parent_obj;
+};
+
+typedef struct KVMS390StAttribState KVMS390StAttribState;
+DECLARE_INSTANCE_CHECKER(KVMS390StAttribState, KVM_S390_STATTRIB,
+ TYPE_KVM_S390_STATTRIB)
+
+struct KVMS390StAttribState {
+ S390StAttribState parent_obj;
+ uint64_t still_dirty;
+ uint8_t *incoming_buffer;
+};
+
+void s390_stattrib_init(void);
+
+#ifdef CONFIG_KVM
+Object *kvm_s390_stattrib_create(void);
+#else
+static inline Object *kvm_s390_stattrib_create(void)
+{
+ return NULL;
+}
+#endif
+
+void hmp_info_cmma(Monitor *mon, const QDict *qdict);
+void hmp_migrationmode(Monitor *mon, const QDict *qdict);
+
+#endif /* S390_STORAGE_ATTRIBUTES_H */
diff --git a/include/hw/s390x/storage-keys.h b/include/hw/s390x/storage-keys.h
new file mode 100644
index 000000000..aa2ec2aae
--- /dev/null
+++ b/include/hw/s390x/storage-keys.h
@@ -0,0 +1,120 @@
+/*
+ * s390 storage key device
+ *
+ * Copyright 2015 IBM Corp.
+ * Author(s): Jason J. Herne <jjherne@linux.vnet.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 S390_STORAGE_KEYS_H
+#define S390_STORAGE_KEYS_H
+
+#include "hw/qdev-core.h"
+#include "monitor/monitor.h"
+#include "qom/object.h"
+
+#define TYPE_S390_SKEYS "s390-skeys"
+OBJECT_DECLARE_TYPE(S390SKeysState, S390SKeysClass, S390_SKEYS)
+
+struct S390SKeysState {
+ DeviceState parent_obj;
+ bool migration_enabled;
+
+};
+
+
+struct S390SKeysClass {
+ DeviceClass parent_class;
+
+ /**
+ * @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);
+};
+
+#define TYPE_KVM_S390_SKEYS "s390-skeys-kvm"
+#define TYPE_QEMU_S390_SKEYS "s390-skeys-qemu"
+typedef struct QEMUS390SKeysState QEMUS390SKeysState;
+DECLARE_INSTANCE_CHECKER(QEMUS390SKeysState, QEMU_S390_SKEYS,
+ TYPE_QEMU_S390_SKEYS)
+
+struct QEMUS390SKeysState {
+ S390SKeysState parent_obj;
+ uint8_t *keydata;
+ uint32_t key_count;
+};
+
+void s390_skeys_init(void);
+
+S390SKeysState *s390_get_skeys_device(void);
+
+void hmp_dump_skeys(Monitor *mon, const QDict *qdict);
+void hmp_info_skeys(Monitor *mon, const QDict *qdict);
+
+#endif /* S390_STORAGE_KEYS_H */
diff --git a/include/hw/s390x/tod.h b/include/hw/s390x/tod.h
new file mode 100644
index 000000000..0935e8508
--- /dev/null
+++ b/include/hw/s390x/tod.h
@@ -0,0 +1,54 @@
+/*
+ * TOD (Time Of Day) clock
+ *
+ * Copyright 2018 Red Hat, Inc.
+ * Author(s): David Hildenbrand <david@redhat.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_S390_TOD_H
+#define HW_S390_TOD_H
+
+#include "hw/qdev-core.h"
+#include "tcg/s390-tod.h"
+#include "qom/object.h"
+
+typedef struct S390TOD {
+ uint8_t high;
+ uint64_t low;
+} S390TOD;
+
+#define TYPE_S390_TOD "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"
+
+struct S390TODState {
+ /* private */
+ DeviceState parent_obj;
+
+ /*
+ * Used by TCG to remember the time base. Used by KVM to backup the TOD
+ * while the TOD is stopped.
+ */
+ S390TOD base;
+ /* Used by KVM to remember if the TOD is stopped and base is valid. */
+ bool stopped;
+};
+
+struct S390TODClass {
+ /* private */
+ DeviceClass parent_class;
+ void (*parent_realize)(DeviceState *dev, Error **errp);
+
+ /* public */
+ void (*get)(const S390TODState *td, S390TOD *tod, Error **errp);
+ void (*set)(S390TODState *td, const S390TOD *tod, Error **errp);
+};
+
+void s390_init_tod(void);
+S390TODState *s390_get_todstate(void);
+
+#endif
diff --git a/include/hw/s390x/vfio-ccw.h b/include/hw/s390x/vfio-ccw.h
new file mode 100644
index 000000000..63a909eb7
--- /dev/null
+++ b/include/hw/s390x/vfio-ccw.h
@@ -0,0 +1,27 @@
+/*
+ * vfio based subchannel assignment support
+ *
+ * Copyright 2017, 2019 IBM Corp.
+ * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
+ * Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
+ * Pierre Morel <pmorel@linux.vnet.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_VFIO_CCW_H
+#define HW_VFIO_CCW_H
+
+#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"
+OBJECT_DECLARE_SIMPLE_TYPE(VFIOCCWDevice, VFIO_CCW)
+
+#define TYPE_VFIO_CCW "vfio-ccw"
+
+#endif
diff --git a/include/hw/scsi/emulation.h b/include/hw/scsi/emulation.h
new file mode 100644
index 000000000..952170432
--- /dev/null
+++ b/include/hw/scsi/emulation.h
@@ -0,0 +1,16 @@
+#ifndef HW_SCSI_EMULATION_H
+#define HW_SCSI_EMULATION_H
+
+typedef struct SCSIBlockLimits {
+ bool wsnz;
+ uint16_t min_io_size;
+ uint32_t max_unmap_descr;
+ uint32_t opt_io_size;
+ uint32_t max_unmap_sectors;
+ uint32_t unmap_sectors;
+ uint32_t max_io_sectors;
+} SCSIBlockLimits;
+
+int scsi_emulate_block_limits(uint8_t *outbuf, const SCSIBlockLimits *bl);
+
+#endif
diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h
new file mode 100644
index 000000000..b1ec27612
--- /dev/null
+++ b/include/hw/scsi/esp.h
@@ -0,0 +1,163 @@
+#ifndef QEMU_HW_ESP_H
+#define QEMU_HW_ESP_H
+
+#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 ESP_FIFO_SZ 16
+#define ESP_CMDFIFO_SZ 32
+
+typedef struct ESPState ESPState;
+
+#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;
+ uint8_t chip_id;
+ bool tchi_written;
+ int32_t ti_size;
+ uint32_t status;
+ uint32_t dma;
+ Fifo8 fifo;
+ SCSIBus bus;
+ SCSIDevice *current_dev;
+ SCSIRequest *current_req;
+ Fifo8 cmdfifo;
+ uint8_t cmdfifo_cdb_offset;
+ uint8_t lun;
+ uint32_t do_cmd;
+
+ bool data_in_ready;
+ uint8_t ti_cmd;
+ int dma_enabled;
+
+ uint32_t async_len;
+ uint8_t *async_buf;
+
+ ESPDMAMemoryReadWriteFunc dma_memory_read;
+ ESPDMAMemoryReadWriteFunc dma_memory_write;
+ void *dma_opaque;
+ void (*dma_cb)(ESPState *s);
+ 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;
+};
+
+#define TYPE_SYSBUS_ESP "sysbus-esp"
+OBJECT_DECLARE_SIMPLE_TYPE(SysBusESPState, SYSBUS_ESP)
+
+struct SysBusESPState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ MemoryRegion iomem;
+ MemoryRegion pdma;
+ uint32_t it_shift;
+ ESPState esp;
+};
+
+#define ESP_TCLO 0x0
+#define ESP_TCMID 0x1
+#define ESP_FIFO 0x2
+#define ESP_CMD 0x3
+#define ESP_RSTAT 0x4
+#define ESP_WBUSID 0x4
+#define ESP_RINTR 0x5
+#define ESP_WSEL 0x5
+#define ESP_RSEQ 0x6
+#define ESP_WSYNTP 0x6
+#define ESP_RFLAGS 0x7
+#define ESP_WSYNO 0x7
+#define ESP_CFG1 0x8
+#define ESP_RRES1 0x9
+#define ESP_WCCF 0x9
+#define ESP_RRES2 0xa
+#define ESP_WTEST 0xa
+#define ESP_CFG2 0xb
+#define ESP_CFG3 0xc
+#define ESP_RES3 0xd
+#define ESP_TCHI 0xe
+#define ESP_RES4 0xf
+
+#define CMD_DMA 0x80
+#define CMD_CMD 0x7f
+
+#define CMD_NOP 0x00
+#define CMD_FLUSH 0x01
+#define CMD_RESET 0x02
+#define CMD_BUSRESET 0x03
+#define CMD_TI 0x10
+#define CMD_ICCS 0x11
+#define CMD_MSGACC 0x12
+#define CMD_PAD 0x18
+#define CMD_SATN 0x1a
+#define CMD_RSTATN 0x1b
+#define CMD_SEL 0x41
+#define CMD_SELATN 0x42
+#define CMD_SELATNS 0x43
+#define CMD_ENSEL 0x44
+#define CMD_DISSEL 0x45
+
+#define STAT_DO 0x00
+#define STAT_DI 0x01
+#define STAT_CD 0x02
+#define STAT_ST 0x03
+#define STAT_MO 0x06
+#define STAT_MI 0x07
+#define STAT_PIO_MASK 0x06
+
+#define STAT_TC 0x10
+#define STAT_PE 0x20
+#define STAT_GE 0x40
+#define STAT_INT 0x80
+
+#define BUSID_DID 0x07
+
+#define INTR_FC 0x08
+#define INTR_BS 0x10
+#define INTR_DC 0x20
+#define INTR_RST 0x80
+
+#define SEQ_0 0x0
+#define SEQ_MO 0x1
+#define SEQ_CD 0x4
+
+#define CFG1_RESREPT 0x40
+
+#define TCHI_FAS100A 0x4
+#define TCHI_AM53C974 0x12
+
+void esp_dma_enable(ESPState *s, int irq, int level);
+void esp_request_cancelled(SCSIRequest *req);
+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
new file mode 100644
index 000000000..a567a5ed8
--- /dev/null
+++ b/include/hw/scsi/scsi.h
@@ -0,0 +1,229 @@
+#ifndef QEMU_HW_SCSI_H
+#define QEMU_HW_SCSI_H
+
+#include "block/aio.h"
+#include "hw/block/block.h"
+#include "hw/qdev-core.h"
+#include "scsi/utils.h"
+#include "qemu/notify.h"
+#include "qom/object.h"
+
+#define MAX_SCSI_DEVS 255
+
+typedef struct SCSIBus SCSIBus;
+typedef struct SCSIBusInfo SCSIBusInfo;
+typedef struct SCSIDevice SCSIDevice;
+typedef struct SCSIRequest SCSIRequest;
+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;
+ SCSIDevice *dev;
+ const SCSIReqOps *ops;
+ uint32_t refcount;
+ uint32_t tag;
+ uint32_t lun;
+ int16_t status;
+ int16_t host_status;
+ void *hba_private;
+ size_t resid;
+ SCSICommand cmd;
+ NotifierList cancel_notifiers;
+
+ /* Note:
+ * - fields before sense are initialized by scsi_req_alloc;
+ * - sense[] is uninitialized;
+ * - fields after sense are memset to 0 by scsi_req_alloc.
+ * */
+
+ uint8_t sense[SCSI_SENSE_BUF_SIZE];
+ uint32_t sense_len;
+ bool enqueued;
+ bool io_canceled;
+ bool retry;
+ bool dma_started;
+ BlockAIOCB *aiocb;
+ QEMUSGList *sg;
+ QTAILQ_ENTRY(SCSIRequest) next;
+};
+
+#define TYPE_SCSI_DEVICE "scsi-device"
+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);
+ SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun,
+ uint8_t *buf, void *hba_private);
+ void (*unit_attention_reported)(SCSIDevice *s);
+};
+
+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;
+ QTAILQ_HEAD(, SCSIRequest) requests;
+ uint32_t channel;
+ uint32_t lun;
+ int blocksize;
+ int type;
+ uint64_t max_lba;
+ uint64_t wwn;
+ uint64_t port_wwn;
+ int scsi_version;
+ int default_scsi_version;
+ uint32_t io_timeout;
+ bool needs_vpd_bl_emulation;
+ bool hba_supports_iothread;
+};
+
+extern const VMStateDescription vmstate_scsi_device;
+
+#define VMSTATE_SCSI_DEVICE(_field, _state) { \
+ .name = (stringify(_field)), \
+ .size = sizeof(SCSIDevice), \
+ .vmsd = &vmstate_scsi_device, \
+ .flags = VMS_STRUCT, \
+ .offset = vmstate_offset_value(_state, _field, SCSIDevice), \
+}
+
+/* cdrom.c */
+int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
+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 (*free_req)(SCSIRequest *req);
+ int32_t (*send_command)(SCSIRequest *req, uint8_t *buf);
+ void (*read_data)(SCSIRequest *req);
+ void (*write_data)(SCSIRequest *req);
+ uint8_t *(*get_buf)(SCSIRequest *req);
+
+ void (*save_request)(QEMUFile *f, SCSIRequest *req);
+ void (*load_request)(QEMUFile *f, SCSIRequest *req);
+};
+
+struct SCSIBusInfo {
+ int tcq;
+ int max_channel, max_target, max_lun;
+ int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
+ void *hba_private);
+ void (*transfer_data)(SCSIRequest *req, uint32_t arg);
+ void (*fail)(SCSIRequest *req);
+ void (*complete)(SCSIRequest *req, size_t resid);
+ void (*cancel)(SCSIRequest *req);
+ void (*change)(SCSIBus *bus, SCSIDevice *dev, SCSISense sense);
+ QEMUSGList *(*get_sg_list)(SCSIRequest *req);
+
+ void (*save_request)(QEMUFile *f, SCSIRequest *req);
+ void *(*load_request)(QEMUFile *f, SCSIRequest *req);
+ void (*free_request)(SCSIBus *bus, void *priv);
+};
+
+#define TYPE_SCSI_BUS "SCSI"
+OBJECT_DECLARE_SIMPLE_TYPE(SCSIBus, SCSI_BUS)
+
+struct SCSIBus {
+ BusState qbus;
+ int busnr;
+
+ SCSISense unit_attention;
+ const SCSIBusInfo *info;
+};
+
+/**
+ * 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_new() 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)
+{
+ return DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus);
+}
+
+SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
+ int unit, bool removable, int bootindex,
+ bool share_rw,
+ BlockdevOnError rerror,
+ BlockdevOnError werror,
+ const char *serial, Error **errp);
+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);
+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);
+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_purge_requests(SCSIDevice *sdev, SCSISense sense);
+void scsi_device_set_ua(SCSIDevice *sdev, SCSISense sense);
+void scsi_device_report_change(SCSIDevice *dev, SCSISense sense);
+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, 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;
+
+#endif
diff --git a/include/hw/sd/allwinner-sdhost.h b/include/hw/sd/allwinner-sdhost.h
new file mode 100644
index 000000000..bfe08ff4e
--- /dev/null
+++ b/include/hw/sd/allwinner-sdhost.h
@@ -0,0 +1,136 @@
+/*
+ * Allwinner (sun4i and above) SD Host Controller emulation
+ *
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.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_SD_ALLWINNER_SDHOST_H
+#define HW_SD_ALLWINNER_SDHOST_H
+
+#include "qom/object.h"
+#include "hw/sysbus.h"
+#include "hw/sd/sd.h"
+
+/**
+ * Object model types
+ * @{
+ */
+
+/** Generic Allwinner SD Host Controller (abstract) */
+#define TYPE_AW_SDHOST "allwinner-sdhost"
+
+/** Allwinner sun4i family (A10, A12) */
+#define TYPE_AW_SDHOST_SUN4I TYPE_AW_SDHOST "-sun4i"
+
+/** Allwinner sun5i family and newer (A13, H2+, H3, etc) */
+#define TYPE_AW_SDHOST_SUN5I TYPE_AW_SDHOST "-sun5i"
+
+/** @} */
+
+/**
+ * Object model macros
+ * @{
+ */
+
+OBJECT_DECLARE_TYPE(AwSdHostState, AwSdHostClass, AW_SDHOST)
+
+/** @} */
+
+/**
+ * Allwinner SD Host Controller object instance state.
+ */
+struct AwSdHostState {
+ /*< private >*/
+ SysBusDevice busdev;
+ /*< public >*/
+
+ /** Secure Digital (SD) bus, which connects to SD card (if present) */
+ SDBus sdbus;
+
+ /** Maps I/O registers in physical memory */
+ MemoryRegion iomem;
+
+ /** 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;
+
+ /**
+ * @name Hardware Registers
+ * @{
+ */
+
+ uint32_t global_ctl; /**< Global Control */
+ uint32_t clock_ctl; /**< Clock Control */
+ uint32_t timeout; /**< Timeout */
+ uint32_t bus_width; /**< Bus Width */
+ uint32_t block_size; /**< Block Size */
+ uint32_t byte_count; /**< Byte Count */
+
+ uint32_t command; /**< Command */
+ uint32_t command_arg; /**< Command Argument */
+ uint32_t response[4]; /**< Command Response */
+
+ uint32_t irq_mask; /**< Interrupt Mask */
+ uint32_t irq_status; /**< Raw Interrupt Status */
+ uint32_t status; /**< Status */
+
+ uint32_t fifo_wlevel; /**< FIFO Water Level */
+ uint32_t fifo_func_sel; /**< FIFO Function Select */
+ uint32_t debug_enable; /**< Debug Enable */
+ uint32_t auto12_arg; /**< Auto Command 12 Argument */
+ uint32_t newtiming_set; /**< SD New Timing Set */
+ uint32_t newtiming_debug; /**< SD New Timing Debug */
+ uint32_t hardware_rst; /**< Hardware Reset */
+ uint32_t dmac; /**< Internal DMA Controller Control */
+ uint32_t desc_base; /**< Descriptor List Base Address */
+ uint32_t dmac_status; /**< Internal DMA Controller Status */
+ uint32_t dmac_irq; /**< Internal DMA Controller IRQ Enable */
+ uint32_t card_threshold; /**< Card Threshold Control */
+ 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 status_crc; /**< Status CRC */
+
+ /** @} */
+
+};
+
+/**
+ * Allwinner SD Host 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 AwSdHostClass {
+ /*< private >*/
+ SysBusDeviceClass parent_class;
+ /*< public >*/
+
+ /** Maximum buffer size in bytes per DMA descriptor */
+ size_t max_desc_size;
+
+};
+
+#endif /* HW_SD_ALLWINNER_SDHOST_H */
diff --git a/include/hw/sd/aspeed_sdhci.h b/include/hw/sd/aspeed_sdhci.h
new file mode 100644
index 000000000..057bc5f3d
--- /dev/null
+++ b/include/hw/sd/aspeed_sdhci.h
@@ -0,0 +1,35 @@
+/*
+ * Aspeed SD Host Controller
+ * Eddie James <eajames@linux.ibm.com>
+ *
+ * Copyright (C) 2019 IBM Corp
+ * 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"
+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
+
+struct AspeedSDHCIState {
+ SysBusDevice parent;
+
+ SDHCIState slots[ASPEED_SDHCI_NUM_SLOTS];
+ uint8_t num_slots;
+
+ MemoryRegion iomem;
+ qemu_irq irq;
+
+ uint32_t regs[ASPEED_SDHCI_NUM_REGS];
+};
+
+#endif /* ASPEED_SDHCI_H */
diff --git a/include/hw/sd/bcm2835_sdhost.h b/include/hw/sd/bcm2835_sdhost.h
new file mode 100644
index 000000000..f6bca5c39
--- /dev/null
+++ b/include/hw/sd/bcm2835_sdhost.h
@@ -0,0 +1,48 @@
+/*
+ * Raspberry Pi (BCM2835) SD Host Controller
+ *
+ * Copyright (c) 2017 Antfield SAS
+ *
+ * Authors:
+ * Clement Deschamps <clement.deschamps@antfield.fr>
+ * Luc Michel <luc.michel@antfield.fr>
+ *
+ * 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_SDHOST_H
+#define BCM2835_SDHOST_H
+
+#include "hw/sysbus.h"
+#include "hw/sd/sd.h"
+#include "qom/object.h"
+
+#define TYPE_BCM2835_SDHOST "bcm2835-sdhost"
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835SDHostState, BCM2835_SDHOST)
+
+#define BCM2835_SDHOST_FIFO_LEN 16
+
+struct BCM2835SDHostState {
+ SysBusDevice busdev;
+ SDBus sdbus;
+ MemoryRegion iomem;
+
+ uint32_t cmd;
+ uint32_t cmdarg;
+ uint32_t status;
+ uint32_t rsp[4];
+ uint32_t config;
+ uint32_t edm;
+ uint32_t vdd;
+ uint32_t hbct;
+ uint32_t hblc;
+ int32_t fifo_pos;
+ int32_t fifo_len;
+ uint32_t fifo[BCM2835_SDHOST_FIFO_LEN];
+ uint32_t datacnt;
+
+ qemu_irq irq;
+};
+
+#endif
diff --git a/include/hw/sd/cadence_sdhci.h b/include/hw/sd/cadence_sdhci.h
new file mode 100644
index 000000000..cd8288b7d
--- /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 000000000..d728f0a40
--- /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;
+
+typedef struct NPCM7xxSDHCIState {
+ SysBusDevice parent;
+
+ MemoryRegion container;
+ MemoryRegion iomem;
+ BusState *bus;
+ NPCM7xxRegisters regs;
+
+ SDHCIState sdhci;
+} NPCM7xxSDHCIState;
+
+#endif /* NPCM7XX_SDHCI_H */
diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
new file mode 100644
index 000000000..47360ba4e
--- /dev/null
+++ b/include/hw/sd/sd.h
@@ -0,0 +1,211 @@
+/*
+ * SD Memory Card emulation. Mostly correct for MMC too.
+ *
+ * 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_SD_H
+#define HW_SD_H
+
+#include "hw/qdev-core.h"
+#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,
+ SD_PHY_SPECv2_00_VERS = 2,
+ SD_PHY_SPECv3_01_VERS = 3,
+};
+
+typedef enum {
+ SD_VOLTAGE_0_4V = 400, /* currently not supported */
+ SD_VOLTAGE_1_8V = 1800,
+ SD_VOLTAGE_3_0V = 3000,
+ SD_VOLTAGE_3_3V = 3300,
+} sd_voltage_mv_t;
+
+typedef enum {
+ UHS_NOT_SUPPORTED = 0,
+ UHS_I = 1,
+ UHS_II = 2, /* currently not supported */
+ UHS_III = 3, /* currently not supported */
+} sd_uhs_mode_t;
+
+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_cmd_type_t;
+
+typedef struct {
+ uint8_t cmd;
+ uint32_t arg;
+ uint8_t crc;
+} SDRequest;
+
+
+#define TYPE_SD_CARD "sd-card"
+OBJECT_DECLARE_TYPE(SDState, SDCardClass, SD_CARD)
+
+struct SDCardClass {
+ /*< private >*/
+ DeviceClass parent_class;
+ /*< public >*/
+
+ int (*do_command)(SDState *sd, SDRequest *req, uint8_t *response);
+ /**
+ * 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);
+ bool (*get_cmd_line)(SDState *sd);
+ void (*enable)(SDState *sd, bool enable);
+ bool (*get_inserted)(SDState *sd);
+ bool (*get_readonly)(SDState *sd);
+};
+
+#define TYPE_SD_BUS "sd-bus"
+OBJECT_DECLARE_TYPE(SDBus, SDBusClass,
+ SD_BUS)
+
+struct SDBus {
+ BusState qbus;
+};
+
+struct SDBusClass {
+ /*< private >*/
+ BusClass parent_class;
+ /*< public >*/
+
+ /* These methods are called by the SD device to notify the controller
+ * when the card insertion or readonly status changes
+ */
+ void (*set_inserted)(DeviceState *dev, bool inserted);
+ void (*set_readonly)(DeviceState *dev, bool readonly);
+};
+
+/* Functions to be used by qdevified callers (working via
+ * an SDBus rather than directly with SDState)
+ */
+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);
+/**
+ * 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);
+/**
+ * sdbus_reparent_card: Reparent an SD card from one controller to another
+ * @from: controller bus to remove card from
+ * @to: controller bus to move card to
+ *
+ * Reparent an SD card, effectively unplugging it from one controller
+ * and inserting it into another. This is useful for SoCs like the
+ * bcm2835 which have two SD controllers and connect a single SD card
+ * to them, selected by the guest reprogramming GPIO line routing.
+ */
+void sdbus_reparent_card(SDBus *from, SDBus *to);
+
+/* Functions to be used by SD devices to report back to qdevified controllers */
+void sdbus_set_inserted(SDBus *sd, bool inserted);
+void sdbus_set_readonly(SDBus *sd, bool inserted);
+
+#endif /* HW_SD_H */
diff --git a/include/hw/sd/sdcard_legacy.h b/include/hw/sd/sdcard_legacy.h
new file mode 100644
index 000000000..0dc388955
--- /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
new file mode 100644
index 000000000..01a64c544
--- /dev/null
+++ b/include/hw/sd/sdhci.h
@@ -0,0 +1,129 @@
+/*
+ * SD Association Host Standard Specification v2.0 controller emulation
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Mitsyanko Igor <i.mitsyanko@samsung.com>
+ * Peter A.G. Crosthwaite <peter.crosthwaite@petalogix.com>
+ *
+ * Based on MMC controller for Samsung S5PC1xx-based board emulation
+ * by Alexey Merkulov and Vladimir Monakhov.
+ *
+ * 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 SDHCI_H
+#define SDHCI_H
+
+#include "hw/pci/pci.h"
+#include "hw/sysbus.h"
+#include "hw/sd/sd.h"
+#include "qom/object.h"
+
+/* SD/MMC host controller state */
+struct SDHCIState {
+ /*< private >*/
+ union {
+ PCIDevice pcidev;
+ SysBusDevice busdev;
+ };
+
+ /*< public >*/
+ SDBus sdbus;
+ MemoryRegion iomem;
+ AddressSpace sysbus_dma_as;
+ AddressSpace *dma_as;
+ MemoryRegion *dma_mr;
+ const MemoryRegionOps *io_ops;
+
+ QEMUTimer *insert_timer; /* timer for 'changing' sd card. */
+ QEMUTimer *transfer_timer;
+ qemu_irq irq;
+
+ /* Registers cleared on reset */
+ uint32_t sdmasysad; /* SDMA System Address register */
+ uint16_t blksize; /* Host DMA Buff Boundary and Transfer BlkSize Reg */
+ uint16_t blkcnt; /* Blocks count for current transfer */
+ uint32_t argument; /* Command Argument Register */
+ uint16_t trnmod; /* Transfer Mode Setting Register */
+ uint16_t cmdreg; /* Command Register */
+ uint32_t rspreg[4]; /* Response Registers 0-3 */
+ uint32_t prnsts; /* Present State Register */
+ uint8_t hostctl1; /* Host Control Register */
+ uint8_t pwrcon; /* Power control Register */
+ uint8_t blkgap; /* Block Gap Control Register */
+ uint8_t wakcon; /* WakeUp Control Register */
+ uint16_t clkcon; /* Clock control Register */
+ uint8_t timeoutcon; /* Timeout Control Register */
+ uint8_t admaerr; /* ADMA Error Status Register */
+ uint16_t norintsts; /* Normal Interrupt Status Register */
+ uint16_t errintsts; /* Error Interrupt Status Register */
+ uint16_t norintstsen; /* Normal Interrupt Status Enable Register */
+ uint16_t errintstsen; /* Error Interrupt Status Enable Register */
+ uint16_t norintsigen; /* Normal Interrupt Signal Enable Register */
+ uint16_t errintsigen; /* Error Interrupt Signal Enable Register */
+ uint16_t acmd12errsts; /* Auto CMD12 error status register */
+ uint16_t hostctl2; /* Host Control 2 */
+ uint64_t admasysaddr; /* ADMA System Address Register */
+ uint16_t vendor_spec; /* Vendor specific register */
+
+ /* Read-only registers */
+ uint64_t capareg; /* Capabilities Register */
+ uint64_t maxcurr; /* Maximum Current Capabilities Register */
+ uint16_t version; /* Host Controller Version Register */
+
+ uint8_t *fifo_buffer; /* SD host i/o FIFO buffer */
+ uint32_t buf_maxsz;
+ uint16_t data_count; /* current element in FIFO buffer */
+ uint8_t stopped_state;/* Current SDHC state */
+ bool pending_insert_state;
+ /* Buffer Data Port Register - virtual access point to R and W buffers */
+ /* Software Reset Register - always reads as 0 */
+ /* Force Event Auto CMD12 Error Interrupt Reg - write only */
+ /* Force Event Error Interrupt Register- write only */
+ /* RO Host Controller Version Register always reads as 0x2401 */
+
+ /* Configurable properties */
+ bool pending_insert_quirk; /* Quirk for Raspberry Pi card insert int */
+ uint32_t quirks;
+ uint8_t sd_spec_version;
+ uint8_t uhs_mode;
+ uint8_t vendor; /* For vendor specific functionality */
+};
+typedef struct SDHCIState SDHCIState;
+
+#define SDHCI_VENDOR_NONE 0
+#define SDHCI_VENDOR_IMX 1
+
+/*
+ * Controller does not provide transfer-complete interrupt when not
+ * busy.
+ *
+ * NOTE: This definition is taken out of Linux kernel and so the
+ * original bit number is preserved
+ */
+#define SDHCI_QUIRK_NO_BUSY_IRQ BIT(14)
+
+#define TYPE_PCI_SDHCI "sdhci-pci"
+DECLARE_INSTANCE_CHECKER(SDHCIState, PCI_SDHCI,
+ TYPE_PCI_SDHCI)
+
+#define TYPE_SYSBUS_SDHCI "generic-sdhci"
+DECLARE_INSTANCE_CHECKER(SDHCIState, SYSBUS_SDHCI,
+ TYPE_SYSBUS_SDHCI)
+
+#define TYPE_IMX_USDHC "imx-usdhc"
+
+#define TYPE_S3C_SDHCI "s3c-sdhci"
+
+#endif /* SDHCI_H */
diff --git a/include/hw/sensor/emc141x_regs.h b/include/hw/sensor/emc141x_regs.h
new file mode 100644
index 000000000..0560fb7c5
--- /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 TMP105_REGS_H
+#define TMP105_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/tmp105.h b/include/hw/sensor/tmp105.h
new file mode 100644
index 000000000..244e2989f
--- /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/sensor/tmp105_regs.h b/include/hw/sensor/tmp105_regs.h
new file mode 100644
index 000000000..ef015ee5c
--- /dev/null
+++ b/include/hw/sensor/tmp105_regs.h
@@ -0,0 +1,51 @@
+/*
+ * Texas Instruments TMP105 Temperature Sensor I2C messages
+ *
+ * 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 TMP105_REGS_H
+#define TMP105_REGS_H
+
+/**
+ * TMP105Reg:
+ * @TMP105_REG_TEMPERATURE: Temperature register
+ * @TMP105_REG_CONFIG: Configuration register
+ * @TMP105_REG_T_LOW: Low temperature register (also known as T_hyst)
+ * @TMP105_REG_T_HIGH: High temperature register (also known as T_OS)
+ *
+ * The following temperature sensors are
+ * compatible with the TMP105 registers:
+ * - adt75
+ * - ds1775
+ * - ds75
+ * - lm75
+ * - lm75a
+ * - max6625
+ * - max6626
+ * - mcp980x
+ * - stds75
+ * - tcn75
+ * - tmp100
+ * - tmp101
+ * - tmp105
+ * - tmp175
+ * - tmp275
+ * - tmp75
+ **/
+typedef enum TMP105Reg {
+ TMP105_REG_TEMPERATURE = 0,
+ TMP105_REG_CONFIG,
+ TMP105_REG_T_LOW,
+ TMP105_REG_T_HIGH,
+} TMP105Reg;
+
+#endif
diff --git a/include/hw/sh4/sh.h b/include/hw/sh4/sh.h
new file mode 100644
index 000000000..ec716cdd4
--- /dev/null
+++ b/include/hw/sh4/sh.h
@@ -0,0 +1,66 @@
+/*
+ * 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"
+
+#define A7ADDR(x) ((x) & 0x1fffffff)
+#define P4ADDR(x) ((x) | 0xe0000000)
+
+/* sh7750.c */
+struct SH7750State;
+
+struct SH7750State *sh7750_init(SuperHCPU *cpu, MemoryRegion *sysmem);
+
+typedef struct {
+ /* The callback will be triggered if any of the designated lines change */
+ uint16_t portamask_trigger;
+ 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);
+} sh7750_io_device;
+
+int sh7750_register_io_device(struct SH7750State *s,
+ sh7750_io_device *device);
+
+/* sh_serial.c */
+#define TYPE_SH_SERIAL "sh-serial"
+#define SH_SERIAL_FEAT_SCIF (1 << 0)
+
+/* sh7750.c */
+qemu_irq sh7750_irl(struct SH7750State *s);
+
+/* tc58128.c */
+int tc58128_init(struct SH7750State *s, const char *zone1, const char *zone2);
+
+#endif
diff --git a/include/hw/sh4/sh_intc.h b/include/hw/sh4/sh_intc.h
new file mode 100644
index 000000000..f62d5c5e1
--- /dev/null
+++ b/include/hw/sh4/sh_intc.h
@@ -0,0 +1,81 @@
+#ifndef SH_INTC_H
+#define SH_INTC_H
+
+#include "exec/memory.h"
+
+typedef unsigned char intc_enum;
+
+struct intc_vect {
+ intc_enum enum_id;
+ unsigned short vect;
+};
+
+#define INTC_VECT(enum_id, vect) { enum_id, vect }
+
+struct intc_group {
+ intc_enum enum_id;
+ intc_enum enum_ids[32];
+};
+
+#define INTC_GROUP(enum_id, ...) { enum_id, { __VA_ARGS__ } }
+
+struct intc_mask_reg {
+ unsigned long set_reg, clr_reg, reg_width;
+ intc_enum enum_ids[32];
+ unsigned long value;
+};
+
+struct intc_prio_reg {
+ unsigned long set_reg, clr_reg, reg_width, field_width;
+ intc_enum enum_ids[16];
+ unsigned long value;
+};
+
+#define _INTC_ARRAY(a) a, ARRAY_SIZE(a)
+
+struct intc_source {
+ unsigned short vect;
+ intc_enum next_enum_id;
+
+ int asserted; /* emulates the interrupt signal line from device to intc */
+ int enable_count;
+ int enable_max;
+ int pending; /* emulates the result of signal and masking */
+ struct intc_desc *parent;
+};
+
+struct intc_desc {
+ MemoryRegion iomem;
+ MemoryRegion *iomem_aliases;
+ qemu_irq *irqs;
+ struct intc_source *sources;
+ int nr_sources;
+ struct intc_mask_reg *mask_regs;
+ int nr_mask_regs;
+ struct intc_prio_reg *prio_regs;
+ int nr_prio_regs;
+ int pending; /* number of interrupt sources that has pending set */
+};
+
+int sh_intc_get_pending_vector(struct intc_desc *desc, int imask);
+
+void sh_intc_toggle_source(struct intc_source *source,
+ int enable_adj, int assert_adj);
+
+void sh_intc_register_sources(struct intc_desc *desc,
+ struct intc_vect *vectors,
+ int nr_vectors,
+ struct intc_group *groups,
+ int nr_groups);
+
+int sh_intc_init(MemoryRegion *sysmem,
+ struct intc_desc *desc,
+ int nr_sources,
+ struct intc_mask_reg *mask_regs,
+ int nr_mask_regs,
+ struct intc_prio_reg *prio_regs,
+ int nr_prio_regs);
+
+void sh_intc_set_irl(void *opaque, int n, int level);
+
+#endif /* SH_INTC_H */
diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h
new file mode 100644
index 000000000..6387f2b61
--- /dev/null
+++ b/include/hw/southbridge/piix.h
@@ -0,0 +1,79 @@
+/*
+ * QEMU PIIX South Bridge Emulation
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ * Copyright (c) 2018 Hervé Poussineau
+ *
+ * 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_SOUTHBRIDGE_PIIX_H
+#define HW_SOUTHBRIDGE_PIIX_H
+
+#include "hw/pci/pci.h"
+#include "qom/object.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);
+
+/* PIRQRC[A:D]: PIRQx Route Control Registers */
+#define PIIX_PIRQCA 0x60
+#define PIIX_PIRQCB 0x61
+#define PIIX_PIRQCC 0x62
+#define PIIX_PIRQCD 0x63
+
+/*
+ * Reset Control Register: PCI-accessible ISA-Compatible Register at address
+ * 0xcf9, provided by the PCI/ISA bridge (PIIX3 PCI function 0, 8086:7000).
+ */
+#define PIIX_RCR_IOPORT 0xcf9
+
+#define PIIX_NUM_PIC_IRQS 16 /* i8259 * 2 */
+#define PIIX_NUM_PIRQS 4ULL /* PIRQ[A-D] */
+
+struct PIIXState {
+ PCIDevice dev;
+
+ /*
+ * bitmap to track pic levels.
+ * The pic level is the logical OR of all the PCI irqs mapped to it
+ * 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
+ * pic_irq * PIIX_NUM_PIRQS + pirq
+ */
+#if PIIX_NUM_PIC_IRQS * PIIX_NUM_PIRQS > 64
+#error "unable to encode pic state in 64bit in pic_levels."
+#endif
+ uint64_t pic_levels;
+
+ qemu_irq *pic;
+
+ /* This member isn't used. Just for save/load compatibility */
+ int32_t pci_irq_levels_vmstate[PIIX_NUM_PIRQS];
+
+ /* Reset Control Register contents */
+ uint8_t rcr;
+
+ /* IO memory region for Reset Control Register (PIIX_RCR_IOPORT) */
+ MemoryRegion rcr_mem;
+};
+typedef struct PIIXState PIIX3State;
+
+#define TYPE_PIIX3_PCI_DEVICE "pci-piix3"
+DECLARE_INSTANCE_CHECKER(PIIX3State, PIIX3_PCI_DEVICE,
+ TYPE_PIIX3_PCI_DEVICE)
+
+extern PCIDevice *piix4_dev;
+
+PIIX3State *piix3_create(PCIBus *pci_bus, ISABus **isa_bus);
+
+DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus);
+
+#endif
diff --git a/include/hw/sparc/grlib.h b/include/hw/sparc/grlib.h
new file mode 100644
index 000000000..ef1946c7f
--- /dev/null
+++ b/include/hw/sparc/grlib.h
@@ -0,0 +1,45 @@
+/*
+ * QEMU GRLIB Components
+ *
+ * Copyright (c) 2010-2019 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_H
+#define GRLIB_H
+
+#include "hw/sysbus.h"
+
+/* Emulation of GrLib device is base on the GRLIB IP Core User's Manual:
+ * http://www.gaisler.com/products/grlib/grip.pdf
+ */
+
+/* IRQMP */
+#define TYPE_GRLIB_IRQMP "grlib-irqmp"
+
+void grlib_irqmp_ack(DeviceState *dev, int intno);
+
+/* GPTimer */
+#define TYPE_GRLIB_GPTIMER "grlib-gptimer"
+
+/* APB UART */
+#define TYPE_GRLIB_APB_UART "grlib-apbuart"
+
+#endif /* GRLIB_H */
diff --git a/include/hw/sparc/sparc32_dma.h b/include/hw/sparc/sparc32_dma.h
new file mode 100644
index 000000000..cde8ec02c
--- /dev/null
+++ b/include/hw/sparc/sparc32_dma.h
@@ -0,0 +1,63 @@
+#ifndef SPARC32_DMA_H
+#define SPARC32_DMA_H
+
+#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"
+OBJECT_DECLARE_SIMPLE_TYPE(DMADeviceState, SPARC32_DMA_DEVICE)
+
+
+struct DMADeviceState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ uint32_t dmaregs[DMA_REGS];
+ qemu_irq irq;
+ void *iommu;
+ qemu_irq gpio[2];
+};
+
+#define TYPE_SPARC32_ESPDMA_DEVICE "sparc32-espdma"
+OBJECT_DECLARE_SIMPLE_TYPE(ESPDMADeviceState, SPARC32_ESPDMA_DEVICE)
+
+struct ESPDMADeviceState {
+ DMADeviceState parent_obj;
+
+ SysBusESPState esp;
+};
+
+#define TYPE_SPARC32_LEDMA_DEVICE "sparc32-ledma"
+OBJECT_DECLARE_SIMPLE_TYPE(LEDMADeviceState, SPARC32_LEDMA_DEVICE)
+
+struct LEDMADeviceState {
+ DMADeviceState parent_obj;
+
+ SysBusPCNetState lance;
+};
+
+#define TYPE_SPARC32_DMA "sparc32-dma"
+OBJECT_DECLARE_SIMPLE_TYPE(SPARC32DMAState, SPARC32_DMA)
+
+struct SPARC32DMAState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion dmamem;
+ MemoryRegion ledma_alias;
+ ESPDMADeviceState espdma;
+ LEDMADeviceState ledma;
+};
+
+/* sparc32_dma.c */
+void ledma_memory_read(void *opaque, hwaddr addr,
+ uint8_t *buf, int len, int do_bswap);
+void ledma_memory_write(void *opaque, hwaddr addr,
+ uint8_t *buf, int len, int do_bswap);
+void espdma_memory_read(void *opaque, uint8_t *buf, int len);
+void espdma_memory_write(void *opaque, uint8_t *buf, int len);
+
+#endif
diff --git a/include/hw/sparc/sparc64.h b/include/hw/sparc/sparc64.h
new file mode 100644
index 000000000..4ced36fb5
--- /dev/null
+++ b/include/hw/sparc/sparc64.h
@@ -0,0 +1,12 @@
+#ifndef HW_SPARC_SPARC64_H
+#define HW_SPARC_SPARC64_H
+
+#include "target/sparc/cpu-qom.h"
+
+#define IVEC_MAX 0x40
+
+SPARCCPU *sparc64_cpu_devinit(const char *cpu_type, uint64_t prom_addr);
+
+void sparc64_cpu_set_ivec_irq(void *opaque, int irq, int level);
+
+#endif
diff --git a/include/hw/sparc/sun4m_iommu.h b/include/hw/sparc/sun4m_iommu.h
new file mode 100644
index 000000000..4e2ab34cd
--- /dev/null
+++ b/include/hw/sparc/sun4m_iommu.h
@@ -0,0 +1,53 @@
+/*
+ * QEMU Sun4m iommu emulation
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ *
+ * 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 SUN4M_IOMMU_H
+#define SUN4M_IOMMU_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define IOMMU_NREGS (4 * 4096 / 4)
+
+struct IOMMUState {
+ SysBusDevice parent_obj;
+
+ AddressSpace iommu_as;
+ IOMMUMemoryRegion iommu;
+
+ MemoryRegion iomem;
+ uint32_t regs[IOMMU_NREGS];
+ hwaddr iostart;
+ qemu_irq irq;
+ uint32_t version;
+};
+typedef struct IOMMUState IOMMUState;
+
+#define TYPE_SUN4M_IOMMU "sun4m-iommu"
+DECLARE_INSTANCE_CHECKER(IOMMUState, SUN4M_IOMMU,
+ TYPE_SUN4M_IOMMU)
+
+#define TYPE_SUN4M_IOMMU_MEMORY_REGION "sun4m-iommu-memory-region"
+
+#endif
diff --git a/include/hw/sparc/sun4u_iommu.h b/include/hw/sparc/sun4u_iommu.h
new file mode 100644
index 000000000..f94566a72
--- /dev/null
+++ b/include/hw/sparc/sun4u_iommu.h
@@ -0,0 +1,52 @@
+/*
+ * QEMU sun4u IOMMU emulation
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ * Copyright (c) 2012,2013 Artyom Tarasenko
+ * Copyright (c) 2017 Mark Cave-Ayland
+ *
+ * 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 SUN4U_IOMMU_H
+#define SUN4U_IOMMU_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define IOMMU_NREGS 3
+
+struct IOMMUState {
+ SysBusDevice parent_obj;
+
+ AddressSpace iommu_as;
+ IOMMUMemoryRegion iommu;
+
+ MemoryRegion iomem;
+ uint64_t regs[IOMMU_NREGS];
+};
+typedef struct IOMMUState IOMMUState;
+
+#define TYPE_SUN4U_IOMMU "sun4u-iommu"
+DECLARE_INSTANCE_CHECKER(IOMMUState, SUN4U_IOMMU,
+ TYPE_SUN4U_IOMMU)
+
+#define TYPE_SUN4U_IOMMU_MEMORY_REGION "sun4u-iommu-memory-region"
+
+#endif
diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h
new file mode 100644
index 000000000..e26555581
--- /dev/null
+++ b/include/hw/ssi/aspeed_smc.h
@@ -0,0 +1,116 @@
+/*
+ * ASPEED AST2400 SMC Controller (SPI Flash Only)
+ *
+ * Copyright (C) 2016 IBM Corp.
+ *
+ * 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 ASPEED_SMC_H
+#define ASPEED_SMC_H
+
+#include "hw/ssi/ssi.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+struct AspeedSMCState;
+
+#define TYPE_ASPEED_SMC_FLASH "aspeed.smc.flash"
+OBJECT_DECLARE_SIMPLE_TYPE(AspeedSMCFlash, ASPEED_SMC_FLASH)
+struct AspeedSMCFlash {
+ SysBusDevice parent_obj;
+
+ struct AspeedSMCState *controller;
+ uint8_t cs;
+
+ MemoryRegion mmio;
+};
+
+#define TYPE_ASPEED_SMC "aspeed.smc"
+OBJECT_DECLARE_TYPE(AspeedSMCState, AspeedSMCClass, ASPEED_SMC)
+
+#define ASPEED_SMC_R_MAX (0x100 / 4)
+#define ASPEED_SMC_CS_MAX 5
+
+struct AspeedSMCState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion mmio;
+ MemoryRegion mmio_flash_container;
+ MemoryRegion mmio_flash;
+
+ qemu_irq irq;
+
+ uint32_t num_cs;
+ qemu_irq *cs_lines;
+ bool inject_failure;
+
+ SSIBus *spi;
+
+ uint32_t regs[ASPEED_SMC_R_MAX];
+
+ /* depends on the controller type */
+ uint8_t r_conf;
+ uint8_t r_ce_ctrl;
+ uint8_t r_ctrl0;
+ uint8_t r_timings;
+ uint8_t conf_enable_w0;
+
+ AddressSpace flash_as;
+ MemoryRegion *dram_mr;
+ AddressSpace dram_as;
+
+ AspeedSMCFlash flashes[ASPEED_SMC_CS_MAX];
+
+ uint8_t snoop_index;
+ uint8_t snoop_dummies;
+};
+
+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 max_peripherals;
+ const uint32_t *resets;
+ const AspeedSegments *segments;
+ 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/imx_spi.h b/include/hw/ssi/imx_spi.h
new file mode 100644
index 000000000..eeaf49bba
--- /dev/null
+++ b/include/hw/ssi/imx_spi.h
@@ -0,0 +1,107 @@
+/*
+ * IMX SPI Controller
+ *
+ * Copyright 2016 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 IMX_SPI_H
+#define IMX_SPI_H
+
+#include "hw/sysbus.h"
+#include "hw/ssi/ssi.h"
+#include "qemu/bitops.h"
+#include "qemu/fifo32.h"
+#include "qom/object.h"
+
+#define ECSPI_FIFO_SIZE 64
+
+#define ECSPI_RXDATA 0
+#define ECSPI_TXDATA 1
+#define ECSPI_CONREG 2
+#define ECSPI_CONFIGREG 3
+#define ECSPI_INTREG 4
+#define ECSPI_DMAREG 5
+#define ECSPI_STATREG 6
+#define ECSPI_PERIODREG 7
+#define ECSPI_TESTREG 8
+#define ECSPI_MSGDATA 16
+#define ECSPI_MAX 17
+
+/* ECSPI_CONREG */
+#define ECSPI_CONREG_EN (1 << 0)
+#define ECSPI_CONREG_HT (1 << 1)
+#define ECSPI_CONREG_XCH (1 << 2)
+#define ECSPI_CONREG_SMC (1 << 3)
+#define ECSPI_CONREG_CHANNEL_MODE_SHIFT 4
+#define ECSPI_CONREG_CHANNEL_MODE_LENGTH 4
+#define ECSPI_CONREG_DRCTL_SHIFT 16
+#define ECSPI_CONREG_DRCTL_LENGTH 2
+#define ECSPI_CONREG_CHANNEL_SELECT_SHIFT 18
+#define ECSPI_CONREG_CHANNEL_SELECT_LENGTH 2
+#define ECSPI_CONREG_BURST_LENGTH_SHIFT 20
+#define ECSPI_CONREG_BURST_LENGTH_LENGTH 12
+
+/* ECSPI_CONFIGREG */
+#define ECSPI_CONFIGREG_SS_CTL_SHIFT 8
+#define ECSPI_CONFIGREG_SS_CTL_LENGTH 4
+
+/* ECSPI_INTREG */
+#define ECSPI_INTREG_TEEN (1 << 0)
+#define ECSPI_INTREG_TDREN (1 << 1)
+#define ECSPI_INTREG_TFEN (1 << 2)
+#define ECSPI_INTREG_RREN (1 << 3)
+#define ECSPI_INTREG_RDREN (1 << 4)
+#define ECSPI_INTREG_RFEN (1 << 5)
+#define ECSPI_INTREG_ROEN (1 << 6)
+#define ECSPI_INTREG_TCEN (1 << 7)
+
+/* ECSPI_DMAREG */
+#define ECSPI_DMAREG_RXTDEN (1 << 31)
+#define ECSPI_DMAREG_RXDEN (1 << 23)
+#define ECSPI_DMAREG_TEDEN (1 << 7)
+#define ECSPI_DMAREG_RX_THRESHOLD_SHIFT 16
+#define ECSPI_DMAREG_RX_THRESHOLD_LENGTH 6
+
+/* ECSPI_STATREG */
+#define ECSPI_STATREG_TE (1 << 0)
+#define ECSPI_STATREG_TDR (1 << 1)
+#define ECSPI_STATREG_TF (1 << 2)
+#define ECSPI_STATREG_RR (1 << 3)
+#define ECSPI_STATREG_RDR (1 << 4)
+#define ECSPI_STATREG_RF (1 << 5)
+#define ECSPI_STATREG_RO (1 << 6)
+#define ECSPI_STATREG_TC (1 << 7)
+
+#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"
+OBJECT_DECLARE_SIMPLE_TYPE(IMXSPIState, IMX_SPI)
+
+struct IMXSPIState {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /* <public> */
+ MemoryRegion iomem;
+
+ qemu_irq irq;
+
+ qemu_irq cs_lines[ECSPI_NUM_CS];
+
+ SSIBus *bus;
+
+ uint32_t regs[ECSPI_MAX];
+
+ Fifo32 rx_fifo;
+ Fifo32 tx_fifo;
+
+ int16_t burst_length;
+};
+
+#endif /* IMX_SPI_H */
diff --git a/include/hw/ssi/mss-spi.h b/include/hw/ssi/mss-spi.h
new file mode 100644
index 000000000..ce6279c43
--- /dev/null
+++ b/include/hw/ssi/mss-spi.h
@@ -0,0 +1,59 @@
+/*
+ * Microsemi SmartFusion2 SPI
+ *
+ * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@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.
+ */
+
+#ifndef HW_MSS_SPI_H
+#define HW_MSS_SPI_H
+
+#include "hw/sysbus.h"
+#include "hw/ssi/ssi.h"
+#include "qemu/fifo32.h"
+#include "qom/object.h"
+
+#define TYPE_MSS_SPI "mss-spi"
+OBJECT_DECLARE_SIMPLE_TYPE(MSSSpiState, MSS_SPI)
+
+#define R_SPI_MAX 16
+
+struct MSSSpiState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion mmio;
+
+ qemu_irq irq;
+
+ qemu_irq cs_line;
+
+ SSIBus *spi;
+
+ Fifo32 rx_fifo;
+ Fifo32 tx_fifo;
+
+ int fifo_depth;
+ uint32_t frame_count;
+ bool enabled;
+
+ uint32_t regs[R_SPI_MAX];
+};
+
+#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 000000000..a3a170428
--- /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/pl022.h b/include/hw/ssi/pl022.h
new file mode 100644
index 000000000..25d58db5f
--- /dev/null
+++ b/include/hw/ssi/pl022.h
@@ -0,0 +1,53 @@
+/*
+ * ARM PrimeCell PL022 Synchronous Serial Port
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * 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 Arm PrimeCell PL022 synchronous serial port.
+ * The PL022 TRM is:
+ * https://developer.arm.com/documentation/ddi0194/latest
+ *
+ * QEMU interface:
+ * + sysbus IRQ: SSPINTR combined interrupt line
+ * + sysbus MMIO region 0: MemoryRegion for the device's registers
+ */
+
+#ifndef HW_SSI_PL022_H
+#define HW_SSI_PL022_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_PL022 "pl022"
+OBJECT_DECLARE_SIMPLE_TYPE(PL022State, PL022)
+
+struct PL022State {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ uint32_t cr0;
+ uint32_t cr1;
+ uint32_t bitmask;
+ uint32_t sr;
+ uint32_t cpsr;
+ uint32_t is;
+ uint32_t im;
+ /* The FIFO head points to the next empty entry. */
+ int tx_fifo_head;
+ int rx_fifo_head;
+ int tx_fifo_len;
+ int rx_fifo_len;
+ uint16_t tx_fifo[8];
+ uint16_t rx_fifo[8];
+ qemu_irq irq;
+ SSIBus *ssi;
+};
+
+#endif
diff --git a/include/hw/ssi/sifive_spi.h b/include/hw/ssi/sifive_spi.h
new file mode 100644
index 000000000..47d0d6a47
--- /dev/null
+++ b/include/hw/ssi/sifive_spi.h
@@ -0,0 +1,47 @@
+/*
+ * 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
+
+#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
new file mode 100644
index 000000000..f411858ab
--- /dev/null
+++ b/include/hw/ssi/ssi.h
@@ -0,0 +1,109 @@
+/* QEMU Synchronous Serial Interface support. */
+
+/*
+ * 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 enum SSICSMode SSICSMode;
+
+#define TYPE_SSI_PERIPHERAL "ssi-peripheral"
+OBJECT_DECLARE_TYPE(SSIPeripheral, SSIPeripheralClass,
+ SSI_PERIPHERAL)
+
+#define SSI_GPIO_CS "ssi-gpio-cs"
+
+enum SSICSMode {
+ SSI_CS_NONE = 0,
+ SSI_CS_LOW,
+ SSI_CS_HIGH,
+};
+
+/* Peripherals. */
+struct SSIPeripheralClass {
+ DeviceClass parent_class;
+
+ 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)(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)(SSIPeripheral *dev, bool select);
+ /* define whether or not CS exists and is active low/high */
+ SSICSMode cs_polarity;
+
+ /* if you have non-standard CS behaviour override this to take control
+ * of the CS behaviour at the device level. transfer, set_cs, and
+ * 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)(SSIPeripheral *dev, uint32_t val);
+};
+
+struct SSIPeripheral {
+ DeviceState parent_obj;
+
+ /* Chip select state */
+ bool cs;
+};
+
+extern const VMStateDescription vmstate_ssi_peripheral;
+
+#define VMSTATE_SSI_PERIPHERAL(_field, _state) { \
+ .name = (stringify(_field)), \
+ .size = sizeof(SSIPeripheral), \
+ .vmsd = &vmstate_ssi_peripheral, \
+ .flags = VMS_STRUCT, \
+ .offset = vmstate_offset_value(_state, _field, SSIPeripheral), \
+}
+
+DeviceState *ssi_create_peripheral(SSIBus *bus, const char *name);
+/**
+ * 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
+ *
+ * Call 'realize' on @dev, put it on the specified @bus, and drop the
+ * reference to it. Errors are reported via @errp and by returning
+ * false.
+ *
+ * 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_peripheral() is probably better (as it
+ * does the create, init and realize in one step).
+ *
+ * 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
+ * via the child<> property, and so the reference-count-drop done here
+ * would be incorrect. (Instead you would want ssi_realize(), which
+ * doesn't currently exist but would be trivial to create if we had
+ * any code that wanted it.)
+ */
+bool ssi_realize_and_unref(DeviceState *dev, SSIBus *bus, Error **errp);
+
+/* Master interface. */
+SSIBus *ssi_create_bus(DeviceState *parent, const char *name);
+
+uint32_t ssi_transfer(SSIBus *bus, uint32_t val);
+
+#endif
diff --git a/include/hw/ssi/stm32f2xx_spi.h b/include/hw/ssi/stm32f2xx_spi.h
new file mode 100644
index 000000000..3683b4ad3
--- /dev/null
+++ b/include/hw/ssi/stm32f2xx_spi.h
@@ -0,0 +1,71 @@
+/*
+ * STM32F2XX SPI
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * 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_STM32F2XX_SPI_H
+#define HW_STM32F2XX_SPI_H
+
+#include "hw/sysbus.h"
+#include "hw/ssi/ssi.h"
+#include "qom/object.h"
+
+#define STM_SPI_CR1 0x00
+#define STM_SPI_CR2 0x04
+#define STM_SPI_SR 0x08
+#define STM_SPI_DR 0x0C
+#define STM_SPI_CRCPR 0x10
+#define STM_SPI_RXCRCR 0x14
+#define STM_SPI_TXCRCR 0x18
+#define STM_SPI_I2SCFGR 0x1C
+#define STM_SPI_I2SPR 0x20
+
+#define STM_SPI_CR1_SPE (1 << 6)
+#define STM_SPI_CR1_MSTR (1 << 2)
+
+#define STM_SPI_SR_RXNE 1
+
+#define TYPE_STM32F2XX_SPI "stm32f2xx-spi"
+OBJECT_DECLARE_SIMPLE_TYPE(STM32F2XXSPIState, STM32F2XX_SPI)
+
+struct STM32F2XXSPIState {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /* <public> */
+ MemoryRegion mmio;
+
+ uint32_t spi_cr1;
+ uint32_t spi_cr2;
+ uint32_t spi_sr;
+ uint32_t spi_dr;
+ uint32_t spi_crcpr;
+ uint32_t spi_rxcrcr;
+ uint32_t spi_txcrcr;
+ uint32_t spi_i2scfgr;
+ uint32_t spi_i2spr;
+
+ qemu_irq irq;
+ SSIBus *ssi;
+};
+
+#endif /* HW_STM32F2XX_SPI_H */
diff --git a/include/hw/ssi/xilinx_spips.h b/include/hw/ssi/xilinx_spips.h
new file mode 100644
index 000000000..06bfd1831
--- /dev/null
+++ b/include/hw/ssi/xilinx_spips.h
@@ -0,0 +1,143 @@
+/*
+ * Header file for the Xilinx Zynq SPI controller
+ *
+ * Copyright (C) 2015 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 XILINX_SPIPS_H
+#define XILINX_SPIPS_H
+
+#include "hw/ssi/ssi.h"
+#include "qemu/fifo32.h"
+#include "hw/stream.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+typedef struct XilinxSPIPS XilinxSPIPS;
+
+#define XLNX_SPIPS_R_MAX (0x100 / 4)
+#define XLNX_ZYNQMP_SPIPS_R_MAX (0x200 / 4)
+
+/* Bite off 4k chunks at a time */
+#define LQSPI_CACHE_SIZE 1024
+
+#define QSPI_DMA_MAX_BURST_SIZE 2048
+
+typedef enum {
+ READ = 0x3, READ_4 = 0x13,
+ FAST_READ = 0xb, FAST_READ_4 = 0x0c,
+ DOR = 0x3b, DOR_4 = 0x3c,
+ QOR = 0x6b, QOR_4 = 0x6c,
+ DIOR = 0xbb, DIOR_4 = 0xbc,
+ QIOR = 0xeb, QIOR_4 = 0xec,
+
+ PP = 0x2, PP_4 = 0x12,
+ DPP = 0xa2,
+ QPP = 0x32, QPP_4 = 0x34,
+} FlashCMD;
+
+struct XilinxSPIPS {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ MemoryRegion mmlqspi;
+
+ qemu_irq irq;
+ int irqline;
+
+ uint8_t num_cs;
+ uint8_t num_busses;
+
+ uint8_t snoop_state;
+ int cmd_dummies;
+ uint8_t link_state;
+ uint8_t link_state_next;
+ uint8_t link_state_next_when;
+ qemu_irq *cs_lines;
+ bool *cs_lines_state;
+ SSIBus **spi;
+
+ Fifo8 rx_fifo;
+ Fifo8 tx_fifo;
+
+ uint8_t num_txrx_bytes;
+ uint32_t rx_discard;
+
+ uint32_t regs[XLNX_SPIPS_R_MAX];
+
+ bool man_start_com;
+};
+
+struct XilinxQSPIPS {
+ XilinxSPIPS parent_obj;
+
+ uint8_t lqspi_buf[LQSPI_CACHE_SIZE];
+ hwaddr lqspi_cached_addr;
+ Error *migration_blocker;
+ bool mmio_execution_enabled;
+};
+typedef struct XilinxQSPIPS XilinxQSPIPS;
+
+struct XlnxZynqMPQSPIPS {
+ XilinxQSPIPS parent_obj;
+
+ StreamSink *dma;
+ int gqspi_irqline;
+
+ uint32_t regs[XLNX_ZYNQMP_SPIPS_R_MAX];
+
+ /* GQSPI has seperate tx/rx fifos */
+ Fifo8 rx_fifo_g;
+ Fifo8 tx_fifo_g;
+ Fifo32 fifo_g;
+ /*
+ * At the end of each generic command, misaligned extra bytes are discard
+ * or padded to tx and rx respectively to round it out (and avoid need for
+ * individual byte access. Since we use byte fifos, keep track of the
+ * alignment WRT to word access.
+ */
+ uint8_t rx_fifo_g_align;
+ uint8_t tx_fifo_g_align;
+ bool man_start_com_g;
+ uint32_t dma_burst_size;
+ uint8_t dma_buf[QSPI_DMA_MAX_BURST_SIZE];
+};
+
+struct XilinxSPIPSClass {
+ SysBusDeviceClass parent_class;
+
+ const MemoryRegionOps *reg_ops;
+
+ uint32_t rx_fifo_size;
+ uint32_t tx_fifo_size;
+};
+
+#define TYPE_XILINX_SPIPS "xlnx.ps7-spi"
+#define TYPE_XILINX_QSPIPS "xlnx.ps7-qspi"
+#define TYPE_XLNX_ZYNQMP_QSPIPS "xlnx.usmp-gqspi"
+
+OBJECT_DECLARE_TYPE(XilinxSPIPS, XilinxSPIPSClass, XILINX_SPIPS)
+
+OBJECT_DECLARE_SIMPLE_TYPE(XilinxQSPIPS, XILINX_QSPIPS)
+
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPQSPIPS, XLNX_ZYNQMP_QSPIPS)
+
+#endif /* XILINX_SPIPS_H */
diff --git a/include/hw/stream.h b/include/hw/stream.h
new file mode 100644
index 000000000..f166facb0
--- /dev/null
+++ b/include/hw/stream.h
@@ -0,0 +1,53 @@
+#ifndef STREAM_H
+#define STREAM_H
+
+#include "qom/object.h"
+
+#define TYPE_STREAM_SINK "stream-sink"
+
+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 StreamSink StreamSink;
+
+typedef void (*StreamCanPushNotifyFn)(void *opaque);
+
+struct StreamSinkClass {
+ InterfaceClass parent;
+ /**
+ * 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
+ * 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)(StreamSink *obj, StreamCanPushNotifyFn notify,
+ void *notify_opaque);
+ /**
+ * 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 sink is ready to receive again, otherwise polling on a QEMU
+ * timer will work.
+ * @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)(StreamSink *obj, unsigned char *buf, size_t len, bool eop);
+};
+
+size_t
+stream_push(StreamSink *sink, uint8_t *buf, size_t len, bool eop);
+
+bool
+stream_can_push(StreamSink *sink, StreamCanPushNotifyFn notify,
+ void *notify_opaque);
+
+
+#endif /* STREAM_H */
diff --git a/include/hw/sysbus.h b/include/hw/sysbus.h
new file mode 100644
index 000000000..3564b7b6a
--- /dev/null
+++ b/include/hw/sysbus.h
@@ -0,0 +1,107 @@
+#ifndef HW_SYSBUS_H
+#define HW_SYSBUS_H
+
+/* Devices attached directly to the main system bus. */
+
+#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"
+DECLARE_INSTANCE_CHECKER(BusState, SYSTEM_BUS,
+ TYPE_SYSTEM_BUS)
+
+
+#define TYPE_SYS_BUS_DEVICE "sys-bus-device"
+OBJECT_DECLARE_TYPE(SysBusDevice, SysBusDeviceClass,
+ SYS_BUS_DEVICE)
+
+/**
+ * SysBusDeviceClass:
+ *
+ * SysBusDeviceClass is not overriding #DeviceClass.realize, so derived
+ * classes overriding it are not required to invoke its implementation.
+ */
+
+#define SYSBUS_DEVICE_GPIO_IRQ "sysbus-irq"
+
+struct SysBusDeviceClass {
+ /*< private >*/
+ DeviceClass parent_class;
+
+ /*
+ * Let the sysbus device format its own non-PIO, non-MMIO unit address.
+ *
+ * Sometimes a class of SysBusDevices has neither MMIO nor PIO resources,
+ * yet instances of it would like to distinguish themselves, in
+ * OpenFirmware device paths, from other instances of the same class on the
+ * sysbus. For that end we expose this callback.
+ *
+ * The implementation is not supposed to change *@dev, or incur other
+ * observable change.
+ *
+ * The function returns a dynamically allocated string. On error, NULL
+ * should be returned; the unit address portion of the OFW node will be
+ * omitted then. (This is not considered a fatal error.)
+ */
+ char *(*explicit_ofw_unit_address)(const SysBusDevice *dev);
+ void (*connect_irq_notifier)(SysBusDevice *dev, qemu_irq irq);
+};
+
+struct SysBusDevice {
+ /*< private >*/
+ DeviceState parent_obj;
+ /*< public >*/
+
+ int num_mmio;
+ struct {
+ hwaddr addr;
+ MemoryRegion *memory;
+ } mmio[QDEV_MAX_MMIO];
+ int num_pio;
+ uint32_t pio[QDEV_MAX_PIO];
+};
+
+typedef void FindSysbusDeviceFunc(SysBusDevice *sbdev, void *opaque);
+
+void sysbus_init_mmio(SysBusDevice *dev, MemoryRegion *memory);
+MemoryRegion *sysbus_mmio_get_region(SysBusDevice *dev, int n);
+void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p);
+void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target);
+void sysbus_init_ioports(SysBusDevice *dev, uint32_t ioport, uint32_t size);
+
+
+bool sysbus_has_irq(SysBusDevice *dev, int n);
+bool sysbus_has_mmio(SysBusDevice *dev, unsigned int n);
+void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq);
+bool sysbus_is_irq_connected(SysBusDevice *dev, int n);
+qemu_irq sysbus_get_connected_irq(SysBusDevice *dev, int n);
+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);
+
+/* Call func for every dynamically created sysbus device in the system */
+void foreach_dynamic_sysbus_device(FindSysbusDeviceFunc *func, void *opaque);
+
+/* Legacy helper function for creating devices. */
+DeviceState *sysbus_create_varargs(const char *name,
+ hwaddr addr, ...);
+
+static inline DeviceState *sysbus_create_simple(const char *name,
+ hwaddr addr,
+ qemu_irq irq)
+{
+ return sysbus_create_varargs(name, addr, irq, NULL);
+}
+
+#endif /* HW_SYSBUS_H */
diff --git a/include/hw/timer/a9gtimer.h b/include/hw/timer/a9gtimer.h
new file mode 100644
index 000000000..6ae9122e4
--- /dev/null
+++ b/include/hw/timer/a9gtimer.h
@@ -0,0 +1,97 @@
+/*
+ * Global peripheral timer block for ARM A9MP
+ *
+ * (C) 2013 Xilinx Inc.
+ *
+ * Written by François LEGAL
+ * Written by Peter Crosthwaite <peter.crosthwaite@xilinx.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 A9GTIMER_H
+#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"
+OBJECT_DECLARE_SIMPLE_TYPE(A9GTimerState, A9_GTIMER)
+
+#define R_COUNTER_LO 0x00
+#define R_COUNTER_HI 0x04
+
+#define R_CONTROL 0x08
+#define R_CONTROL_TIMER_ENABLE (1 << 0)
+#define R_CONTROL_COMP_ENABLE (1 << 1)
+#define R_CONTROL_IRQ_ENABLE (1 << 2)
+#define R_CONTROL_AUTO_INCREMENT (1 << 3)
+#define R_CONTROL_PRESCALER_SHIFT 8
+#define R_CONTROL_PRESCALER_LEN 8
+#define R_CONTROL_PRESCALER_MASK (((1 << R_CONTROL_PRESCALER_LEN) - 1) << \
+ R_CONTROL_PRESCALER_SHIFT)
+
+#define R_CONTROL_BANKED (R_CONTROL_COMP_ENABLE | \
+ R_CONTROL_IRQ_ENABLE | \
+ R_CONTROL_AUTO_INCREMENT)
+#define R_CONTROL_NEEDS_SYNC (R_CONTROL_TIMER_ENABLE | \
+ R_CONTROL_PRESCALER_MASK)
+
+#define R_INTERRUPT_STATUS 0x0C
+#define R_COMPARATOR_LO 0x10
+#define R_COMPARATOR_HI 0x14
+#define R_AUTO_INCREMENT 0x18
+
+typedef struct A9GTimerPerCPU A9GTimerPerCPU;
+
+struct A9GTimerPerCPU {
+ A9GTimerState *parent;
+
+ uint32_t control; /* only per cpu banked bits valid */
+ uint64_t compare;
+ uint32_t status;
+ uint32_t inc;
+
+ MemoryRegion iomem;
+ qemu_irq irq; /* PPI interrupts */
+};
+
+struct A9GTimerState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ MemoryRegion iomem;
+ /* static props */
+ uint32_t num_cpu;
+
+ QEMUTimer *timer;
+
+ uint64_t counter; /* current timer value */
+
+ uint64_t ref_counter;
+ uint64_t cpu_ref_time; /* the cpu time as of last update of ref_counter */
+ uint32_t control; /* only non per cpu banked bits valid */
+
+ A9GTimerPerCPU per_cpu[A9_GTIMER_MAX_CPUS];
+};
+
+typedef struct A9GTimerUpdate {
+ uint64_t now;
+ uint64_t new;
+} A9GTimerUpdate;
+
+#endif /* A9GTIMER_H */
diff --git a/include/hw/timer/allwinner-a10-pit.h b/include/hw/timer/allwinner-a10-pit.h
new file mode 100644
index 000000000..8435758ad
--- /dev/null
+++ b/include/hw/timer/allwinner-a10-pit.h
@@ -0,0 +1,68 @@
+#ifndef ALLWINNER_A10_PIT_H
+#define ALLWINNER_A10_PIT_H
+
+#include "hw/ptimer.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_AW_A10_PIT "allwinner-A10-timer"
+OBJECT_DECLARE_SIMPLE_TYPE(AwA10PITState, AW_A10_PIT)
+
+#define AW_A10_PIT_TIMER_NR 6
+#define AW_A10_PIT_TIMER_IRQ 0x1
+#define AW_A10_PIT_WDOG_IRQ 0x100
+
+#define AW_A10_PIT_TIMER_IRQ_EN 0
+#define AW_A10_PIT_TIMER_IRQ_ST 0x4
+
+#define AW_A10_PIT_TIMER_CONTROL 0x0
+#define AW_A10_PIT_TIMER_EN 0x1
+#define AW_A10_PIT_TIMER_RELOAD 0x2
+#define AW_A10_PIT_TIMER_MODE 0x80
+
+#define AW_A10_PIT_TIMER_INTERVAL 0x4
+#define AW_A10_PIT_TIMER_COUNT 0x8
+#define AW_A10_PIT_WDOG_CONTROL 0x90
+#define AW_A10_PIT_WDOG_MODE 0x94
+
+#define AW_A10_PIT_COUNT_CTL 0xa0
+#define AW_A10_PIT_COUNT_RL_EN 0x2
+#define AW_A10_PIT_COUNT_CLR_EN 0x1
+#define AW_A10_PIT_COUNT_LO 0xa4
+#define AW_A10_PIT_COUNT_HI 0xa8
+
+#define AW_A10_PIT_TIMER_BASE 0x10
+#define AW_A10_PIT_TIMER_BASE_END \
+ (AW_A10_PIT_TIMER_BASE * 6 + AW_A10_PIT_TIMER_COUNT)
+
+#define AW_A10_PIT_DEFAULT_CLOCK 0x4
+
+
+typedef struct AwA10TimerContext {
+ AwA10PITState *container;
+ int index;
+} AwA10TimerContext;
+
+struct AwA10PITState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+ qemu_irq irq[AW_A10_PIT_TIMER_NR];
+ ptimer_state * timer[AW_A10_PIT_TIMER_NR];
+ AwA10TimerContext timer_context[AW_A10_PIT_TIMER_NR];
+ MemoryRegion iomem;
+ uint32_t clk_freq[4];
+
+ uint32_t irq_enable;
+ uint32_t irq_status;
+ uint32_t control[AW_A10_PIT_TIMER_NR];
+ uint32_t interval[AW_A10_PIT_TIMER_NR];
+ uint32_t count[AW_A10_PIT_TIMER_NR];
+ uint32_t watch_dog_mode;
+ uint32_t watch_dog_control;
+ uint32_t count_lo;
+ uint32_t count_hi;
+ uint32_t count_ctl;
+};
+
+#endif
diff --git a/include/hw/timer/arm_mptimer.h b/include/hw/timer/arm_mptimer.h
new file mode 100644
index 000000000..65a96e2a0
--- /dev/null
+++ b/include/hw/timer/arm_mptimer.h
@@ -0,0 +1,51 @@
+/*
+ * Private peripheral timer/watchdog blocks for ARM 11MPCore and A9MP
+ *
+ * Copyright (c) 2006-2007 CodeSourcery.
+ * Copyright (c) 2011 Linaro Limited
+ * Written by Paul Brook, Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef HW_TIMER_ARM_MPTIMER_H
+#define HW_TIMER_ARM_MPTIMER_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define ARM_MPTIMER_MAX_CPUS 4
+
+/* State of a single timer or watchdog block */
+typedef struct {
+ uint32_t control;
+ uint32_t status;
+ struct ptimer_state *timer;
+ qemu_irq irq;
+ MemoryRegion iomem;
+} TimerBlock;
+
+#define TYPE_ARM_MPTIMER "arm_mptimer"
+OBJECT_DECLARE_SIMPLE_TYPE(ARMMPTimerState, ARM_MPTIMER)
+
+struct ARMMPTimerState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ uint32_t num_cpu;
+ TimerBlock timerblock[ARM_MPTIMER_MAX_CPUS];
+ MemoryRegion iomem;
+};
+
+#endif
diff --git a/include/hw/timer/armv7m_systick.h b/include/hw/timer/armv7m_systick.h
new file mode 100644
index 000000000..ee09b1388
--- /dev/null
+++ b/include/hw/timer/armv7m_systick.h
@@ -0,0 +1,50 @@
+/*
+ * ARMv7M SysTick timer
+ *
+ * Copyright (c) 2006-2007 CodeSourcery.
+ * Written by Paul Brook
+ * Copyright (c) 2017 Linaro Ltd
+ * Written by Peter Maydell
+ *
+ * This code is licensed under the GPL (version 2 or later).
+ */
+
+#ifndef HW_TIMER_ARMV7M_SYSTICK_H
+#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"
+
+OBJECT_DECLARE_SIMPLE_TYPE(SysTickState, SYSTICK)
+
+/*
+ * 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 >*/
+
+ uint32_t control;
+ uint32_t reload;
+ int64_t tick;
+ ptimer_state *ptimer;
+ MemoryRegion iomem;
+ qemu_irq irq;
+ Clock *refclk;
+ Clock *cpuclk;
+};
+
+#endif
diff --git a/include/hw/timer/aspeed_timer.h b/include/hw/timer/aspeed_timer.h
new file mode 100644
index 000000000..d36034a10
--- /dev/null
+++ b/include/hw/timer/aspeed_timer.h
@@ -0,0 +1,77 @@
+/*
+ * ASPEED AST2400 Timer
+ *
+ * Andrew Jeffery <andrew@aj.id.au>
+ *
+ * Copyright (C) 2016 IBM Corp.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef ASPEED_TIMER_H
+#define ASPEED_TIMER_H
+
+#include "qemu/timer.h"
+#include "hw/misc/aspeed_scu.h"
+#include "qom/object.h"
+
+#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 ASPEED_TIMER_NR_TIMERS 8
+
+typedef struct AspeedTimer {
+ qemu_irq irq;
+
+ uint8_t id;
+ QEMUTimer timer;
+
+ /**
+ * Track the line level as the ASPEED timers implement edge triggered
+ * interrupts, signalling with both the rising and falling edge.
+ */
+ int32_t level;
+ uint32_t reload;
+ uint32_t match[2];
+ uint64_t start;
+} AspeedTimer;
+
+struct AspeedTimerCtrlState {
+ /*< private >*/
+ SysBusDevice parent;
+
+ /*< public >*/
+ MemoryRegion iomem;
+
+ uint32_t ctrl;
+ uint32_t ctrl2;
+ uint32_t ctrl3;
+ uint32_t irq_sts;
+ AspeedTimer timers[ASPEED_TIMER_NR_TIMERS];
+
+ AspeedSCUState *scu;
+};
+
+
+struct AspeedTimerClass {
+ SysBusDeviceClass parent_class;
+
+ uint64_t (*read)(AspeedTimerCtrlState *s, hwaddr offset);
+ void (*write)(AspeedTimerCtrlState *s, hwaddr offset, uint64_t value);
+};
+
+#endif /* ASPEED_TIMER_H */
diff --git a/include/hw/timer/avr_timer16.h b/include/hw/timer/avr_timer16.h
new file mode 100644
index 000000000..a1a032a24
--- /dev/null
+++ b/include/hw/timer/avr_timer16.h
@@ -0,0 +1,93 @@
+/*
+ * AVR 16-bit timer
+ *
+ * Copyright (c) 2018 University of Kent
+ * Author: Ed Robbins
+ *
+ * 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/lgpl-2.1.html>
+ */
+
+/*
+ * Driver for 16 bit timers on 8 bit AVR devices.
+ * Note:
+ * On ATmega640/V-1280/V-1281/V-2560/V-2561/V timers 1, 3, 4 and 5 are 16 bit
+ */
+
+#ifndef HW_TIMER_AVR_TIMER16_H
+#define HW_TIMER_AVR_TIMER16_H
+
+#include "hw/sysbus.h"
+#include "qemu/timer.h"
+#include "qom/object.h"
+
+enum NextInterrupt {
+ OVERFLOW,
+ COMPA,
+ COMPB,
+ COMPC,
+ CAPT
+};
+
+#define TYPE_AVR_TIMER16 "avr-timer16"
+OBJECT_DECLARE_SIMPLE_TYPE(AVRTimer16State, AVR_TIMER16)
+
+struct AVRTimer16State {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /* <public> */
+ MemoryRegion iomem;
+ MemoryRegion imsk_iomem;
+ MemoryRegion ifr_iomem;
+ QEMUTimer *timer;
+ qemu_irq capt_irq;
+ qemu_irq compa_irq;
+ qemu_irq compb_irq;
+ qemu_irq compc_irq;
+ qemu_irq ovf_irq;
+
+ bool enabled;
+
+ /* registers */
+ uint8_t cra;
+ uint8_t crb;
+ uint8_t crc;
+ uint8_t cntl;
+ uint8_t cnth;
+ uint8_t icrl;
+ uint8_t icrh;
+ uint8_t ocral;
+ uint8_t ocrah;
+ uint8_t ocrbl;
+ uint8_t ocrbh;
+ uint8_t ocrcl;
+ uint8_t ocrch;
+ /*
+ * Reads and writes to CNT and ICR utilise a bizarre temporary
+ * register, which we emulate
+ */
+ uint8_t rtmp;
+ uint8_t imsk;
+ uint8_t ifr;
+
+ uint8_t id;
+ uint64_t cpu_freq_hz;
+ uint64_t freq_hz;
+ uint64_t period_ns;
+ uint64_t reset_time_ns;
+ enum NextInterrupt next_interrupt;
+};
+
+#endif /* HW_TIMER_AVR_TIMER16_H */
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
new file mode 100644
index 000000000..bd3097d74
--- /dev/null
+++ b/include/hw/timer/bcm2835_systmr.h
@@ -0,0 +1,42 @@
+/*
+ * BCM2835 SYS timer emulation
+ *
+ * Copyright (c) 2019 Philippe Mathieu-Daudé <f4bug@amsat.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef BCM2835_SYSTIMER_H
+#define BCM2835_SYSTIMER_H
+
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "qemu/timer.h"
+#include "qom/object.h"
+
+#define TYPE_BCM2835_SYSTIMER "bcm2835-sys-timer"
+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;
+ struct {
+ uint32_t ctrl_status;
+ uint32_t compare[BCM2835_SYSTIMER_COUNT];
+ } reg;
+ BCM2835SystemTimerCompare tmr[BCM2835_SYSTIMER_COUNT];
+};
+
+#endif
diff --git a/include/hw/timer/cmsdk-apb-dualtimer.h b/include/hw/timer/cmsdk-apb-dualtimer.h
new file mode 100644
index 000000000..f3ec86c00
--- /dev/null
+++ b/include/hw/timer/cmsdk-apb-dualtimer.h
@@ -0,0 +1,72 @@
+/*
+ * ARM CMSDK APB dual-timer emulation
+ *
+ * Copyright (c) 2018 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 "APB dual-input timer" which is part of the Cortex-M
+ * System Design Kit (CMSDK) and documented in the Cortex-M System
+ * Design Kit Technical Reference Manual (ARM DDI0479C):
+ * https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
+ *
+ * QEMU interface:
+ * + 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
+ * + sysbus IRQ 2: timer block 2 interrupt TIMINT2
+ */
+
+#ifndef CMSDK_APB_DUALTIMER_H
+#define CMSDK_APB_DUALTIMER_H
+
+#include "hw/sysbus.h"
+#include "hw/ptimer.h"
+#include "hw/clock.h"
+#include "qom/object.h"
+
+#define TYPE_CMSDK_APB_DUALTIMER "cmsdk-apb-dualtimer"
+OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBDualTimer, CMSDK_APB_DUALTIMER)
+
+
+/* One of the two identical timer modules in the dual-timer module */
+typedef struct CMSDKAPBDualTimerModule {
+ CMSDKAPBDualTimer *parent;
+ struct ptimer_state *timer;
+ qemu_irq timerint;
+ /*
+ * We must track the guest LOAD and VALUE register state by hand
+ * rather than leaving this state only in the ptimer limit/count,
+ * because if CONTROL.SIZE is 0 then only the low 16 bits of the
+ * counter actually counts, but the high half is still guest
+ * accessible.
+ */
+ uint32_t load;
+ uint32_t value;
+ uint32_t control;
+ uint32_t intstatus;
+} CMSDKAPBDualTimerModule;
+
+#define CMSDK_APB_DUALTIMER_NUM_MODULES 2
+
+struct CMSDKAPBDualTimer {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+ qemu_irq timerintc;
+ Clock *timclk;
+
+ CMSDKAPBDualTimerModule timermod[CMSDK_APB_DUALTIMER_NUM_MODULES];
+ uint32_t timeritcr;
+ uint32_t timeritop;
+};
+
+#endif
diff --git a/include/hw/timer/cmsdk-apb-timer.h b/include/hw/timer/cmsdk-apb-timer.h
new file mode 100644
index 000000000..c4c7eae84
--- /dev/null
+++ b/include/hw/timer/cmsdk-apb-timer.h
@@ -0,0 +1,46 @@
+/*
+ * ARM CMSDK APB timer emulation
+ *
+ * Copyright (c) 2017 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 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"
+OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBTimer, CMSDK_APB_TIMER)
+
+/*
+ * 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;
+ struct ptimer_state *timer;
+ Clock *pclk;
+
+ uint32_t ctrl;
+ uint32_t value;
+ uint32_t reload;
+ uint32_t intstatus;
+};
+
+#endif
diff --git a/include/hw/timer/digic-timer.h b/include/hw/timer/digic-timer.h
new file mode 100644
index 000000000..da82fb466
--- /dev/null
+++ b/include/hw/timer/digic-timer.h
@@ -0,0 +1,46 @@
+/*
+ * Canon DIGIC timer block declarations.
+ *
+ * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.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 HW_TIMER_DIGIC_TIMER_H
+#define HW_TIMER_DIGIC_TIMER_H
+
+#include "hw/sysbus.h"
+#include "hw/ptimer.h"
+#include "qom/object.h"
+
+#define TYPE_DIGIC_TIMER "digic-timer"
+OBJECT_DECLARE_SIMPLE_TYPE(DigicTimerState, DIGIC_TIMER)
+
+#define DIGIC_TIMER_CONTROL 0x00
+#define DIGIC_TIMER_CONTROL_RST 0x80000000
+#define DIGIC_TIMER_CONTROL_EN 0x00000001
+#define DIGIC_TIMER_RELVALUE 0x08
+#define DIGIC_TIMER_VALUE 0x0c
+
+struct DigicTimerState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ MemoryRegion iomem;
+ ptimer_state *ptimer;
+
+ uint32_t control;
+ uint32_t relvalue;
+};
+
+#endif /* HW_TIMER_DIGIC_TIMER_H */
diff --git a/include/hw/timer/hpet.h b/include/hw/timer/hpet.h
new file mode 100644
index 000000000..f04c4d323
--- /dev/null
+++ b/include/hw/timer/hpet.h
@@ -0,0 +1,86 @@
+/*
+ * QEMU Emulated HPET support
+ *
+ * Copyright IBM, Corp. 2008
+ *
+ * Authors:
+ * Beth Kon <bkon@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 HW_HPET_H
+#define HW_HPET_H
+
+#include "qom/object.h"
+
+#define HPET_BASE 0xfed00000
+#define HPET_LEN 0x400
+#define HPET_CLK_PERIOD 10 /* 10 ns*/
+
+#define FS_PER_NS 1000000 /* 1000000 femtoseconds == 1 ns */
+#define HPET_MIN_TIMERS 3
+#define HPET_MAX_TIMERS 32
+
+#define HPET_NUM_IRQ_ROUTES 32
+
+#define HPET_LEGACY_PIT_INT 0
+#define HPET_LEGACY_RTC_INT 1
+
+#define HPET_CFG_ENABLE 0x001
+#define HPET_CFG_LEGACY 0x002
+
+#define HPET_ID 0x000
+#define HPET_PERIOD 0x004
+#define HPET_CFG 0x010
+#define HPET_STATUS 0x020
+#define HPET_COUNTER 0x0f0
+#define HPET_TN_CFG 0x000
+#define HPET_TN_CMP 0x008
+#define HPET_TN_ROUTE 0x010
+#define HPET_CFG_WRITE_MASK 0x3
+
+#define HPET_ID_NUM_TIM_SHIFT 8
+#define HPET_ID_NUM_TIM_MASK 0x1f00
+
+#define HPET_TN_TYPE_LEVEL 0x002
+#define HPET_TN_ENABLE 0x004
+#define HPET_TN_PERIODIC 0x008
+#define HPET_TN_PERIODIC_CAP 0x010
+#define HPET_TN_SIZE_CAP 0x020
+#define HPET_TN_SETVAL 0x040
+#define HPET_TN_32BIT 0x100
+#define HPET_TN_INT_ROUTE_MASK 0x3e00
+#define HPET_TN_FSB_ENABLE 0x4000
+#define HPET_TN_FSB_CAP 0x8000
+#define HPET_TN_CFG_WRITE_MASK 0x7f4e
+#define HPET_TN_INT_ROUTE_SHIFT 9
+#define HPET_TN_INT_ROUTE_CAP_SHIFT 32
+#define HPET_TN_CFG_BITS_READONLY_OR_RESERVED 0xffff80b1U
+
+struct hpet_fw_entry
+{
+ uint32_t event_timer_block_id;
+ uint64_t address;
+ uint16_t min_tick;
+ uint8_t page_prot;
+} QEMU_PACKED;
+
+struct hpet_fw_config
+{
+ uint8_t count;
+ struct hpet_fw_entry hpet[8];
+} QEMU_PACKED;
+
+extern struct hpet_fw_config hpet_cfg;
+
+#define TYPE_HPET "hpet"
+
+static inline bool hpet_find(void)
+{
+ return object_resolve_path_type("", TYPE_HPET, NULL);
+}
+
+#endif
diff --git a/include/hw/timer/i8254.h b/include/hw/timer/i8254.h
new file mode 100644
index 000000000..3e569f42b
--- /dev/null
+++ b/include/hw/timer/i8254.h
@@ -0,0 +1,80 @@
+/*
+ * QEMU 8253/8254 interval timer emulation
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * 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_I8254_H
+#define HW_I8254_H
+
+#include "hw/qdev-properties.h"
+#include "hw/isa/isa.h"
+#include "qapi/error.h"
+#include "qom/object.h"
+
+#define PIT_FREQ 1193182
+
+typedef struct PITChannelInfo {
+ int gate;
+ int mode;
+ int initial_count;
+ int out;
+} PITChannelInfo;
+
+#define TYPE_PIT_COMMON "pit-common"
+OBJECT_DECLARE_TYPE(PITCommonState, PITCommonClass, PIT_COMMON)
+
+#define TYPE_I8254 "isa-pit"
+#define TYPE_KVM_I8254 "kvm-pit"
+
+static inline ISADevice *i8254_pit_init(ISABus *bus, int base, int isa_irq,
+ qemu_irq alt_irq)
+{
+ DeviceState *dev;
+ ISADevice *d;
+
+ d = isa_new(TYPE_I8254);
+ dev = DEVICE(d);
+ 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);
+
+ return d;
+}
+
+static inline ISADevice *kvm_pit_init(ISABus *bus, int base)
+{
+ DeviceState *dev;
+ ISADevice *d;
+
+ d = isa_new(TYPE_KVM_I8254);
+ dev = DEVICE(d);
+ qdev_prop_set_uint32(dev, "iobase", base);
+ isa_realize_and_unref(d, bus, &error_fatal);
+
+ return d;
+}
+
+void pit_set_gate(ISADevice *dev, int channel, int val);
+void pit_get_channel_info(ISADevice *dev, int channel, PITChannelInfo *info);
+
+#endif /* HW_I8254_H */
diff --git a/include/hw/timer/i8254_internal.h b/include/hw/timer/i8254_internal.h
new file mode 100644
index 000000000..a9a600d94
--- /dev/null
+++ b/include/hw/timer/i8254_internal.h
@@ -0,0 +1,76 @@
+/*
+ * QEMU 8253/8254 - internal interfaces
+ *
+ * Copyright (c) 2011 Jan Kiszka, Siemens AG
+ *
+ * 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 QEMU_I8254_INTERNAL_H
+#define QEMU_I8254_INTERNAL_H
+
+#include "hw/isa/isa.h"
+#include "hw/timer/i8254.h"
+#include "qemu/timer.h"
+
+typedef struct PITChannelState {
+ int count; /* can be 65536 */
+ uint16_t latched_count;
+ uint8_t count_latched;
+ uint8_t status_latched;
+ uint8_t status;
+ uint8_t read_state;
+ uint8_t write_state;
+ uint8_t write_latch;
+ uint8_t rw_mode;
+ uint8_t mode;
+ uint8_t bcd; /* not supported */
+ uint8_t gate; /* timer start */
+ int64_t count_load_time;
+ /* irq handling */
+ int64_t next_transition_time;
+ QEMUTimer *irq_timer;
+ qemu_irq irq;
+ uint32_t irq_disabled;
+} PITChannelState;
+
+struct PITCommonState {
+ ISADevice dev;
+ MemoryRegion ioports;
+ uint32_t iobase;
+ PITChannelState channels[3];
+};
+
+struct PITCommonClass {
+ ISADeviceClass 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);
+};
+
+int pit_get_out(PITChannelState *s, int64_t current_time);
+int64_t pit_get_next_transition_time(PITChannelState *s, int64_t current_time);
+void pit_get_channel_info_common(PITCommonState *s, PITChannelState *sc,
+ PITChannelInfo *info);
+void pit_reset_common(PITCommonState *s);
+
+#endif /* QEMU_I8254_INTERNAL_H */
diff --git a/include/hw/timer/ibex_timer.h b/include/hw/timer/ibex_timer.h
new file mode 100644
index 000000000..b6f69b38e
--- /dev/null
+++ b/include/hw/timer/ibex_timer.h
@@ -0,0 +1,54 @@
+/*
+ * 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;
+
+ /* <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 timer_intr_test;
+
+ 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
new file mode 100644
index 000000000..2acc41e98
--- /dev/null
+++ b/include/hw/timer/imx_epit.h
@@ -0,0 +1,81 @@
+/*
+ * i.MX EPIT Timer
+ *
+ * Copyright (c) 2008 OK Labs
+ * Copyright (c) 2011 NICTA Pty Ltd
+ * Originally written by Hans Jiang
+ * Updated by Peter Chubb
+ * Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
+ *
+ * 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 IMX_EPIT_H
+#define IMX_EPIT_H
+
+#include "hw/sysbus.h"
+#include "hw/ptimer.h"
+#include "hw/misc/imx_ccm.h"
+#include "qom/object.h"
+
+/*
+ * EPIT: Enhanced periodic interrupt timer
+ */
+
+#define CR_EN (1 << 0)
+#define CR_ENMOD (1 << 1)
+#define CR_OCIEN (1 << 2)
+#define CR_RLD (1 << 3)
+#define CR_PRESCALE_SHIFT (4)
+#define CR_PRESCALE_MASK (0xfff)
+#define CR_SWR (1 << 16)
+#define CR_IOVW (1 << 17)
+#define CR_DBGEN (1 << 18)
+#define CR_WAITEN (1 << 19)
+#define CR_DOZEN (1 << 20)
+#define CR_STOPEN (1 << 21)
+#define CR_CLKSRC_SHIFT (24)
+#define CR_CLKSRC_MASK (0x3 << CR_CLKSRC_SHIFT)
+
+#define EPIT_TIMER_MAX 0XFFFFFFFFUL
+
+#define TYPE_IMX_EPIT "imx.epit"
+OBJECT_DECLARE_SIMPLE_TYPE(IMXEPITState, IMX_EPIT)
+
+struct IMXEPITState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ ptimer_state *timer_reload;
+ ptimer_state *timer_cmp;
+ MemoryRegion iomem;
+ IMXCCMState *ccm;
+
+ uint32_t cr;
+ uint32_t sr;
+ uint32_t lr;
+ uint32_t cmp;
+ uint32_t cnt;
+
+ uint32_t freq;
+ qemu_irq irq;
+};
+
+#endif /* IMX_EPIT_H */
diff --git a/include/hw/timer/imx_gpt.h b/include/hw/timer/imx_gpt.h
new file mode 100644
index 000000000..ff5c8a351
--- /dev/null
+++ b/include/hw/timer/imx_gpt.h
@@ -0,0 +1,119 @@
+/*
+ * i.MX GPT Timer
+ *
+ * Copyright (c) 2008 OK Labs
+ * Copyright (c) 2011 NICTA Pty Ltd
+ * Originally written by Hans Jiang
+ * Updated by Peter Chubb
+ * Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
+ *
+ * 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 IMX_GPT_H
+#define IMX_GPT_H
+
+#include "hw/sysbus.h"
+#include "hw/ptimer.h"
+#include "hw/misc/imx_ccm.h"
+#include "qom/object.h"
+
+/*
+ * GPT : General purpose timer
+ *
+ * This timer counts up continuously while it is enabled, resetting itself
+ * to 0 when it reaches GPT_TIMER_MAX (in freerun mode) or when it
+ * reaches the value of one of the ocrX (in periodic mode).
+ */
+
+#define GPT_TIMER_MAX 0XFFFFFFFFUL
+
+/* Control register. Not all of these bits have any effect (yet) */
+#define GPT_CR_EN (1 << 0) /* GPT Enable */
+#define GPT_CR_ENMOD (1 << 1) /* GPT Enable Mode */
+#define GPT_CR_DBGEN (1 << 2) /* GPT Debug mode enable */
+#define GPT_CR_WAITEN (1 << 3) /* GPT Wait Mode Enable */
+#define GPT_CR_DOZEN (1 << 4) /* GPT Doze mode enable */
+#define GPT_CR_STOPEN (1 << 5) /* GPT Stop Mode Enable */
+#define GPT_CR_CLKSRC_SHIFT (6)
+#define GPT_CR_CLKSRC_MASK (0x7)
+
+#define GPT_CR_FRR (1 << 9) /* Freerun or Restart */
+#define GPT_CR_SWR (1 << 15) /* Software Reset */
+#define GPT_CR_IM1 (3 << 16) /* Input capture channel 1 mode (2 bits) */
+#define GPT_CR_IM2 (3 << 18) /* Input capture channel 2 mode (2 bits) */
+#define GPT_CR_OM1 (7 << 20) /* Output Compare Channel 1 Mode (3 bits) */
+#define GPT_CR_OM2 (7 << 23) /* Output Compare Channel 2 Mode (3 bits) */
+#define GPT_CR_OM3 (7 << 26) /* Output Compare Channel 3 Mode (3 bits) */
+#define GPT_CR_FO1 (1 << 29) /* Force Output Compare Channel 1 */
+#define GPT_CR_FO2 (1 << 30) /* Force Output Compare Channel 2 */
+#define GPT_CR_FO3 (1 << 31) /* Force Output Compare Channel 3 */
+
+#define GPT_SR_OF1 (1 << 0)
+#define GPT_SR_OF2 (1 << 1)
+#define GPT_SR_OF3 (1 << 2)
+#define GPT_SR_ROV (1 << 5)
+
+#define GPT_IR_OF1IE (1 << 0)
+#define GPT_IR_OF2IE (1 << 1)
+#define GPT_IR_OF3IE (1 << 2)
+#define GPT_IR_ROVIE (1 << 5)
+
+#define TYPE_IMX25_GPT "imx25.gpt"
+#define TYPE_IMX31_GPT "imx31.gpt"
+#define TYPE_IMX6_GPT "imx6.gpt"
+#define TYPE_IMX7_GPT "imx7.gpt"
+
+#define TYPE_IMX_GPT TYPE_IMX25_GPT
+
+typedef struct IMXGPTState IMXGPTState;
+DECLARE_INSTANCE_CHECKER(IMXGPTState, IMX_GPT,
+ TYPE_IMX_GPT)
+
+struct IMXGPTState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ ptimer_state *timer;
+ MemoryRegion iomem;
+ IMXCCMState *ccm;
+
+ uint32_t cr;
+ uint32_t pr;
+ uint32_t sr;
+ uint32_t ir;
+ uint32_t ocr1;
+ uint32_t ocr2;
+ uint32_t ocr3;
+ uint32_t icr1;
+ uint32_t icr2;
+ uint32_t cnt;
+
+ uint32_t next_timeout;
+ uint32_t next_int;
+
+ uint32_t freq;
+
+ qemu_irq irq;
+
+ const IMXClk *clocks;
+};
+
+#endif /* IMX_GPT_H */
diff --git a/include/hw/timer/mips_gictimer.h b/include/hw/timer/mips_gictimer.h
new file mode 100644
index 000000000..c7ca6c821
--- /dev/null
+++ b/include/hw/timer/mips_gictimer.h
@@ -0,0 +1,47 @@
+/*
+ * 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) 2016 Imagination Technologies
+ *
+ */
+
+#ifndef MIPS_GICTIMER_H
+#define MIPS_GICTIMER_H
+
+typedef struct MIPSGICTimerVPState MIPSGICTimerVPState;
+typedef struct MIPSGICTimerState MIPSGICTimerState;
+
+typedef void MIPSGICTimerCB(void *opaque, uint32_t vp_index);
+
+struct MIPSGICTimerVPState {
+ QEMUTimer *qtimer;
+ uint32_t vp_index;
+ uint32_t comparelo;
+ MIPSGICTimerState *gictimer;
+};
+
+struct MIPSGICTimerState {
+ void *opaque;
+ uint8_t countstop;
+ uint32_t sh_counterlo;
+ int32_t num_vps;
+ MIPSGICTimerVPState *vptimers;
+ MIPSGICTimerCB *cb;
+};
+
+uint32_t mips_gictimer_get_freq(MIPSGICTimerState *gic);
+uint32_t mips_gictimer_get_sh_count(MIPSGICTimerState *gic);
+void mips_gictimer_store_sh_count(MIPSGICTimerState *gic, uint64_t count);
+uint32_t mips_gictimer_get_vp_compare(MIPSGICTimerState *gictimer,
+ uint32_t vp_index);
+void mips_gictimer_store_vp_compare(MIPSGICTimerState *gic, uint32_t vp_index,
+ uint64_t compare);
+uint8_t mips_gictimer_get_countstop(MIPSGICTimerState *gic);
+void mips_gictimer_start_count(MIPSGICTimerState *gic);
+void mips_gictimer_stop_count(MIPSGICTimerState *gic);
+MIPSGICTimerState *mips_gictimer_init(void *opaque, uint32_t nvps,
+ MIPSGICTimerCB *cb);
+
+#endif /* MIPS_GICTIMER_H */
diff --git a/include/hw/timer/mss-timer.h b/include/hw/timer/mss-timer.h
new file mode 100644
index 000000000..da3851290
--- /dev/null
+++ b/include/hw/timer/mss-timer.h
@@ -0,0 +1,63 @@
+/*
+ * Microsemi SmartFusion2 Timer.
+ *
+ * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@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.
+ */
+
+#ifndef HW_MSS_TIMER_H
+#define HW_MSS_TIMER_H
+
+#include "hw/sysbus.h"
+#include "hw/ptimer.h"
+#include "qom/object.h"
+
+#define TYPE_MSS_TIMER "mss-timer"
+OBJECT_DECLARE_SIMPLE_TYPE(MSSTimerState, MSS_TIMER)
+
+/*
+ * There are two 32-bit down counting timers.
+ * Timers 1 and 2 can be concatenated into a single 64-bit Timer
+ * that operates either in Periodic mode or in One-shot mode.
+ * Writing 1 to the TIM64_MODE register bit 0 sets the Timers in 64-bit mode.
+ * In 64-bit mode, writing to the 32-bit registers has no effect.
+ * Similarly, in 32-bit mode, writing to the 64-bit mode registers
+ * has no effect. Only two 32-bit timers are supported currently.
+ */
+#define NUM_TIMERS 2
+
+#define R_TIM1_MAX 6
+
+struct Msf2Timer {
+ ptimer_state *ptimer;
+
+ uint32_t regs[R_TIM1_MAX];
+ qemu_irq irq;
+};
+
+struct MSSTimerState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion mmio;
+ uint32_t freq_hz;
+ struct Msf2Timer timers[NUM_TIMERS];
+};
+
+#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 000000000..d45c051b5
--- /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
new file mode 100644
index 000000000..76827c11d
--- /dev/null
+++ b/include/hw/timer/nrf51_timer.h
@@ -0,0 +1,82 @@
+/*
+ * nRF51 System-on-Chip Timer peripheral
+ *
+ * QEMU interface:
+ * + sysbus MMIO regions 0: GPIO registers
+ * + sysbus irq
+ *
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
+ *
+ * This code is licensed under the GPL version 2 or later. See
+ * the COPYING file in the top-level directory.
+ */
+#ifndef NRF51_TIMER_H
+#define NRF51_TIMER_H
+
+#include "hw/sysbus.h"
+#include "qemu/timer.h"
+#include "qom/object.h"
+#define TYPE_NRF51_TIMER "nrf51_soc.timer"
+OBJECT_DECLARE_SIMPLE_TYPE(NRF51TimerState, NRF51_TIMER)
+
+#define NRF51_TIMER_REG_COUNT 4
+
+#define NRF51_TIMER_TASK_START 0x000
+#define NRF51_TIMER_TASK_STOP 0x004
+#define NRF51_TIMER_TASK_COUNT 0x008
+#define NRF51_TIMER_TASK_CLEAR 0x00C
+#define NRF51_TIMER_TASK_SHUTDOWN 0x010
+#define NRF51_TIMER_TASK_CAPTURE_0 0x040
+#define NRF51_TIMER_TASK_CAPTURE_3 0x04C
+
+#define NRF51_TIMER_EVENT_COMPARE_0 0x140
+#define NRF51_TIMER_EVENT_COMPARE_1 0x144
+#define NRF51_TIMER_EVENT_COMPARE_2 0x148
+#define NRF51_TIMER_EVENT_COMPARE_3 0x14C
+
+#define NRF51_TIMER_REG_SHORTS 0x200
+#define NRF51_TIMER_REG_SHORTS_MASK 0xf0f
+#define NRF51_TIMER_REG_INTENSET 0x304
+#define NRF51_TIMER_REG_INTENCLR 0x308
+#define NRF51_TIMER_REG_INTEN_MASK 0xf0000
+#define NRF51_TIMER_REG_MODE 0x504
+#define NRF51_TIMER_REG_MODE_MASK 0x01
+#define NRF51_TIMER_TIMER 0
+#define NRF51_TIMER_COUNTER 1
+#define NRF51_TIMER_REG_BITMODE 0x508
+#define NRF51_TIMER_REG_BITMODE_MASK 0x03
+#define NRF51_TIMER_WIDTH_16 0
+#define NRF51_TIMER_WIDTH_8 1
+#define NRF51_TIMER_WIDTH_24 2
+#define NRF51_TIMER_WIDTH_32 3
+#define NRF51_TIMER_REG_PRESCALER 0x510
+#define NRF51_TIMER_REG_PRESCALER_MASK 0x0F
+#define NRF51_TIMER_REG_CC0 0x540
+#define NRF51_TIMER_REG_CC3 0x54C
+
+struct NRF51TimerState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ qemu_irq irq;
+
+ uint8_t id;
+ QEMUTimer timer;
+ int64_t timer_start_ns;
+ int64_t update_counter_ns;
+ uint32_t counter;
+
+ bool running;
+
+ uint8_t events_compare[NRF51_TIMER_REG_COUNT];
+ uint32_t cc[NRF51_TIMER_REG_COUNT];
+ uint32_t shorts;
+ uint32_t inten;
+ uint32_t mode;
+ uint32_t bitmode;
+ uint32_t prescaler;
+
+};
+
+
+#endif
diff --git a/include/hw/timer/renesas_cmt.h b/include/hw/timer/renesas_cmt.h
new file mode 100644
index 000000000..1c0b65c1d
--- /dev/null
+++ b/include/hw/timer/renesas_cmt.h
@@ -0,0 +1,43 @@
+/*
+ * Renesas Compare-match timer Object
+ *
+ * Copyright (c) 2019 Yoshinori Sato
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_TIMER_RENESAS_CMT_H
+#define HW_TIMER_RENESAS_CMT_H
+
+#include "qemu/timer.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_RENESAS_CMT "renesas-cmt"
+typedef struct RCMTState RCMTState;
+DECLARE_INSTANCE_CHECKER(RCMTState, RCMT,
+ TYPE_RENESAS_CMT)
+
+enum {
+ CMT_CH = 2,
+ CMT_NR_IRQ = 1 * CMT_CH
+};
+
+struct RCMTState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ uint64_t input_freq;
+ MemoryRegion memory;
+
+ uint16_t cmstr;
+ uint16_t cmcr[CMT_CH];
+ uint16_t cmcnt[CMT_CH];
+ uint16_t cmcor[CMT_CH];
+ int64_t tick[CMT_CH];
+ qemu_irq cmi[CMT_CH];
+ QEMUTimer timer[CMT_CH];
+};
+
+#endif
diff --git a/include/hw/timer/renesas_tmr.h b/include/hw/timer/renesas_tmr.h
new file mode 100644
index 000000000..caf7eec0d
--- /dev/null
+++ b/include/hw/timer/renesas_tmr.h
@@ -0,0 +1,58 @@
+/*
+ * Renesas 8bit timer Object
+ *
+ * Copyright (c) 2018 Yoshinori Sato
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_TIMER_RENESAS_TMR_H
+#define HW_TIMER_RENESAS_TMR_H
+
+#include "qemu/timer.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_RENESAS_TMR "renesas-tmr"
+typedef struct RTMRState RTMRState;
+DECLARE_INSTANCE_CHECKER(RTMRState, RTMR,
+ TYPE_RENESAS_TMR)
+
+enum timer_event {
+ cmia = 0,
+ cmib = 1,
+ ovi = 2,
+ none = 3,
+ TMR_NR_EVENTS = 4
+};
+
+enum {
+ TMR_CH = 2,
+ TMR_NR_IRQ = 3 * TMR_CH
+};
+
+struct RTMRState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ uint64_t input_freq;
+ MemoryRegion memory;
+
+ int64_t tick;
+ uint8_t tcnt[TMR_CH];
+ uint8_t tcora[TMR_CH];
+ uint8_t tcorb[TMR_CH];
+ uint8_t tcr[TMR_CH];
+ uint8_t tccr[TMR_CH];
+ uint8_t tcor[TMR_CH];
+ uint8_t tcsr[TMR_CH];
+ int64_t div_round[TMR_CH];
+ uint8_t next[TMR_CH];
+ qemu_irq cmia[TMR_CH];
+ qemu_irq cmib[TMR_CH];
+ qemu_irq ovi[TMR_CH];
+ QEMUTimer timer[TMR_CH];
+};
+
+#endif
diff --git a/include/hw/timer/sifive_pwm.h b/include/hw/timer/sifive_pwm.h
new file mode 100644
index 000000000..6a8cf7b29
--- /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 000000000..b433e58d3
--- /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 000000000..b4ee8e7f6
--- /dev/null
+++ b/include/hw/timer/sse-timer.h
@@ -0,0 +1,53 @@
+/*
+ * 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 "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 000000000..fde1fc6f0
--- /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
new file mode 100644
index 000000000..90f40f174
--- /dev/null
+++ b/include/hw/timer/stm32f2xx_timer.h
@@ -0,0 +1,102 @@
+/*
+ * STM32F2XX Timer
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * 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_STM32F2XX_TIMER_H
+#define HW_STM32F2XX_TIMER_H
+
+#include "hw/sysbus.h"
+#include "qemu/timer.h"
+#include "qom/object.h"
+
+#define TIM_CR1 0x00
+#define TIM_CR2 0x04
+#define TIM_SMCR 0x08
+#define TIM_DIER 0x0C
+#define TIM_SR 0x10
+#define TIM_EGR 0x14
+#define TIM_CCMR1 0x18
+#define TIM_CCMR2 0x1C
+#define TIM_CCER 0x20
+#define TIM_CNT 0x24
+#define TIM_PSC 0x28
+#define TIM_ARR 0x2C
+#define TIM_CCR1 0x34
+#define TIM_CCR2 0x38
+#define TIM_CCR3 0x3C
+#define TIM_CCR4 0x40
+#define TIM_DCR 0x48
+#define TIM_DMAR 0x4C
+#define TIM_OR 0x50
+
+#define TIM_CR1_CEN 1
+
+#define TIM_EGR_UG 1
+
+#define TIM_CCER_CC2E (1 << 4)
+#define TIM_CCMR1_OC2M2 (1 << 14)
+#define TIM_CCMR1_OC2M1 (1 << 13)
+#define TIM_CCMR1_OC2M0 (1 << 12)
+#define TIM_CCMR1_OC2PE (1 << 11)
+
+#define TIM_DIER_UIE 1
+
+#define TYPE_STM32F2XX_TIMER "stm32f2xx-timer"
+typedef struct STM32F2XXTimerState STM32F2XXTimerState;
+DECLARE_INSTANCE_CHECKER(STM32F2XXTimerState, STM32F2XXTIMER,
+ TYPE_STM32F2XX_TIMER)
+
+struct STM32F2XXTimerState {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /* <public> */
+ MemoryRegion iomem;
+ QEMUTimer *timer;
+ qemu_irq irq;
+
+ int64_t tick_offset;
+ uint64_t hit_time;
+ uint64_t freq_hz;
+
+ uint32_t tim_cr1;
+ uint32_t tim_cr2;
+ uint32_t tim_smcr;
+ uint32_t tim_dier;
+ uint32_t tim_sr;
+ uint32_t tim_egr;
+ uint32_t tim_ccmr1;
+ uint32_t tim_ccmr2;
+ uint32_t tim_ccer;
+ uint32_t tim_psc;
+ uint32_t tim_arr;
+ uint32_t tim_ccr1;
+ uint32_t tim_ccr2;
+ uint32_t tim_ccr3;
+ uint32_t tim_ccr4;
+ uint32_t tim_dcr;
+ uint32_t tim_dmar;
+ uint32_t tim_or;
+};
+
+#endif /* HW_STM32F2XX_TIMER_H */
diff --git a/include/hw/timer/tmu012.h b/include/hw/timer/tmu012.h
new file mode 100644
index 000000000..808ed8de1
--- /dev/null
+++ b/include/hw/timer/tmu012.h
@@ -0,0 +1,23 @@
+/*
+ * SuperH Timer
+ *
+ * Copyright (c) 2007 Magnus Damm
+ *
+ * This code is licensed under the GPL.
+ */
+
+#ifndef HW_TIMER_TMU012_H
+#define HW_TIMER_TMU012_H
+
+#include "exec/hwaddr.h"
+
+#define TMU012_FEAT_TOCR (1 << 0)
+#define TMU012_FEAT_3CHAN (1 << 1)
+#define TMU012_FEAT_EXTCLK (1 << 2)
+
+void tmu012_init(MemoryRegion *sysmem, hwaddr base,
+ int feat, uint32_t freq,
+ qemu_irq ch0_irq, qemu_irq ch1_irq,
+ qemu_irq ch2_irq0, qemu_irq ch2_irq1);
+
+#endif
diff --git a/include/hw/tricore/tc27x_soc.h b/include/hw/tricore/tc27x_soc.h
new file mode 100644
index 000000000..6a7e5b54f
--- /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 000000000..f3844be44
--- /dev/null
+++ b/include/hw/tricore/triboard.h
@@ -0,0 +1,50 @@
+/*
+ * 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 "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/boards.h"
+#include "hw/arm/boot.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.h b/include/hw/tricore/tricore.h
new file mode 100644
index 000000000..c19ed3f01
--- /dev/null
+++ b/include/hw/tricore/tricore.h
@@ -0,0 +1,10 @@
+#ifndef HW_TRICORE_H
+#define HW_TRICORE_H
+
+#include "exec/memory.h"
+
+struct tricore_boot_info {
+ uint64_t ram_size;
+ const char *kernel_filename;
+};
+#endif
diff --git a/include/hw/tricore/tricore_testdevice.h b/include/hw/tricore/tricore_testdevice.h
new file mode 100644
index 000000000..2c56c51bc
--- /dev/null
+++ b/include/hw/tricore/tricore_testdevice.h
@@ -0,0 +1,38 @@
+/*
+ * 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_TESTDEV_H
+#define HW_TRICORE_TESTDEV_H
+
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+
+#define TYPE_TRICORE_TESTDEVICE "tricore_testdevice"
+#define TRICORE_TESTDEVICE(obj) \
+ OBJECT_CHECK(TriCoreTestDeviceState, (obj), TYPE_TRICORE_TESTDEVICE)
+
+typedef struct {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /* <public> */
+ MemoryRegion iomem;
+
+} TriCoreTestDeviceState;
+
+#endif
diff --git a/include/hw/usb.h b/include/hw/usb.h
new file mode 100644
index 000000000..33668dd0a
--- /dev/null
+++ b/include/hw/usb.h
@@ -0,0 +1,585 @@
+#ifndef QEMU_USB_H
+#define QEMU_USB_H
+
+/*
+ * QEMU USB API
+ *
+ * Copyright (c) 2005 Fabrice Bellard
+ *
+ * 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 "exec/memory.h"
+#include "hw/qdev-core.h"
+#include "qemu/iov.h"
+#include "qemu/queue.h"
+#include "qom/object.h"
+
+/* Constants related to the USB / PCI interaction */
+#define USB_SBRN 0x60 /* Serial Bus Release Number Register */
+#define USB_RELEASE_1 0x10 /* USB 1.0 */
+#define USB_RELEASE_2 0x20 /* USB 2.0 */
+#define USB_RELEASE_3 0x30 /* USB 3.0 */
+
+#define USB_TOKEN_SETUP 0x2d
+#define USB_TOKEN_IN 0x69 /* device -> host */
+#define USB_TOKEN_OUT 0xe1 /* host -> device */
+
+#define USB_RET_SUCCESS (0)
+#define USB_RET_NODEV (-1)
+#define USB_RET_NAK (-2)
+#define USB_RET_STALL (-3)
+#define USB_RET_BABBLE (-4)
+#define USB_RET_IOERROR (-5)
+#define USB_RET_ASYNC (-6)
+#define USB_RET_ADD_TO_QUEUE (-7)
+#define USB_RET_REMOVE_FROM_QUEUE (-8)
+
+#define USB_SPEED_LOW 0
+#define USB_SPEED_FULL 1
+#define USB_SPEED_HIGH 2
+#define USB_SPEED_SUPER 3
+
+#define USB_SPEED_MASK_LOW (1 << USB_SPEED_LOW)
+#define USB_SPEED_MASK_FULL (1 << USB_SPEED_FULL)
+#define USB_SPEED_MASK_HIGH (1 << USB_SPEED_HIGH)
+#define USB_SPEED_MASK_SUPER (1 << USB_SPEED_SUPER)
+
+#define USB_STATE_NOTATTACHED 0
+#define USB_STATE_ATTACHED 1
+//#define USB_STATE_POWERED 2
+#define USB_STATE_DEFAULT 3
+//#define USB_STATE_ADDRESS 4
+//#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_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_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 DeviceRequest ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8)
+#define DeviceOutRequest ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8)
+#define VendorDeviceRequest ((USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8)
+#define VendorDeviceOutRequest \
+ ((USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8)
+
+#define InterfaceRequest \
+ ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
+#define InterfaceOutRequest \
+ ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
+#define ClassInterfaceRequest \
+ ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE)<<8)
+#define ClassInterfaceOutRequest \
+ ((USB_DIR_OUT|USB_TYPE_CLASS|USB_RECIP_INTERFACE)<<8)
+#define VendorInterfaceRequest \
+ ((USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_INTERFACE)<<8)
+#define VendorInterfaceOutRequest \
+ ((USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE)<<8)
+
+#define EndpointRequest ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8)
+#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_SET_SEL 0x30
+#define USB_REQ_SET_ISOCH_DELAY 0x31
+
+#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_QUALIFIER 0x06
+#define USB_DT_OTHER_SPEED_CONFIG 0x07
+#define USB_DT_DEBUG 0x0A
+#define USB_DT_INTERFACE_ASSOC 0x0B
+#define USB_DT_BOS 0x0F
+#define USB_DT_DEVICE_CAPABILITY 0x10
+#define USB_DT_CS_INTERFACE 0x24
+#define USB_DT_CS_ENDPOINT 0x25
+#define USB_DT_ENDPOINT_COMPANION 0x30
+
+#define USB_DEV_CAP_WIRELESS 0x01
+#define USB_DEV_CAP_USB2_EXT 0x02
+#define USB_DEV_CAP_SUPERSPEED 0x03
+
+#define USB_CFG_ATT_ONE (1 << 7) /* should always be set */
+#define USB_CFG_ATT_SELFPOWER (1 << 6)
+#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_INVALID 255
+
+#define USB_INTERFACE_INVALID 255
+
+typedef struct USBBusOps USBBusOps;
+typedef struct USBPort USBPort;
+typedef struct USBDevice USBDevice;
+typedef struct USBPacket USBPacket;
+typedef struct USBCombinedPacket USBCombinedPacket;
+typedef struct USBEndpoint USBEndpoint;
+
+typedef struct USBDesc USBDesc;
+typedef struct USBDescID USBDescID;
+typedef struct USBDescDevice USBDescDevice;
+typedef struct USBDescConfig USBDescConfig;
+typedef struct USBDescIfaceAssoc USBDescIfaceAssoc;
+typedef struct USBDescIface USBDescIface;
+typedef struct USBDescEndpoint USBDescEndpoint;
+typedef struct USBDescOther USBDescOther;
+typedef struct USBDescString USBDescString;
+typedef struct USBDescMSOS USBDescMSOS;
+
+struct USBDescString {
+ uint8_t index;
+ char *str;
+ QLIST_ENTRY(USBDescString) next;
+};
+
+#define USB_MAX_ENDPOINTS 15
+#define USB_MAX_INTERFACES 16
+
+struct USBEndpoint {
+ uint8_t nr;
+ uint8_t pid;
+ uint8_t type;
+ uint8_t ifnum;
+ int max_packet_size;
+ int max_streams;
+ bool pipeline;
+ bool halted;
+ USBDevice *dev;
+ QTAILQ_HEAD(, USBPacket) queue;
+};
+
+enum USBDeviceFlags {
+ 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 */
+struct USBDevice {
+ DeviceState qdev;
+ USBPort *port;
+ char *port_path;
+ char *serial;
+ 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) */
+ int speedmask;
+ uint8_t addr;
+ char product_desc[32];
+ int auto_attach;
+ bool attached;
+
+ int32_t state;
+ uint8_t setup_buf[8];
+ uint8_t data_buf[4096];
+ int32_t remote_wakeup;
+ int32_t setup_state;
+ int32_t setup_len;
+ int32_t setup_index;
+
+ USBEndpoint ep_ctl;
+ USBEndpoint ep_in[USB_MAX_ENDPOINTS];
+ USBEndpoint ep_out[USB_MAX_ENDPOINTS];
+
+ QLIST_HEAD(, USBDescString) strings;
+ const USBDesc *usb_desc; /* Overrides class usb_desc if not NULL */
+ const USBDescDevice *device;
+
+ int configuration;
+ int ninterfaces;
+ int altsetting[USB_MAX_INTERFACES];
+ const USBDescConfig *config;
+ const USBDescIface *ifaces[USB_MAX_INTERFACES];
+};
+
+#define TYPE_USB_DEVICE "usb-device"
+OBJECT_DECLARE_TYPE(USBDevice, USBDeviceClass, USB_DEVICE)
+
+typedef void (*USBDeviceRealize)(USBDevice *dev, Error **errp);
+typedef void (*USBDeviceUnrealize)(USBDevice *dev);
+
+struct USBDeviceClass {
+ DeviceClass parent_class;
+
+ USBDeviceRealize realize;
+ USBDeviceUnrealize unrealize;
+
+ /*
+ * Walk (enabled) downstream ports, check for a matching device.
+ * Only hubs implement this.
+ */
+ USBDevice *(*find_device)(USBDevice *dev, uint8_t addr);
+
+ /*
+ * Called when a packet is canceled.
+ */
+ void (*cancel_packet)(USBDevice *dev, USBPacket *p);
+
+ /*
+ * Attach the device
+ */
+ void (*handle_attach)(USBDevice *dev);
+
+ /*
+ * Reset the device
+ */
+ void (*handle_reset)(USBDevice *dev);
+
+ /*
+ * Process control request.
+ * Called from handle_packet().
+ *
+ * Status gets stored in p->status, and if p->status == USB_RET_SUCCESS
+ * then the number of bytes transferred is stored in p->actual_length
+ */
+ void (*handle_control)(USBDevice *dev, USBPacket *p, int request, int value,
+ int index, int length, uint8_t *data);
+
+ /*
+ * Process data transfers (both BULK and ISOC).
+ * Called from handle_packet().
+ *
+ * Status gets stored in p->status, and if p->status == USB_RET_SUCCESS
+ * then the number of bytes transferred is stored in p->actual_length
+ */
+ void (*handle_data)(USBDevice *dev, USBPacket *p);
+
+ void (*set_interface)(USBDevice *dev, int interface,
+ int alt_old, int alt_new);
+
+ /*
+ * Called when the hcd is done queuing packets for an endpoint, only
+ * necessary for devices which can return USB_RET_ADD_TO_QUEUE.
+ */
+ void (*flush_ep_queue)(USBDevice *dev, USBEndpoint *ep);
+
+ /*
+ * Called by the hcd to let the device know the queue for an endpoint
+ * has been unlinked / stopped. Optional may be NULL.
+ */
+ void (*ep_stopped)(USBDevice *dev, USBEndpoint *ep);
+
+ /*
+ * Called by the hcd to alloc / free streams on a bulk endpoint.
+ * Optional may be NULL.
+ */
+ int (*alloc_streams)(USBDevice *dev, USBEndpoint **eps, int nr_eps,
+ int streams);
+ void (*free_streams)(USBDevice *dev, USBEndpoint **eps, int nr_eps);
+
+ const char *product_desc;
+ const USBDesc *usb_desc;
+ bool attached_settable;
+};
+
+typedef struct USBPortOps {
+ void (*attach)(USBPort *port);
+ void (*detach)(USBPort *port);
+ /*
+ * This gets called when a device downstream from the device attached to
+ * the port (iow attached through a hub) gets detached.
+ */
+ void (*child_detach)(USBPort *port, USBDevice *child);
+ void (*wakeup)(USBPort *port);
+ /*
+ * Note that port->dev will be different then the device from which
+ * the packet originated when a hub is involved.
+ */
+ void (*complete)(USBPort *port, USBPacket *p);
+} USBPortOps;
+
+/* USB port on which a device can be connected */
+struct USBPort {
+ USBDevice *dev;
+ int speedmask;
+ int hubcount;
+ char path[16];
+ USBPortOps *ops;
+ void *opaque;
+ int index; /* internal port index, may be used with the opaque */
+ QTAILQ_ENTRY(USBPort) next;
+};
+
+typedef void USBCallback(USBPacket * packet, void *opaque);
+
+typedef enum USBPacketState {
+ USB_PACKET_UNDEFINED = 0,
+ USB_PACKET_SETUP,
+ USB_PACKET_QUEUED,
+ USB_PACKET_ASYNC,
+ USB_PACKET_COMPLETE,
+ USB_PACKET_CANCELED,
+} USBPacketState;
+
+/* Structure used to hold information about an active USB packet. */
+struct USBPacket {
+ /* Data fields for use by the driver. */
+ int pid;
+ uint64_t id;
+ USBEndpoint *ep;
+ unsigned int stream;
+ QEMUIOVector iov;
+ uint64_t parameter; /* control transfers */
+ bool short_not_ok;
+ bool int_req;
+ int status; /* USB_RET_* status code */
+ int actual_length; /* Number of bytes actually transferred */
+ /* Internal use by the USB layer. */
+ USBPacketState state;
+ USBCombinedPacket *combined;
+ QTAILQ_ENTRY(USBPacket) queue;
+ QTAILQ_ENTRY(USBPacket) combined_entry;
+};
+
+struct USBCombinedPacket {
+ USBPacket *first;
+ QTAILQ_HEAD(, USBPacket) packets;
+ QEMUIOVector iov;
+};
+
+void usb_packet_init(USBPacket *p);
+void usb_packet_set_state(USBPacket *p, USBPacketState state);
+void usb_packet_check_state(USBPacket *p, USBPacketState expected);
+void usb_packet_setup(USBPacket *p, int pid,
+ USBEndpoint *ep, unsigned int stream,
+ uint64_t id, bool short_not_ok, bool int_req);
+void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len);
+int usb_packet_map(USBPacket *p, QEMUSGList *sgl);
+void usb_packet_unmap(USBPacket *p, QEMUSGList *sgl);
+void usb_packet_copy(USBPacket *p, void *ptr, size_t bytes);
+void usb_packet_skip(USBPacket *p, size_t bytes);
+size_t usb_packet_size(USBPacket *p);
+void usb_packet_cleanup(USBPacket *p);
+
+static inline bool usb_packet_is_inflight(USBPacket *p)
+{
+ return (p->state == USB_PACKET_QUEUED ||
+ p->state == USB_PACKET_ASYNC);
+}
+
+USBDevice *usb_find_device(USBPort *port, uint8_t addr);
+
+void usb_handle_packet(USBDevice *dev, USBPacket *p);
+void usb_packet_complete(USBDevice *dev, USBPacket *p);
+void usb_packet_complete_one(USBDevice *dev, USBPacket *p);
+void usb_cancel_packet(USBPacket * p);
+
+void usb_ep_init(USBDevice *dev);
+void usb_ep_reset(USBDevice *dev);
+void usb_ep_dump(USBDevice *dev);
+struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep);
+uint8_t usb_ep_get_type(USBDevice *dev, int pid, int ep);
+void usb_ep_set_type(USBDevice *dev, int pid, int ep, uint8_t type);
+void usb_ep_set_ifnum(USBDevice *dev, int pid, int ep, uint8_t ifnum);
+void usb_ep_set_max_packet_size(USBDevice *dev, int pid, int ep,
+ uint16_t raw);
+void usb_ep_set_max_streams(USBDevice *dev, int pid, int ep, uint8_t raw);
+void usb_ep_set_halted(USBDevice *dev, int pid, int ep, bool halted);
+USBPacket *usb_ep_find_packet_by_id(USBDevice *dev, int pid, int ep,
+ uint64_t id);
+
+void usb_ep_combine_input_packets(USBEndpoint *ep);
+void usb_combined_input_packet_complete(USBDevice *dev, USBPacket *p);
+void usb_combined_packet_cancel(USBDevice *dev, USBPacket *p);
+
+void usb_pick_speed(USBPort *port);
+void usb_attach(USBPort *port);
+void usb_detach(USBPort *port);
+void usb_port_reset(USBPort *port);
+void usb_device_reset(USBDevice *dev);
+void usb_wakeup(USBEndpoint *ep, unsigned int stream);
+void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p);
+
+/* usb-linux.c */
+void hmp_info_usbhost(Monitor *mon, const QDict *qdict);
+
+/* usb ports of the VM */
+
+#define VM_USB_HUB_SIZE 8
+
+/* usb-bus.c */
+
+#define TYPE_USB_BUS "usb-bus"
+OBJECT_DECLARE_SIMPLE_TYPE(USBBus, USB_BUS)
+
+struct USBBus {
+ BusState qbus;
+ USBBusOps *ops;
+ int busnr;
+ int nfree;
+ int nused;
+ QTAILQ_HEAD(, USBPort) free;
+ QTAILQ_HEAD(, USBPort) used;
+ QTAILQ_ENTRY(USBBus) next;
+};
+
+struct USBBusOps {
+ void (*register_companion)(USBBus *bus, USBPort *ports[],
+ uint32_t portcount, uint32_t firstport,
+ Error **errp);
+ void (*wakeup_endpoint)(USBBus *bus, USBEndpoint *ep, unsigned int stream);
+};
+
+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)(void));
+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_create(const char *cmdline);
+void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
+ USBPortOps *ops, int speedmask);
+void usb_register_companion(const char *masterbus, USBPort *ports[],
+ uint32_t portcount, uint32_t firstport,
+ void *opaque, USBPortOps *ops, int speedmask,
+ Error **errp);
+void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr);
+void usb_unregister_port(USBBus *bus, USBPort *port);
+void usb_claim_port(USBDevice *dev, Error **errp);
+void usb_release_port(USBDevice *dev);
+void usb_device_attach(USBDevice *dev, Error **errp);
+int usb_device_detach(USBDevice *dev);
+void usb_check_attach(USBDevice *dev, Error **errp);
+
+static inline USBBus *usb_bus_from_device(USBDevice *d)
+{
+ return DO_UPCAST(USBBus, qbus, d->qdev.parent_bus);
+}
+
+extern const VMStateDescription vmstate_usb_device;
+
+#define VMSTATE_USB_DEVICE(_field, _state) { \
+ .name = (stringify(_field)), \
+ .size = sizeof(USBDevice), \
+ .vmsd = &vmstate_usb_device, \
+ .flags = VMS_STRUCT, \
+ .offset = vmstate_offset_value(_state, _field, USBDevice), \
+}
+
+USBDevice *usb_device_find_device(USBDevice *dev, uint8_t addr);
+
+void usb_device_cancel_packet(USBDevice *dev, USBPacket *p);
+
+void usb_device_handle_attach(USBDevice *dev);
+
+void usb_device_handle_reset(USBDevice *dev);
+
+void usb_device_handle_control(USBDevice *dev, USBPacket *p, int request,
+ int val, int index, int length, uint8_t *data);
+
+void usb_device_handle_data(USBDevice *dev, USBPacket *p);
+
+void usb_device_set_interface(USBDevice *dev, int interface,
+ int alt_old, int alt_new);
+
+void usb_device_flush_ep_queue(USBDevice *dev, USBEndpoint *ep);
+
+void usb_device_ep_stopped(USBDevice *dev, USBEndpoint *ep);
+
+int usb_device_alloc_streams(USBDevice *dev, USBEndpoint **eps, int nr_eps,
+ int streams);
+void usb_device_free_streams(USBDevice *dev, USBEndpoint **eps, int nr_eps);
+
+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
+/* Bulk pkts in FTDI format, need special handling when combining packets */
+#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);
+
+#endif
diff --git a/include/hw/usb/chipidea.h b/include/hw/usb/chipidea.h
new file mode 100644
index 000000000..fe4113ee0
--- /dev/null
+++ b/include/hw/usb/chipidea.h
@@ -0,0 +1,17 @@
+#ifndef CHIPIDEA_H
+#define CHIPIDEA_H
+
+#include "hw/usb/hcd-ehci.h"
+#include "qom/object.h"
+
+struct ChipideaState {
+ /*< private >*/
+ EHCISysBusState parent_obj;
+
+ MemoryRegion iomem[3];
+};
+
+#define TYPE_CHIPIDEA "usb-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
new file mode 100644
index 000000000..a7eb53148
--- /dev/null
+++ b/include/hw/usb/dwc2-regs.h
@@ -0,0 +1,899 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * Imported from the Linux kernel file drivers/usb/dwc2/hw.h, commit
+ * a89bae709b3492b478480a2c9734e7e9393b279c ("usb: dwc2: Move
+ * UTMI_PHY_DATA defines closer")
+ *
+ * hw.h - DesignWare HS OTG Controller hardware definitions
+ *
+ * Copyright 2004-2013 Synopsys, Inc.
+ *
+ * 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,
+ * without modification.
+ * 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.
+ * 3. The names of the above-listed copyright holders may not be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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 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)
+/* 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 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 GREFCLK_SOF_CNT_WKUP_ALERT_SHIFT 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 HPTXFSIZ HSOTG_REG(0x100)
+/* Use FIFOSIZE_* constants to access this register */
+
+#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)
+
+/* 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 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))
+
+/* 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 PCGCCTL1 HSOTG_REG(0xe04)
+#define PCGCCTL1_TIMER (0x3 << 1)
+#define PCGCCTL1_GATEEN BIT(0)
+
+#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))
+
+/**
+ * struct dwc2_dma_desc - DMA descriptor structure,
+ * used for both host and gadget modes
+ *
+ * @status: DMA descriptor status quadlet
+ * @buf: DMA descriptor data buffer pointer
+ *
+ * DMA Descriptor structure contains two quadlets:
+ * Status quadlet and Data buffer pointer.
+ */
+struct dwc2_dma_desc {
+ 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
+
+/* 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__ */
diff --git a/include/hw/usb/ehci-regs.h b/include/hw/usb/ehci-regs.h
new file mode 100644
index 000000000..3e91b8e61
--- /dev/null
+++ b/include/hw/usb/ehci-regs.h
@@ -0,0 +1,82 @@
+#ifndef HW_USB_EHCI_REGS_H
+#define HW_USB_EHCI_REGS_H
+
+/* Capability Registers Base Address - section 2.2 */
+#define CAPLENGTH 0x0000 /* 1-byte, 0x0001 reserved */
+#define HCIVERSION 0x0002 /* 2-bytes, i/f version # */
+#define HCSPARAMS 0x0004 /* 4-bytes, structural params */
+#define HCCPARAMS 0x0008 /* 4-bytes, capability params */
+#define EECP HCCPARAMS + 1
+#define HCSPPORTROUTE1 0x000c
+#define HCSPPORTROUTE2 0x0010
+
+#define USBCMD 0x0000
+#define USBCMD_RUNSTOP (1 << 0) // run / Stop
+#define USBCMD_HCRESET (1 << 1) // HC Reset
+#define USBCMD_FLS (3 << 2) // Frame List Size
+#define USBCMD_FLS_SH 2 // Frame List Size Shift
+#define USBCMD_PSE (1 << 4) // Periodic Schedule Enable
+#define USBCMD_ASE (1 << 5) // Asynch Schedule Enable
+#define USBCMD_IAAD (1 << 6) // Int Asynch Advance Doorbell
+#define USBCMD_LHCR (1 << 7) // Light Host Controller Reset
+#define USBCMD_ASPMC (3 << 8) // Async Sched Park Mode Count
+#define USBCMD_ASPME (1 << 11) // Async Sched Park Mode Enable
+#define USBCMD_ITC (0x7f << 16) // Int Threshold Control
+#define USBCMD_ITC_SH 16 // Int Threshold Control Shift
+
+#define USBSTS 0x0004
+#define USBSTS_RO_MASK 0x0000003f
+#define USBSTS_INT (1 << 0) // USB Interrupt
+#define USBSTS_ERRINT (1 << 1) // Error Interrupt
+#define USBSTS_PCD (1 << 2) // Port Change Detect
+#define USBSTS_FLR (1 << 3) // Frame List Rollover
+#define USBSTS_HSE (1 << 4) // Host System Error
+#define USBSTS_IAA (1 << 5) // Interrupt on Async Advance
+#define USBSTS_HALT (1 << 12) // HC Halted
+#define USBSTS_REC (1 << 13) // Reclamation
+#define USBSTS_PSS (1 << 14) // Periodic Schedule Status
+#define USBSTS_ASS (1 << 15) // Asynchronous Schedule Status
+
+/*
+ * Interrupt enable bits correspond to the interrupt active bits in USBSTS
+ * so no need to redefine here.
+ */
+#define USBINTR 0x0008
+#define USBINTR_MASK 0x0000003f
+
+#define FRINDEX 0x000c
+#define CTRLDSSEGMENT 0x0010
+#define PERIODICLISTBASE 0x0014
+#define ASYNCLISTADDR 0x0018
+#define ASYNCLISTADDR_MASK 0xffffffe0
+
+#define CONFIGFLAG 0x0040
+
+/*
+ * Bits that are reserved or are read-only are masked out of values
+ * written to us by software
+ */
+#define PORTSC_RO_MASK 0x007001c0
+#define PORTSC_RWC_MASK 0x0000002a
+#define PORTSC_WKOC_E (1 << 22) // Wake on Over Current Enable
+#define PORTSC_WKDS_E (1 << 21) // Wake on Disconnect Enable
+#define PORTSC_WKCN_E (1 << 20) // Wake on Connect Enable
+#define PORTSC_PTC (15 << 16) // Port Test Control
+#define PORTSC_PTC_SH 16 // Port Test Control shift
+#define PORTSC_PIC (3 << 14) // Port Indicator Control
+#define PORTSC_PIC_SH 14 // Port Indicator Control Shift
+#define PORTSC_POWNER (1 << 13) // Port Owner
+#define PORTSC_PPOWER (1 << 12) // Port Power
+#define PORTSC_LINESTAT (3 << 10) // Port Line Status
+#define PORTSC_LINESTAT_SH 10 // Port Line Status Shift
+#define PORTSC_PRESET (1 << 8) // Port Reset
+#define PORTSC_SUSPEND (1 << 7) // Port Suspend
+#define PORTSC_FPRES (1 << 6) // Force Port Resume
+#define PORTSC_OCC (1 << 5) // Over Current Change
+#define PORTSC_OCA (1 << 4) // Over Current Active
+#define PORTSC_PEDC (1 << 3) // Port Enable/Disable Change
+#define PORTSC_PED (1 << 2) // Port Enable/Disable
+#define PORTSC_CSC (1 << 1) // Connect Status Change
+#define PORTSC_CONNECT (1 << 0) // Current Connect Status
+
+#endif /* HW_USB_EHCI_REGS_H */
diff --git a/include/hw/usb/hcd-dwc3.h b/include/hw/usb/hcd-dwc3.h
new file mode 100644
index 000000000..7c804d536
--- /dev/null
+++ b/include/hw/usb/hcd-dwc3.h
@@ -0,0 +1,55 @@
+/*
+ * 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/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
new file mode 100644
index 000000000..c874b9f29
--- /dev/null
+++ b/include/hw/usb/hcd-musb.h
@@ -0,0 +1,47 @@
+/*
+ * "Inventra" High-speed Dual-Role Controller (MUSB-HDRC), Mentor Graphics,
+ * USB2.0 OTG compliant core used in various chips.
+ *
+ * Only host-mode and non-DMA accesses are currently supported.
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Written by Andrzej Zaborowski <balrog@zabor.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_USB_MUSB_H
+#define HW_USB_MUSB_H
+
+enum musb_irq_source_e {
+ musb_irq_suspend = 0,
+ musb_irq_resume,
+ musb_irq_rst_babble,
+ musb_irq_sof,
+ musb_irq_connect,
+ musb_irq_disconnect,
+ musb_irq_vbus_request,
+ musb_irq_vbus_error,
+ musb_irq_rx,
+ musb_irq_tx,
+ musb_set_vbus,
+ musb_set_session,
+ /* Add new interrupts here */
+ musb_irq_max /* total number of interrupts defined */
+};
+
+/* TODO convert hcd-musb to QOM/qdev and remove MUSBReadFunc/MUSBWriteFunc */
+typedef void MUSBWriteFunc(void *opaque, hwaddr addr, uint32_t value);
+typedef uint32_t MUSBReadFunc(void *opaque, hwaddr addr);
+extern MUSBReadFunc * const musb_read[];
+extern MUSBWriteFunc * const musb_write[];
+
+typedef struct MUSBState MUSBState;
+
+MUSBState *musb_init(DeviceState *parent_device, int gpio_base);
+void musb_reset(MUSBState *s);
+uint32_t musb_core_intr_get(MUSBState *s);
+void musb_core_intr_clear(MUSBState *s, uint32_t mask);
+void musb_set_size(MUSBState *s, int epnum, int size, int is_tx);
+
+#endif
diff --git a/include/hw/usb/hid.h b/include/hw/usb/hid.h
new file mode 100644
index 000000000..1c142584f
--- /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
new file mode 100644
index 000000000..d1e867b77
--- /dev/null
+++ b/include/hw/usb/imx-usb-phy.h
@@ -0,0 +1,54 @@
+#ifndef IMX_USB_PHY_H
+#define IMX_USB_PHY_H
+
+#include "hw/sysbus.h"
+#include "qemu/bitops.h"
+#include "qom/object.h"
+
+enum IMXUsbPhyRegisters {
+ USBPHY_PWD,
+ USBPHY_PWD_SET,
+ USBPHY_PWD_CLR,
+ USBPHY_PWD_TOG,
+ USBPHY_TX,
+ USBPHY_TX_SET,
+ USBPHY_TX_CLR,
+ USBPHY_TX_TOG,
+ USBPHY_RX,
+ USBPHY_RX_SET,
+ USBPHY_RX_CLR,
+ USBPHY_RX_TOG,
+ USBPHY_CTRL,
+ USBPHY_CTRL_SET,
+ USBPHY_CTRL_CLR,
+ USBPHY_CTRL_TOG,
+ USBPHY_STATUS,
+ USBPHY_DEBUG = 0x14,
+ USBPHY_DEBUG_SET,
+ USBPHY_DEBUG_CLR,
+ USBPHY_DEBUG_TOG,
+ USBPHY_DEBUG0_STATUS,
+ USBPHY_DEBUG1 = 0x1c,
+ USBPHY_DEBUG1_SET,
+ USBPHY_DEBUG1_CLR,
+ USBPHY_DEBUG1_TOG,
+ USBPHY_VERSION,
+ USBPHY_MAX
+};
+
+#define USBPHY_CTRL_SFTRST BIT(31)
+
+#define TYPE_IMX_USBPHY "imx.usbphy"
+OBJECT_DECLARE_SIMPLE_TYPE(IMXUSBPHYState, IMX_USBPHY)
+
+struct IMXUSBPHYState {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /* <public> */
+ MemoryRegion iomem;
+
+ uint32_t usbphy[USBPHY_MAX];
+};
+
+#endif /* IMX_USB_PHY_H */
diff --git a/include/hw/usb/msd.h b/include/hw/usb/msd.h
new file mode 100644
index 000000000..54e9f38bd
--- /dev/null
+++ b/include/hw/usb/msd.h
@@ -0,0 +1,54 @@
+/*
+ * 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;
+};
+
+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/uhci-regs.h b/include/hw/usb/uhci-regs.h
new file mode 100644
index 000000000..fd45d29db
--- /dev/null
+++ b/include/hw/usb/uhci-regs.h
@@ -0,0 +1,40 @@
+#ifndef HW_USB_UHCI_REGS_H
+#define HW_USB_UHCI_REGS_H
+
+#define UHCI_CMD_FGR (1 << 4)
+#define UHCI_CMD_EGSM (1 << 3)
+#define UHCI_CMD_GRESET (1 << 2)
+#define UHCI_CMD_HCRESET (1 << 1)
+#define UHCI_CMD_RS (1 << 0)
+
+#define UHCI_STS_HCHALTED (1 << 5)
+#define UHCI_STS_HCPERR (1 << 4)
+#define UHCI_STS_HSERR (1 << 3)
+#define UHCI_STS_RD (1 << 2)
+#define UHCI_STS_USBERR (1 << 1)
+#define UHCI_STS_USBINT (1 << 0)
+
+#define TD_CTRL_SPD (1 << 29)
+#define TD_CTRL_ERROR_SHIFT 27
+#define TD_CTRL_IOS (1 << 25)
+#define TD_CTRL_IOC (1 << 24)
+#define TD_CTRL_ACTIVE (1 << 23)
+#define TD_CTRL_STALL (1 << 22)
+#define TD_CTRL_BABBLE (1 << 20)
+#define TD_CTRL_NAK (1 << 19)
+#define TD_CTRL_TIMEOUT (1 << 18)
+
+#define UHCI_PORT_SUSPEND (1 << 12)
+#define UHCI_PORT_RESET (1 << 9)
+#define UHCI_PORT_LSDA (1 << 8)
+#define UHCI_PORT_RSVD1 (1 << 7)
+#define UHCI_PORT_RD (1 << 6)
+#define UHCI_PORT_ENC (1 << 3)
+#define UHCI_PORT_EN (1 << 2)
+#define UHCI_PORT_CSC (1 << 1)
+#define UHCI_PORT_CCS (1 << 0)
+
+#define UHCI_PORT_READ_ONLY (0x1bb)
+#define UHCI_PORT_WRITE_CLEAR (UHCI_PORT_CSC | UHCI_PORT_ENC)
+
+#endif /* HW_USB_UHCI_REGS_H */
diff --git a/include/hw/usb/xhci.h b/include/hw/usb/xhci.h
new file mode 100644
index 000000000..5c90e1373
--- /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 000000000..999e42395
--- /dev/null
+++ b/include/hw/usb/xlnx-usb-subsystem.h
@@ -0,0 +1,45 @@
+/*
+ * 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_VERSAL_USB_SUBSYSTEM_H
+#define XLNX_VERSAL_USB_SUBSYSTEM_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 000000000..b76dce041
--- /dev/null
+++ b/include/hw/usb/xlnx-versal-usb2-ctrl-regs.h
@@ -0,0 +1,45 @@
+/*
+ * 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_USB2_REGS_H
+#define XLNX_USB2_REGS_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
new file mode 100644
index 000000000..a894546c0
--- /dev/null
+++ b/include/hw/vfio/vfio-amd-xgbe.h
@@ -0,0 +1,46 @@
+/*
+ * VFIO AMD XGBE device
+ *
+ * Copyright Linaro Limited, 2015
+ *
+ * Authors:
+ * Eric Auger <eric.auger@linaro.org>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef HW_VFIO_VFIO_AMD_XGBE_H
+#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"
+
+/**
+ * This device exposes:
+ * - 5 MMIO regions: MAC, PCS, SerDes Rx/Tx regs,
+ SerDes Integration Registers 1/2 & 2/2
+ * - 2 level sensitive IRQs and optional DMA channel IRQs
+ */
+struct VFIOAmdXgbeDevice {
+ VFIOPlatformDevice vdev;
+};
+
+typedef struct VFIOAmdXgbeDevice VFIOAmdXgbeDevice;
+
+struct VFIOAmdXgbeDeviceClass {
+ /*< private >*/
+ VFIOPlatformDeviceClass parent_class;
+ /*< public >*/
+ DeviceRealize parent_realize;
+};
+
+typedef struct VFIOAmdXgbeDeviceClass VFIOAmdXgbeDeviceClass;
+
+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
new file mode 100644
index 000000000..8482f151d
--- /dev/null
+++ b/include/hw/vfio/vfio-calxeda-xgmac.h
@@ -0,0 +1,43 @@
+/*
+ * VFIO calxeda xgmac device
+ *
+ * Copyright Linaro Limited, 2014
+ *
+ * Authors:
+ * Eric Auger <eric.auger@linaro.org>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef HW_VFIO_VFIO_CALXEDA_XGMAC_H
+#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"
+
+/**
+ * This device exposes:
+ * - a single MMIO region corresponding to its register space
+ * - 3 IRQS (main and 2 power related IRQs)
+ */
+struct VFIOCalxedaXgmacDevice {
+ VFIOPlatformDevice vdev;
+};
+typedef struct VFIOCalxedaXgmacDevice VFIOCalxedaXgmacDevice;
+
+struct VFIOCalxedaXgmacDeviceClass {
+ /*< private >*/
+ VFIOPlatformDeviceClass parent_class;
+ /*< public >*/
+ DeviceRealize parent_realize;
+};
+typedef struct VFIOCalxedaXgmacDeviceClass VFIOCalxedaXgmacDeviceClass;
+
+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
new file mode 100644
index 000000000..8af11b0a7
--- /dev/null
+++ b/include/hw/vfio/vfio-common.h
@@ -0,0 +1,247 @@
+/*
+ * common header for vfio based device assignment support
+ *
+ * Copyright Red Hat, Inc. 2012
+ *
+ * Authors:
+ * Alex Williamson <alex.williamson@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ * Based on qemu-kvm device-assignment:
+ * Adapted for KVM by Qumranet.
+ * Copyright (c) 2007, Neocleus, Alex Novik (alex@neocleus.com)
+ * Copyright (c) 2007, Neocleus, Guy Zana (guy@neocleus.com)
+ * Copyright (C) 2008, Qumranet, Amit Shah (amit.shah@qumranet.com)
+ * Copyright (C) 2008, Red Hat, Amit Shah (amit.shah@redhat.com)
+ * Copyright (C) 2008, IBM, Muli Ben-Yehuda (muli@il.ibm.com)
+ */
+
+#ifndef HW_VFIO_VFIO_COMMON_H
+#define HW_VFIO_VFIO_COMMON_H
+
+#include "exec/memory.h"
+#include "qemu/queue.h"
+#include "qemu/notify.h"
+#include "ui/console.h"
+#include "hw/display/ramfb.h"
+#ifdef CONFIG_LINUX
+#include <linux/vfio.h>
+#endif
+#include "sysemu/sysemu.h"
+
+#define VFIO_MSG_PREFIX "vfio %s: "
+
+enum {
+ VFIO_DEVICE_TYPE_PCI = 0,
+ VFIO_DEVICE_TYPE_PLATFORM = 1,
+ VFIO_DEVICE_TYPE_CCW = 2,
+ VFIO_DEVICE_TYPE_AP = 3,
+};
+
+typedef struct VFIOMmap {
+ MemoryRegion mem;
+ void *mmap;
+ off_t offset;
+ size_t size;
+} VFIOMmap;
+
+typedef struct VFIORegion {
+ struct VFIODevice *vbasedev;
+ off_t fd_offset; /* offset of region within device fd */
+ MemoryRegion *mem; /* slow, read/write access */
+ size_t size;
+ uint32_t flags; /* VFIO region flags (rd/wr/mmap) */
+ uint32_t nr_mmaps;
+ VFIOMmap *mmaps;
+ uint8_t nr; /* cache the region number for debug */
+} VFIORegion;
+
+typedef struct VFIOMigration {
+ struct VFIODevice *vbasedev;
+ VMChangeStateEntry *vm_state;
+ VFIORegion region;
+ uint32_t device_state;
+ int vm_running;
+ Notifier migration_state;
+ uint64_t pending_bytes;
+} VFIOMigration;
+
+typedef struct VFIOAddressSpace {
+ AddressSpace *as;
+ QLIST_HEAD(, VFIOContainer) containers;
+ QLIST_ENTRY(VFIOAddressSpace) list;
+} VFIOAddressSpace;
+
+struct VFIOGroup;
+
+typedef struct VFIOContainer {
+ VFIOAddressSpace *space;
+ int fd; /* /dev/vfio/vfio, empowered by the attached groups */
+ MemoryListener listener;
+ MemoryListener prereg_listener;
+ unsigned iommu_type;
+ Error *error;
+ bool initialized;
+ bool dirty_pages_supported;
+ uint64_t dirty_pgsizes;
+ uint64_t max_dirty_bitmap_size;
+ unsigned long pgsizes;
+ unsigned int dma_max_mappings;
+ QLIST_HEAD(, VFIOGuestIOMMU) giommu_list;
+ QLIST_HEAD(, VFIOHostDMAWindow) hostwin_list;
+ QLIST_HEAD(, VFIOGroup) group_list;
+ QLIST_HEAD(, VFIORamDiscardListener) vrdl_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 VFIORamDiscardListener {
+ VFIOContainer *container;
+ MemoryRegion *mr;
+ hwaddr offset_within_address_space;
+ hwaddr size;
+ uint64_t granularity;
+ RamDiscardListener listener;
+ QLIST_ENTRY(VFIORamDiscardListener) next;
+} VFIORamDiscardListener;
+
+typedef struct VFIOHostDMAWindow {
+ hwaddr min_iova;
+ hwaddr max_iova;
+ uint64_t iova_pgsizes;
+ QLIST_ENTRY(VFIOHostDMAWindow) hostwin_next;
+} VFIOHostDMAWindow;
+
+typedef struct VFIODeviceOps VFIODeviceOps;
+
+typedef struct VFIODevice {
+ QLIST_ENTRY(VFIODevice) next;
+ struct VFIOGroup *group;
+ char *sysfsdev;
+ char *name;
+ DeviceState *dev;
+ int fd;
+ int type;
+ bool reset_works;
+ bool needs_reset;
+ bool no_mmap;
+ bool ram_block_discard_allowed;
+ bool 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;
+} 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 {
+ int fd;
+ int groupid;
+ VFIOContainer *container;
+ QLIST_HEAD(, VFIODevice) device_list;
+ QLIST_ENTRY(VFIOGroup) next;
+ QLIST_ENTRY(VFIOGroup) container_next;
+ bool ram_block_discard_allowed;
+} VFIOGroup;
+
+typedef struct VFIODMABuf {
+ QemuDmaBuf buf;
+ uint32_t pos_x, pos_y, pos_updates;
+ uint32_t hot_x, hot_y, hot_updates;
+ int dmabuf_id;
+ QTAILQ_ENTRY(VFIODMABuf) next;
+} VFIODMABuf;
+
+typedef struct VFIODisplay {
+ QemuConsole *con;
+ RAMFBState *ramfb;
+ struct vfio_region_info *edid_info;
+ struct vfio_region_gfx_edid *edid_regs;
+ uint8_t *edid_blob;
+ QEMUTimer *edid_link_timer;
+ struct {
+ VFIORegion buffer;
+ DisplaySurface *surface;
+ } region;
+ struct {
+ QTAILQ_HEAD(, VFIODMABuf) bufs;
+ VFIODMABuf *primary;
+ VFIODMABuf *cursor;
+ } dmabuf;
+} VFIODisplay;
+
+void vfio_put_base_device(VFIODevice *vbasedev);
+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);
+int vfio_set_irq_signaling(VFIODevice *vbasedev, int index, int subindex,
+ int action, int fd, Error **errp);
+void vfio_region_write(void *opaque, hwaddr addr,
+ uint64_t data, unsigned size);
+uint64_t vfio_region_read(void *opaque,
+ hwaddr addr, unsigned size);
+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);
+
+extern const MemoryRegionOps vfio_region_ops;
+typedef QLIST_HEAD(VFIOGroupList, VFIOGroup) VFIOGroupList;
+extern VFIOGroupList vfio_group_list;
+
+bool vfio_mig_active(void);
+int64_t vfio_mig_bytes_transferred(void);
+
+#ifdef CONFIG_LINUX
+int vfio_get_region_info(VFIODevice *vbasedev, int index,
+ struct vfio_region_info **info);
+int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type,
+ uint32_t subtype, struct vfio_region_info **info);
+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);
+#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);
+
+int vfio_migration_probe(VFIODevice *vbasedev, Error **errp);
+void vfio_migration_finalize(VFIODevice *vbasedev);
+
+#endif /* HW_VFIO_VFIO_COMMON_H */
diff --git a/include/hw/vfio/vfio-platform.h b/include/hw/vfio/vfio-platform.h
new file mode 100644
index 000000000..c414c3dff
--- /dev/null
+++ b/include/hw/vfio/vfio-platform.h
@@ -0,0 +1,76 @@
+/*
+ * vfio based device assignment support - platform devices
+ *
+ * Copyright Linaro Limited, 2014
+ *
+ * Authors:
+ * Kim Phillips <kim.phillips@linaro.org>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ * Based on vfio based PCI device assignment support:
+ * Copyright Red Hat, Inc. 2012
+ */
+
+#ifndef HW_VFIO_VFIO_PLATFORM_H
+#define HW_VFIO_VFIO_PLATFORM_H
+
+#include "hw/sysbus.h"
+#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"
+
+enum {
+ VFIO_IRQ_INACTIVE = 0,
+ VFIO_IRQ_PENDING = 1,
+ VFIO_IRQ_ACTIVE = 2,
+ /* VFIO_IRQ_ACTIVE_AND_PENDING cannot happen with VFIO */
+};
+
+typedef struct VFIOINTp {
+ QLIST_ENTRY(VFIOINTp) next; /* entry for IRQ list */
+ QSIMPLEQ_ENTRY(VFIOINTp) pqnext; /* entry for pending IRQ queue */
+ EventNotifier *interrupt; /* eventfd triggered on interrupt */
+ EventNotifier *unmask; /* eventfd for unmask on QEMU bypass */
+ qemu_irq qemuirq;
+ struct VFIOPlatformDevice *vdev; /* back pointer to device */
+ int state; /* inactive, pending, active */
+ uint8_t pin; /* index */
+ uint32_t flags; /* IRQ info flags */
+ bool kvm_accel; /* set when QEMU bypass through KVM enabled */
+} VFIOINTp;
+
+/* function type for user side eventfd handler */
+typedef void (*eventfd_user_side_handler_t)(VFIOINTp *intp);
+
+struct VFIOPlatformDevice {
+ SysBusDevice sbdev;
+ VFIODevice vbasedev; /* not a QOM object */
+ VFIORegion **regions;
+ QLIST_HEAD(, VFIOINTp) intp_list; /* list of IRQs */
+ /* queue of pending IRQs */
+ QSIMPLEQ_HEAD(, VFIOINTp) pending_intp_queue;
+ char *compat; /* DT compatible values, separated by NUL */
+ unsigned int num_compat; /* number of compatible values */
+ uint32_t mmap_timeout; /* delay to re-enable mmaps after interrupt */
+ 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 */
+};
+typedef struct VFIOPlatformDevice VFIOPlatformDevice;
+
+struct VFIOPlatformDeviceClass {
+ /*< private >*/
+ SysBusDeviceClass parent_class;
+ /*< public >*/
+};
+typedef struct VFIOPlatformDeviceClass VFIOPlatformDeviceClass;
+
+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
new file mode 100644
index 000000000..86248f543
--- /dev/null
+++ b/include/hw/vfio/vfio.h
@@ -0,0 +1,7 @@
+#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/vhost-backend.h b/include/hw/virtio/vhost-backend.h
new file mode 100644
index 000000000..81bf3109f
--- /dev/null
+++ b/include/hw/virtio/vhost-backend.h
@@ -0,0 +1,189 @@
+/*
+ * vhost-backend
+ *
+ * Copyright (c) 2013 Virtual Open Systems Sarl.
+ *
+ * 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 VHOST_BACKEND_H
+#define VHOST_BACKEND_H
+
+#include "exec/memory.h"
+
+typedef enum VhostBackendType {
+ VHOST_BACKEND_TYPE_NONE = 0,
+ VHOST_BACKEND_TYPE_KERNEL = 1,
+ VHOST_BACKEND_TYPE_USER = 2,
+ VHOST_BACKEND_TYPE_VDPA = 3,
+ VHOST_BACKEND_TYPE_MAX = 4,
+} VhostBackendType;
+
+typedef enum VhostSetConfigType {
+ VHOST_SET_CONFIG_TYPE_MASTER = 0,
+ VHOST_SET_CONFIG_TYPE_MIGRATION = 1,
+} VhostSetConfigType;
+
+struct vhost_inflight;
+struct vhost_dev;
+struct vhost_log;
+struct vhost_memory;
+struct vhost_vring_file;
+struct vhost_vring_state;
+struct vhost_vring_addr;
+struct vhost_scsi_target;
+struct vhost_iotlb_msg;
+struct vhost_virtqueue;
+
+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);
+
+typedef int (*vhost_net_set_backend_op)(struct vhost_dev *dev,
+ struct vhost_vring_file *file);
+typedef int (*vhost_net_set_mtu_op)(struct vhost_dev *dev, uint16_t mtu);
+typedef int (*vhost_scsi_set_endpoint_op)(struct vhost_dev *dev,
+ struct vhost_scsi_target *target);
+typedef int (*vhost_scsi_clear_endpoint_op)(struct vhost_dev *dev,
+ struct vhost_scsi_target *target);
+typedef int (*vhost_scsi_get_abi_version_op)(struct vhost_dev *dev,
+ int *version);
+typedef int (*vhost_set_log_base_op)(struct vhost_dev *dev, uint64_t base,
+ struct vhost_log *log);
+typedef int (*vhost_set_mem_table_op)(struct vhost_dev *dev,
+ struct vhost_memory *mem);
+typedef int (*vhost_set_vring_addr_op)(struct vhost_dev *dev,
+ struct vhost_vring_addr *addr);
+typedef int (*vhost_set_vring_endian_op)(struct vhost_dev *dev,
+ struct vhost_vring_state *ring);
+typedef int (*vhost_set_vring_num_op)(struct vhost_dev *dev,
+ struct vhost_vring_state *ring);
+typedef int (*vhost_set_vring_base_op)(struct vhost_dev *dev,
+ struct vhost_vring_state *ring);
+typedef int (*vhost_get_vring_base_op)(struct vhost_dev *dev,
+ struct vhost_vring_state *ring);
+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_busyloop_timeout_op)(struct vhost_dev *dev,
+ struct vhost_vring_state *r);
+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);
+typedef int (*vhost_set_vring_enable_op)(struct vhost_dev *dev,
+ int enable);
+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);
+typedef void (*vhost_set_iotlb_callback_op)(struct vhost_dev *dev,
+ int enabled);
+typedef int (*vhost_send_device_iotlb_msg_op)(struct vhost_dev *dev,
+ struct vhost_iotlb_msg *imsg);
+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, Error **errp);
+
+typedef int (*vhost_crypto_create_session_op)(struct vhost_dev *dev,
+ void *session_info,
+ uint64_t *session_id);
+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 int (*vhost_get_inflight_fd_op)(struct vhost_dev *dev,
+ uint16_t queue_size,
+ struct vhost_inflight *inflight);
+
+typedef int (*vhost_set_inflight_fd_op)(struct vhost_dev *dev,
+ struct vhost_inflight *inflight);
+
+typedef int (*vhost_dev_start_op)(struct vhost_dev *dev, bool started);
+
+typedef int (*vhost_vq_get_addr_op)(struct vhost_dev *dev,
+ struct vhost_vring_addr *addr,
+ struct vhost_virtqueue *vq);
+
+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 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_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;
+ vhost_scsi_clear_endpoint_op vhost_scsi_clear_endpoint;
+ vhost_scsi_get_abi_version_op vhost_scsi_get_abi_version;
+ vhost_set_log_base_op vhost_set_log_base;
+ vhost_set_mem_table_op vhost_set_mem_table;
+ vhost_set_vring_addr_op vhost_set_vring_addr;
+ vhost_set_vring_endian_op vhost_set_vring_endian;
+ vhost_set_vring_num_op vhost_set_vring_num;
+ vhost_set_vring_base_op vhost_set_vring_base;
+ 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_busyloop_timeout_op vhost_set_vring_busyloop_timeout;
+ 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;
+ vhost_send_device_iotlb_msg_op vhost_send_device_iotlb_msg;
+ vhost_get_config_op vhost_get_config;
+ 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;
+} VhostOps;
+
+int vhost_backend_update_device_iotlb(struct vhost_dev *dev,
+ uint64_t iova, uint64_t uaddr,
+ uint64_t len,
+ IOMMUAccessFlags perm);
+
+int vhost_backend_invalidate_device_iotlb(struct vhost_dev *dev,
+ uint64_t iova, uint64_t len);
+
+int vhost_backend_handle_iotlb_msg(struct vhost_dev *dev,
+ struct vhost_iotlb_msg *imsg);
+
+int vhost_user_gpu_set_socket(struct vhost_dev *dev, int fd);
+
+#endif /* VHOST_BACKEND_H */
diff --git a/include/hw/virtio/vhost-scsi-common.h b/include/hw/virtio/vhost-scsi-common.h
new file mode 100644
index 000000000..18f115527
--- /dev/null
+++ b/include/hw/virtio/vhost-scsi-common.h
@@ -0,0 +1,50 @@
+/*
+ * vhost_scsi host device
+ *
+ * Copyright (c) 2016 Nutanix Inc. All rights reserved.
+ *
+ * Author:
+ * Felipe Franciosi <felipe@nutanix.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_SCSI_COMMON_H
+#define VHOST_SCSI_COMMON_H
+
+#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"
+OBJECT_DECLARE_SIMPLE_TYPE(VHostSCSICommon, VHOST_SCSI_COMMON)
+
+struct VHostSCSICommon {
+ VirtIOSCSICommon parent_obj;
+
+ Error *migration_blocker;
+
+ struct vhost_dev dev;
+ const int *feature_bits;
+ int32_t bootindex;
+ int channel;
+ int target;
+ int lun;
+ uint64_t host_features;
+ bool migratable;
+
+ struct vhost_inflight *inflight;
+};
+
+int vhost_scsi_common_start(VHostSCSICommon *vsc);
+void vhost_scsi_common_stop(VHostSCSICommon *vsc);
+char *vhost_scsi_common_get_fw_dev_path(FWPathProvider *p, BusState *bus,
+ DeviceState *dev);
+void vhost_scsi_common_set_config(VirtIODevice *vdev, const uint8_t *config);
+uint64_t vhost_scsi_common_get_features(VirtIODevice *vdev, uint64_t features,
+ Error **errp);
+
+#endif /* VHOST_SCSI_COMMON_H */
diff --git a/include/hw/virtio/vhost-scsi.h b/include/hw/virtio/vhost-scsi.h
new file mode 100644
index 000000000..7dc2bdd69
--- /dev/null
+++ b/include/hw/virtio/vhost-scsi.h
@@ -0,0 +1,35 @@
+/*
+ * vhost_scsi host device
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ * Stefan Hajnoczi <stefanha@linux.vnet.ibm.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_SCSI_H
+#define VHOST_SCSI_H
+
+#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,
+ VHOST_SCSI_VQ_EVENT = 1,
+ VHOST_SCSI_VQ_NUM_FIXED = 2,
+};
+
+#define TYPE_VHOST_SCSI "vhost-scsi"
+OBJECT_DECLARE_SIMPLE_TYPE(VHostSCSI, VHOST_SCSI)
+
+struct VHostSCSI {
+ VHostSCSICommon parent_obj;
+};
+
+#endif
diff --git a/include/hw/virtio/vhost-user-blk.h b/include/hw/virtio/vhost-user-blk.h
new file mode 100644
index 000000000..7c91f1504
--- /dev/null
+++ b/include/hw/virtio/vhost-user-blk.h
@@ -0,0 +1,56 @@
+/*
+ * vhost-user-blk host device
+ * Copyright(C) 2017 Intel Corporation.
+ *
+ * Authors:
+ * Changpeng Liu <changpeng.liu@intel.com>
+ *
+ * Based on vhost-scsi.h, Copyright IBM, Corp. 2011
+ *
+ * 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_USER_BLK_H
+#define VHOST_USER_BLK_H
+
+#include "standard-headers/linux/virtio_blk.h"
+#include "hw/block/block.h"
+#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"
+OBJECT_DECLARE_SIMPLE_TYPE(VHostUserBlk, VHOST_USER_BLK)
+
+#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;
+ /* 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
new file mode 100644
index 000000000..0d62834c2
--- /dev/null
+++ b/include/hw/virtio/vhost-user-fs.h
@@ -0,0 +1,47 @@
+/*
+ * Vhost-user filesystem virtio device
+ *
+ * Copyright 2018-2019 Red Hat, Inc.
+ *
+ * Authors:
+ * Stefan Hajnoczi <stefanha@redhat.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 _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"
+OBJECT_DECLARE_SIMPLE_TYPE(VHostUserFS, VHOST_USER_FS)
+
+typedef struct {
+ CharBackend chardev;
+ char *tag;
+ uint16_t num_request_queues;
+ uint16_t queue_size;
+} VHostUserFSConf;
+
+struct VHostUserFS {
+ /*< private >*/
+ VirtIODevice parent;
+ VHostUserFSConf conf;
+ struct vhost_virtqueue *vhost_vqs;
+ struct vhost_dev vhost_dev;
+ VhostUserState vhost_user;
+ VirtQueue **req_vqs;
+ VirtQueue *hiprio_vq;
+ int32_t bootindex;
+
+ /*< public >*/
+};
+
+#endif /* _QEMU_VHOST_USER_FS_H */
diff --git a/include/hw/virtio/vhost-user-i2c.h b/include/hw/virtio/vhost-user-i2c.h
new file mode 100644
index 000000000..deae47a76
--- /dev/null
+++ b/include/hw/virtio/vhost-user-i2c.h
@@ -0,0 +1,28 @@
+/*
+ * 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/vhost.h"
+#include "hw/virtio/vhost-user.h"
+
+#define TYPE_VHOST_USER_I2C "vhost-user-i2c-device"
+OBJECT_DECLARE_SIMPLE_TYPE(VHostUserI2C, VHOST_USER_I2C)
+
+struct VHostUserI2C {
+ VirtIODevice parent;
+ CharBackend chardev;
+ struct vhost_virtqueue *vhost_vq;
+ struct vhost_dev vhost_dev;
+ VhostUserState vhost_user;
+ VirtQueue *vq;
+ bool connected;
+};
+
+#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 000000000..071539996
--- /dev/null
+++ b/include/hw/virtio/vhost-user-rng.h
@@ -0,0 +1,33 @@
+/*
+ * 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 "chardev/char-fe.h"
+
+#define TYPE_VHOST_USER_RNG "vhost-user-rng"
+OBJECT_DECLARE_SIMPLE_TYPE(VHostUserRNG, VHOST_USER_RNG)
+
+struct VHostUserRNG {
+ /*< private >*/
+ VirtIODevice parent;
+ CharBackend chardev;
+ struct vhost_virtqueue *vhost_vq;
+ struct vhost_dev vhost_dev;
+ VhostUserState vhost_user;
+ VirtQueue *req_vq;
+ bool connected;
+
+ /*< public >*/
+};
+
+#endif /* _QEMU_VHOST_USER_RNG_H */
diff --git a/include/hw/virtio/vhost-user-scsi.h b/include/hw/virtio/vhost-user-scsi.h
new file mode 100644
index 000000000..521b08e55
--- /dev/null
+++ b/include/hw/virtio/vhost-user-scsi.h
@@ -0,0 +1,34 @@
+/*
+ * vhost-user-scsi host device
+ *
+ * Copyright (c) 2016 Nutanix Inc. All rights reserved.
+ *
+ * Author:
+ * Felipe Franciosi <felipe@nutanix.com>
+ *
+ * This file is largely based on "vhost-scsi.h" by:
+ * Stefan Hajnoczi <stefanha@linux.vnet.ibm.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_USER_SCSI_H
+#define VHOST_USER_SCSI_H
+
+#include "hw/virtio/virtio-scsi.h"
+#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"
+OBJECT_DECLARE_SIMPLE_TYPE(VHostUserSCSI, VHOST_USER_SCSI)
+
+struct VHostUserSCSI {
+ VHostSCSICommon parent_obj;
+ VhostUserState vhost_user;
+};
+
+#endif /* VHOST_USER_SCSI_H */
diff --git a/include/hw/virtio/vhost-user-vsock.h b/include/hw/virtio/vhost-user-vsock.h
new file mode 100644
index 000000000..4cfd55824
--- /dev/null
+++ b/include/hw/virtio/vhost-user-vsock.h
@@ -0,0 +1,36 @@
+/*
+ * Vhost-user vsock virtio device
+ *
+ * Copyright 2020 Red Hat, Inc.
+ *
+ * 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_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"
+OBJECT_DECLARE_SIMPLE_TYPE(VHostUserVSock, VHOST_USER_VSOCK)
+
+typedef struct {
+ CharBackend chardev;
+} VHostUserVSockConf;
+
+struct VHostUserVSock {
+ /*< private >*/
+ VHostVSockCommon parent;
+ VhostUserState vhost_user;
+ VHostUserVSockConf conf;
+ struct virtio_vsock_config vsockcfg;
+
+ /*< public >*/
+};
+
+#endif /* _QEMU_VHOST_USER_VSOCK_H */
diff --git a/include/hw/virtio/vhost-user.h b/include/hw/virtio/vhost-user.h
new file mode 100644
index 000000000..a9abca328
--- /dev/null
+++ b/include/hw/virtio/vhost-user.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017-2018 Intel Corporation
+ *
+ * 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_VHOST_USER_H
+#define HW_VIRTIO_VHOST_USER_H
+
+#include "chardev/char-fe.h"
+#include "hw/virtio/virtio.h"
+
+typedef struct VhostUserHostNotifier {
+ MemoryRegion mr;
+ void *addr;
+ bool set;
+} VhostUserHostNotifier;
+
+typedef struct VhostUserState {
+ CharBackend *chr;
+ VhostUserHostNotifier notifier[VIRTIO_QUEUE_MAX];
+ int memory_slots;
+} VhostUserState;
+
+bool vhost_user_init(VhostUserState *user, CharBackend *chr, Error **errp);
+void vhost_user_cleanup(VhostUserState *user);
+
+#endif
diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h
new file mode 100644
index 000000000..3ce79a646
--- /dev/null
+++ b/include/hw/virtio/vhost-vdpa.h
@@ -0,0 +1,34 @@
+/*
+ * vhost-vdpa.h
+ *
+ * Copyright(c) 2017-2018 Intel Corporation.
+ * Copyright(c) 2020 Red Hat, 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 HW_VIRTIO_VHOST_VDPA_H
+#define HW_VIRTIO_VHOST_VDPA_H
+
+#include "hw/virtio/virtio.h"
+#include "standard-headers/linux/vhost_types.h"
+
+typedef struct VhostVDPAHostNotifier {
+ MemoryRegion mr;
+ void *addr;
+} VhostVDPAHostNotifier;
+
+typedef struct vhost_vdpa {
+ int device_fd;
+ int index;
+ uint32_t msg_type;
+ bool iotlb_batch_begin_sent;
+ MemoryListener listener;
+ struct vhost_vdpa_iova_range iova_range;
+ struct vhost_dev *dev;
+ VhostVDPAHostNotifier notifier[VIRTIO_QUEUE_MAX];
+} VhostVDPA;
+
+#endif
diff --git a/include/hw/virtio/vhost-vsock-common.h b/include/hw/virtio/vhost-vsock-common.h
new file mode 100644
index 000000000..d8b565b4d
--- /dev/null
+++ b/include/hw/virtio/vhost-vsock-common.h
@@ -0,0 +1,52 @@
+/*
+ * Parent class for vhost-vsock devices
+ *
+ * Copyright 2015-2020 Red Hat, Inc.
+ *
+ * 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_VHOST_VSOCK_COMMON_H
+#define _QEMU_VHOST_VSOCK_COMMON_H
+
+#include "hw/virtio/virtio.h"
+#include "hw/virtio/vhost.h"
+#include "qom/object.h"
+
+#define TYPE_VHOST_VSOCK_COMMON "vhost-vsock-common"
+OBJECT_DECLARE_SIMPLE_TYPE(VHostVSockCommon, VHOST_VSOCK_COMMON)
+
+enum {
+ VHOST_VSOCK_SAVEVM_VERSION = 0,
+
+ VHOST_VSOCK_QUEUE_SIZE = 128,
+};
+
+struct VHostVSockCommon {
+ VirtIODevice parent;
+
+ struct vhost_virtqueue vhost_vqs[2];
+ struct vhost_dev vhost_dev;
+
+ VirtQueue *event_vq;
+ VirtQueue *recv_vq;
+ VirtQueue *trans_vq;
+
+ QEMUTimer *post_load_timer;
+
+ /* 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_unrealize(VirtIODevice *vdev);
+uint64_t vhost_vsock_common_get_features(VirtIODevice *vdev, uint64_t features,
+ Error **errp);
+
+#endif /* _QEMU_VHOST_VSOCK_COMMON_H */
diff --git a/include/hw/virtio/vhost-vsock.h b/include/hw/virtio/vhost-vsock.h
new file mode 100644
index 000000000..84f4e727c
--- /dev/null
+++ b/include/hw/virtio/vhost-vsock.h
@@ -0,0 +1,36 @@
+/*
+ * Vhost vsock virtio device
+ *
+ * Copyright 2015 Red Hat, Inc.
+ *
+ * Authors:
+ * Stefan Hajnoczi <stefanha@redhat.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 QEMU_VHOST_VSOCK_H
+#define QEMU_VHOST_VSOCK_H
+
+#include "hw/virtio/vhost-vsock-common.h"
+#include "qom/object.h"
+
+#define TYPE_VHOST_VSOCK "vhost-vsock-device"
+OBJECT_DECLARE_SIMPLE_TYPE(VHostVSock, VHOST_VSOCK)
+
+typedef struct {
+ uint64_t guest_cid;
+ char *vhostfd;
+} VHostVSockConf;
+
+struct VHostVSock {
+ /*< private >*/
+ VHostVSockCommon parent;
+ VHostVSockConf conf;
+
+ /*< public >*/
+};
+
+#endif /* QEMU_VHOST_VSOCK_H */
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
new file mode 100644
index 000000000..58a73e7b7
--- /dev/null
+++ b/include/hw/virtio/vhost.h
@@ -0,0 +1,157 @@
+#ifndef VHOST_H
+#define VHOST_H
+
+#include "hw/virtio/vhost-backend.h"
+#include "hw/virtio/virtio.h"
+#include "exec/memory.h"
+
+/* Generic structures common for any vhost based device. */
+
+struct vhost_inflight {
+ int fd;
+ void *addr;
+ uint64_t size;
+ uint64_t offset;
+ uint16_t queue_size;
+};
+
+struct vhost_virtqueue {
+ int kick;
+ int call;
+ void *desc;
+ void *avail;
+ void *used;
+ int num;
+ unsigned long long desc_phys;
+ unsigned desc_size;
+ unsigned long long avail_phys;
+ unsigned avail_size;
+ unsigned long long used_phys;
+ unsigned used_size;
+ EventNotifier masked_notifier;
+ struct vhost_dev *dev;
+};
+
+typedef unsigned long vhost_log_chunk_t;
+#define VHOST_LOG_PAGE 0x1000
+#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)
+
+struct vhost_log {
+ unsigned long long size;
+ int refcnt;
+ int fd;
+ vhost_log_chunk_t *log;
+};
+
+struct vhost_dev;
+struct vhost_iommu {
+ struct vhost_dev *hdev;
+ MemoryRegion *mr;
+ hwaddr iommu_offset;
+ IOMMUNotifier n;
+ QLIST_ENTRY(vhost_iommu) iommu_next;
+};
+
+typedef struct VhostDevConfigOps {
+ /* Vhost device config space changed callback
+ */
+ int (*vhost_dev_config_notifier)(struct vhost_dev *dev);
+} VhostDevConfigOps;
+
+struct vhost_memory;
+struct vhost_dev {
+ VirtIODevice *vdev;
+ MemoryListener memory_listener;
+ MemoryListener iommu_listener;
+ struct vhost_memory *mem;
+ int n_mem_sections;
+ MemoryRegionSection *mem_sections;
+ int n_tmp_sections;
+ MemoryRegionSection *tmp_sections;
+ struct vhost_virtqueue *vqs;
+ 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;
+ uint64_t features;
+ uint64_t acked_features;
+ uint64_t backend_features;
+ uint64_t protocol_features;
+ uint64_t max_queues;
+ uint64_t backend_cap;
+ bool started;
+ bool log_enabled;
+ uint64_t log_size;
+ Error *migration_blocker;
+ const VhostOps *vhost_ops;
+ void *opaque;
+ struct vhost_log *log;
+ QLIST_ENTRY(vhost_dev) entry;
+ QLIST_HEAD(, vhost_iommu) iommu_list;
+ IOMMUNotifier n;
+ 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];
+ int backend;
+ NetClientState *nc;
+};
+
+int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
+ VhostBackendType backend_type,
+ uint32_t busyloop_timeout, Error **errp);
+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);
+int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev);
+void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev);
+
+/* Test and clear masked event pending status.
+ * Should be called after unmask to avoid losing events.
+ */
+bool vhost_virtqueue_pending(struct vhost_dev *hdev, int n);
+
+/* Mask/unmask events from this vq.
+ */
+void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n,
+ bool mask);
+uint64_t vhost_get_features(struct vhost_dev *hdev, const int *feature_bits,
+ uint64_t features);
+void vhost_ack_features(struct vhost_dev *hdev, const int *feature_bits,
+ uint64_t features);
+bool vhost_has_free_slot(void);
+
+int vhost_net_set_backend(struct vhost_dev *hdev,
+ struct vhost_vring_file *file);
+
+int vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t iova, int write);
+int vhost_dev_get_config(struct vhost_dev *hdev, uint8_t *config,
+ uint32_t config_len, Error **errp);
+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);
+
+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);
+#endif
diff --git a/include/hw/virtio/virtio-access.h b/include/hw/virtio/virtio-access.h
new file mode 100644
index 000000000..6818a23a2
--- /dev/null
+++ b/include/hw/virtio/virtio-access.h
@@ -0,0 +1,243 @@
+/*
+ * Virtio Accessor Support: In case your target can change endian.
+ *
+ * Copyright IBM, Corp. 2013
+ *
+ * Authors:
+ * Rusty Russell <rusty@au.ibm.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.
+ *
+ */
+
+#ifndef QEMU_VIRTIO_ACCESS_H
+#define QEMU_VIRTIO_ACCESS_H
+
+#include "exec/hwaddr.h"
+#include "hw/virtio/virtio.h"
+#include "hw/virtio/virtio-bus.h"
+
+#if defined(TARGET_PPC64) || defined(TARGET_ARM)
+#define LEGACY_VIRTIO_IS_BIENDIAN 1
+#endif
+
+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)
+ if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
+ /* Devices conforming to VIRTIO 1.0 or later are always LE. */
+ return false;
+ }
+ return true;
+#else
+ return false;
+#endif
+}
+
+static inline uint16_t virtio_lduw_phys(VirtIODevice *vdev, hwaddr pa)
+{
+ AddressSpace *dma_as = vdev->dma_as;
+
+ if (virtio_access_is_big_endian(vdev)) {
+ return lduw_be_phys(dma_as, pa);
+ }
+ return lduw_le_phys(dma_as, pa);
+}
+
+static inline uint32_t virtio_ldl_phys(VirtIODevice *vdev, hwaddr pa)
+{
+ AddressSpace *dma_as = vdev->dma_as;
+
+ if (virtio_access_is_big_endian(vdev)) {
+ return ldl_be_phys(dma_as, pa);
+ }
+ return ldl_le_phys(dma_as, pa);
+}
+
+static inline uint64_t virtio_ldq_phys(VirtIODevice *vdev, hwaddr pa)
+{
+ AddressSpace *dma_as = vdev->dma_as;
+
+ if (virtio_access_is_big_endian(vdev)) {
+ return ldq_be_phys(dma_as, pa);
+ }
+ return ldq_le_phys(dma_as, pa);
+}
+
+static inline void virtio_stw_phys(VirtIODevice *vdev, hwaddr pa,
+ uint16_t value)
+{
+ AddressSpace *dma_as = vdev->dma_as;
+
+ if (virtio_access_is_big_endian(vdev)) {
+ stw_be_phys(dma_as, pa, value);
+ } else {
+ stw_le_phys(dma_as, pa, value);
+ }
+}
+
+static inline void virtio_stl_phys(VirtIODevice *vdev, hwaddr pa,
+ uint32_t value)
+{
+ AddressSpace *dma_as = vdev->dma_as;
+
+ if (virtio_access_is_big_endian(vdev)) {
+ stl_be_phys(dma_as, pa, value);
+ } else {
+ stl_le_phys(dma_as, pa, value);
+ }
+}
+
+static inline void virtio_stw_p(VirtIODevice *vdev, void *ptr, uint16_t v)
+{
+ if (virtio_access_is_big_endian(vdev)) {
+ stw_be_p(ptr, v);
+ } else {
+ stw_le_p(ptr, v);
+ }
+}
+
+static inline void virtio_stl_p(VirtIODevice *vdev, void *ptr, uint32_t v)
+{
+ if (virtio_access_is_big_endian(vdev)) {
+ stl_be_p(ptr, v);
+ } else {
+ stl_le_p(ptr, v);
+ }
+}
+
+static inline void virtio_stq_p(VirtIODevice *vdev, void *ptr, uint64_t v)
+{
+ if (virtio_access_is_big_endian(vdev)) {
+ stq_be_p(ptr, v);
+ } else {
+ stq_le_p(ptr, v);
+ }
+}
+
+static inline int virtio_lduw_p(VirtIODevice *vdev, const void *ptr)
+{
+ if (virtio_access_is_big_endian(vdev)) {
+ return lduw_be_p(ptr);
+ } else {
+ return lduw_le_p(ptr);
+ }
+}
+
+static inline int virtio_ldl_p(VirtIODevice *vdev, const void *ptr)
+{
+ if (virtio_access_is_big_endian(vdev)) {
+ return ldl_be_p(ptr);
+ } else {
+ return ldl_le_p(ptr);
+ }
+}
+
+static inline uint64_t virtio_ldq_p(VirtIODevice *vdev, const void *ptr)
+{
+ if (virtio_access_is_big_endian(vdev)) {
+ return ldq_be_p(ptr);
+ } else {
+ return ldq_le_p(ptr);
+ }
+}
+
+static inline uint16_t virtio_tswap16(VirtIODevice *vdev, uint16_t s)
+{
+#ifdef HOST_WORDS_BIGENDIAN
+ return virtio_access_is_big_endian(vdev) ? s : bswap16(s);
+#else
+ return virtio_access_is_big_endian(vdev) ? bswap16(s) : s;
+#endif
+}
+
+static inline uint16_t virtio_lduw_phys_cached(VirtIODevice *vdev,
+ MemoryRegionCache *cache,
+ hwaddr pa)
+{
+ if (virtio_access_is_big_endian(vdev)) {
+ return lduw_be_phys_cached(cache, pa);
+ }
+ return lduw_le_phys_cached(cache, pa);
+}
+
+static inline uint32_t virtio_ldl_phys_cached(VirtIODevice *vdev,
+ MemoryRegionCache *cache,
+ hwaddr pa)
+{
+ if (virtio_access_is_big_endian(vdev)) {
+ return ldl_be_phys_cached(cache, pa);
+ }
+ return ldl_le_phys_cached(cache, pa);
+}
+
+static inline uint64_t virtio_ldq_phys_cached(VirtIODevice *vdev,
+ MemoryRegionCache *cache,
+ hwaddr pa)
+{
+ if (virtio_access_is_big_endian(vdev)) {
+ return ldq_be_phys_cached(cache, pa);
+ }
+ return ldq_le_phys_cached(cache, pa);
+}
+
+static inline void virtio_stw_phys_cached(VirtIODevice *vdev,
+ MemoryRegionCache *cache,
+ hwaddr pa, uint16_t value)
+{
+ if (virtio_access_is_big_endian(vdev)) {
+ stw_be_phys_cached(cache, pa, value);
+ } else {
+ stw_le_phys_cached(cache, pa, value);
+ }
+}
+
+static inline void virtio_stl_phys_cached(VirtIODevice *vdev,
+ MemoryRegionCache *cache,
+ hwaddr pa, uint32_t value)
+{
+ if (virtio_access_is_big_endian(vdev)) {
+ stl_be_phys_cached(cache, pa, value);
+ } else {
+ stl_le_phys_cached(cache, pa, value);
+ }
+}
+
+static inline void virtio_tswap16s(VirtIODevice *vdev, uint16_t *s)
+{
+ *s = virtio_tswap16(vdev, *s);
+}
+
+static inline uint32_t virtio_tswap32(VirtIODevice *vdev, uint32_t s)
+{
+#ifdef HOST_WORDS_BIGENDIAN
+ return virtio_access_is_big_endian(vdev) ? s : bswap32(s);
+#else
+ return virtio_access_is_big_endian(vdev) ? bswap32(s) : s;
+#endif
+}
+
+static inline void virtio_tswap32s(VirtIODevice *vdev, uint32_t *s)
+{
+ *s = virtio_tswap32(vdev, *s);
+}
+
+static inline uint64_t virtio_tswap64(VirtIODevice *vdev, uint64_t s)
+{
+#ifdef HOST_WORDS_BIGENDIAN
+ return virtio_access_is_big_endian(vdev) ? s : bswap64(s);
+#else
+ return virtio_access_is_big_endian(vdev) ? bswap64(s) : s;
+#endif
+}
+
+static inline void virtio_tswap64s(VirtIODevice *vdev, uint64_t *s)
+{
+ *s = virtio_tswap64(vdev, *s);
+}
+#endif /* QEMU_VIRTIO_ACCESS_H */
diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h
new file mode 100644
index 000000000..5139cf8ab
--- /dev/null
+++ b/include/hw/virtio/virtio-balloon.h
@@ -0,0 +1,76 @@
+/*
+ * Virtio Support
+ *
+ * Copyright IBM, Corp. 2007-2008
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@us.ibm.com>
+ * Rusty Russell <rusty@rustcorp.com.au>
+ *
+ * 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_BALLOON_H
+#define QEMU_VIRTIO_BALLOON_H
+
+#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"
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIOBalloon, VIRTIO_BALLOON)
+
+#define VIRTIO_BALLOON_FREE_PAGE_HINT_CMD_ID_MIN 0x80000000
+
+typedef struct virtio_balloon_stat VirtIOBalloonStat;
+
+typedef struct virtio_balloon_stat_modern {
+ uint16_t tag;
+ uint8_t reserved[6];
+ uint64_t val;
+} VirtIOBalloonStatModern;
+
+enum virtio_balloon_free_page_hint_status {
+ FREE_PAGE_HINT_S_STOP = 0,
+ FREE_PAGE_HINT_S_REQUESTED = 1,
+ FREE_PAGE_HINT_S_START = 2,
+ FREE_PAGE_HINT_S_DONE = 3,
+};
+
+struct VirtIOBalloon {
+ VirtIODevice parent_obj;
+ VirtQueue *ivq, *dvq, *svq, *free_page_vq, *reporting_vq;
+ uint32_t free_page_hint_status;
+ uint32_t num_pages;
+ uint32_t actual;
+ uint32_t free_page_hint_cmd_id;
+ uint64_t stats[VIRTIO_BALLOON_S_NR];
+ VirtQueueElement *stats_vq_elem;
+ size_t stats_vq_offset;
+ QEMUTimer *stats_timer;
+ IOThread *iothread;
+ QEMUBH *free_page_bh;
+ /*
+ * Lock to synchronize threads to access the free page reporting related
+ * fields (e.g. free_page_hint_status).
+ */
+ QemuMutex free_page_lock;
+ QemuCond free_page_cond;
+ /*
+ * Set to block iothread to continue reading free page hints as the VM is
+ * stopped.
+ */
+ bool block_iothread;
+ NotifierWithReturn free_page_hint_notify;
+ int64_t stats_last_update;
+ int64_t stats_poll_interval;
+ uint32_t host_features;
+
+ bool qemu_4_0_config_size;
+ uint32_t poison_val;
+};
+
+#endif
diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
new file mode 100644
index 000000000..29655a406
--- /dev/null
+++ b/include/hw/virtio/virtio-blk.h
@@ -0,0 +1,96 @@
+/*
+ * Virtio Block Device
+ *
+ * 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 QEMU_VIRTIO_BLK_H
+#define QEMU_VIRTIO_BLK_H
+
+#include "standard-headers/linux/virtio_blk.h"
+#include "hw/virtio/virtio.h"
+#include "hw/block/block.h"
+#include "sysemu/iothread.h"
+#include "sysemu/block-backend.h"
+#include "qom/object.h"
+
+#define TYPE_VIRTIO_BLK "virtio-blk-device"
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIOBlock, VIRTIO_BLK)
+
+/* This is the last element of the write scatter-gather list */
+struct virtio_blk_inhdr
+{
+ unsigned char status;
+};
+
+#define VIRTIO_BLK_AUTO_NUM_QUEUES UINT16_MAX
+
+struct VirtIOBlkConf
+{
+ BlockConf conf;
+ IOThread *iothread;
+ 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;
+struct VirtIOBlock {
+ VirtIODevice parent_obj;
+ BlockBackend *blk;
+ void *rq;
+ QEMUBH *bh;
+ VirtIOBlkConf conf;
+ unsigned short sector_mask;
+ bool original_wce;
+ VMChangeStateEntry *change;
+ bool dataplane_disabled;
+ bool dataplane_started;
+ struct VirtIOBlockDataPlane *dataplane;
+ uint64_t host_features;
+ size_t config_size;
+};
+
+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;
+ size_t in_len;
+ struct VirtIOBlockReq *next;
+ struct VirtIOBlockReq *mr_next;
+ BlockAcctCookie acct;
+} VirtIOBlockReq;
+
+#define VIRTIO_BLK_MAX_MERGE_REQS 32
+
+typedef struct MultiReqBuffer {
+ VirtIOBlockReq *reqs[VIRTIO_BLK_MAX_MERGE_REQS];
+ unsigned int num_reqs;
+ bool is_write;
+} MultiReqBuffer;
+
+bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq);
+void virtio_blk_process_queued_requests(VirtIOBlock *s, bool is_bh);
+
+#endif
diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h
new file mode 100644
index 000000000..7ab8c9dab
--- /dev/null
+++ b/include/hw/virtio/virtio-bus.h
@@ -0,0 +1,160 @@
+/*
+ * VirtioBus
+ *
+ * Copyright (C) 2012 : GreenSocs Ltd
+ * http://www.greensocs.com/ , email: info@greensocs.com
+ *
+ * Developed by :
+ * Frederic Konrad <fred.konrad@greensocs.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 VIRTIO_BUS_H
+#define VIRTIO_BUS_H
+
+#include "hw/qdev-core.h"
+#include "hw/virtio/virtio.h"
+#include "qom/object.h"
+
+#define TYPE_VIRTIO_BUS "virtio-bus"
+typedef struct VirtioBusClass VirtioBusClass;
+typedef struct VirtioBusState VirtioBusState;
+DECLARE_OBJ_CHECKERS(VirtioBusState, VirtioBusClass,
+ VIRTIO_BUS, TYPE_VIRTIO_BUS)
+
+
+struct VirtioBusClass {
+ /* This is what a VirtioBus must implement */
+ BusClass parent;
+ void (*notify)(DeviceState *d, uint16_t vector);
+ void (*save_config)(DeviceState *d, QEMUFile *f);
+ void (*save_queue)(DeviceState *d, int n, QEMUFile *f);
+ void (*save_extra_state)(DeviceState *d, QEMUFile *f);
+ int (*load_config)(DeviceState *d, QEMUFile *f);
+ int (*load_queue)(DeviceState *d, int n, QEMUFile *f);
+ int (*load_done)(DeviceState *d, QEMUFile *f);
+ int (*load_extra_state)(DeviceState *d, QEMUFile *f);
+ bool (*has_extra_state)(DeviceState *d);
+ bool (*query_guest_notifiers)(DeviceState *d);
+ int (*set_guest_notifiers)(DeviceState *d, int nvqs, bool assign);
+ int (*set_host_notifier_mr)(DeviceState *d, int n,
+ MemoryRegion *mr, bool assign);
+ void (*vmstate_change)(DeviceState *d, bool running);
+ /*
+ * Expose the features the transport layer supports before
+ * the negotiation takes place.
+ */
+ void (*pre_plugged)(DeviceState *d, Error **errp);
+ /*
+ * transport independent init function.
+ * This is called by virtio-bus just after the device is plugged.
+ */
+ void (*device_plugged)(DeviceState *d, Error **errp);
+ /*
+ * transport independent exit function.
+ * This is called by virtio-bus just before the device is unplugged.
+ */
+ void (*device_unplugged)(DeviceState *d);
+ int (*query_nvectors)(DeviceState *d);
+ /*
+ * ioeventfd handling: if the transport implements ioeventfd_assign,
+ * it must implement ioeventfd_enabled as well.
+ */
+ /* Returns true if the ioeventfd is enabled for the device. */
+ bool (*ioeventfd_enabled)(DeviceState *d);
+ /*
+ * Assigns/deassigns the ioeventfd backing for the transport on
+ * the device for queue number n. Returns an error value on
+ * failure.
+ */
+ int (*ioeventfd_assign)(DeviceState *d, EventNotifier *notifier,
+ int n, bool assign);
+ /*
+ * Whether queue number n is enabled.
+ */
+ bool (*queue_enabled)(DeviceState *d, int n);
+ /*
+ * Does the transport have variable vring alignment?
+ * (ie can it ever call virtio_queue_set_align()?)
+ * Note that changing this will break migration for this transport.
+ */
+ bool has_variable_vring_alignment;
+ AddressSpace *(*get_dma_as)(DeviceState *d);
+ bool (*iommu_enabled)(DeviceState *d);
+};
+
+struct VirtioBusState {
+ BusState parent_obj;
+
+ /*
+ * Set if ioeventfd has been started.
+ */
+ bool ioeventfd_started;
+
+ /*
+ * Set if ioeventfd has been grabbed by vhost. When ioeventfd
+ * is grabbed by vhost, we track its started/stopped state (which
+ * depends in turn on the virtio status register), but do not
+ * register a handler for the ioeventfd. When ioeventfd is
+ * released, if ioeventfd_started is true we finally register
+ * the handler so that QEMU's device model can use ioeventfd.
+ */
+ int ioeventfd_grabbed;
+};
+
+void virtio_bus_device_plugged(VirtIODevice *vdev, Error **errp);
+void virtio_bus_reset(VirtioBusState *bus);
+void virtio_bus_device_unplugged(VirtIODevice *bus);
+/* Get the device id of the plugged device. */
+uint16_t virtio_bus_get_vdev_id(VirtioBusState *bus);
+/* Get the config_len field of the plugged device. */
+size_t virtio_bus_get_vdev_config_len(VirtioBusState *bus);
+/* Get bad features of the plugged device. */
+uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus);
+/* Get config of the plugged device. */
+void virtio_bus_get_vdev_config(VirtioBusState *bus, uint8_t *config);
+/* Set config of the plugged device. */
+void virtio_bus_set_vdev_config(VirtioBusState *bus, uint8_t *config);
+
+static inline VirtIODevice *virtio_bus_get_device(VirtioBusState *bus)
+{
+ BusState *qbus = &bus->parent_obj;
+ BusChild *kid = QTAILQ_FIRST(&qbus->children);
+ DeviceState *qdev = kid ? kid->child : NULL;
+
+ /* This is used on the data path, the cast is guaranteed
+ * to succeed by the qdev machinery.
+ */
+ return (VirtIODevice *)qdev;
+}
+
+/* Return whether the proxy allows ioeventfd. */
+bool virtio_bus_ioeventfd_enabled(VirtioBusState *bus);
+/* Start the ioeventfd. */
+int virtio_bus_start_ioeventfd(VirtioBusState *bus);
+/* Stop the ioeventfd. */
+void virtio_bus_stop_ioeventfd(VirtioBusState *bus);
+/* Tell the bus that vhost is grabbing the ioeventfd. */
+int virtio_bus_grab_ioeventfd(VirtioBusState *bus);
+/* bus that vhost is not using the ioeventfd anymore. */
+void virtio_bus_release_ioeventfd(VirtioBusState *bus);
+/* Switch from/to the generic ioeventfd handler */
+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
new file mode 100644
index 000000000..a2228d7b2
--- /dev/null
+++ b/include/hw/virtio/virtio-crypto.h
@@ -0,0 +1,102 @@
+/*
+ * Virtio crypto Support
+ *
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ *
+ * Authors:
+ * Gonglei <arei.gonglei@huawei.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 QEMU_VIRTIO_CRYPTO_H
+#define QEMU_VIRTIO_CRYPTO_H
+
+#include "standard-headers/linux/virtio_crypto.h"
+#include "hw/virtio/virtio.h"
+#include "sysemu/iothread.h"
+#include "sysemu/cryptodev.h"
+#include "qom/object.h"
+
+
+#define DEBUG_VIRTIO_CRYPTO 0
+
+#define DPRINTF(fmt, ...) \
+do { \
+ if (DEBUG_VIRTIO_CRYPTO) { \
+ fprintf(stderr, "virtio_crypto: " fmt, ##__VA_ARGS__); \
+ } \
+} while (0)
+
+
+#define TYPE_VIRTIO_CRYPTO "virtio-crypto-device"
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIOCrypto, VIRTIO_CRYPTO)
+#define VIRTIO_CRYPTO_GET_PARENT_CLASS(obj) \
+ OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_CRYPTO)
+
+
+typedef struct VirtIOCryptoConf {
+ CryptoDevBackend *cryptodev;
+
+ /* Supported service mask */
+ uint32_t crypto_services;
+
+ /* Detailed algorithms mask */
+ uint32_t cipher_algo_l;
+ uint32_t cipher_algo_h;
+ uint32_t hash_algo;
+ uint32_t mac_algo_l;
+ uint32_t mac_algo_h;
+ uint32_t aead_algo;
+
+ /* Maximum length of cipher key */
+ uint32_t max_cipher_key_len;
+ /* Maximum length of authenticated key */
+ uint32_t max_auth_key_len;
+ /* Maximum size of each crypto request's content */
+ uint64_t max_size;
+} VirtIOCryptoConf;
+
+struct VirtIOCrypto;
+
+typedef struct VirtIOCryptoReq {
+ VirtQueueElement elem;
+ /* flags of operation, such as type of algorithm */
+ uint32_t flags;
+ struct virtio_crypto_inhdr *in;
+ struct iovec *in_iov; /* Head address of dest iovec */
+ unsigned int in_num; /* Number of dest iovec */
+ size_t in_len;
+ VirtQueue *vq;
+ struct VirtIOCrypto *vcrypto;
+ union {
+ CryptoDevBackendSymOpInfo *sym_op_info;
+ } u;
+} VirtIOCryptoReq;
+
+typedef struct VirtIOCryptoQueue {
+ VirtQueue *dataq;
+ QEMUBH *dataq_bh;
+ struct VirtIOCrypto *vcrypto;
+} VirtIOCryptoQueue;
+
+struct VirtIOCrypto {
+ VirtIODevice parent_obj;
+
+ VirtQueue *ctrl_vq;
+ VirtIOCryptoQueue *vqs;
+ VirtIOCryptoConf conf;
+ CryptoDevBackend *cryptodev;
+
+ uint32_t max_queues;
+ uint32_t status;
+
+ int multiqueue;
+ uint32_t curr_queues;
+ size_t config_size;
+ uint8_t vhost_started;
+};
+
+#endif /* QEMU_VIRTIO_CRYPTO_H */
diff --git a/include/hw/virtio/virtio-gpu-bswap.h b/include/hw/virtio/virtio-gpu-bswap.h
new file mode 100644
index 000000000..e2bee8f59
--- /dev/null
+++ b/include/hw/virtio/virtio-gpu-bswap.h
@@ -0,0 +1,78 @@
+/*
+ * Virtio GPU Device
+ *
+ * Copyright Red Hat, Inc. 2013-2014
+ *
+ * Authors:
+ * Dave Airlie <airlied@redhat.com>
+ * Gerd Hoffmann <kraxel@redhat.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_VIRTIO_GPU_BSWAP_H
+#define HW_VIRTIO_GPU_BSWAP_H
+
+#include "qemu/bswap.h"
+#include "standard-headers/linux/virtio_gpu.h"
+
+static inline void
+virtio_gpu_ctrl_hdr_bswap(struct virtio_gpu_ctrl_hdr *hdr)
+{
+ le32_to_cpus(&hdr->type);
+ 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
+
+ size_t i;
+ struct virtio_gpu_ctrl_hdr *hdr = (struct virtio_gpu_ctrl_hdr *) ptr;
+
+ virtio_gpu_ctrl_hdr_bswap(hdr);
+
+ i = sizeof(struct virtio_gpu_ctrl_hdr);
+ while (i < size) {
+ le32_to_cpus((uint32_t *)(ptr + i));
+ i = i + sizeof(uint32_t);
+ }
+
+#endif
+}
+
+static inline void
+virtio_gpu_t2d_bswap(struct virtio_gpu_transfer_to_host_2d *t2d)
+{
+ virtio_gpu_ctrl_hdr_bswap(&t2d->hdr);
+ le32_to_cpus(&t2d->r.x);
+ le32_to_cpus(&t2d->r.y);
+ le32_to_cpus(&t2d->r.width);
+ le32_to_cpus(&t2d->r.height);
+ le64_to_cpus(&t2d->offset);
+ le32_to_cpus(&t2d->resource_id);
+ 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_flags);
+ le64_to_cpus(&cblob->size);
+}
+
+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
new file mode 100644
index 000000000..225cbbc2e
--- /dev/null
+++ b/include/hw/virtio/virtio-gpu-pci.h
@@ -0,0 +1,39 @@
+/*
+ * Virtio GPU PCI Device
+ *
+ * Copyright Red Hat, Inc. 2013-2014
+ *
+ * Authors:
+ * Dave Airlie <airlied@redhat.com>
+ * Gerd Hoffmann <kraxel@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_GPU_PCI_H
+#define HW_VIRTIO_GPU_PCI_H
+
+#include "hw/virtio/virtio-pci.h"
+#include "hw/virtio/virtio-gpu.h"
+#include "qom/object.h"
+
+
+/*
+ * virtio-gpu-pci-base: This extends VirtioPCIProxy.
+ */
+#define TYPE_VIRTIO_GPU_PCI_BASE "virtio-gpu-pci-base"
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIOGPUPCIBase, VIRTIO_GPU_PCI_BASE)
+
+struct VirtIOGPUPCIBase {
+ VirtIOPCIProxy parent_obj;
+ VirtIOGPUBase *vgpu;
+};
+
+/* to share between PCI and VGA */
+#define DEFINE_VIRTIO_GPU_PCI_PROPERTIES(_state) \
+ DEFINE_PROP_BIT("ioeventfd", _state, flags, \
+ VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false), \
+ DEFINE_PROP_UINT32("vectors", _state, nvectors, 3)
+
+#endif /* HW_VIRTIO_GPU_PCI_H */
diff --git a/include/hw/virtio/virtio-gpu-pixman.h b/include/hw/virtio/virtio-gpu-pixman.h
new file mode 100644
index 000000000..4dba78275
--- /dev/null
+++ b/include/hw/virtio/virtio-gpu-pixman.h
@@ -0,0 +1,45 @@
+/*
+ * Virtio GPU Device
+ *
+ * Copyright Red Hat, Inc. 2013-2014
+ *
+ * Authors:
+ * Dave Airlie <airlied@redhat.com>
+ * Gerd Hoffmann <kraxel@redhat.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_VIRTIO_GPU_PIXMAN_H
+#define HW_VIRTIO_GPU_PIXMAN_H
+
+#include "ui/qemu-pixman.h"
+#include "standard-headers/linux/virtio_gpu.h"
+
+static inline pixman_format_code_t
+virtio_gpu_get_pixman_format(uint32_t virtio_gpu_format)
+{
+ switch (virtio_gpu_format) {
+ case VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM:
+ return PIXMAN_BE_b8g8r8x8;
+ case VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM:
+ return PIXMAN_BE_b8g8r8a8;
+ case VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM:
+ return PIXMAN_BE_x8r8g8b8;
+ case VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM:
+ return PIXMAN_BE_a8r8g8b8;
+ case VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM:
+ return PIXMAN_BE_r8g8b8x8;
+ case VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM:
+ return PIXMAN_BE_r8g8b8a8;
+ case VIRTIO_GPU_FORMAT_X8B8G8R8_UNORM:
+ return PIXMAN_BE_x8b8g8r8;
+ case VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM:
+ return PIXMAN_BE_a8b8g8r8;
+ default:
+ return 0;
+ }
+}
+
+#endif
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
new file mode 100644
index 000000000..acfba7c76
--- /dev/null
+++ b/include/hw/virtio/virtio-gpu.h
@@ -0,0 +1,288 @@
+/*
+ * Virtio GPU Device
+ *
+ * Copyright Red Hat, Inc. 2013-2014
+ *
+ * Authors:
+ * Dave Airlie <airlied@redhat.com>
+ * Gerd Hoffmann <kraxel@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_GPU_H
+#define HW_VIRTIO_GPU_H
+
+#include "qemu/queue.h"
+#include "ui/qemu-pixman.h"
+#include "ui/console.h"
+#include "hw/virtio/virtio.h"
+#include "qemu/log.h"
+#include "sysemu/vhost-user-backend.h"
+
+#include "standard-headers/linux/virtio_gpu.h"
+#include "qom/object.h"
+
+#define TYPE_VIRTIO_GPU_BASE "virtio-gpu-base"
+OBJECT_DECLARE_TYPE(VirtIOGPUBase, VirtIOGPUBaseClass,
+ VIRTIO_GPU_BASE)
+
+#define TYPE_VIRTIO_GPU "virtio-gpu-device"
+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
+
+struct virtio_gpu_simple_resource {
+ uint32_t resource_id;
+ uint32_t width;
+ uint32_t height;
+ uint32_t format;
+ uint64_t *addrs;
+ struct iovec *iov;
+ unsigned int iov_cnt;
+ uint32_t scanout_bitmask;
+ pixman_image_t *image;
+ 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;
+ uint32_t width, height;
+ int x, y;
+ int invalidate;
+ uint32_t resource_id;
+ struct virtio_gpu_update_cursor cursor;
+ QEMUCursor *current_cursor;
+};
+
+struct virtio_gpu_requested_state {
+ uint16_t width_mm, height_mm;
+ uint32_t width, height;
+ int x, y;
+};
+
+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,
+};
+
+#define virtio_gpu_virgl_enabled(_cfg) \
+ (_cfg.flags & (1 << VIRTIO_GPU_FLAG_VIRGL_ENABLED))
+#define virtio_gpu_stats_enabled(_cfg) \
+ (_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))
+
+struct virtio_gpu_base_conf {
+ uint32_t max_outputs;
+ uint32_t flags;
+ uint32_t xres;
+ uint32_t yres;
+};
+
+struct virtio_gpu_ctrl_command {
+ VirtQueueElement elem;
+ VirtQueue *vq;
+ struct virtio_gpu_ctrl_hdr cmd_hdr;
+ uint32_t error;
+ bool finished;
+ QTAILQ_ENTRY(virtio_gpu_ctrl_command) next;
+};
+
+struct VirtIOGPUBase {
+ VirtIODevice parent_obj;
+
+ Error *migration_blocker;
+
+ struct virtio_gpu_base_conf conf;
+ struct virtio_gpu_config virtio_config;
+ const GraphicHwOps *hw_ops;
+
+ int renderer_blocked;
+ int enable;
+
+ struct virtio_gpu_scanout scanout[VIRTIO_GPU_MAX_SCANOUTS];
+
+ int enabled_output_bitmask;
+ struct virtio_gpu_requested_state req_state[VIRTIO_GPU_MAX_SCANOUTS];
+};
+
+struct VirtIOGPUBaseClass {
+ VirtioDeviceClass parent;
+
+ 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)
+
+typedef struct VGPUDMABuf {
+ QemuDmaBuf buf;
+ uint32_t scanout_id;
+ QTAILQ_ENTRY(VGPUDMABuf) next;
+} VGPUDMABuf;
+
+struct VirtIOGPU {
+ VirtIOGPUBase parent_obj;
+
+ uint64_t conf_max_hostmem;
+
+ VirtQueue *ctrl_vq;
+ VirtQueue *cursor_vq;
+
+ QEMUBH *ctrl_bh;
+ QEMUBH *cursor_bh;
+
+ QTAILQ_HEAD(, virtio_gpu_simple_resource) reslist;
+ QTAILQ_HEAD(, virtio_gpu_ctrl_command) cmdq;
+ QTAILQ_HEAD(, virtio_gpu_ctrl_command) fenceq;
+
+ uint64_t hostmem;
+
+ bool processing_cmdq;
+ QEMUTimer *fence_poll;
+ QEMUTimer *print_stats;
+
+ uint32_t inflight;
+ struct {
+ uint32_t max_inflight;
+ uint32_t requests;
+ uint32_t req_3d;
+ uint32_t bytes_3d;
+ } stats;
+
+ 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);
+};
+
+struct VirtIOGPUGL {
+ struct VirtIOGPU parent_obj;
+
+ bool renderer_inited;
+ bool renderer_reset;
+};
+
+struct VhostUserGPU {
+ VirtIOGPUBase parent_obj;
+
+ VhostUserBackend *vhost;
+ int vhost_gpu_fd; /* closed by the chardev */
+ CharBackend vhost_chr;
+ QemuDmaBuf dmabuf[VIRTIO_GPU_MAX_SCANOUTS];
+ bool backend_blocked;
+};
+
+#define VIRTIO_GPU_FILL_CMD(out) do { \
+ size_t s; \
+ s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, 0, \
+ &out, sizeof(out)); \
+ if (s != sizeof(out)) { \
+ qemu_log_mask(LOG_GUEST_ERROR, \
+ "%s: command size incorrect %zu vs %zu\n", \
+ __func__, s, sizeof(out)); \
+ return; \
+ } \
+ } while (0)
+
+/* virtio-gpu-base.c */
+bool virtio_gpu_base_device_realize(DeviceState *qdev,
+ VirtIOHandleOutput ctrl_cb,
+ VirtIOHandleOutput cursor_cb,
+ Error **errp);
+void virtio_gpu_base_reset(VirtIOGPUBase *g);
+void virtio_gpu_base_fill_display_info(VirtIOGPUBase *g,
+ struct virtio_gpu_resp_display_info *dpy_info);
+
+/* virtio-gpu.c */
+void virtio_gpu_ctrl_response(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd,
+ struct virtio_gpu_ctrl_hdr *resp,
+ size_t resp_len);
+void virtio_gpu_ctrl_response_nodata(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd,
+ enum virtio_gpu_ctrl_type type);
+void virtio_gpu_get_display_info(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd);
+void virtio_gpu_get_edid(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd);
+int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
+ uint32_t nr_entries, uint32_t offset,
+ struct virtio_gpu_ctrl_command *cmd,
+ 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_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);
+
+#endif
diff --git a/include/hw/virtio/virtio-input.h b/include/hw/virtio/virtio-input.h
new file mode 100644
index 000000000..f2da63d30
--- /dev/null
+++ b/include/hw/virtio/virtio-input.h
@@ -0,0 +1,115 @@
+#ifndef QEMU_VIRTIO_INPUT_H
+#define QEMU_VIRTIO_INPUT_H
+
+#include "ui/input.h"
+#include "sysemu/vhost-user-backend.h"
+
+/* ----------------------------------------------------------------- */
+/* virtio input protocol */
+
+#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;
+typedef struct virtio_input_event virtio_input_event;
+
+/* ----------------------------------------------------------------- */
+/* qemu internals */
+
+#define TYPE_VIRTIO_INPUT "virtio-input-device"
+OBJECT_DECLARE_TYPE(VirtIOInput, VirtIOInputClass,
+ VIRTIO_INPUT)
+#define VIRTIO_INPUT_GET_PARENT_CLASS(obj) \
+ OBJECT_GET_PARENT_CLASS(obj, 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"
+
+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"
+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"
+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 VirtIOInputConfig VirtIOInputConfig;
+
+struct VirtIOInputConfig {
+ virtio_input_config config;
+ QTAILQ_ENTRY(VirtIOInputConfig) node;
+};
+
+struct VirtIOInput {
+ VirtIODevice parent_obj;
+ uint8_t cfg_select;
+ uint8_t cfg_subsel;
+ uint32_t cfg_size;
+ QTAILQ_HEAD(, VirtIOInputConfig) cfg_list;
+ VirtQueue *evt, *sts;
+ char *serial;
+
+ struct {
+ virtio_input_event event;
+ VirtQueueElement *elem;
+ } *queue;
+ uint32_t qindex, qsize;
+
+ bool active;
+};
+
+struct VirtIOInputClass {
+ /*< private >*/
+ VirtioDeviceClass parent;
+ /*< public >*/
+
+ DeviceRealize realize;
+ DeviceUnrealize unrealize;
+ void (*change_active)(VirtIOInput *vinput);
+ void (*handle_status)(VirtIOInput *vinput, virtio_input_event *event);
+};
+
+struct VirtIOInputHID {
+ VirtIOInput parent_obj;
+ char *display;
+ uint32_t head;
+ QemuInputHandler *handler;
+ QemuInputHandlerState *hs;
+ int ledstate;
+ bool wheel_axis;
+};
+
+struct VirtIOInputHost {
+ VirtIOInput parent_obj;
+ char *evdev;
+ int fd;
+};
+
+struct VHostUserInput {
+ VirtIOInput parent_obj;
+
+ VhostUserBackend *vhost;
+};
+
+void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event);
+void virtio_input_init_config(VirtIOInput *vinput,
+ virtio_input_config *config);
+virtio_input_config *virtio_input_find_config(VirtIOInput *vinput,
+ uint8_t select,
+ uint8_t subsel);
+void virtio_input_add_config(VirtIOInput *vinput,
+ virtio_input_config *config);
+void virtio_input_idstr_config(VirtIOInput *vinput,
+ uint8_t select, const char *string);
+
+#endif /* QEMU_VIRTIO_INPUT_H */
diff --git a/include/hw/virtio/virtio-iommu.h b/include/hw/virtio/virtio-iommu.h
new file mode 100644
index 000000000..e2339e5b7
--- /dev/null
+++ b/include/hw/virtio/virtio-iommu.h
@@ -0,0 +1,63 @@
+/*
+ * virtio-iommu device
+ *
+ * Copyright (c) 2020 Red Hat, 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 QEMU_VIRTIO_IOMMU_H
+#define QEMU_VIRTIO_IOMMU_H
+
+#include "standard-headers/linux/virtio_iommu.h"
+#include "hw/virtio/virtio.h"
+#include "hw/pci/pci.h"
+#include "qom/object.h"
+
+#define TYPE_VIRTIO_IOMMU "virtio-iommu-device"
+#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"
+
+typedef struct IOMMUDevice {
+ void *viommu;
+ PCIBus *bus;
+ int devfn;
+ IOMMUMemoryRegion iommu_mr;
+ AddressSpace as;
+} IOMMUDevice;
+
+typedef struct IOMMUPciBus {
+ PCIBus *bus;
+ IOMMUDevice *pbdev[]; /* Parent array is sparse, so dynamically alloc */
+} IOMMUPciBus;
+
+struct VirtIOIOMMU {
+ VirtIODevice parent_obj;
+ VirtQueue *req_vq;
+ VirtQueue *event_vq;
+ struct virtio_iommu_config config;
+ uint64_t features;
+ GHashTable *as_by_busptr;
+ IOMMUPciBus *iommu_pcibus_by_bus_num[PCI_BUS_MAX];
+ PCIBus *primary_bus;
+ ReservedRegion *reserved_regions;
+ uint32_t nb_reserved_regions;
+ GTree *domains;
+ QemuMutex mutex;
+ GTree *endpoints;
+};
+
+#endif
diff --git a/include/hw/virtio/virtio-mem.h b/include/hw/virtio/virtio-mem.h
new file mode 100644
index 000000000..a5dd6a493
--- /dev/null
+++ b/include/hw/virtio/virtio-mem.h
@@ -0,0 +1,83 @@
+/*
+ * Virtio MEM device
+ *
+ * Copyright (C) 2020 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_MEM_H
+#define HW_VIRTIO_MEM_H
+
+#include "standard-headers/linux/virtio_mem.h"
+#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"
+
+OBJECT_DECLARE_TYPE(VirtIOMEM, VirtIOMEMClass,
+ VIRTIO_MEM)
+
+#define VIRTIO_MEM_MEMDEV_PROP "memdev"
+#define VIRTIO_MEM_NODE_PROP "node"
+#define VIRTIO_MEM_SIZE_PROP "size"
+#define VIRTIO_MEM_REQUESTED_SIZE_PROP "requested-size"
+#define VIRTIO_MEM_BLOCK_SIZE_PROP "block-size"
+#define VIRTIO_MEM_ADDR_PROP "memaddr"
+
+struct VirtIOMEM {
+ VirtIODevice parent_obj;
+
+ /* guest -> host request queue */
+ VirtQueue *vq;
+
+ /* bitmap used to track unplugged memory */
+ int32_t bitmap_size;
+ unsigned long *bitmap;
+
+ /* assigned memory backend and memory region */
+ HostMemoryBackend *memdev;
+
+ /* NUMA node */
+ uint32_t node;
+
+ /* assigned address of the region in guest physical memory */
+ uint64_t addr;
+
+ /* usable region size (<= region_size) */
+ uint64_t usable_region_size;
+
+ /* actual size (how much the guest plugged) */
+ uint64_t size;
+
+ /* requested size */
+ uint64_t requested_size;
+
+ /* block size and alignment */
+ uint64_t block_size;
+
+ /* notifiers to notify when "size" changes */
+ NotifierList size_change_notifiers;
+
+ /* listeners to notify on plug/unplug activity. */
+ QLIST_HEAD(, RamDiscardListener) rdl_list;
+};
+
+struct VirtIOMEMClass {
+ /* private */
+ VirtIODevice parent;
+
+ /* public */
+ void (*fill_device_info)(const VirtIOMEM *vmen, VirtioMEMDeviceInfo *vi);
+ MemoryRegion *(*get_memory_region)(VirtIOMEM *vmem, Error **errp);
+ void (*add_size_change_notifier)(VirtIOMEM *vmem, Notifier *notifier);
+ void (*remove_size_change_notifier)(VirtIOMEM *vmem, Notifier *notifier);
+};
+
+#endif
diff --git a/include/hw/virtio/virtio-mmio.h b/include/hw/virtio/virtio-mmio.h
new file mode 100644
index 000000000..090f7730e
--- /dev/null
+++ b/include/hw/virtio/virtio-mmio.h
@@ -0,0 +1,75 @@
+/*
+ * Virtio MMIO bindings
+ *
+ * Copyright (c) 2011 Linaro Limited
+ *
+ * Author:
+ * Peter Maydell <peter.maydell@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License; 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_VIRTIO_MMIO_H
+#define HW_VIRTIO_MMIO_H
+
+#include "hw/virtio/virtio-bus.h"
+#include "qom/object.h"
+
+/* QOM macros */
+/* virtio-mmio-bus */
+#define TYPE_VIRTIO_MMIO_BUS "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"
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIOMMIOProxy, VIRTIO_MMIO)
+
+#define VIRT_MAGIC 0x74726976 /* 'virt' */
+#define VIRT_VERSION 2
+#define VIRT_VERSION_LEGACY 1
+#define VIRT_VENDOR 0x554D4551 /* 'QEMU' */
+
+typedef struct VirtIOMMIOQueue {
+ uint16_t num;
+ bool enabled;
+ uint32_t desc[2];
+ uint32_t avail[2];
+ uint32_t used[2];
+} VirtIOMMIOQueue;
+
+#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;
+ uint32_t guest_page_shift;
+ /* virtio-bus */
+ VirtioBusState bus;
+ bool format_transport_address;
+ /* Fields only used for non-legacy (v2) devices */
+ uint32_t guest_features[2];
+ VirtIOMMIOQueue vqs[VIRTIO_QUEUE_MAX];
+};
+
+#endif
diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
new file mode 100644
index 000000000..eb8703262
--- /dev/null
+++ b/include/hw/virtio/virtio-net.h
@@ -0,0 +1,224 @@
+/*
+ * Virtio Network Device
+ *
+ * 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 QEMU_VIRTIO_NET_H
+#define QEMU_VIRTIO_NET_H
+
+#include "qemu/units.h"
+#include "standard-headers/linux/virtio_net.h"
+#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"
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIONet, VIRTIO_NET)
+
+#define TX_TIMER_INTERVAL 150000 /* 150 us */
+
+/* Limit the number of packets that can be sent via a single flush
+ * of the TX queue. This gives us a guaranteed exit condition and
+ * ensures fairness in the io path. 256 conveniently matches the
+ * length of the TX queue and shows a good balance of performance
+ * and latency. */
+#define TX_BURST 256
+
+typedef struct virtio_net_conf
+{
+ uint32_t txtimer;
+ int32_t txburst;
+ char *tx;
+ uint16_t rx_queue_size;
+ uint16_t tx_queue_size;
+ uint16_t mtu;
+ int32_t speed;
+ char *duplex_str;
+ uint8_t duplex;
+ char *primary_id_str;
+} virtio_net_conf;
+
+/* Coalesced packets type & status */
+typedef enum {
+ RSC_COALESCE, /* Data been coalesced */
+ RSC_FINAL, /* Will terminate current connection */
+ RSC_NO_MATCH, /* No matched in the buffer pool */
+ RSC_BYPASS, /* Packet to be bypass, not tcp, tcp ctrl, etc */
+ RSC_CANDIDATE /* Data want to be coalesced */
+} CoalesceStatus;
+
+typedef struct VirtioNetRscStat {
+ uint32_t received;
+ uint32_t coalesced;
+ uint32_t over_size;
+ uint32_t cache;
+ uint32_t empty_cache;
+ uint32_t no_match_cache;
+ uint32_t win_update;
+ uint32_t no_match;
+ uint32_t tcp_syn;
+ uint32_t tcp_ctrl_drain;
+ uint32_t dup_ack;
+ uint32_t dup_ack1;
+ uint32_t dup_ack2;
+ uint32_t pure_ack;
+ uint32_t ack_out_of_win;
+ uint32_t data_out_of_win;
+ uint32_t data_out_of_order;
+ uint32_t data_after_pure_ack;
+ uint32_t bypass_not_tcp;
+ uint32_t tcp_option;
+ uint32_t tcp_all_opt;
+ uint32_t ip_frag;
+ uint32_t ip_ecn;
+ uint32_t ip_hacked;
+ uint32_t ip_option;
+ uint32_t purge_failed;
+ uint32_t drain_failed;
+ uint32_t final_failed;
+ int64_t timer;
+} VirtioNetRscStat;
+
+/* Rsc unit general info used to checking if can coalescing */
+typedef struct VirtioNetRscUnit {
+ void *ip; /* ip header */
+ uint16_t *ip_plen; /* data len pointer in ip header field */
+ struct tcp_header *tcp; /* tcp header */
+ uint16_t tcp_hdrlen; /* tcp header len */
+ uint16_t payload; /* pure payload without virtio/eth/ip/tcp */
+} VirtioNetRscUnit;
+
+/* Coalesced segment */
+typedef struct VirtioNetRscSeg {
+ QTAILQ_ENTRY(VirtioNetRscSeg) next;
+ void *buf;
+ size_t size;
+ uint16_t packets;
+ uint16_t dup_ack;
+ bool is_coalesced; /* need recal ipv4 header checksum, mark here */
+ VirtioNetRscUnit unit;
+ NetClientState *nc;
+} VirtioNetRscSeg;
+
+
+/* Chain is divided by protocol(ipv4/v6) and NetClientInfo */
+typedef struct VirtioNetRscChain {
+ QTAILQ_ENTRY(VirtioNetRscChain) next;
+ VirtIONet *n; /* VirtIONet */
+ uint16_t proto;
+ uint8_t gso_type;
+ uint16_t max_payload;
+ QEMUTimer *drain_timer;
+ QTAILQ_HEAD(, VirtioNetRscSeg) buffers;
+ VirtioNetRscStat stat;
+} VirtioNetRscChain;
+
+/* Maximum packet size we can receive from tap device: header + 64k */
+#define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 * KiB))
+
+#define VIRTIO_NET_RSS_MAX_KEY_SIZE 40
+#define VIRTIO_NET_RSS_MAX_TABLE_LEN 128
+
+typedef struct VirtioNetRssData {
+ bool enabled;
+ bool enabled_software_rss;
+ bool redirect;
+ bool populate_hash;
+ uint32_t hash_types;
+ uint8_t key[VIRTIO_NET_RSS_MAX_KEY_SIZE];
+ uint16_t indirections_len;
+ uint16_t *indirections_table;
+ uint16_t default_queue;
+} VirtioNetRssData;
+
+typedef struct VirtIONetQueue {
+ VirtQueue *rx_vq;
+ VirtQueue *tx_vq;
+ QEMUTimer *tx_timer;
+ QEMUBH *tx_bh;
+ uint32_t tx_waiting;
+ struct {
+ VirtQueueElement *elem;
+ } async_tx;
+ struct VirtIONet *n;
+} VirtIONetQueue;
+
+struct VirtIONet {
+ VirtIODevice parent_obj;
+ uint8_t mac[ETH_ALEN];
+ uint16_t status;
+ VirtIONetQueue *vqs;
+ VirtQueue *ctrl_vq;
+ NICState *nic;
+ /* RSC Chains - temporary storage of coalesced data,
+ all these data are lost in case of migration */
+ QTAILQ_HEAD(, VirtioNetRscChain) rsc_chains;
+ uint32_t tx_timeout;
+ int32_t tx_burst;
+ uint32_t has_vnet_hdr;
+ size_t host_hdr_len;
+ size_t guest_hdr_len;
+ uint64_t host_features;
+ uint32_t rsc_timeout;
+ uint8_t rsc4_enabled;
+ uint8_t rsc6_enabled;
+ uint8_t has_ufo;
+ uint32_t mergeable_rx_bufs;
+ uint8_t promisc;
+ uint8_t allmulti;
+ uint8_t alluni;
+ uint8_t nomulti;
+ uint8_t nouni;
+ uint8_t nobcast;
+ uint8_t vhost_started;
+ struct {
+ uint32_t in_use;
+ uint32_t first_multi;
+ uint8_t multi_overflow;
+ uint8_t uni_overflow;
+ uint8_t *macs;
+ } mac_table;
+ uint32_t *vlans;
+ virtio_net_conf net_conf;
+ NICConf nic_conf;
+ DeviceState *qdev;
+ int multiqueue;
+ uint16_t max_queue_pairs;
+ uint16_t curr_queue_pairs;
+ uint16_t max_ncs;
+ size_t config_size;
+ char *netclient_name;
+ char *netclient_type;
+ uint64_t curr_guest_offloads;
+ /* used on saved state restore phase to preserve the curr_guest_offloads */
+ uint64_t saved_guest_offloads;
+ AnnounceTimer announce_timer;
+ bool needs_vnet_hdr_swap;
+ bool mtu_bypass_backend;
+ /* primary failover device is hidden*/
+ bool failover_primary_hidden;
+ bool failover;
+ DeviceListener primary_listener;
+ QDict *primary_opts;
+ bool primary_opts_from_json;
+ Notifier migration_state;
+ VirtioNetRssData rss_data;
+ struct NetRxPkt *rx_pkt;
+ struct EBPFRSSContext ebpf_rss;
+};
+
+void virtio_net_set_netclient_name(VirtIONet *n, const char *name,
+ const char *type);
+
+#endif
diff --git a/include/hw/virtio/virtio-pmem.h b/include/hw/virtio/virtio-pmem.h
new file mode 100644
index 000000000..fc4fd1f7f
--- /dev/null
+++ b/include/hw/virtio/virtio-pmem.h
@@ -0,0 +1,46 @@
+/*
+ * Virtio PMEM device
+ *
+ * Copyright (C) 2018-2019 Red Hat, Inc.
+ *
+ * Authors:
+ * Pankaj Gupta <pagupta@redhat.com>
+ * 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_PMEM_H
+#define HW_VIRTIO_PMEM_H
+
+#include "hw/virtio/virtio.h"
+#include "qapi/qapi-types-machine.h"
+#include "qom/object.h"
+
+#define TYPE_VIRTIO_PMEM "virtio-pmem"
+
+OBJECT_DECLARE_TYPE(VirtIOPMEM, VirtIOPMEMClass,
+ VIRTIO_PMEM)
+
+#define VIRTIO_PMEM_ADDR_PROP "memaddr"
+#define VIRTIO_PMEM_MEMDEV_PROP "memdev"
+
+struct VirtIOPMEM {
+ VirtIODevice parent_obj;
+
+ VirtQueue *rq_vq;
+ uint64_t start;
+ HostMemoryBackend *memdev;
+};
+
+struct VirtIOPMEMClass {
+ /* private */
+ VirtIODevice parent;
+
+ /* public */
+ void (*fill_device_info)(const VirtIOPMEM *pmem, VirtioPMEMDeviceInfo *vi);
+ MemoryRegion *(*get_memory_region)(VirtIOPMEM *pmem, Error **errp);
+};
+
+#endif
diff --git a/include/hw/virtio/virtio-rng.h b/include/hw/virtio/virtio-rng.h
new file mode 100644
index 000000000..82734255d
--- /dev/null
+++ b/include/hw/virtio/virtio-rng.h
@@ -0,0 +1,51 @@
+/*
+ * Virtio RNG Support
+ *
+ * Copyright Red Hat, Inc. 2012
+ * Copyright Amit Shah <amit.shah@redhat.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 QEMU_VIRTIO_RNG_H
+#define QEMU_VIRTIO_RNG_H
+
+#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"
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIORNG, VIRTIO_RNG)
+#define VIRTIO_RNG_GET_PARENT_CLASS(obj) \
+ OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_RNG)
+
+struct VirtIORNGConf {
+ RngBackend *rng;
+ uint64_t max_bytes;
+ uint32_t period_ms;
+};
+
+struct VirtIORNG {
+ VirtIODevice parent_obj;
+
+ /* Only one vq - guest puts buffer(s) on it when it needs entropy */
+ VirtQueue *vq;
+
+ VirtIORNGConf conf;
+
+ RngBackend *rng;
+
+ /* We purposefully don't migrate this state. The quota will reset on the
+ * destination as a result. Rate limiting is host state, not guest state.
+ */
+ QEMUTimer *rate_limit_timer;
+ int64_t quota_remaining;
+ bool activate_timer;
+
+ VMChangeStateEntry *vmstate;
+};
+
+#endif
diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
new file mode 100644
index 000000000..543681bc1
--- /dev/null
+++ b/include/hw/virtio/virtio-scsi.h
@@ -0,0 +1,166 @@
+/*
+ * Virtio SCSI HBA
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ * Stefan Hajnoczi <stefanha@linux.vnet.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 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"
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIOSCSICommon, VIRTIO_SCSI_COMMON)
+
+#define TYPE_VIRTIO_SCSI "virtio-scsi-device"
+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;
+typedef struct virtio_scsi_ctrl_tmf_resp VirtIOSCSICtrlTMFResp;
+typedef struct virtio_scsi_ctrl_an_req VirtIOSCSICtrlANReq;
+typedef struct virtio_scsi_ctrl_an_resp VirtIOSCSICtrlANResp;
+typedef struct virtio_scsi_event VirtIOSCSIEvent;
+typedef struct virtio_scsi_config VirtIOSCSIConfig;
+
+struct VirtIOSCSIConf {
+ uint32_t num_queues;
+ uint32_t virtqueue_size;
+ 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;
+};
+
+struct VirtIOSCSI;
+
+struct VirtIOSCSICommon {
+ VirtIODevice parent_obj;
+ VirtIOSCSIConf conf;
+
+ uint32_t sense_size;
+ uint32_t cdb_size;
+ VirtQueue *ctrl_vq;
+ VirtQueue *event_vq;
+ VirtQueue **cmd_vqs;
+};
+
+struct VirtIOSCSI {
+ VirtIOSCSICommon parent_obj;
+
+ SCSIBus bus;
+ int resetting;
+ bool events_dropped;
+
+ /* Fields for dataplane below */
+ AioContext *ctx; /* one iothread per virtio-scsi-pci for now */
+
+ bool dataplane_started;
+ bool dataplane_starting;
+ bool dataplane_stopping;
+ bool dataplane_fenced;
+ uint32_t host_features;
+};
+
+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,
+ VirtIOHandleOutput evt,
+ VirtIOHandleOutput cmd,
+ 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);
+void virtio_scsi_dataplane_stop(VirtIODevice *s);
+
+#endif /* QEMU_VIRTIO_SCSI_H */
diff --git a/include/hw/virtio/virtio-serial.h b/include/hw/virtio/virtio-serial.h
new file mode 100644
index 000000000..d87c62eab
--- /dev/null
+++ b/include/hw/virtio/virtio-serial.h
@@ -0,0 +1,227 @@
+/*
+ * Virtio Serial / Console Support
+ *
+ * Copyright IBM, Corp. 2008
+ * Copyright Red Hat, Inc. 2009, 2010
+ *
+ * Authors:
+ * Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
+ * Amit Shah <amit.shah@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 QEMU_VIRTIO_SERIAL_H
+#define QEMU_VIRTIO_SERIAL_H
+
+#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 */
+ uint32_t max_virtserial_ports;
+};
+
+#define TYPE_VIRTIO_SERIAL_PORT "virtio-serial-port"
+OBJECT_DECLARE_TYPE(VirtIOSerialPort, VirtIOSerialPortClass,
+ VIRTIO_SERIAL_PORT)
+
+typedef struct VirtIOSerial VirtIOSerial;
+
+#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? */
+ bool is_console;
+
+ /*
+ * The per-port (or per-app) realize function that's called when a
+ * new device is found on the bus.
+ */
+ DeviceRealize realize;
+ /*
+ * Per-port unrealize function that's called when a port gets
+ * hot-unplugged or removed.
+ */
+ DeviceUnrealize unrealize;
+
+ /* Callbacks for guest events */
+ /* Guest opened/closed device. */
+ void (*set_guest_connected)(VirtIOSerialPort *port, int guest_connected);
+
+ /* Enable/disable backend for virtio serial port */
+ void (*enable_backend)(VirtIOSerialPort *port, bool enable);
+
+ /* Guest is now ready to accept data (virtqueues set up). */
+ void (*guest_ready)(VirtIOSerialPort *port);
+
+ /*
+ * Guest has enqueued a buffer for the host to write into.
+ * Called each time a buffer is enqueued by the guest;
+ * irrespective of whether there already were free buffers the
+ * host could have consumed.
+ *
+ * This is dependent on both the guest and host end being
+ * connected.
+ */
+ void (*guest_writable)(VirtIOSerialPort *port);
+
+ /*
+ * Guest wrote some data to the port. This data is handed over to
+ * the app via this callback. The app can return a size less than
+ * 'len'. In this case, throttling will be enabled for this port.
+ */
+ ssize_t (*have_data)(VirtIOSerialPort *port, const uint8_t *buf,
+ ssize_t len);
+};
+
+/*
+ * This is the state that's shared between all the ports. Some of the
+ * state is configurable via command-line options. Some of it can be
+ * set by individual devices in their initfn routines. Some of the
+ * state is set by the generic qdev device init routine.
+ */
+struct VirtIOSerialPort {
+ DeviceState dev;
+
+ QTAILQ_ENTRY(VirtIOSerialPort) next;
+
+ /*
+ * This field gives us the virtio device as well as the qdev bus
+ * that we are associated with
+ */
+ VirtIOSerial *vser;
+
+ VirtQueue *ivq, *ovq;
+
+ /*
+ * This name is sent to the guest and exported via sysfs.
+ * The guest could create symlinks based on this information.
+ * The name is in the reverse fqdn format, like org.qemu.console.0
+ */
+ char *name;
+
+ /*
+ * This id helps identify ports between the guest and the host.
+ * The guest sends a "header" with this id with each data packet
+ * that it sends and the host can then find out which associated
+ * device to send out this data to
+ */
+ uint32_t id;
+
+ /*
+ * This is the elem that we pop from the virtqueue. A slow
+ * backend that consumes guest data (e.g. the file backend for
+ * qemu chardevs) can cause the guest to block till all the output
+ * is flushed. This isn't desired, so we keep a note of the last
+ * element popped and continue consuming it once the backend
+ * becomes writable again.
+ */
+ VirtQueueElement *elem;
+
+ /*
+ * The index and the offset into the iov buffer that was popped in
+ * elem above.
+ */
+ uint32_t iov_idx;
+ uint64_t iov_offset;
+
+ /*
+ * When unthrottling we use a bottom-half to call flush_queued_data.
+ */
+ QEMUBH *bh;
+
+ /* Is the corresponding guest device open? */
+ bool guest_connected;
+ /* Is this device open for IO on the host? */
+ bool host_connected;
+ /* Do apps not want to receive data? */
+ bool throttled;
+};
+
+/* The virtio-serial bus on top of which the ports will ride as devices */
+struct VirtIOSerialBus {
+ BusState qbus;
+
+ /* This is the parent device that provides the bus for ports. */
+ VirtIOSerial *vser;
+
+ /* The maximum number of ports that can ride on top of this bus */
+ uint32_t max_nr_ports;
+};
+
+typedef struct VirtIOSerialPostLoad {
+ QEMUTimer *timer;
+ uint32_t nr_active_ports;
+ struct {
+ VirtIOSerialPort *port;
+ uint8_t host_connected;
+ } *connected;
+} VirtIOSerialPostLoad;
+
+struct VirtIOSerial {
+ VirtIODevice parent_obj;
+
+ VirtQueue *c_ivq, *c_ovq;
+ /* Arrays of ivqs and ovqs: one per port */
+ VirtQueue **ivqs, **ovqs;
+
+ VirtIOSerialBus bus;
+
+ QTAILQ_HEAD(, VirtIOSerialPort) ports;
+
+ QLIST_ENTRY(VirtIOSerial) next;
+
+ /* bitmap for identifying active ports */
+ uint32_t *ports_map;
+
+ struct VirtIOSerialPostLoad *post_load;
+
+ virtio_serial_conf serial;
+
+ uint64_t host_features;
+};
+
+/* Interface to the virtio-serial bus */
+
+/*
+ * Open a connection to the port
+ * Returns 0 on success (always).
+ */
+int virtio_serial_open(VirtIOSerialPort *port);
+
+/*
+ * Close the connection to the port
+ * Returns 0 on success (always).
+ */
+int virtio_serial_close(VirtIOSerialPort *port);
+
+/*
+ * Send data to Guest
+ */
+ssize_t virtio_serial_write(VirtIOSerialPort *port, const uint8_t *buf,
+ size_t size);
+
+/*
+ * Query whether a guest is ready to receive data.
+ */
+size_t virtio_serial_guest_ready(VirtIOSerialPort *port);
+
+/*
+ * Flow control: Ports can signal to the virtio-serial core to stop
+ * sending data or re-start sending data, depending on the 'throttle'
+ * value here.
+ */
+void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle);
+
+#define TYPE_VIRTIO_SERIAL "virtio-serial-device"
+OBJECT_DECLARE_SIMPLE_TYPE(VirtIOSerial, VIRTIO_SERIAL)
+
+#endif
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
new file mode 100644
index 000000000..8bab9cfb7
--- /dev/null
+++ b/include/hw/virtio/virtio.h
@@ -0,0 +1,400 @@
+/*
+ * Virtio Support
+ *
+ * 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 QEMU_VIRTIO_H
+#define QEMU_VIRTIO_H
+
+#include "exec/memory.h"
+#include "hw/qdev-core.h"
+#include "net/net.h"
+#include "migration/vmstate.h"
+#include "qemu/event_notifier.h"
+#include "standard-headers/linux/virtio_config.h"
+#include "standard-headers/linux/virtio_ring.h"
+#include "qom/object.h"
+
+/* A guest should never accept this. It implies negotiation is broken. */
+#define VIRTIO_F_BAD_FEATURE 30
+
+#define VIRTIO_LEGACY_FEATURES ((0x1ULL << VIRTIO_F_BAD_FEATURE) | \
+ (0x1ULL << VIRTIO_F_NOTIFY_ON_EMPTY) | \
+ (0x1ULL << VIRTIO_F_ANY_LAYOUT))
+
+struct VirtQueue;
+
+static inline hwaddr vring_align(hwaddr addr,
+ unsigned long align)
+{
+ return QEMU_ALIGN_UP(addr, align);
+}
+
+typedef struct VirtIOFeature {
+ uint64_t flags;
+ size_t end;
+} VirtIOFeature;
+
+size_t virtio_feature_get_config_size(const VirtIOFeature *features,
+ uint64_t host_features);
+
+typedef struct VirtQueue VirtQueue;
+
+#define VIRTQUEUE_MAX_SIZE 1024
+
+typedef struct VirtQueueElement
+{
+ unsigned int index;
+ unsigned int len;
+ unsigned int ndescs;
+ unsigned int out_num;
+ unsigned int in_num;
+ hwaddr *in_addr;
+ hwaddr *out_addr;
+ struct iovec *in_sg;
+ struct iovec *out_sg;
+} VirtQueueElement;
+
+#define VIRTIO_QUEUE_MAX 1024
+
+#define VIRTIO_NO_VECTOR 0xffff
+
+#define TYPE_VIRTIO_DEVICE "virtio-device"
+OBJECT_DECLARE_TYPE(VirtIODevice, VirtioDeviceClass, VIRTIO_DEVICE)
+
+enum virtio_device_endian {
+ VIRTIO_DEVICE_ENDIAN_UNKNOWN,
+ VIRTIO_DEVICE_ENDIAN_LITTLE,
+ VIRTIO_DEVICE_ENDIAN_BIG,
+};
+
+struct VirtIODevice
+{
+ DeviceState parent_obj;
+ const char *name;
+ uint8_t status;
+ uint8_t isr;
+ uint16_t queue_sel;
+ uint64_t guest_features;
+ uint64_t host_features;
+ uint64_t backend_features;
+ size_t config_len;
+ void *config;
+ uint16_t config_vector;
+ uint32_t generation;
+ int nvectors;
+ VirtQueue *vq;
+ MemoryListener listener;
+ uint16_t device_id;
+ 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 */
+ bool use_started;
+ bool started;
+ bool start_on_kick; /* when virtio 1.0 feature has not been negotiated */
+ bool disable_legacy_check;
+ VMChangeStateEntry *vmstate;
+ char *bus_name;
+ uint8_t device_endian;
+ bool use_guest_notifier_mask;
+ AddressSpace *dma_as;
+ QLIST_HEAD(, VirtQueue) *vector_queues;
+};
+
+struct VirtioDeviceClass {
+ /*< private >*/
+ DeviceClass parent;
+ /*< public >*/
+
+ /* This is what a VirtioDevice must implement */
+ DeviceRealize realize;
+ DeviceUnrealize unrealize;
+ uint64_t (*get_features)(VirtIODevice *vdev,
+ uint64_t requested_features,
+ Error **errp);
+ uint64_t (*bad_features)(VirtIODevice *vdev);
+ void (*set_features)(VirtIODevice *vdev, uint64_t val);
+ int (*validate_features)(VirtIODevice *vdev);
+ void (*get_config)(VirtIODevice *vdev, uint8_t *config);
+ void (*set_config)(VirtIODevice *vdev, const uint8_t *config);
+ void (*reset)(VirtIODevice *vdev);
+ void (*set_status)(VirtIODevice *vdev, uint8_t val);
+ /* For transitional devices, this is a bitmap of features
+ * that are only exposed on the legacy interface but not
+ * the modern one.
+ */
+ uint64_t legacy_features;
+ /* Test and clear event pending status.
+ * Should be called after unmask to avoid losing events.
+ * If backend does not support masking,
+ * must check in frontend instead.
+ */
+ bool (*guest_notifier_pending)(VirtIODevice *vdev, int n);
+ /* Mask/unmask events from this vq. Any events reported
+ * while masked will become pending.
+ * If backend does not support masking,
+ * must mask in frontend instead.
+ */
+ void (*guest_notifier_mask)(VirtIODevice *vdev, int n, bool mask);
+ int (*start_ioeventfd)(VirtIODevice *vdev);
+ void (*stop_ioeventfd)(VirtIODevice *vdev);
+ /* Saving and loading of a device; trying to deprecate save/load
+ * use vmsd for new devices.
+ */
+ void (*save)(VirtIODevice *vdev, QEMUFile *f);
+ int (*load)(VirtIODevice *vdev, QEMUFile *f, int version_id);
+ /* Post load hook in vmsd is called early while device is processed, and
+ * when VirtIODevice isn't fully initialized. Devices should use this instead,
+ * unless they specifically want to verify the migration stream as it's
+ * processed, e.g. for bounds checking.
+ */
+ int (*post_load)(VirtIODevice *vdev);
+ const VMStateDescription *vmsd;
+ bool (*primary_unplug_pending)(void *opaque);
+};
+
+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);
+void virtio_cleanup(VirtIODevice *vdev);
+
+void virtio_error(VirtIODevice *vdev, const char *fmt, ...) GCC_FMT_ATTR(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);
+
+void virtio_del_queue(VirtIODevice *vdev, int n);
+
+void virtio_delete_queue(VirtQueue *vq);
+
+void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem,
+ unsigned int len);
+void virtqueue_flush(VirtQueue *vq, unsigned int count);
+void virtqueue_detach_element(VirtQueue *vq, const VirtQueueElement *elem,
+ unsigned int len);
+void virtqueue_unpop(VirtQueue *vq, const VirtQueueElement *elem,
+ unsigned int len);
+bool virtqueue_rewind(VirtQueue *vq, unsigned int num);
+void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
+ unsigned int len, unsigned int idx);
+
+void virtqueue_map(VirtIODevice *vdev, VirtQueueElement *elem);
+void *virtqueue_pop(VirtQueue *vq, size_t sz);
+unsigned int virtqueue_drop_all(VirtQueue *vq);
+void *qemu_get_virtqueue_element(VirtIODevice *vdev, QEMUFile *f, size_t sz);
+void qemu_put_virtqueue_element(VirtIODevice *vdev, QEMUFile *f,
+ VirtQueueElement *elem);
+int virtqueue_avail_bytes(VirtQueue *vq, unsigned int in_bytes,
+ unsigned int out_bytes);
+void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes,
+ unsigned int *out_bytes,
+ unsigned max_in_bytes, unsigned max_out_bytes);
+
+void virtio_notify_irqfd(VirtIODevice *vdev, VirtQueue *vq);
+void virtio_notify(VirtIODevice *vdev, VirtQueue *vq);
+
+int virtio_save(VirtIODevice *vdev, QEMUFile *f);
+
+extern const VMStateInfo virtio_vmstate_info;
+
+#define VMSTATE_VIRTIO_DEVICE \
+ { \
+ .name = "virtio", \
+ .info = &virtio_vmstate_info, \
+ .flags = VMS_SINGLE, \
+ }
+
+int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id);
+
+void virtio_notify_config(VirtIODevice *vdev);
+
+bool virtio_queue_get_notification(VirtQueue *vq);
+void virtio_queue_set_notification(VirtQueue *vq, int enable);
+
+int virtio_queue_ready(VirtQueue *vq);
+
+int virtio_queue_empty(VirtQueue *vq);
+
+/* Host binding interface. */
+
+uint32_t virtio_config_readb(VirtIODevice *vdev, uint32_t addr);
+uint32_t virtio_config_readw(VirtIODevice *vdev, uint32_t addr);
+uint32_t virtio_config_readl(VirtIODevice *vdev, uint32_t addr);
+void virtio_config_writeb(VirtIODevice *vdev, uint32_t addr, uint32_t data);
+void virtio_config_writew(VirtIODevice *vdev, uint32_t addr, uint32_t data);
+void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data);
+uint32_t virtio_config_modern_readb(VirtIODevice *vdev, uint32_t addr);
+uint32_t virtio_config_modern_readw(VirtIODevice *vdev, uint32_t addr);
+uint32_t virtio_config_modern_readl(VirtIODevice *vdev, uint32_t addr);
+void virtio_config_modern_writeb(VirtIODevice *vdev,
+ uint32_t addr, uint32_t data);
+void virtio_config_modern_writew(VirtIODevice *vdev,
+ uint32_t addr, uint32_t data);
+void virtio_config_modern_writel(VirtIODevice *vdev,
+ uint32_t addr, uint32_t data);
+void virtio_queue_set_addr(VirtIODevice *vdev, int n, hwaddr addr);
+hwaddr virtio_queue_get_addr(VirtIODevice *vdev, int n);
+void virtio_queue_set_num(VirtIODevice *vdev, int n, int num);
+int virtio_queue_get_num(VirtIODevice *vdev, int n);
+int virtio_queue_get_max_num(VirtIODevice *vdev, int n);
+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_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);
+void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector);
+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_update_irq(VirtIODevice *vdev);
+int virtio_set_features(VirtIODevice *vdev, uint64_t val);
+
+/* Base devices. */
+typedef struct VirtIOBlkConf VirtIOBlkConf;
+struct virtio_net_conf;
+typedef struct virtio_serial_conf virtio_serial_conf;
+typedef struct virtio_input_conf virtio_input_conf;
+typedef struct VirtIOSCSIConf VirtIOSCSIConf;
+typedef struct VirtIORNGConf VirtIORNGConf;
+
+#define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \
+ DEFINE_PROP_BIT64("indirect_desc", _state, _field, \
+ VIRTIO_RING_F_INDIRECT_DESC, true), \
+ DEFINE_PROP_BIT64("event_idx", _state, _field, \
+ VIRTIO_RING_F_EVENT_IDX, true), \
+ DEFINE_PROP_BIT64("notify_on_empty", _state, _field, \
+ VIRTIO_F_NOTIFY_ON_EMPTY, true), \
+ DEFINE_PROP_BIT64("any_layout", _state, _field, \
+ VIRTIO_F_ANY_LAYOUT, true), \
+ DEFINE_PROP_BIT64("iommu_platform", _state, _field, \
+ VIRTIO_F_IOMMU_PLATFORM, false), \
+ DEFINE_PROP_BIT64("packed", _state, _field, \
+ VIRTIO_F_RING_PACKED, false)
+
+hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, int n);
+bool virtio_queue_enabled_legacy(VirtIODevice *vdev, int n);
+bool virtio_queue_enabled(VirtIODevice *vdev, int n);
+hwaddr virtio_queue_get_avail_addr(VirtIODevice *vdev, int n);
+hwaddr virtio_queue_get_used_addr(VirtIODevice *vdev, int n);
+hwaddr virtio_queue_get_desc_size(VirtIODevice *vdev, int n);
+hwaddr virtio_queue_get_avail_size(VirtIODevice *vdev, int n);
+hwaddr virtio_queue_get_used_size(VirtIODevice *vdev, int n);
+unsigned int virtio_queue_get_last_avail_idx(VirtIODevice *vdev, int n);
+void virtio_queue_set_last_avail_idx(VirtIODevice *vdev, int n,
+ unsigned int idx);
+void virtio_queue_restore_last_avail_idx(VirtIODevice *vdev, int n);
+void virtio_queue_invalidate_signalled_used(VirtIODevice *vdev, int n);
+void virtio_queue_update_used_idx(VirtIODevice *vdev, int n);
+VirtQueue *virtio_get_queue(VirtIODevice *vdev, int n);
+uint16_t virtio_get_queue_index(VirtQueue *vq);
+EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq);
+void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign,
+ bool with_irqfd);
+int virtio_device_start_ioeventfd(VirtIODevice *vdev);
+int virtio_device_grab_ioeventfd(VirtIODevice *vdev);
+void virtio_device_release_ioeventfd(VirtIODevice *vdev);
+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);
+VirtQueue *virtio_vector_first_queue(VirtIODevice *vdev, uint16_t vector);
+VirtQueue *virtio_vector_next_queue(VirtQueue *vq);
+
+static inline void virtio_add_feature(uint64_t *features, unsigned int fbit)
+{
+ assert(fbit < 64);
+ *features |= (1ULL << fbit);
+}
+
+static inline void virtio_clear_feature(uint64_t *features, unsigned int fbit)
+{
+ assert(fbit < 64);
+ *features &= ~(1ULL << fbit);
+}
+
+static inline bool virtio_has_feature(uint64_t features, unsigned int fbit)
+{
+ assert(fbit < 64);
+ return !!(features & (1ULL << fbit));
+}
+
+static inline bool virtio_vdev_has_feature(VirtIODevice *vdev,
+ unsigned int fbit)
+{
+ return virtio_has_feature(vdev->guest_features, fbit);
+}
+
+static inline bool virtio_host_has_feature(VirtIODevice *vdev,
+ unsigned int fbit)
+{
+ return virtio_has_feature(vdev->host_features, fbit);
+}
+
+static inline bool virtio_is_big_endian(VirtIODevice *vdev)
+{
+ if (!virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
+ assert(vdev->device_endian != VIRTIO_DEVICE_ENDIAN_UNKNOWN);
+ return vdev->device_endian == VIRTIO_DEVICE_ENDIAN_BIG;
+ }
+ /* Devices conforming to VIRTIO 1.0 or later are always LE. */
+ return false;
+}
+
+static inline bool virtio_device_started(VirtIODevice *vdev, uint8_t status)
+{
+ if (vdev->use_started) {
+ return vdev->started;
+ }
+
+ return status & VIRTIO_CONFIG_S_DRIVER_OK;
+}
+
+static inline void virtio_set_started(VirtIODevice *vdev, bool started)
+{
+ if (started) {
+ vdev->start_on_kick = false;
+ }
+
+ if (vdev->use_started) {
+ vdev->started = started;
+ }
+}
+
+static inline void virtio_set_disabled(VirtIODevice *vdev, bool disable)
+{
+ if (vdev->use_disabled_flag) {
+ vdev->disabled = disable;
+ }
+}
+
+static inline bool virtio_device_disabled(VirtIODevice *vdev)
+{
+ return unlikely(vdev->disabled || vdev->broken);
+}
+
+bool virtio_legacy_allowed(VirtIODevice *vdev);
+bool virtio_legacy_check_disabled(VirtIODevice *vdev);
+
+#endif
diff --git a/include/hw/vmstate-if.h b/include/hw/vmstate-if.h
new file mode 100644
index 000000000..52df571d1
--- /dev/null
+++ b/include/hw/vmstate-if.h
@@ -0,0 +1,39 @@
+/*
+ * VMState interface
+ *
+ * Copyright (c) 2009-2019 Red Hat 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 VMSTATE_IF_H
+#define VMSTATE_IF_H
+
+#include "qom/object.h"
+
+#define TYPE_VMSTATE_IF "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;
+
+struct VMStateIfClass {
+ InterfaceClass parent_class;
+
+ char * (*get_id)(VMStateIf *obj);
+};
+
+static inline char *vmstate_if_get_id(VMStateIf *vmif)
+{
+ if (!vmif) {
+ return NULL;
+ }
+
+ return VMSTATE_IF_GET_CLASS(vmif)->get_id(vmif);
+}
+
+#endif /* VMSTATE_IF_H */
diff --git a/include/hw/watchdog/cmsdk-apb-watchdog.h b/include/hw/watchdog/cmsdk-apb-watchdog.h
new file mode 100644
index 000000000..c6b3e7873
--- /dev/null
+++ b/include/hw/watchdog/cmsdk-apb-watchdog.h
@@ -0,0 +1,68 @@
+/*
+ * ARM CMSDK APB watchdog emulation
+ *
+ * Copyright (c) 2018 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 "APB watchdog" which is part of the Cortex-M
+ * System Design Kit (CMSDK) and documented in the Cortex-M System
+ * Design Kit Technical Reference Manual (ARM DDI0479C):
+ * https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
+ *
+ * QEMU interface:
+ * + Clock input "WDOGCLK": clock for the watchdog's timer
+ * + sysbus MMIO region 0: the register bank
+ * + sysbus IRQ 0: watchdog interrupt
+ *
+ * In real hardware the watchdog's reset output is just a GPIO line
+ * which can then be masked by the board or treated as a simple interrupt.
+ * (For instance the IoTKit does this with the non-secure watchdog, so that
+ * secure code can control whether non-secure code can perform a system
+ * reset via its watchdog.) In QEMU, we just wire up the watchdog reset
+ * to watchdog_perform_action(), at least for the moment.
+ */
+
+#ifndef CMSDK_APB_WATCHDOG_H
+#define CMSDK_APB_WATCHDOG_H
+
+#include "hw/sysbus.h"
+#include "hw/ptimer.h"
+#include "hw/clock.h"
+#include "qom/object.h"
+
+#define TYPE_CMSDK_APB_WATCHDOG "cmsdk-apb-watchdog"
+OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBWatchdog, CMSDK_APB_WATCHDOG)
+
+/*
+ * This shares the same struct (and cast macro) as the base
+ * cmsdk-apb-watchdog device.
+ */
+#define TYPE_LUMINARY_WATCHDOG "luminary-watchdog"
+
+struct CMSDKAPBWatchdog {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+ qemu_irq wdogint;
+ bool is_luminary;
+ struct ptimer_state *timer;
+ Clock *wdogclk;
+
+ uint32_t control;
+ uint32_t intstatus;
+ uint32_t lock;
+ uint32_t itcr;
+ uint32_t itop;
+ uint32_t resetstatus;
+ const uint32_t *id;
+};
+
+#endif
diff --git a/include/hw/watchdog/sbsa_gwdt.h b/include/hw/watchdog/sbsa_gwdt.h
new file mode 100644
index 000000000..70b137de3
--- /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
new file mode 100644
index 000000000..f945cd6c5
--- /dev/null
+++ b/include/hw/watchdog/wdt_aspeed.h
@@ -0,0 +1,50 @@
+/*
+ * ASPEED Watchdog Controller
+ *
+ * Copyright (C) 2016-2017 IBM Corp.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+
+#ifndef WDT_ASPEED_H
+#define WDT_ASPEED_H
+
+#include "hw/misc/aspeed_scu.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_ASPEED_WDT "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 ASPEED_WDT_REGS_MAX (0x20 / 4)
+
+struct AspeedWDTState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ QEMUTimer *timer;
+
+ /*< public >*/
+ MemoryRegion iomem;
+ uint32_t regs[ASPEED_WDT_REGS_MAX];
+
+ AspeedSCUState *scu;
+ uint32_t pclk_freq;
+};
+
+
+struct AspeedWDTClass {
+ SysBusDeviceClass parent_class;
+
+ uint32_t offset;
+ uint32_t ext_pulse_width_mask;
+ uint32_t reset_ctrl_reg;
+ void (*reset_pulse)(AspeedWDTState *s, uint32_t property);
+ void (*wdt_reload)(AspeedWDTState *s);
+ uint64_t (*sanitize_ctrl)(uint64_t data);
+};
+
+#endif /* WDT_ASPEED_H */
diff --git a/include/hw/watchdog/wdt_diag288.h b/include/hw/watchdog/wdt_diag288.h
new file mode 100644
index 000000000..f72c1d331
--- /dev/null
+++ b/include/hw/watchdog/wdt_diag288.h
@@ -0,0 +1,35 @@
+#ifndef WDT_DIAG288_H
+#define WDT_DIAG288_H
+
+#include "hw/qdev-core.h"
+#include "qom/object.h"
+
+#define TYPE_WDT_DIAG288 "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
+
+struct DIAG288State {
+ /*< private >*/
+ DeviceState parent_obj;
+ QEMUTimer *timer;
+ bool enabled;
+
+ /*< public >*/
+};
+
+struct DIAG288Class {
+ /*< private >*/
+ DeviceClass parent_class;
+
+ /*< public >*/
+ int (*handle_timer)(DIAG288State *dev,
+ uint64_t func, uint64_t timeout);
+};
+
+#endif /* WDT_DIAG288_H */
diff --git a/include/hw/watchdog/wdt_imx2.h b/include/hw/watchdog/wdt_imx2.h
new file mode 100644
index 000000000..023d83f48
--- /dev/null
+++ b/include/hw/watchdog/wdt_imx2.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX2 Watchdog IP block
+ *
+ * Author: Andrey Smirnov <andrew.smirnov@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 IMX2_WDT_H
+#define IMX2_WDT_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"
+OBJECT_DECLARE_SIMPLE_TYPE(IMX2WdtState, IMX2_WDT)
+
+enum IMX2WdtRegisters {
+ IMX2_WDT_WCR = 0x0000, /* Control Register */
+ IMX2_WDT_WSR = 0x0002, /* Service Register */
+ IMX2_WDT_WRSR = 0x0004, /* Reset Status Register */
+ IMX2_WDT_WICR = 0x0006, /* Interrupt Control Register */
+ IMX2_WDT_WMCR = 0x0008, /* Misc Register */
+};
+
+#define IMX2_WDT_MMIO_SIZE 0x000a
+
+/* Control Register definitions */
+#define IMX2_WDT_WCR_WT (0xFF << 8) /* Watchdog Timeout Field */
+#define IMX2_WDT_WCR_WDW BIT(7) /* WDOG Disable for Wait */
+#define IMX2_WDT_WCR_WDA BIT(5) /* WDOG Assertion */
+#define IMX2_WDT_WCR_SRS BIT(4) /* Software Reset Signal */
+#define IMX2_WDT_WCR_WDT BIT(3) /* WDOG Timeout Assertion */
+#define IMX2_WDT_WCR_WDE BIT(2) /* Watchdog Enable */
+#define IMX2_WDT_WCR_WDBG BIT(1) /* Watchdog Debug Enable */
+#define IMX2_WDT_WCR_WDZST BIT(0) /* Watchdog Timer Suspend */
+
+#define IMX2_WDT_WCR_LOCK_MASK (IMX2_WDT_WCR_WDZST | IMX2_WDT_WCR_WDBG \
+ | IMX2_WDT_WCR_WDW)
+
+/* Service Register definitions */
+#define IMX2_WDT_SEQ1 0x5555 /* service sequence 1 */
+#define IMX2_WDT_SEQ2 0xAAAA /* service sequence 2 */
+
+/* Reset Status Register definitions */
+#define IMX2_WDT_WRSR_TOUT BIT(1) /* Reset due to Timeout */
+#define IMX2_WDT_WRSR_SFTW BIT(0) /* Reset due to software reset */
+
+/* Interrupt Control Register definitions */
+#define IMX2_WDT_WICR_WIE BIT(15) /* Interrupt Enable */
+#define IMX2_WDT_WICR_WTIS BIT(14) /* Interrupt Status */
+#define IMX2_WDT_WICR_WICT 0xff /* Interrupt Timeout */
+#define IMX2_WDT_WICR_WICT_DEF 0x04 /* Default interrupt timeout (2s) */
+
+#define IMX2_WDT_WICR_LOCK_MASK (IMX2_WDT_WICR_WIE | IMX2_WDT_WICR_WICT)
+
+/* Misc Control Register definitions */
+#define IMX2_WDT_WMCR_PDE BIT(0) /* Power-Down Enable */
+
+struct IMX2WdtState {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion mmio;
+ qemu_irq irq;
+
+ struct ptimer_state *timer;
+ struct ptimer_state *itimer;
+
+ bool pretimeout_support;
+ bool wicr_locked;
+
+ uint16_t wcr;
+ uint16_t wsr;
+ uint16_t wrsr;
+ uint16_t wicr;
+ uint16_t wmcr;
+
+ bool wcr_locked; /* affects WDZST, WDBG, and WDW */
+ bool wcr_wde_locked; /* affects WDE */
+ bool wcr_wdt_locked; /* affects WDT (never cleared) */
+};
+
+#endif /* IMX2_WDT_H */
diff --git a/include/hw/xen/interface/grant_table.h b/include/hw/xen/interface/grant_table.h
new file mode 100644
index 000000000..2af0cbdde
--- /dev/null
+++ b/include/hw/xen/interface/grant_table.h
@@ -0,0 +1,36 @@
+/******************************************************************************
+ * 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__
+
+/*
+ * Reference to a grant entry in a specified domain's grant table.
+ */
+typedef uint32_t grant_ref_t;
+
+#endif /* __XEN_PUBLIC_GRANT_TABLE_H__ */
diff --git a/include/hw/xen/interface/io/blkif.h b/include/hw/xen/interface/io/blkif.h
new file mode 100644
index 000000000..d07fa1e07
--- /dev/null
+++ b/include/hw/xen/interface/io/blkif.h
@@ -0,0 +1,712 @@
+/******************************************************************************
+ * 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
+ */
+
+#ifndef __XEN_PUBLIC_IO_BLKIF_H__
+#define __XEN_PUBLIC_IO_BLKIF_H__
+
+#include "ring.h"
+#include "../grant_table.h"
+
+/*
+ * Front->back notifications: When enqueuing a new request, sending a
+ * notification can be made conditional on req_event (i.e., the generic
+ * hold-off mechanism provided by the ring macros). Backends must set
+ * req_event appropriately (e.g., using RING_FINAL_CHECK_FOR_REQUESTS()).
+ *
+ * Back->front notifications: When enqueuing a new response, sending a
+ * notification can be made conditional on rsp_event (i.e., the generic
+ * hold-off mechanism provided by the ring macros). Frontends must set
+ * rsp_event appropriately (e.g., using RING_FINAL_CHECK_FOR_RESPONSES()).
+ */
+
+#ifndef blkif_vdev_t
+#define blkif_vdev_t uint16_t
+#endif
+#define blkif_sector_t uint64_t
+
+/*
+ * Feature and Parameter Negotiation
+ * =================================
+ * The two halves of a Xen block driver utilize nodes within the XenStore to
+ * communicate capabilities and to negotiate operating parameters. This
+ * section enumerates these nodes which reside in the respective front and
+ * backend portions of the XenStore, following the XenBus convention.
+ *
+ * All data in the XenStore is stored as strings. Nodes specifying numeric
+ * values are encoded in decimal. Integer value ranges listed below are
+ * expressed as fixed sized integer types capable of storing the conversion
+ * of a properly formated node string, without loss of information.
+ *
+ * Any specified default value is in effect if the corresponding XenBus node
+ * is not present in the XenStore.
+ *
+ * XenStore nodes in sections marked "PRIVATE" are solely for use by the
+ * driver side whose XenBus tree contains them.
+ *
+ * XenStore nodes marked "DEPRECATED" in their notes section should only be
+ * used to provide interoperability with legacy implementations.
+ *
+ * See the XenBus state transition diagram below for details on when XenBus
+ * nodes must be published and when they can be queried.
+ *
+ *****************************************************************************
+ * Backend XenBus Nodes
+ *****************************************************************************
+ *
+ *------------------ Backend Device Identification (PRIVATE) ------------------
+ *
+ * mode
+ * Values: "r" (read only), "w" (writable)
+ *
+ * The read or write access permissions to the backing store to be
+ * granted to the frontend.
+ *
+ * params
+ * Values: string
+ *
+ * A free formatted string providing sufficient information for the
+ * hotplug script to attach the device and provide a suitable
+ * handler (ie: a block device) for blkback to use.
+ *
+ * physical-device
+ * Values: "MAJOR:MINOR"
+ * Notes: 11
+ *
+ * MAJOR and MINOR are the major number and minor number of the
+ * backing device respectively.
+ *
+ * physical-device-path
+ * Values: path string
+ *
+ * A string that contains the absolute path to the disk image. On
+ * NetBSD and Linux this is always a block device, while on FreeBSD
+ * it can be either a block device or a regular file.
+ *
+ * type
+ * Values: "file", "phy", "tap"
+ *
+ * The type of the backing device/object.
+ *
+ *
+ * direct-io-safe
+ * Values: 0/1 (boolean)
+ * Default Value: 0
+ *
+ * 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
+ *
+ * Therefore this option gives the backend permission to use
+ * O_DIRECT, notwithstanding that bug.
+ *
+ * That is, if this option is enabled, use of O_DIRECT is safe,
+ * in circumstances where we would normally have avoided it as a
+ * workaround for that bug. This option is not relevant for all
+ * backends, and even not necessarily supported for those for
+ * which it is relevant. A backend which knows that it is not
+ * affected by the bug can ignore this option.
+ *
+ * This option doesn't require a backend to use O_DIRECT, so it
+ * should not be used to try to control the caching behaviour.
+ *
+ *--------------------------------- Features ---------------------------------
+ *
+ * feature-barrier
+ * Values: 0/1 (boolean)
+ * Default Value: 0
+ *
+ * A value of "1" indicates that the backend can process requests
+ * containing the BLKIF_OP_WRITE_BARRIER request opcode. Requests
+ * of this type may still be returned at any time with the
+ * BLKIF_RSP_EOPNOTSUPP result code.
+ *
+ * feature-flush-cache
+ * Values: 0/1 (boolean)
+ * Default Value: 0
+ *
+ * A value of "1" indicates that the backend can process requests
+ * containing the BLKIF_OP_FLUSH_DISKCACHE request opcode. Requests
+ * of this type may still be returned at any time with the
+ * BLKIF_RSP_EOPNOTSUPP result code.
+ *
+ * feature-discard
+ * Values: 0/1 (boolean)
+ * Default Value: 0
+ *
+ * A value of "1" indicates that the backend can process requests
+ * containing the BLKIF_OP_DISCARD request opcode. Requests
+ * of this type may still be returned at any time with the
+ * BLKIF_RSP_EOPNOTSUPP result code.
+ *
+ * feature-persistent
+ * Values: 0/1 (boolean)
+ * Default Value: 0
+ * Notes: 7
+ *
+ * A value of "1" indicates that the backend can keep the grants used
+ * by the frontend driver mapped, so the same set of grants should be
+ * used in all transactions. The maximum number of grants the backend
+ * can map persistently depends on the implementation, but ideally it
+ * should be RING_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST. Using this
+ * feature the backend doesn't need to unmap each grant, preventing
+ * costly TLB flushes. The backend driver should only map grants
+ * persistently if the frontend supports it. If a backend driver chooses
+ * to use the persistent protocol when the frontend doesn't support it,
+ * it will probably hit the maximum number of persistently mapped grants
+ * (due to the fact that the frontend won't be reusing the same grants),
+ * and fall back to non-persistent mode. Backend implementations may
+ * shrink or expand the number of persistently mapped grants without
+ * notifying the frontend depending on memory constraints (this might
+ * cause a performance degradation).
+ *
+ * If a backend driver wants to limit the maximum number of persistently
+ * mapped grants to a value less than RING_SIZE *
+ * BLKIF_MAX_SEGMENTS_PER_REQUEST a LRU strategy should be used to
+ * discard the grants that are less commonly used. Using a LRU in the
+ * backend driver paired with a LIFO queue in the frontend will
+ * allow us to have better performance in this scenario.
+ *
+ *----------------------- Request Transport Parameters ------------------------
+ *
+ * max-ring-page-order
+ * Values: <uint32_t>
+ * Default Value: 0
+ * Notes: 1, 3
+ *
+ * The maximum supported size of the request ring buffer in units of
+ * lb(machine pages). (e.g. 0 == 1 page, 1 = 2 pages, 2 == 4 pages,
+ * etc.).
+ *
+ * max-ring-pages
+ * Values: <uint32_t>
+ * Default Value: 1
+ * Notes: DEPRECATED, 2, 3
+ *
+ * The maximum supported size of the request ring buffer in units of
+ * machine pages. The value must be a power of 2.
+ *
+ *------------------------- Backend Device Properties -------------------------
+ *
+ * discard-enable
+ * Values: 0/1 (boolean)
+ * Default Value: 1
+ *
+ * This optional property, set by the toolstack, instructs the backend
+ * to offer (or not to offer) discard to the frontend. If the property
+ * is missing the backend should offer discard if the backing storage
+ * actually supports it.
+ *
+ * discard-alignment
+ * Values: <uint32_t>
+ * Default Value: 0
+ * Notes: 4, 5
+ *
+ * The offset, in bytes from the beginning of the virtual block device,
+ * to the first, addressable, discard extent on the underlying device.
+ *
+ * discard-granularity
+ * Values: <uint32_t>
+ * Default Value: <"sector-size">
+ * Notes: 4
+ *
+ * The size, in bytes, of the individually addressable discard extents
+ * of the underlying device.
+ *
+ * discard-secure
+ * Values: 0/1 (boolean)
+ * Default Value: 0
+ * Notes: 10
+ *
+ * A value of "1" indicates that the backend can process BLKIF_OP_DISCARD
+ * requests with the BLKIF_DISCARD_SECURE flag set.
+ *
+ * info
+ * Values: <uint32_t> (bitmap)
+ *
+ * A collection of bit flags describing attributes of the backing
+ * device. The VDISK_* macros define the meaning of each bit
+ * location.
+ *
+ * sector-size
+ * Values: <uint32_t>
+ *
+ * The logical block size, in bytes, of the underlying storage. This
+ * must be a power of two with a minimum value of 512.
+ *
+ * NOTE: Because of implementation bugs in some frontends this must be
+ * set to 512, unless the frontend advertizes a non-zero value
+ * in its "feature-large-sector-size" xenbus node. (See below).
+ *
+ * physical-sector-size
+ * Values: <uint32_t>
+ * Default Value: <"sector-size">
+ *
+ * The physical block size, in bytes, of the backend storage. This
+ * must be an integer multiple of "sector-size".
+ *
+ * sectors
+ * Values: <uint64_t>
+ *
+ * The size of the backend device, expressed in units of "sector-size".
+ * The product of "sector-size" and "sectors" must also be an integer
+ * multiple of "physical-sector-size", if that node is present.
+ *
+ *****************************************************************************
+ * Frontend XenBus Nodes
+ *****************************************************************************
+ *
+ *----------------------- Request Transport Parameters -----------------------
+ *
+ * event-channel
+ * Values: <uint32_t>
+ *
+ * The identifier of the Xen event channel used to signal activity
+ * in the ring buffer.
+ *
+ * ring-ref
+ * Values: <uint32_t>
+ * Notes: 6
+ *
+ * The Xen grant reference granting permission for the backend to map
+ * the sole page in a single page sized ring buffer.
+ *
+ * ring-ref%u
+ * Values: <uint32_t>
+ * Notes: 6
+ *
+ * For a frontend providing a multi-page ring, a "number of ring pages"
+ * sized list of nodes, each containing a Xen grant reference granting
+ * permission for the backend to map the page of the ring located
+ * at page index "%u". Page indexes are zero based.
+ *
+ * protocol
+ * Values: string (XEN_IO_PROTO_ABI_*)
+ * Default Value: XEN_IO_PROTO_ABI_NATIVE
+ *
+ * The machine ABI rules governing the format of all ring request and
+ * response structures.
+ *
+ * ring-page-order
+ * Values: <uint32_t>
+ * Default Value: 0
+ * Maximum Value: MAX(ffs(max-ring-pages) - 1, max-ring-page-order)
+ * Notes: 1, 3
+ *
+ * The size of the frontend allocated request ring buffer in units
+ * of lb(machine pages). (e.g. 0 == 1 page, 1 = 2 pages, 2 == 4 pages,
+ * etc.).
+ *
+ * num-ring-pages
+ * Values: <uint32_t>
+ * Default Value: 1
+ * Maximum Value: MAX(max-ring-pages,(0x1 << max-ring-page-order))
+ * Notes: DEPRECATED, 2, 3
+ *
+ * The size of the frontend allocated request ring buffer in units of
+ * machine pages. The value must be a power of 2.
+ *
+ *--------------------------------- Features ---------------------------------
+ *
+ * feature-persistent
+ * Values: 0/1 (boolean)
+ * Default Value: 0
+ * Notes: 7, 8, 9
+ *
+ * A value of "1" indicates that the frontend will reuse the same grants
+ * for all transactions, allowing the backend to map them with write
+ * 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
+ * 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.
+ *
+ * It is recommended that the frontend driver stores the persistently
+ * mapped grants in a LIFO queue, so a subset of all persistently mapped
+ * grants gets used commonly. This is done in case the backend driver
+ * decides to limit the maximum number of persistently mapped grants
+ * to a value less than RING_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST.
+ *
+ * feature-large-sector-size
+ * Values: 0/1 (boolean)
+ * Default Value: 0
+ *
+ * A value of "1" indicates that the frontend will correctly supply and
+ * interpret all sector-based quantities in terms of the "sector-size"
+ * value supplied in the backend info, whatever that may be set to.
+ * If this node is not present or its value is "0" then it is assumed
+ * that the frontend requires that the logical block size is 512 as it
+ * is hardcoded (which is the case in some frontend implementations).
+ *
+ *------------------------- Virtual Device Properties -------------------------
+ *
+ * device-type
+ * Values: "disk", "cdrom", "floppy", etc.
+ *
+ * virtual-device
+ * Values: <uint32_t>
+ *
+ * A value indicating the physical device to virtualize within the
+ * frontend's domain. (e.g. "The first ATA disk", "The third SCSI
+ * disk", etc.)
+ *
+ * See docs/misc/vbd-interface.txt for details on the format of this
+ * value.
+ *
+ * Notes
+ * -----
+ * (1) Multi-page ring buffer scheme first developed in the Citrix XenServer
+ * PV drivers.
+ * (2) Multi-page ring buffer scheme first used in some RedHat distributions
+ * including a distribution deployed on certain nodes of the Amazon
+ * EC2 cluster.
+ * (3) Support for multi-page ring buffers was implemented independently,
+ * in slightly different forms, by both Citrix and RedHat/Amazon.
+ * For full interoperability, block front and backends should publish
+ * identical ring parameters, adjusted for unit differences, to the
+ * XenStore nodes used in both schemes.
+ * (4) Devices that support discard functionality may internally allocate space
+ * (discardable extents) in units that are larger than the exported logical
+ * block size. If the backing device has such discardable extents the
+ * backend should provide both discard-granularity and discard-alignment.
+ * Providing just one of the two may be considered an error by the frontend.
+ * Backends supporting discard should include discard-granularity and
+ * discard-alignment even if it supports discarding individual sectors.
+ * Frontends should assume discard-alignment == 0 and discard-granularity
+ * == sector size if these keys are missing.
+ * (5) The discard-alignment parameter allows a physical device to be
+ * partitioned into virtual devices that do not necessarily begin or
+ * end on a discardable extent boundary.
+ * (6) When there is only a single page allocated to the request ring,
+ * 'ring-ref' is used to communicate the grant reference for this
+ * page to the backend. When using a multi-page ring, the 'ring-ref'
+ * node is not created. Instead 'ring-ref0' - 'ring-refN' are used.
+ * (7) When using persistent grants data has to be copied from/to the page
+ * where the grant is currently mapped. The overhead of doing this copy
+ * however doesn't suppress the speed improvement of not having to unmap
+ * the grants.
+ * (8) The frontend driver has to allow the backend driver to map all grants
+ * with write access, even when they should be mapped read-only, since
+ * further requests may reuse these grants and require write permissions.
+ * (9) Linux implementation doesn't have a limit on the maximum number of
+ * grants that can be persistently mapped in the frontend driver, but
+ * due to the frontent driver implementation it should never be bigger
+ * than RING_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST.
+ *(10) The discard-secure property may be present and will be set to 1 if the
+ * backing device supports secure discard.
+ *(11) Only used by Linux and NetBSD.
+ */
+
+/*
+ * Multiple hardware queues/rings:
+ * If supported, the backend will write the key "multi-queue-max-queues" to
+ * the directory for that vbd, and set its value to the maximum supported
+ * number of queues.
+ * Frontends that are aware of this feature and wish to use it can write the
+ * key "multi-queue-num-queues" with the number they wish to use, which must be
+ * greater than zero, and no more than the value reported by the backend in
+ * "multi-queue-max-queues".
+ *
+ * For frontends requesting just one queue, the usual event-channel and
+ * ring-ref keys are written as before, simplifying the backend processing
+ * to avoid distinguishing between a frontend that doesn't understand the
+ * multi-queue feature, and one that does, but requested only one queue.
+ *
+ * Frontends requesting two or more queues must not write the toplevel
+ * event-channel and ring-ref keys, instead writing those keys under sub-keys
+ * having the name "queue-N" where N is the integer ID of the queue/ring for
+ * which those keys belong. Queues are indexed from zero.
+ * For example, a frontend with two queues must write the following set of
+ * queue-related keys:
+ *
+ * /local/domain/1/device/vbd/0/multi-queue-num-queues = "2"
+ * /local/domain/1/device/vbd/0/queue-0 = ""
+ * /local/domain/1/device/vbd/0/queue-0/ring-ref = "<ring-ref#0>"
+ * /local/domain/1/device/vbd/0/queue-0/event-channel = "<evtchn#0>"
+ * /local/domain/1/device/vbd/0/queue-1 = ""
+ * /local/domain/1/device/vbd/0/queue-1/ring-ref = "<ring-ref#1>"
+ * /local/domain/1/device/vbd/0/queue-1/event-channel = "<evtchn#1>"
+ *
+ * It is also possible to use multiple queues/rings together with
+ * feature multi-page ring buffer.
+ * For example, a frontend requests two queues/rings and the size of each ring
+ * buffer is two pages must write the following set of related keys:
+ *
+ * /local/domain/1/device/vbd/0/multi-queue-num-queues = "2"
+ * /local/domain/1/device/vbd/0/ring-page-order = "1"
+ * /local/domain/1/device/vbd/0/queue-0 = ""
+ * /local/domain/1/device/vbd/0/queue-0/ring-ref0 = "<ring-ref#0>"
+ * /local/domain/1/device/vbd/0/queue-0/ring-ref1 = "<ring-ref#1>"
+ * /local/domain/1/device/vbd/0/queue-0/event-channel = "<evtchn#0>"
+ * /local/domain/1/device/vbd/0/queue-1 = ""
+ * /local/domain/1/device/vbd/0/queue-1/ring-ref0 = "<ring-ref#2>"
+ * /local/domain/1/device/vbd/0/queue-1/ring-ref1 = "<ring-ref#3>"
+ * /local/domain/1/device/vbd/0/queue-1/event-channel = "<evtchn#1>"
+ *
+ */
+
+/*
+ * STATE DIAGRAMS
+ *
+ *****************************************************************************
+ * Startup *
+ *****************************************************************************
+ *
+ * Tool stack creates front and back nodes with state XenbusStateInitialising.
+ *
+ * Front Back
+ * ================================= =====================================
+ * XenbusStateInitialising XenbusStateInitialising
+ * o Query virtual device o Query backend device identification
+ * properties. data.
+ * o Setup OS device instance. o Open and validate backend device.
+ * o Publish backend features and
+ * transport parameters.
+ * |
+ * |
+ * V
+ * XenbusStateInitWait
+ *
+ * o Query backend features and
+ * transport parameters.
+ * o Allocate and initialize the
+ * request ring.
+ * o Publish transport parameters
+ * that will be in effect during
+ * this connection.
+ * |
+ * |
+ * V
+ * XenbusStateInitialised
+ *
+ * o Query frontend transport parameters.
+ * o Connect to the request ring and
+ * event channel.
+ * o Publish backend device properties.
+ * |
+ * |
+ * V
+ * XenbusStateConnected
+ *
+ * o Query backend device properties.
+ * o Finalize OS virtual device
+ * instance.
+ * |
+ * |
+ * V
+ * XenbusStateConnected
+ *
+ * Note: Drivers that do not support any optional features, or the negotiation
+ * of transport parameters, can skip certain states in the state machine:
+ *
+ * o A frontend may transition to XenbusStateInitialised without
+ * waiting for the backend to enter XenbusStateInitWait. In this
+ * case, default transport parameters are in effect and any
+ * transport parameters published by the frontend must contain
+ * their default values.
+ *
+ * o A backend may transition to XenbusStateInitialised, bypassing
+ * XenbusStateInitWait, without waiting for the frontend to first
+ * enter the XenbusStateInitialised state. In this case, default
+ * transport parameters are in effect and any transport parameters
+ * published by the backend must contain their default values.
+ *
+ * Drivers that support optional features and/or transport parameter
+ * negotiation must tolerate these additional state transition paths.
+ * In general this means performing the work of any skipped state
+ * transition, if it has not already been performed, in addition to the
+ * work associated with entry into the current state.
+ */
+
+/*
+ * REQUEST CODES.
+ */
+#define BLKIF_OP_READ 0
+#define BLKIF_OP_WRITE 1
+/*
+ * All writes issued prior to a request with the BLKIF_OP_WRITE_BARRIER
+ * operation code ("barrier request") must be completed prior to the
+ * execution of the barrier request. All writes issued after the barrier
+ * request must not execute until after the completion of the barrier request.
+ *
+ * Optional. See "feature-barrier" XenBus node documentation above.
+ */
+#define BLKIF_OP_WRITE_BARRIER 2
+/*
+ * Commit any uncommitted contents of the backing device's volatile cache
+ * to stable storage.
+ *
+ * Optional. See "feature-flush-cache" XenBus node documentation above.
+ */
+#define BLKIF_OP_FLUSH_DISKCACHE 3
+/*
+ * Used in SLES sources for device specific command packet
+ * contained within the request. Reserved for that purpose.
+ */
+#define BLKIF_OP_RESERVED_1 4
+/*
+ * Indicate to the backend device that a region of storage is no longer in
+ * use, and may be discarded at any time without impact to the client. If
+ * the BLKIF_DISCARD_SECURE flag is set on the request, all copies of the
+ * discarded region on the device must be rendered unrecoverable before the
+ * command returns.
+ *
+ * This operation is analogous to performing a trim (ATA) or unamp (SCSI),
+ * command on a native device.
+ *
+ * More information about trim/unmap operations can be found at:
+ * http://t13.org/Documents/UploadedDocuments/docs2008/
+ * e07154r6-Data_Set_Management_Proposal_for_ATA-ACS2.doc
+ * http://www.seagate.com/staticfiles/support/disc/manuals/
+ * Interface%20manuals/100293068c.pdf
+ *
+ * Optional. See "feature-discard", "discard-alignment",
+ * "discard-granularity", and "discard-secure" in the XenBus node
+ * documentation above.
+ */
+#define BLKIF_OP_DISCARD 5
+
+/*
+ * Recognized if "feature-max-indirect-segments" in present in the backend
+ * xenbus info. The "feature-max-indirect-segments" node contains the maximum
+ * number of segments allowed by the backend per request. If the node is
+ * present, the frontend might use blkif_request_indirect structs in order to
+ * issue requests with more than BLKIF_MAX_SEGMENTS_PER_REQUEST (11). The
+ * maximum number of indirect segments is fixed by the backend, but the
+ * frontend can issue requests with any number of indirect segments as long as
+ * it's less than the number provided by the backend. The indirect_grefs field
+ * in blkif_request_indirect should be filled by the frontend with the
+ * grant references of the pages that are holding the indirect segments.
+ * These pages are filled with an array of blkif_request_segment that hold the
+ * information about the segments. The number of indirect pages to use is
+ * determined by the number of segments an indirect request contains. Every
+ * indirect page can contain a maximum of
+ * (PAGE_SIZE / sizeof(struct blkif_request_segment)) segments, so to
+ * calculate the number of indirect pages to use we have to do
+ * ceil(indirect_segments / (PAGE_SIZE / sizeof(struct blkif_request_segment))).
+ *
+ * If a backend does not recognize BLKIF_OP_INDIRECT, it should *not*
+ * create the "feature-max-indirect-segments" node!
+ */
+#define BLKIF_OP_INDIRECT 6
+
+/*
+ * Maximum scatter/gather segments per request.
+ * This is carefully chosen so that sizeof(blkif_ring_t) <= PAGE_SIZE.
+ * NB. This could be 12 if the ring indexes weren't stored in the same page.
+ */
+#define BLKIF_MAX_SEGMENTS_PER_REQUEST 11
+
+/*
+ * Maximum number of indirect pages to use per request.
+ */
+#define BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST 8
+
+/*
+ * NB. 'first_sect' and 'last_sect' in blkif_request_segment, as well as
+ * 'sector_number' in blkif_request, blkif_request_discard and
+ * blkif_request_indirect are sector-based quantities. See the description
+ * of the "feature-large-sector-size" frontend xenbus node above for
+ * more information.
+ */
+struct blkif_request_segment {
+ grant_ref_t gref; /* reference to I/O buffer frame */
+ /* @first_sect: first sector in frame to transfer (inclusive). */
+ /* @last_sect: last sector in frame to transfer (inclusive). */
+ uint8_t first_sect, last_sect;
+};
+
+/*
+ * Starting ring element for any I/O request.
+ */
+struct blkif_request {
+ uint8_t operation; /* BLKIF_OP_??? */
+ uint8_t nr_segments; /* number of segments */
+ blkif_vdev_t handle; /* only for read/write requests */
+ uint64_t id; /* private guest value, echoed in resp */
+ blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */
+ struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+};
+typedef struct blkif_request blkif_request_t;
+
+/*
+ * Cast to this structure when blkif_request.operation == BLKIF_OP_DISCARD
+ * sizeof(struct blkif_request_discard) <= sizeof(struct blkif_request)
+ */
+struct blkif_request_discard {
+ uint8_t operation; /* BLKIF_OP_DISCARD */
+ uint8_t flag; /* BLKIF_DISCARD_SECURE or zero */
+#define BLKIF_DISCARD_SECURE (1<<0) /* ignored if discard-secure=0 */
+ blkif_vdev_t handle; /* same as for read/write requests */
+ uint64_t id; /* private guest value, echoed in resp */
+ blkif_sector_t sector_number;/* start sector idx on disk */
+ uint64_t nr_sectors; /* number of contiguous sectors to discard*/
+};
+typedef struct blkif_request_discard blkif_request_discard_t;
+
+struct blkif_request_indirect {
+ uint8_t operation; /* BLKIF_OP_INDIRECT */
+ uint8_t indirect_op; /* BLKIF_OP_{READ/WRITE} */
+ uint16_t nr_segments; /* number of segments */
+ uint64_t id; /* private guest value, echoed in resp */
+ blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */
+ blkif_vdev_t handle; /* same as for read/write requests */
+ grant_ref_t indirect_grefs[BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST];
+#ifdef __i386__
+ uint64_t pad; /* Make it 64 byte aligned on i386 */
+#endif
+};
+typedef struct blkif_request_indirect blkif_request_indirect_t;
+
+struct blkif_response {
+ uint64_t id; /* copied from request */
+ uint8_t operation; /* copied from request */
+ int16_t status; /* BLKIF_RSP_??? */
+};
+typedef struct blkif_response blkif_response_t;
+
+/*
+ * STATUS RETURN CODES.
+ */
+ /* Operation not supported (only happens on barrier writes). */
+#define BLKIF_RSP_EOPNOTSUPP -2
+ /* Operation failed for some unspecified reason (-EIO). */
+#define BLKIF_RSP_ERROR -1
+ /* Operation completed successfully. */
+#define BLKIF_RSP_OKAY 0
+
+/*
+ * Generate blkif ring structures and types.
+ */
+DEFINE_RING_TYPES(blkif, struct blkif_request, struct blkif_response);
+
+#define VDISK_CDROM 0x1
+#define VDISK_REMOVABLE 0x2
+#define VDISK_READONLY 0x4
+
+#endif /* __XEN_PUBLIC_IO_BLKIF_H__ */
diff --git a/include/hw/xen/interface/io/console.h b/include/hw/xen/interface/io/console.h
new file mode 100644
index 000000000..e2155d1cf
--- /dev/null
+++ b/include/hw/xen/interface/io/console.h
@@ -0,0 +1,46 @@
+/******************************************************************************
+ * 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
+ */
+
+#ifndef __XEN_PUBLIC_IO_CONSOLE_H__
+#define __XEN_PUBLIC_IO_CONSOLE_H__
+
+typedef uint32_t XENCONS_RING_IDX;
+
+#define MASK_XENCONS_IDX(idx, ring) ((idx) & (sizeof(ring)-1))
+
+struct xencons_interface {
+ char in[1024];
+ char out[2048];
+ XENCONS_RING_IDX in_cons, in_prod;
+ XENCONS_RING_IDX out_cons, out_prod;
+};
+
+#ifdef XEN_WANT_FLEX_CONSOLE_RING
+#include "ring.h"
+DEFINE_XEN_FLEX_RING(xencons);
+#endif
+
+#endif /* __XEN_PUBLIC_IO_CONSOLE_H__ */
diff --git a/include/hw/xen/interface/io/fbif.h b/include/hw/xen/interface/io/fbif.h
new file mode 100644
index 000000000..ea87ebec0
--- /dev/null
+++ b/include/hw/xen/interface/io/fbif.h
@@ -0,0 +1,156 @@
+/*
+ * 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>
+ */
+
+#ifndef __XEN_PUBLIC_IO_FBIF_H__
+#define __XEN_PUBLIC_IO_FBIF_H__
+
+/* Out events (frontend -> backend) */
+
+/*
+ * Out events may be sent only when requested by backend, and receipt
+ * of an unknown out event is an error.
+ */
+
+/* Event type 1 currently not used */
+/*
+ * Framebuffer update notification event
+ * Capable frontend sets feature-update in xenstore.
+ * Backend requests it by setting request-update in xenstore.
+ */
+#define XENFB_TYPE_UPDATE 2
+
+struct xenfb_update
+{
+ uint8_t type; /* XENFB_TYPE_UPDATE */
+ int32_t x; /* source x */
+ int32_t y; /* source y */
+ int32_t width; /* rect width */
+ int32_t height; /* rect height */
+};
+
+/*
+ * Framebuffer resize notification event
+ * Capable backend sets feature-resize in xenstore.
+ */
+#define XENFB_TYPE_RESIZE 3
+
+struct xenfb_resize
+{
+ uint8_t type; /* XENFB_TYPE_RESIZE */
+ int32_t width; /* width in pixels */
+ int32_t height; /* height in pixels */
+ int32_t stride; /* stride in bytes */
+ int32_t depth; /* depth in bits */
+ int32_t offset; /* offset of the framebuffer in bytes */
+};
+
+#define XENFB_OUT_EVENT_SIZE 40
+
+union xenfb_out_event
+{
+ uint8_t type;
+ struct xenfb_update update;
+ struct xenfb_resize resize;
+ char pad[XENFB_OUT_EVENT_SIZE];
+};
+
+/* In events (backend -> frontend) */
+
+/*
+ * Frontends should ignore unknown in events.
+ */
+
+/*
+ * Framebuffer refresh period advice
+ * Backend sends it to advise the frontend their preferred period of
+ * refresh. Frontends that keep the framebuffer constantly up-to-date
+ * just ignore it. Frontends that use the advice should immediately
+ * refresh the framebuffer (and send an update notification event if
+ * those have been requested), then use the update frequency to guide
+ * their periodical refreshs.
+ */
+#define XENFB_TYPE_REFRESH_PERIOD 1
+#define XENFB_NO_REFRESH 0
+
+struct xenfb_refresh_period
+{
+ uint8_t type; /* XENFB_TYPE_UPDATE_PERIOD */
+ uint32_t period; /* period of refresh, in ms,
+ * XENFB_NO_REFRESH if no refresh is needed */
+};
+
+#define XENFB_IN_EVENT_SIZE 40
+
+union xenfb_in_event
+{
+ uint8_t type;
+ struct xenfb_refresh_period refresh_period;
+ char pad[XENFB_IN_EVENT_SIZE];
+};
+
+/* shared page */
+
+#define XENFB_IN_RING_SIZE 1024
+#define XENFB_IN_RING_LEN (XENFB_IN_RING_SIZE / XENFB_IN_EVENT_SIZE)
+#define XENFB_IN_RING_OFFS 1024
+#define XENFB_IN_RING(page) \
+ ((union xenfb_in_event *)((char *)(page) + XENFB_IN_RING_OFFS))
+#define XENFB_IN_RING_REF(page, idx) \
+ (XENFB_IN_RING((page))[(idx) % XENFB_IN_RING_LEN])
+
+#define XENFB_OUT_RING_SIZE 2048
+#define XENFB_OUT_RING_LEN (XENFB_OUT_RING_SIZE / XENFB_OUT_EVENT_SIZE)
+#define XENFB_OUT_RING_OFFS (XENFB_IN_RING_OFFS + XENFB_IN_RING_SIZE)
+#define XENFB_OUT_RING(page) \
+ ((union xenfb_out_event *)((char *)(page) + XENFB_OUT_RING_OFFS))
+#define XENFB_OUT_RING_REF(page, idx) \
+ (XENFB_OUT_RING((page))[(idx) % XENFB_OUT_RING_LEN])
+
+struct xenfb_page
+{
+ uint32_t in_cons, in_prod;
+ uint32_t out_cons, out_prod;
+
+ int32_t width; /* the width of the framebuffer (in pixels) */
+ int32_t height; /* the height of the framebuffer (in pixels) */
+ uint32_t line_length; /* the length of a row of pixels (in bytes) */
+ uint32_t mem_length; /* the length of the framebuffer (in bytes) */
+ uint8_t depth; /* the depth of a pixel (in bits) */
+
+ /*
+ * Framebuffer page directory
+ *
+ * Each directory page holds PAGE_SIZE / sizeof(*pd)
+ * framebuffer pages, and can thus map up to PAGE_SIZE *
+ * PAGE_SIZE / sizeof(*pd) bytes. With PAGE_SIZE == 4096 and
+ * sizeof(unsigned long) == 4/8, that's 4 Megs 32 bit and 2 Megs
+ * 64 bit. 256 directories give enough room for a 512 Meg
+ * framebuffer with a max resolution of 12,800x10,240. Should
+ * be enough for a while with room leftover for expansion.
+ */
+ unsigned long pd[256];
+};
+
+#endif
diff --git a/include/hw/xen/interface/io/kbdif.h b/include/hw/xen/interface/io/kbdif.h
new file mode 100644
index 000000000..1d68cd458
--- /dev/null
+++ b/include/hw/xen/interface/io/kbdif.h
@@ -0,0 +1,566 @@
+/*
+ * 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>
+ */
+
+#ifndef __XEN_PUBLIC_IO_KBDIF_H__
+#define __XEN_PUBLIC_IO_KBDIF_H__
+
+/*
+ *****************************************************************************
+ * Feature and Parameter Negotiation
+ *****************************************************************************
+ *
+ * The two halves of a para-virtual driver utilize nodes within
+ * XenStore to communicate capabilities and to negotiate operating parameters.
+ * This section enumerates these nodes which reside in the respective front and
+ * backend portions of XenStore, following XenBus convention.
+ *
+ * All data in XenStore is stored as strings. Nodes specifying numeric
+ * values are encoded in decimal. Integer value ranges listed below are
+ * expressed as fixed sized integer types capable of storing the conversion
+ * of a properly formated node string, without loss of information.
+ *
+ *****************************************************************************
+ * Backend XenBus Nodes
+ *****************************************************************************
+ *
+ *---------------------------- Features supported ----------------------------
+ *
+ * Capable backend advertises supported features by publishing
+ * corresponding entries in XenStore and puts 1 as the value of the entry.
+ * If a feature is not supported then 0 must be set or feature entry omitted.
+ *
+ * feature-disable-keyboard
+ * Values: <uint>
+ *
+ * If there is no need to expose a virtual keyboard device by the
+ * frontend then this must be set to 1.
+ *
+ * feature-disable-pointer
+ * Values: <uint>
+ *
+ * If there is no need to expose a virtual pointer device by the
+ * frontend then this must be set to 1.
+ *
+ * feature-abs-pointer
+ * Values: <uint>
+ *
+ * Backends, which support reporting of absolute coordinates for pointer
+ * device should set this to 1.
+ *
+ * feature-multi-touch
+ * Values: <uint>
+ *
+ * Backends, which support reporting of multi-touch events
+ * should set this to 1.
+ *
+ * feature-raw-pointer
+ * Values: <uint>
+ *
+ * Backends, which support reporting raw (unscaled) absolute coordinates
+ * for pointer devices should set this to 1. Raw (unscaled) values have
+ * a range of [0, 0x7fff].
+ *
+ *----------------------- Device Instance Parameters ------------------------
+ *
+ * unique-id
+ * Values: <string>
+ *
+ * After device instance initialization it is assigned a unique ID,
+ * so every instance of the frontend can be identified by the backend
+ * by this ID. This can be UUID or such.
+ *
+ *------------------------- Pointer Device Parameters ------------------------
+ *
+ * width
+ * Values: <uint>
+ *
+ * Maximum X coordinate (width) to be used by the frontend
+ * while reporting input events, pixels, [0; UINT32_MAX].
+ *
+ * height
+ * Values: <uint>
+ *
+ * Maximum Y coordinate (height) to be used by the frontend
+ * while reporting input events, pixels, [0; UINT32_MAX].
+ *
+ *----------------------- Multi-touch Device Parameters ----------------------
+ *
+ * multi-touch-num-contacts
+ * Values: <uint>
+ *
+ * Number of simultaneous touches reported.
+ *
+ * multi-touch-width
+ * Values: <uint>
+ *
+ * Width of the touch area to be used by the frontend
+ * while reporting input events, pixels, [0; UINT32_MAX].
+ *
+ * multi-touch-height
+ * Values: <uint>
+ *
+ * Height of the touch area to be used by the frontend
+ * while reporting input events, pixels, [0; UINT32_MAX].
+ *
+ *****************************************************************************
+ * Frontend XenBus Nodes
+ *****************************************************************************
+ *
+ *------------------------------ Feature request -----------------------------
+ *
+ * Capable frontend requests features from backend via setting corresponding
+ * entries to 1 in XenStore. Requests for features not advertised as supported
+ * by the backend have no effect.
+ *
+ * request-abs-pointer
+ * Values: <uint>
+ *
+ * Request backend to report absolute pointer coordinates
+ * (XENKBD_TYPE_POS) instead of relative ones (XENKBD_TYPE_MOTION).
+ *
+ * request-multi-touch
+ * Values: <uint>
+ *
+ * Request backend to report multi-touch events.
+ *
+ * request-raw-pointer
+ * Values: <uint>
+ *
+ * Request backend to report raw unscaled absolute pointer coordinates.
+ * This option is only valid if request-abs-pointer is also set.
+ * Raw unscaled coordinates have the range [0, 0x7fff]
+ *
+ *----------------------- Request Transport Parameters -----------------------
+ *
+ * event-channel
+ * Values: <uint>
+ *
+ * The identifier of the Xen event channel used to signal activity
+ * in the ring buffer.
+ *
+ * page-gref
+ * Values: <uint>
+ *
+ * The Xen grant reference granting permission for the backend to map
+ * a sole page in a single page sized event ring buffer.
+ *
+ * page-ref
+ * Values: <uint>
+ *
+ * OBSOLETE, not recommended for use.
+ * PFN of the shared page.
+ */
+
+/*
+ * EVENT CODES.
+ */
+
+#define XENKBD_TYPE_MOTION 1
+#define XENKBD_TYPE_RESERVED 2
+#define XENKBD_TYPE_KEY 3
+#define XENKBD_TYPE_POS 4
+#define XENKBD_TYPE_MTOUCH 5
+
+/* Multi-touch event sub-codes */
+
+#define XENKBD_MT_EV_DOWN 0
+#define XENKBD_MT_EV_UP 1
+#define XENKBD_MT_EV_MOTION 2
+#define XENKBD_MT_EV_SYN 3
+#define XENKBD_MT_EV_SHAPE 4
+#define XENKBD_MT_EV_ORIENT 5
+
+/*
+ * CONSTANTS, XENSTORE FIELD AND PATH NAME STRINGS, HELPERS.
+ */
+
+#define XENKBD_DRIVER_NAME "vkbd"
+
+#define XENKBD_FIELD_FEAT_DSBL_KEYBRD "feature-disable-keyboard"
+#define XENKBD_FIELD_FEAT_DSBL_POINTER "feature-disable-pointer"
+#define XENKBD_FIELD_FEAT_ABS_POINTER "feature-abs-pointer"
+#define XENKBD_FIELD_FEAT_RAW_POINTER "feature-raw-pointer"
+#define XENKBD_FIELD_FEAT_MTOUCH "feature-multi-touch"
+#define XENKBD_FIELD_REQ_ABS_POINTER "request-abs-pointer"
+#define XENKBD_FIELD_REQ_RAW_POINTER "request-raw-pointer"
+#define XENKBD_FIELD_REQ_MTOUCH "request-multi-touch"
+#define XENKBD_FIELD_RING_GREF "page-gref"
+#define XENKBD_FIELD_EVT_CHANNEL "event-channel"
+#define XENKBD_FIELD_WIDTH "width"
+#define XENKBD_FIELD_HEIGHT "height"
+#define XENKBD_FIELD_MT_WIDTH "multi-touch-width"
+#define XENKBD_FIELD_MT_HEIGHT "multi-touch-height"
+#define XENKBD_FIELD_MT_NUM_CONTACTS "multi-touch-num-contacts"
+#define XENKBD_FIELD_UNIQUE_ID "unique-id"
+
+/* OBSOLETE, not recommended for use */
+#define XENKBD_FIELD_RING_REF "page-ref"
+
+/*
+ *****************************************************************************
+ * Description of the protocol between frontend and backend driver.
+ *****************************************************************************
+ *
+ * The two halves of a Para-virtual driver communicate with
+ * each other using a shared page and an event channel.
+ * Shared page contains a ring with event structures.
+ *
+ * All reserved fields in the structures below must be 0.
+ *
+ *****************************************************************************
+ * Backend to frontend events
+ *****************************************************************************
+ *
+ * Frontends should ignore unknown in events.
+ * All event packets have the same length (40 octets)
+ * All event packets have common header:
+ *
+ * 0 octet
+ * +-----------------+
+ * | type |
+ * +-----------------+
+ * type - uint8_t, event code, XENKBD_TYPE_???
+ *
+ *
+ * Pointer relative movement event
+ * 0 1 2 3 octet
+ * +----------------+----------------+----------------+----------------+
+ * | _TYPE_MOTION | reserved | 4
+ * +----------------+----------------+----------------+----------------+
+ * | rel_x | 8
+ * +----------------+----------------+----------------+----------------+
+ * | rel_y | 12
+ * +----------------+----------------+----------------+----------------+
+ * | rel_z | 16
+ * +----------------+----------------+----------------+----------------+
+ * | reserved | 20
+ * +----------------+----------------+----------------+----------------+
+ * |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/|
+ * +----------------+----------------+----------------+----------------+
+ * | reserved | 40
+ * +----------------+----------------+----------------+----------------+
+ *
+ * rel_x - int32_t, relative X motion
+ * rel_y - int32_t, relative Y motion
+ * rel_z - int32_t, relative Z motion (wheel)
+ */
+
+struct xenkbd_motion
+{
+ uint8_t type;
+ int32_t rel_x;
+ int32_t rel_y;
+ int32_t rel_z;
+};
+
+/*
+ * Key event (includes pointer buttons)
+ * 0 1 2 3 octet
+ * +----------------+----------------+----------------+----------------+
+ * | _TYPE_KEY | pressed | reserved | 4
+ * +----------------+----------------+----------------+----------------+
+ * | keycode | 8
+ * +----------------+----------------+----------------+----------------+
+ * | reserved | 12
+ * +----------------+----------------+----------------+----------------+
+ * |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/|
+ * +----------------+----------------+----------------+----------------+
+ * | reserved | 40
+ * +----------------+----------------+----------------+----------------+
+ *
+ * pressed - uint8_t, 1 if pressed; 0 otherwise
+ * keycode - uint32_t, KEY_* from linux/input.h
+ */
+
+struct xenkbd_key
+{
+ uint8_t type;
+ uint8_t pressed;
+ uint32_t keycode;
+};
+
+/*
+ * Pointer absolute position event
+ * 0 1 2 3 octet
+ * +----------------+----------------+----------------+----------------+
+ * | _TYPE_POS | reserved | 4
+ * +----------------+----------------+----------------+----------------+
+ * | abs_x | 8
+ * +----------------+----------------+----------------+----------------+
+ * | abs_y | 12
+ * +----------------+----------------+----------------+----------------+
+ * | rel_z | 16
+ * +----------------+----------------+----------------+----------------+
+ * | reserved | 20
+ * +----------------+----------------+----------------+----------------+
+ * |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/|
+ * +----------------+----------------+----------------+----------------+
+ * | reserved | 40
+ * +----------------+----------------+----------------+----------------+
+ *
+ * abs_x - int32_t, absolute X position (in FB pixels)
+ * abs_y - int32_t, absolute Y position (in FB pixels)
+ * rel_z - int32_t, relative Z motion (wheel)
+ */
+
+struct xenkbd_position
+{
+ uint8_t type;
+ int32_t abs_x;
+ int32_t abs_y;
+ int32_t rel_z;
+};
+
+/*
+ * Multi-touch event and its sub-types
+ *
+ * All multi-touch event packets have common header:
+ *
+ * 0 1 2 3 octet
+ * +----------------+----------------+----------------+----------------+
+ * | _TYPE_MTOUCH | event_type | contact_id | reserved | 4
+ * +----------------+----------------+----------------+----------------+
+ * | reserved | 8
+ * +----------------+----------------+----------------+----------------+
+ *
+ * event_type - unt8_t, multi-touch event sub-type, XENKBD_MT_EV_???
+ * contact_id - unt8_t, ID of the contact
+ *
+ * Touch interactions can consist of one or more contacts.
+ * For each contact, a series of events is generated, starting
+ * with a down event, followed by zero or more motion events,
+ * and ending with an up event. Events relating to the same
+ * contact point can be identified by the ID of the sequence: contact ID.
+ * Contact ID may be reused after XENKBD_MT_EV_UP event and
+ * is in the [0; XENKBD_FIELD_NUM_CONTACTS - 1] range.
+ *
+ * For further information please refer to documentation on Wayland [1],
+ * Linux [2] and Windows [3] multi-touch support.
+ *
+ * [1] https://cgit.freedesktop.org/wayland/wayland/tree/protocol/wayland.xml
+ * [2] https://www.kernel.org/doc/Documentation/input/multi-touch-protocol.txt
+ * [3] https://msdn.microsoft.com/en-us/library/jj151564(v=vs.85).aspx
+ *
+ *
+ * Multi-touch down event - sent when a new touch is made: touch is assigned
+ * a unique contact ID, sent with this and consequent events related
+ * to this touch.
+ * 0 1 2 3 octet
+ * +----------------+----------------+----------------+----------------+
+ * | _TYPE_MTOUCH | _MT_EV_DOWN | contact_id | reserved | 4
+ * +----------------+----------------+----------------+----------------+
+ * | reserved | 8
+ * +----------------+----------------+----------------+----------------+
+ * | abs_x | 12
+ * +----------------+----------------+----------------+----------------+
+ * | abs_y | 16
+ * +----------------+----------------+----------------+----------------+
+ * | reserved | 20
+ * +----------------+----------------+----------------+----------------+
+ * |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/|
+ * +----------------+----------------+----------------+----------------+
+ * | reserved | 40
+ * +----------------+----------------+----------------+----------------+
+ *
+ * abs_x - int32_t, absolute X position, in pixels
+ * abs_y - int32_t, absolute Y position, in pixels
+ *
+ * Multi-touch contact release event
+ * 0 1 2 3 octet
+ * +----------------+----------------+----------------+----------------+
+ * | _TYPE_MTOUCH | _MT_EV_UP | contact_id | reserved | 4
+ * +----------------+----------------+----------------+----------------+
+ * | reserved | 8
+ * +----------------+----------------+----------------+----------------+
+ * |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/|
+ * +----------------+----------------+----------------+----------------+
+ * | reserved | 40
+ * +----------------+----------------+----------------+----------------+
+ *
+ * Multi-touch motion event
+ * 0 1 2 3 octet
+ * +----------------+----------------+----------------+----------------+
+ * | _TYPE_MTOUCH | _MT_EV_MOTION | contact_id | reserved | 4
+ * +----------------+----------------+----------------+----------------+
+ * | reserved | 8
+ * +----------------+----------------+----------------+----------------+
+ * | abs_x | 12
+ * +----------------+----------------+----------------+----------------+
+ * | abs_y | 16
+ * +----------------+----------------+----------------+----------------+
+ * | reserved | 20
+ * +----------------+----------------+----------------+----------------+
+ * |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/|
+ * +----------------+----------------+----------------+----------------+
+ * | reserved | 40
+ * +----------------+----------------+----------------+----------------+
+ *
+ * abs_x - int32_t, absolute X position, in pixels,
+ * abs_y - int32_t, absolute Y position, in pixels,
+ *
+ * Multi-touch input synchronization event - shows end of a set of events
+ * which logically belong together.
+ * 0 1 2 3 octet
+ * +----------------+----------------+----------------+----------------+
+ * | _TYPE_MTOUCH | _MT_EV_SYN | contact_id | reserved | 4
+ * +----------------+----------------+----------------+----------------+
+ * | reserved | 8
+ * +----------------+----------------+----------------+----------------+
+ * |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/|
+ * +----------------+----------------+----------------+----------------+
+ * | reserved | 40
+ * +----------------+----------------+----------------+----------------+
+ *
+ * Multi-touch shape event - touch point's shape has changed its shape.
+ * Shape is approximated by an ellipse through the major and minor axis
+ * lengths: major is the longer diameter of the ellipse and minor is the
+ * shorter one. Center of the ellipse is reported via
+ * XENKBD_MT_EV_DOWN/XENKBD_MT_EV_MOTION events.
+ * 0 1 2 3 octet
+ * +----------------+----------------+----------------+----------------+
+ * | _TYPE_MTOUCH | _MT_EV_SHAPE | contact_id | reserved | 4
+ * +----------------+----------------+----------------+----------------+
+ * | reserved | 8
+ * +----------------+----------------+----------------+----------------+
+ * | major | 12
+ * +----------------+----------------+----------------+----------------+
+ * | minor | 16
+ * +----------------+----------------+----------------+----------------+
+ * | reserved | 20
+ * +----------------+----------------+----------------+----------------+
+ * |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/|
+ * +----------------+----------------+----------------+----------------+
+ * | reserved | 40
+ * +----------------+----------------+----------------+----------------+
+ *
+ * major - unt32_t, length of the major axis, pixels
+ * minor - unt32_t, length of the minor axis, pixels
+ *
+ * Multi-touch orientation event - touch point's shape has changed
+ * its orientation: calculated as a clockwise angle between the major axis
+ * of the ellipse and positive Y axis in degrees, [-180; +180].
+ * 0 1 2 3 octet
+ * +----------------+----------------+----------------+----------------+
+ * | _TYPE_MTOUCH | _MT_EV_ORIENT | contact_id | reserved | 4
+ * +----------------+----------------+----------------+----------------+
+ * | reserved | 8
+ * +----------------+----------------+----------------+----------------+
+ * | orientation | reserved | 12
+ * +----------------+----------------+----------------+----------------+
+ * | reserved | 16
+ * +----------------+----------------+----------------+----------------+
+ * |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/|
+ * +----------------+----------------+----------------+----------------+
+ * | reserved | 40
+ * +----------------+----------------+----------------+----------------+
+ *
+ * orientation - int16_t, clockwise angle of the major axis
+ */
+
+struct xenkbd_mtouch {
+ uint8_t type; /* XENKBD_TYPE_MTOUCH */
+ uint8_t event_type; /* XENKBD_MT_EV_??? */
+ uint8_t contact_id;
+ uint8_t reserved[5]; /* reserved for the future use */
+ union {
+ struct {
+ int32_t abs_x; /* absolute X position, pixels */
+ int32_t abs_y; /* absolute Y position, pixels */
+ } pos;
+ struct {
+ uint32_t major; /* length of the major axis, pixels */
+ uint32_t minor; /* length of the minor axis, pixels */
+ } shape;
+ int16_t orientation; /* clockwise angle of the major axis */
+ } u;
+};
+
+#define XENKBD_IN_EVENT_SIZE 40
+
+union xenkbd_in_event
+{
+ uint8_t type;
+ struct xenkbd_motion motion;
+ struct xenkbd_key key;
+ struct xenkbd_position pos;
+ struct xenkbd_mtouch mtouch;
+ char pad[XENKBD_IN_EVENT_SIZE];
+};
+
+/*
+ *****************************************************************************
+ * Frontend to backend events
+ *****************************************************************************
+ *
+ * Out events may be sent only when requested by backend, and receipt
+ * of an unknown out event is an error.
+ * No out events currently defined.
+
+ * All event packets have the same length (40 octets)
+ * All event packets have common header:
+ * 0 octet
+ * +-----------------+
+ * | type |
+ * +-----------------+
+ * type - uint8_t, event code
+ */
+
+#define XENKBD_OUT_EVENT_SIZE 40
+
+union xenkbd_out_event
+{
+ uint8_t type;
+ char pad[XENKBD_OUT_EVENT_SIZE];
+};
+
+/*
+ *****************************************************************************
+ * Shared page
+ *****************************************************************************
+ */
+
+#define XENKBD_IN_RING_SIZE 2048
+#define XENKBD_IN_RING_LEN (XENKBD_IN_RING_SIZE / XENKBD_IN_EVENT_SIZE)
+#define XENKBD_IN_RING_OFFS 1024
+#define XENKBD_IN_RING(page) \
+ ((union xenkbd_in_event *)((char *)(page) + XENKBD_IN_RING_OFFS))
+#define XENKBD_IN_RING_REF(page, idx) \
+ (XENKBD_IN_RING((page))[(idx) % XENKBD_IN_RING_LEN])
+
+#define XENKBD_OUT_RING_SIZE 1024
+#define XENKBD_OUT_RING_LEN (XENKBD_OUT_RING_SIZE / XENKBD_OUT_EVENT_SIZE)
+#define XENKBD_OUT_RING_OFFS (XENKBD_IN_RING_OFFS + XENKBD_IN_RING_SIZE)
+#define XENKBD_OUT_RING(page) \
+ ((union xenkbd_out_event *)((char *)(page) + XENKBD_OUT_RING_OFFS))
+#define XENKBD_OUT_RING_REF(page, idx) \
+ (XENKBD_OUT_RING((page))[(idx) % XENKBD_OUT_RING_LEN])
+
+struct xenkbd_page
+{
+ uint32_t in_cons, in_prod;
+ uint32_t out_cons, out_prod;
+};
+
+#endif /* __XEN_PUBLIC_IO_KBDIF_H__ */
diff --git a/include/hw/xen/interface/io/netif.h b/include/hw/xen/interface/io/netif.h
new file mode 100644
index 000000000..48fa53095
--- /dev/null
+++ b/include/hw/xen/interface/io/netif.h
@@ -0,0 +1,1010 @@
+/******************************************************************************
+ * 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
+ */
+
+#ifndef __XEN_PUBLIC_IO_NETIF_H__
+#define __XEN_PUBLIC_IO_NETIF_H__
+
+#include "ring.h"
+#include "../grant_table.h"
+
+/*
+ * Older implementation of Xen network frontend / backend has an
+ * implicit dependency on the MAX_SKB_FRAGS as the maximum number of
+ * ring slots a skb can use. Netfront / netback may not work as
+ * expected when frontend and backend have different MAX_SKB_FRAGS.
+ *
+ * A better approach is to add mechanism for netfront / netback to
+ * negotiate this value. However we cannot fix all possible
+ * frontends, so we need to define a value which states the minimum
+ * slots backend must support.
+ *
+ * The minimum value derives from older Linux kernel's MAX_SKB_FRAGS
+ * (18), which is proved to work with most frontends. Any new backend
+ * which doesn't negotiate with frontend should expect frontend to
+ * send a valid packet using slots up to this value.
+ */
+#define XEN_NETIF_NR_SLOTS_MIN 18
+
+/*
+ * Notifications after enqueuing any type of message should be conditional on
+ * the appropriate req_event or rsp_event field in the shared ring.
+ * If the client sends notification for rx requests then it should specify
+ * feature 'feature-rx-notify' via xenbus. Otherwise the backend will assume
+ * that it cannot safely queue packets (as it may not be kicked to send them).
+ */
+
+/*
+ * "feature-split-event-channels" is introduced to separate guest TX
+ * and RX notification. Backend either doesn't support this feature or
+ * advertises it via xenstore as 0 (disabled) or 1 (enabled).
+ *
+ * To make use of this feature, frontend should allocate two event
+ * channels for TX and RX, advertise them to backend as
+ * "event-channel-tx" and "event-channel-rx" respectively. If frontend
+ * doesn't want to use this feature, it just writes "event-channel"
+ * node as before.
+ */
+
+/*
+ * Multiple transmit and receive queues:
+ * If supported, the backend will write the key "multi-queue-max-queues" to
+ * the directory for that vif, and set its value to the maximum supported
+ * number of queues.
+ * Frontends that are aware of this feature and wish to use it can write the
+ * key "multi-queue-num-queues", set to the number they wish to use, which
+ * must be greater than zero, and no more than the value reported by the backend
+ * in "multi-queue-max-queues".
+ *
+ * Queues replicate the shared rings and event channels.
+ * "feature-split-event-channels" may optionally be used when using
+ * multiple queues, but is not mandatory.
+ *
+ * Each queue consists of one shared ring pair, i.e. there must be the same
+ * number of tx and rx rings.
+ *
+ * For frontends requesting just one queue, the usual event-channel and
+ * ring-ref keys are written as before, simplifying the backend processing
+ * to avoid distinguishing between a frontend that doesn't understand the
+ * multi-queue feature, and one that does, but requested only one queue.
+ *
+ * Frontends requesting two or more queues must not write the toplevel
+ * event-channel (or event-channel-{tx,rx}) and {tx,rx}-ring-ref keys,
+ * instead writing those keys under sub-keys having the name "queue-N" where
+ * N is the integer ID of the queue for which those keys belong. Queues
+ * are indexed from zero. For example, a frontend with two queues and split
+ * event channels must write the following set of queue-related keys:
+ *
+ * /local/domain/1/device/vif/0/multi-queue-num-queues = "2"
+ * /local/domain/1/device/vif/0/queue-0 = ""
+ * /local/domain/1/device/vif/0/queue-0/tx-ring-ref = "<ring-ref-tx0>"
+ * /local/domain/1/device/vif/0/queue-0/rx-ring-ref = "<ring-ref-rx0>"
+ * /local/domain/1/device/vif/0/queue-0/event-channel-tx = "<evtchn-tx0>"
+ * /local/domain/1/device/vif/0/queue-0/event-channel-rx = "<evtchn-rx0>"
+ * /local/domain/1/device/vif/0/queue-1 = ""
+ * /local/domain/1/device/vif/0/queue-1/tx-ring-ref = "<ring-ref-tx1>"
+ * /local/domain/1/device/vif/0/queue-1/rx-ring-ref = "<ring-ref-rx1"
+ * /local/domain/1/device/vif/0/queue-1/event-channel-tx = "<evtchn-tx1>"
+ * /local/domain/1/device/vif/0/queue-1/event-channel-rx = "<evtchn-rx1>"
+ *
+ * If there is any inconsistency in the XenStore data, the backend may
+ * choose not to connect any queues, instead treating the request as an
+ * error. This includes scenarios where more (or fewer) queues were
+ * requested than the frontend provided details for.
+ *
+ * Mapping of packets to queues is considered to be a function of the
+ * transmitting system (backend or frontend) and is not negotiated
+ * between the two. Guests are free to transmit packets on any queue
+ * they choose, provided it has been set up correctly. Guests must be
+ * prepared to receive packets on any queue they have requested be set up.
+ */
+
+/*
+ * "feature-no-csum-offload" should be used to turn IPv4 TCP/UDP checksum
+ * offload off or on. If it is missing then the feature is assumed to be on.
+ * "feature-ipv6-csum-offload" should be used to turn IPv6 TCP/UDP checksum
+ * offload on or off. If it is missing then the feature is assumed to be off.
+ */
+
+/*
+ * "feature-gso-tcpv4" and "feature-gso-tcpv6" advertise the capability to
+ * handle large TCP packets (in IPv4 or IPv6 form respectively). Neither
+ * frontends nor backends are assumed to be capable unless the flags are
+ * present.
+ */
+
+/*
+ * "feature-multicast-control" and "feature-dynamic-multicast-control"
+ * advertise the capability to filter ethernet multicast packets in the
+ * backend. If the frontend wishes to take advantage of this feature then
+ * it may set "request-multicast-control". If the backend only advertises
+ * "feature-multicast-control" then "request-multicast-control" must be set
+ * before the frontend moves into the connected state. The backend will
+ * sample the value on this state transition and any subsequent change in
+ * value will have no effect. However, if the backend also advertises
+ * "feature-dynamic-multicast-control" then "request-multicast-control"
+ * may be set by the frontend at any time. In this case, the backend will
+ * watch the value and re-sample on watch events.
+ *
+ * If the sampled value of "request-multicast-control" is set then the
+ * backend transmit side should no longer flood multicast packets to the
+ * frontend, it should instead drop any multicast packet that does not
+ * match in a filter list.
+ * The list is amended by the frontend by sending dummy transmit requests
+ * containing XEN_NETIF_EXTRA_TYPE_MCAST_{ADD,DEL} extra-info fragments as
+ * specified below.
+ * Note that the filter list may be amended even if the sampled value of
+ * "request-multicast-control" is not set, however the filter should only
+ * be applied if it is set.
+ */
+
+/*
+ * Control ring
+ * ============
+ *
+ * Some features, such as hashing (detailed below), require a
+ * significant amount of out-of-band data to be passed from frontend to
+ * backend. Use of xenstore is not suitable for large quantities of data
+ * because of quota limitations and so a dedicated 'control ring' is used.
+ * The ability of the backend to use a control ring is advertised by
+ * setting:
+ *
+ * /local/domain/X/backend/<domid>/<vif>/feature-ctrl-ring = "1"
+ *
+ * The frontend provides a control ring to the backend by setting:
+ *
+ * /local/domain/<domid>/device/vif/<vif>/ctrl-ring-ref = <gref>
+ * /local/domain/<domid>/device/vif/<vif>/event-channel-ctrl = <port>
+ *
+ * where <gref> is the grant reference of the shared page used to
+ * implement the control ring and <port> is an event channel to be used
+ * as a mailbox interrupt. These keys must be set before the frontend
+ * moves into the connected state.
+ *
+ * The control ring uses a fixed request/response message size and is
+ * balanced (i.e. one request to one response), so operationally it is much
+ * the same as a transmit or receive ring.
+ * Note that there is no requirement that responses are issued in the same
+ * order as requests.
+ */
+
+/*
+ * Hash types
+ * ==========
+ *
+ * For the purposes of the definitions below, 'Packet[]' is an array of
+ * octets containing an IP packet without options, 'Array[X..Y]' means a
+ * sub-array of 'Array' containing bytes X thru Y inclusive, and '+' is
+ * used to indicate concatenation of arrays.
+ */
+
+/*
+ * A hash calculated over an IP version 4 header as follows:
+ *
+ * Buffer[0..8] = Packet[12..15] (source address) +
+ * Packet[16..19] (destination address)
+ *
+ * Result = Hash(Buffer, 8)
+ */
+#define _XEN_NETIF_CTRL_HASH_TYPE_IPV4 0
+#define XEN_NETIF_CTRL_HASH_TYPE_IPV4 \
+ (1 << _XEN_NETIF_CTRL_HASH_TYPE_IPV4)
+
+/*
+ * A hash calculated over an IP version 4 header and TCP header as
+ * follows:
+ *
+ * Buffer[0..12] = Packet[12..15] (source address) +
+ * Packet[16..19] (destination address) +
+ * Packet[20..21] (source port) +
+ * Packet[22..23] (destination port)
+ *
+ * Result = Hash(Buffer, 12)
+ */
+#define _XEN_NETIF_CTRL_HASH_TYPE_IPV4_TCP 1
+#define XEN_NETIF_CTRL_HASH_TYPE_IPV4_TCP \
+ (1 << _XEN_NETIF_CTRL_HASH_TYPE_IPV4_TCP)
+
+/*
+ * A hash calculated over an IP version 6 header as follows:
+ *
+ * Buffer[0..32] = Packet[8..23] (source address ) +
+ * Packet[24..39] (destination address)
+ *
+ * Result = Hash(Buffer, 32)
+ */
+#define _XEN_NETIF_CTRL_HASH_TYPE_IPV6 2
+#define XEN_NETIF_CTRL_HASH_TYPE_IPV6 \
+ (1 << _XEN_NETIF_CTRL_HASH_TYPE_IPV6)
+
+/*
+ * A hash calculated over an IP version 6 header and TCP header as
+ * follows:
+ *
+ * Buffer[0..36] = Packet[8..23] (source address) +
+ * Packet[24..39] (destination address) +
+ * Packet[40..41] (source port) +
+ * Packet[42..43] (destination port)
+ *
+ * Result = Hash(Buffer, 36)
+ */
+#define _XEN_NETIF_CTRL_HASH_TYPE_IPV6_TCP 3
+#define XEN_NETIF_CTRL_HASH_TYPE_IPV6_TCP \
+ (1 << _XEN_NETIF_CTRL_HASH_TYPE_IPV6_TCP)
+
+/*
+ * Hash algorithms
+ * ===============
+ */
+
+#define XEN_NETIF_CTRL_HASH_ALGORITHM_NONE 0
+
+/*
+ * Toeplitz hash:
+ */
+
+#define XEN_NETIF_CTRL_HASH_ALGORITHM_TOEPLITZ 1
+
+/*
+ * Control requests (struct xen_netif_ctrl_request)
+ * ================================================
+ *
+ * All requests have the following format:
+ *
+ * 0 1 2 3 4 5 6 7 octet
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | id | type | data[0] |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | data[1] | data[2] |
+ * +-----+-----+-----+-----+-----------------------+
+ *
+ * id: the request identifier, echoed in response.
+ * type: the type of request (see below)
+ * data[]: any data associated with the request (determined by type)
+ */
+
+struct xen_netif_ctrl_request {
+ uint16_t id;
+ uint16_t type;
+
+#define XEN_NETIF_CTRL_TYPE_INVALID 0
+#define XEN_NETIF_CTRL_TYPE_GET_HASH_FLAGS 1
+#define XEN_NETIF_CTRL_TYPE_SET_HASH_FLAGS 2
+#define XEN_NETIF_CTRL_TYPE_SET_HASH_KEY 3
+#define XEN_NETIF_CTRL_TYPE_GET_HASH_MAPPING_SIZE 4
+#define XEN_NETIF_CTRL_TYPE_SET_HASH_MAPPING_SIZE 5
+#define XEN_NETIF_CTRL_TYPE_SET_HASH_MAPPING 6
+#define XEN_NETIF_CTRL_TYPE_SET_HASH_ALGORITHM 7
+#define XEN_NETIF_CTRL_TYPE_GET_GREF_MAPPING_SIZE 8
+#define XEN_NETIF_CTRL_TYPE_ADD_GREF_MAPPING 9
+#define XEN_NETIF_CTRL_TYPE_DEL_GREF_MAPPING 10
+
+ uint32_t data[3];
+};
+
+/*
+ * Control responses (struct xen_netif_ctrl_response)
+ * ==================================================
+ *
+ * All responses have the following format:
+ *
+ * 0 1 2 3 4 5 6 7 octet
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | id | type | status |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | data |
+ * +-----+-----+-----+-----+
+ *
+ * id: the corresponding request identifier
+ * type: the type of the corresponding request
+ * status: the status of request processing
+ * data: any data associated with the response (determined by type and
+ * status)
+ */
+
+struct xen_netif_ctrl_response {
+ uint16_t id;
+ uint16_t type;
+ uint32_t status;
+
+#define XEN_NETIF_CTRL_STATUS_SUCCESS 0
+#define XEN_NETIF_CTRL_STATUS_NOT_SUPPORTED 1
+#define XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER 2
+#define XEN_NETIF_CTRL_STATUS_BUFFER_OVERFLOW 3
+
+ uint32_t data;
+};
+
+/*
+ * Static Grants (struct xen_netif_gref)
+ * =====================================
+ *
+ * A frontend may provide a fixed set of grant references to be mapped on
+ * the backend. The message of type XEN_NETIF_CTRL_TYPE_ADD_GREF_MAPPING
+ * prior its usage in the command ring allows for creation of these mappings.
+ * The backend will maintain a fixed amount of these mappings.
+ *
+ * XEN_NETIF_CTRL_TYPE_GET_GREF_MAPPING_SIZE lets a frontend query how many
+ * of these mappings can be kept.
+ *
+ * Each entry in the XEN_NETIF_CTRL_TYPE_{ADD,DEL}_GREF_MAPPING input table has
+ * the following format:
+ *
+ * 0 1 2 3 4 5 6 7 octet
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | grant ref | flags | status |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ *
+ * grant ref: grant reference (IN)
+ * flags: flags describing the control operation (IN)
+ * status: XEN_NETIF_CTRL_STATUS_* (OUT)
+ *
+ * 'status' is an output parameter which does not require to be set to zero
+ * prior to its usage in the corresponding control messages.
+ */
+
+struct xen_netif_gref {
+ grant_ref_t ref;
+ uint16_t flags;
+
+#define _XEN_NETIF_CTRLF_GREF_readonly 0
+#define XEN_NETIF_CTRLF_GREF_readonly (1U<<_XEN_NETIF_CTRLF_GREF_readonly)
+
+ uint16_t status;
+};
+
+/*
+ * Control messages
+ * ================
+ *
+ * XEN_NETIF_CTRL_TYPE_SET_HASH_ALGORITHM
+ * --------------------------------------
+ *
+ * This is sent by the frontend to set the desired hash algorithm.
+ *
+ * Request:
+ *
+ * type = XEN_NETIF_CTRL_TYPE_SET_HASH_ALGORITHM
+ * data[0] = a XEN_NETIF_CTRL_HASH_ALGORITHM_* value
+ * data[1] = 0
+ * data[2] = 0
+ *
+ * Response:
+ *
+ * status = XEN_NETIF_CTRL_STATUS_NOT_SUPPORTED - Operation not
+ * supported
+ * XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER - The algorithm is not
+ * supported
+ * XEN_NETIF_CTRL_STATUS_SUCCESS - Operation successful
+ *
+ * NOTE: Setting data[0] to XEN_NETIF_CTRL_HASH_ALGORITHM_NONE disables
+ * hashing and the backend is free to choose how it steers packets
+ * to queues (which is the default behaviour).
+ *
+ * XEN_NETIF_CTRL_TYPE_GET_HASH_FLAGS
+ * ----------------------------------
+ *
+ * This is sent by the frontend to query the types of hash supported by
+ * the backend.
+ *
+ * Request:
+ *
+ * type = XEN_NETIF_CTRL_TYPE_GET_HASH_FLAGS
+ * data[0] = 0
+ * data[1] = 0
+ * data[2] = 0
+ *
+ * Response:
+ *
+ * status = XEN_NETIF_CTRL_STATUS_NOT_SUPPORTED - Operation not supported
+ * XEN_NETIF_CTRL_STATUS_SUCCESS - Operation successful
+ * data = supported hash types (if operation was successful)
+ *
+ * NOTE: A valid hash algorithm must be selected before this operation can
+ * succeed.
+ *
+ * XEN_NETIF_CTRL_TYPE_SET_HASH_FLAGS
+ * ----------------------------------
+ *
+ * This is sent by the frontend to set the types of hash that the backend
+ * should calculate. (See above for hash type definitions).
+ * Note that the 'maximal' type of hash should always be chosen. For
+ * example, if the frontend sets both IPV4 and IPV4_TCP hash types then
+ * the latter hash type should be calculated for any TCP packet and the
+ * former only calculated for non-TCP packets.
+ *
+ * Request:
+ *
+ * type = XEN_NETIF_CTRL_TYPE_SET_HASH_FLAGS
+ * data[0] = bitwise OR of XEN_NETIF_CTRL_HASH_TYPE_* values
+ * data[1] = 0
+ * data[2] = 0
+ *
+ * Response:
+ *
+ * status = XEN_NETIF_CTRL_STATUS_NOT_SUPPORTED - Operation not
+ * supported
+ * XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER - One or more flag
+ * value is invalid or
+ * unsupported
+ * XEN_NETIF_CTRL_STATUS_SUCCESS - Operation successful
+ * data = 0
+ *
+ * NOTE: A valid hash algorithm must be selected before this operation can
+ * succeed.
+ * Also, setting data[0] to zero disables hashing and the backend
+ * is free to choose how it steers packets to queues.
+ *
+ * XEN_NETIF_CTRL_TYPE_SET_HASH_KEY
+ * --------------------------------
+ *
+ * This is sent by the frontend to set the key of the hash if the algorithm
+ * requires it. (See hash algorithms above).
+ *
+ * Request:
+ *
+ * type = XEN_NETIF_CTRL_TYPE_SET_HASH_KEY
+ * data[0] = grant reference of page containing the key (assumed to
+ * start at beginning of grant)
+ * data[1] = size of key in octets
+ * data[2] = 0
+ *
+ * Response:
+ *
+ * status = XEN_NETIF_CTRL_STATUS_NOT_SUPPORTED - Operation not
+ * supported
+ * XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER - Key size is invalid
+ * XEN_NETIF_CTRL_STATUS_BUFFER_OVERFLOW - Key size is larger
+ * than the backend
+ * supports
+ * XEN_NETIF_CTRL_STATUS_SUCCESS - Operation successful
+ * data = 0
+ *
+ * NOTE: Any key octets not specified are assumed to be zero (the key
+ * is assumed to be empty by default) and specifying a new key
+ * invalidates any previous key, hence specifying a key size of
+ * zero will clear the key (which ensures that the calculated hash
+ * will always be zero).
+ * The maximum size of key is algorithm and backend specific, but
+ * is also limited by the single grant reference.
+ * The grant reference may be read-only and must remain valid until
+ * the response has been processed.
+ *
+ * XEN_NETIF_CTRL_TYPE_GET_HASH_MAPPING_SIZE
+ * -----------------------------------------
+ *
+ * This is sent by the frontend to query the maximum size of mapping
+ * table supported by the backend. The size is specified in terms of
+ * table entries.
+ *
+ * Request:
+ *
+ * type = XEN_NETIF_CTRL_TYPE_GET_HASH_MAPPING_SIZE
+ * data[0] = 0
+ * data[1] = 0
+ * data[2] = 0
+ *
+ * Response:
+ *
+ * status = XEN_NETIF_CTRL_STATUS_NOT_SUPPORTED - Operation not supported
+ * XEN_NETIF_CTRL_STATUS_SUCCESS - Operation successful
+ * data = maximum number of entries allowed in the mapping table
+ * (if operation was successful) or zero if a mapping table is
+ * not supported (i.e. hash mapping is done only by modular
+ * arithmetic).
+ *
+ * XEN_NETIF_CTRL_TYPE_SET_HASH_MAPPING_SIZE
+ * -------------------------------------
+ *
+ * This is sent by the frontend to set the actual size of the mapping
+ * table to be used by the backend. The size is specified in terms of
+ * table entries.
+ * Any previous table is invalidated by this message and any new table
+ * is assumed to be zero filled.
+ *
+ * Request:
+ *
+ * type = XEN_NETIF_CTRL_TYPE_SET_HASH_MAPPING_SIZE
+ * data[0] = number of entries in mapping table
+ * data[1] = 0
+ * data[2] = 0
+ *
+ * Response:
+ *
+ * status = XEN_NETIF_CTRL_STATUS_NOT_SUPPORTED - Operation not
+ * supported
+ * XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER - Table size is invalid
+ * XEN_NETIF_CTRL_STATUS_SUCCESS - Operation successful
+ * data = 0
+ *
+ * NOTE: Setting data[0] to 0 means that hash mapping should be done
+ * using modular arithmetic.
+ *
+ * XEN_NETIF_CTRL_TYPE_SET_HASH_MAPPING
+ * ------------------------------------
+ *
+ * This is sent by the frontend to set the content of the table mapping
+ * hash value to queue number. The backend should calculate the hash from
+ * the packet header, use it as an index into the table (modulo the size
+ * of the table) and then steer the packet to the queue number found at
+ * that index.
+ *
+ * Request:
+ *
+ * type = XEN_NETIF_CTRL_TYPE_SET_HASH_MAPPING
+ * data[0] = grant reference of page containing the mapping (sub-)table
+ * (assumed to start at beginning of grant)
+ * data[1] = size of (sub-)table in entries
+ * data[2] = offset, in entries, of sub-table within overall table
+ *
+ * Response:
+ *
+ * status = XEN_NETIF_CTRL_STATUS_NOT_SUPPORTED - Operation not
+ * supported
+ * XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER - Table size or content
+ * is invalid
+ * XEN_NETIF_CTRL_STATUS_BUFFER_OVERFLOW - Table size is larger
+ * than the backend
+ * supports
+ * XEN_NETIF_CTRL_STATUS_SUCCESS - Operation successful
+ * data = 0
+ *
+ * NOTE: The overall table has the following format:
+ *
+ * 0 1 2 3 4 5 6 7 octet
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | mapping[0] | mapping[1] |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | . |
+ * | . |
+ * | . |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | mapping[N-2] | mapping[N-1] |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ *
+ * where N is specified by a XEN_NETIF_CTRL_TYPE_SET_HASH_MAPPING_SIZE
+ * message and each mapping must specifies a queue between 0 and
+ * "multi-queue-num-queues" (see above).
+ * The backend may support a mapping table larger than can be
+ * mapped by a single grant reference. Thus sub-tables within a
+ * larger table can be individually set by sending multiple messages
+ * with differing offset values. Specifying a new sub-table does not
+ * invalidate any table data outside that range.
+ * The grant reference may be read-only and must remain valid until
+ * the response has been processed.
+ *
+ * XEN_NETIF_CTRL_TYPE_GET_GREF_MAPPING_SIZE
+ * -----------------------------------------
+ *
+ * This is sent by the frontend to fetch the number of grefs that can be kept
+ * mapped in the backend.
+ *
+ * Request:
+ *
+ * type = XEN_NETIF_CTRL_TYPE_GET_GREF_MAPPING_SIZE
+ * data[0] = queue index (assumed 0 for single queue)
+ * data[1] = 0
+ * data[2] = 0
+ *
+ * Response:
+ *
+ * status = XEN_NETIF_CTRL_STATUS_NOT_SUPPORTED - Operation not
+ * supported
+ * XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER - The queue index is
+ * out of range
+ * XEN_NETIF_CTRL_STATUS_SUCCESS - Operation successful
+ * data = maximum number of entries allowed in the gref mapping table
+ * (if operation was successful) or zero if it is not supported.
+ *
+ * XEN_NETIF_CTRL_TYPE_ADD_GREF_MAPPING
+ * ------------------------------------
+ *
+ * This is sent by the frontend for backend to map a list of grant
+ * references.
+ *
+ * Request:
+ *
+ * type = XEN_NETIF_CTRL_TYPE_ADD_GREF_MAPPING
+ * data[0] = queue index
+ * data[1] = grant reference of page containing the mapping list
+ * (r/w and assumed to start at beginning of page)
+ * data[2] = size of list in entries
+ *
+ * Response:
+ *
+ * status = XEN_NETIF_CTRL_STATUS_NOT_SUPPORTED - Operation not
+ * supported
+ * XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER - Operation failed
+ * XEN_NETIF_CTRL_STATUS_SUCCESS - Operation successful
+ *
+ * NOTE: Each entry in the input table has the format outlined
+ * in struct xen_netif_gref.
+ * Contrary to XEN_NETIF_CTRL_TYPE_DEL_GREF_MAPPING, the struct
+ * xen_netif_gref 'status' field is not used and therefore the response
+ * 'status' determines the success of this operation. In case of
+ * failure none of grants mappings get added in the backend.
+ *
+ * XEN_NETIF_CTRL_TYPE_DEL_GREF_MAPPING
+ * ------------------------------------
+ *
+ * This is sent by the frontend for backend to unmap a list of grant
+ * references.
+ *
+ * Request:
+ *
+ * type = XEN_NETIF_CTRL_TYPE_DEL_GREF_MAPPING
+ * data[0] = queue index
+ * data[1] = grant reference of page containing the mapping list
+ * (r/w and assumed to start at beginning of page)
+ * data[2] = size of list in entries
+ *
+ * Response:
+ *
+ * status = XEN_NETIF_CTRL_STATUS_NOT_SUPPORTED - Operation not
+ * supported
+ * XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER - Operation failed
+ * XEN_NETIF_CTRL_STATUS_SUCCESS - Operation successful
+ * data = number of entries that were unmapped
+ *
+ * NOTE: Each entry in the input table has the format outlined in struct
+ * xen_netif_gref.
+ * The struct xen_netif_gref 'status' field determines if the entry
+ * was successfully removed.
+ * The entries used are only the ones representing grant references that
+ * were previously the subject of a XEN_NETIF_CTRL_TYPE_ADD_GREF_MAPPING
+ * operation. Any other entries will have their status set to
+ * XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER upon completion.
+ */
+
+DEFINE_RING_TYPES(xen_netif_ctrl,
+ struct xen_netif_ctrl_request,
+ struct xen_netif_ctrl_response);
+
+/*
+ * Guest transmit
+ * ==============
+ *
+ * This is the 'wire' format for transmit (frontend -> backend) packets:
+ *
+ * Fragment 1: netif_tx_request_t - flags = NETTXF_*
+ * size = total packet size
+ * [Extra 1: netif_extra_info_t] - (only if fragment 1 flags include
+ * NETTXF_extra_info)
+ * ...
+ * [Extra N: netif_extra_info_t] - (only if extra N-1 flags include
+ * XEN_NETIF_EXTRA_MORE)
+ * ...
+ * Fragment N: netif_tx_request_t - (only if fragment N-1 flags include
+ * NETTXF_more_data - flags on preceding
+ * extras are not relevant here)
+ * flags = 0
+ * size = fragment size
+ *
+ * NOTE:
+ *
+ * This format slightly is different from that used for receive
+ * (backend -> frontend) packets. Specifically, in a multi-fragment
+ * packet the actual size of fragment 1 can only be determined by
+ * subtracting the sizes of fragments 2..N from the total packet size.
+ *
+ * Ring slot size is 12 octets, however not all request/response
+ * structs use the full size.
+ *
+ * tx request data (netif_tx_request_t)
+ * ------------------------------------
+ *
+ * 0 1 2 3 4 5 6 7 octet
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | grant ref | offset | flags |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | id | size |
+ * +-----+-----+-----+-----+
+ *
+ * grant ref: Reference to buffer page.
+ * offset: Offset within buffer page.
+ * flags: NETTXF_*.
+ * id: request identifier, echoed in response.
+ * size: packet size in bytes.
+ *
+ * tx response (netif_tx_response_t)
+ * ---------------------------------
+ *
+ * 0 1 2 3 4 5 6 7 octet
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | id | status | unused |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | unused |
+ * +-----+-----+-----+-----+
+ *
+ * id: reflects id in transmit request
+ * status: NETIF_RSP_*
+ *
+ * Guest receive
+ * =============
+ *
+ * This is the 'wire' format for receive (backend -> frontend) packets:
+ *
+ * Fragment 1: netif_rx_request_t - flags = NETRXF_*
+ * size = fragment size
+ * [Extra 1: netif_extra_info_t] - (only if fragment 1 flags include
+ * NETRXF_extra_info)
+ * ...
+ * [Extra N: netif_extra_info_t] - (only if extra N-1 flags include
+ * XEN_NETIF_EXTRA_MORE)
+ * ...
+ * Fragment N: netif_rx_request_t - (only if fragment N-1 flags include
+ * NETRXF_more_data - flags on preceding
+ * extras are not relevant here)
+ * flags = 0
+ * size = fragment size
+ *
+ * NOTE:
+ *
+ * This format slightly is different from that used for transmit
+ * (frontend -> backend) packets. Specifically, in a multi-fragment
+ * packet the size of the packet can only be determined by summing the
+ * sizes of fragments 1..N.
+ *
+ * Ring slot size is 8 octets.
+ *
+ * rx request (netif_rx_request_t)
+ * -------------------------------
+ *
+ * 0 1 2 3 4 5 6 7 octet
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | id | pad | gref |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ *
+ * id: request identifier, echoed in response.
+ * gref: reference to incoming granted frame.
+ *
+ * rx response (netif_rx_response_t)
+ * ---------------------------------
+ *
+ * 0 1 2 3 4 5 6 7 octet
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | id | offset | flags | status |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ *
+ * id: reflects id in receive request
+ * offset: offset in page of start of received packet
+ * flags: NETRXF_*
+ * status: -ve: NETIF_RSP_*; +ve: Rx'ed pkt size.
+ *
+ * NOTE: Historically, to support GSO on the frontend receive side, Linux
+ * netfront does not make use of the rx response id (because, as
+ * described below, extra info structures overlay the id field).
+ * Instead it assumes that responses always appear in the same ring
+ * slot as their corresponding request. Thus, to maintain
+ * compatibility, backends must make sure this is the case.
+ *
+ * Extra Info
+ * ==========
+ *
+ * Can be present if initial request or response has NET{T,R}XF_extra_info,
+ * or previous extra request has XEN_NETIF_EXTRA_MORE.
+ *
+ * The struct therefore needs to fit into either a tx or rx slot and
+ * is therefore limited to 8 octets.
+ *
+ * NOTE: Because extra info data overlays the usual request/response
+ * structures, there is no id information in the opposite direction.
+ * So, if an extra info overlays an rx response the frontend can
+ * assume that it is in the same ring slot as the request that was
+ * consumed to make the slot available, and the backend must ensure
+ * this assumption is true.
+ *
+ * extra info (netif_extra_info_t)
+ * -------------------------------
+ *
+ * General format:
+ *
+ * 0 1 2 3 4 5 6 7 octet
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * |type |flags| type specific data |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | padding for tx |
+ * +-----+-----+-----+-----+
+ *
+ * type: XEN_NETIF_EXTRA_TYPE_*
+ * flags: XEN_NETIF_EXTRA_FLAG_*
+ * padding for tx: present only in the tx case due to 8 octet limit
+ * from rx case. Not shown in type specific entries
+ * below.
+ *
+ * XEN_NETIF_EXTRA_TYPE_GSO:
+ *
+ * 0 1 2 3 4 5 6 7 octet
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * |type |flags| size |type | pad | features |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ *
+ * type: Must be XEN_NETIF_EXTRA_TYPE_GSO
+ * flags: XEN_NETIF_EXTRA_FLAG_*
+ * size: Maximum payload size of each segment. For example,
+ * for TCP this is just the path MSS.
+ * type: XEN_NETIF_GSO_TYPE_*: This determines the protocol of
+ * the packet and any extra features required to segment the
+ * packet properly.
+ * features: EN_NETIF_GSO_FEAT_*: This specifies any extra GSO
+ * features required to process this packet, such as ECN
+ * support for TCPv4.
+ *
+ * XEN_NETIF_EXTRA_TYPE_MCAST_{ADD,DEL}:
+ *
+ * 0 1 2 3 4 5 6 7 octet
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * |type |flags| addr |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ *
+ * type: Must be XEN_NETIF_EXTRA_TYPE_MCAST_{ADD,DEL}
+ * flags: XEN_NETIF_EXTRA_FLAG_*
+ * addr: address to add/remove
+ *
+ * XEN_NETIF_EXTRA_TYPE_HASH:
+ *
+ * A backend that supports teoplitz hashing is assumed to accept
+ * this type of extra info in transmit packets.
+ * A frontend that enables hashing is assumed to accept
+ * this type of extra info in receive packets.
+ *
+ * 0 1 2 3 4 5 6 7 octet
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * |type |flags|htype| alg |LSB ---- value ---- MSB|
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ *
+ * type: Must be XEN_NETIF_EXTRA_TYPE_HASH
+ * flags: XEN_NETIF_EXTRA_FLAG_*
+ * htype: Hash type (one of _XEN_NETIF_CTRL_HASH_TYPE_* - see above)
+ * alg: The algorithm used to calculate the hash (one of
+ * XEN_NETIF_CTRL_HASH_TYPE_ALGORITHM_* - see above)
+ * value: Hash value
+ */
+
+/* Protocol checksum field is blank in the packet (hardware offload)? */
+#define _NETTXF_csum_blank (0)
+#define NETTXF_csum_blank (1U<<_NETTXF_csum_blank)
+
+/* Packet data has been validated against protocol checksum. */
+#define _NETTXF_data_validated (1)
+#define NETTXF_data_validated (1U<<_NETTXF_data_validated)
+
+/* Packet continues in the next request descriptor. */
+#define _NETTXF_more_data (2)
+#define NETTXF_more_data (1U<<_NETTXF_more_data)
+
+/* Packet to be followed by extra descriptor(s). */
+#define _NETTXF_extra_info (3)
+#define NETTXF_extra_info (1U<<_NETTXF_extra_info)
+
+#define XEN_NETIF_MAX_TX_SIZE 0xFFFF
+struct netif_tx_request {
+ grant_ref_t gref;
+ uint16_t offset;
+ uint16_t flags;
+ uint16_t id;
+ uint16_t size;
+};
+typedef struct netif_tx_request netif_tx_request_t;
+
+/* Types of netif_extra_info descriptors. */
+#define XEN_NETIF_EXTRA_TYPE_NONE (0) /* Never used - invalid */
+#define XEN_NETIF_EXTRA_TYPE_GSO (1) /* u.gso */
+#define XEN_NETIF_EXTRA_TYPE_MCAST_ADD (2) /* u.mcast */
+#define XEN_NETIF_EXTRA_TYPE_MCAST_DEL (3) /* u.mcast */
+#define XEN_NETIF_EXTRA_TYPE_HASH (4) /* u.hash */
+#define XEN_NETIF_EXTRA_TYPE_MAX (5)
+
+/* netif_extra_info_t flags. */
+#define _XEN_NETIF_EXTRA_FLAG_MORE (0)
+#define XEN_NETIF_EXTRA_FLAG_MORE (1U<<_XEN_NETIF_EXTRA_FLAG_MORE)
+
+/* GSO types */
+#define XEN_NETIF_GSO_TYPE_NONE (0)
+#define XEN_NETIF_GSO_TYPE_TCPV4 (1)
+#define XEN_NETIF_GSO_TYPE_TCPV6 (2)
+
+/*
+ * This structure needs to fit within both netif_tx_request_t and
+ * netif_rx_response_t for compatibility.
+ */
+struct netif_extra_info {
+ uint8_t type;
+ uint8_t flags;
+ union {
+ struct {
+ uint16_t size;
+ uint8_t type;
+ uint8_t pad;
+ uint16_t features;
+ } gso;
+ struct {
+ uint8_t addr[6];
+ } mcast;
+ struct {
+ uint8_t type;
+ uint8_t algorithm;
+ uint8_t value[4];
+ } hash;
+ uint16_t pad[3];
+ } u;
+};
+typedef struct netif_extra_info netif_extra_info_t;
+
+struct netif_tx_response {
+ uint16_t id;
+ int16_t status;
+};
+typedef struct netif_tx_response netif_tx_response_t;
+
+struct netif_rx_request {
+ uint16_t id; /* Echoed in response message. */
+ uint16_t pad;
+ grant_ref_t gref;
+};
+typedef struct netif_rx_request netif_rx_request_t;
+
+/* Packet data has been validated against protocol checksum. */
+#define _NETRXF_data_validated (0)
+#define NETRXF_data_validated (1U<<_NETRXF_data_validated)
+
+/* Protocol checksum field is blank in the packet (hardware offload)? */
+#define _NETRXF_csum_blank (1)
+#define NETRXF_csum_blank (1U<<_NETRXF_csum_blank)
+
+/* Packet continues in the next request descriptor. */
+#define _NETRXF_more_data (2)
+#define NETRXF_more_data (1U<<_NETRXF_more_data)
+
+/* Packet to be followed by extra descriptor(s). */
+#define _NETRXF_extra_info (3)
+#define NETRXF_extra_info (1U<<_NETRXF_extra_info)
+
+/* Packet has GSO prefix. Deprecated but included for compatibility */
+#define _NETRXF_gso_prefix (4)
+#define NETRXF_gso_prefix (1U<<_NETRXF_gso_prefix)
+
+struct netif_rx_response {
+ uint16_t id;
+ uint16_t offset;
+ uint16_t flags;
+ int16_t status;
+};
+typedef struct netif_rx_response netif_rx_response_t;
+
+/*
+ * Generate netif ring structures and types.
+ */
+
+DEFINE_RING_TYPES(netif_tx, struct netif_tx_request, struct netif_tx_response);
+DEFINE_RING_TYPES(netif_rx, struct netif_rx_request, struct netif_rx_response);
+
+#define NETIF_RSP_DROPPED -2
+#define NETIF_RSP_ERROR -1
+#define NETIF_RSP_OKAY 0
+/* No response: used for auxiliary requests (e.g., netif_extra_info_t). */
+#define NETIF_RSP_NULL 1
+
+#endif
diff --git a/include/hw/xen/interface/io/protocols.h b/include/hw/xen/interface/io/protocols.h
new file mode 100644
index 000000000..52b4de0f8
--- /dev/null
+++ b/include/hw/xen/interface/io/protocols.h
@@ -0,0 +1,42 @@
+/******************************************************************************
+ * 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
+ */
+
+#ifndef __XEN_PROTOCOLS_H__
+#define __XEN_PROTOCOLS_H__
+
+#define XEN_IO_PROTO_ABI_X86_32 "x86_32-abi"
+#define XEN_IO_PROTO_ABI_X86_64 "x86_64-abi"
+#define XEN_IO_PROTO_ABI_ARM "arm-abi"
+
+#if defined(__i386__)
+# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_32
+#elif defined(__x86_64__)
+# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_64
+#elif defined(__arm__) || defined(__aarch64__)
+# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_ARM
+#else
+# error arch fixup needed here
+#endif
+
+#endif
diff --git a/include/hw/xen/interface/io/ring.h b/include/hw/xen/interface/io/ring.h
new file mode 100644
index 000000000..115705f3f
--- /dev/null
+++ b/include/hw/xen/interface/io/ring.h
@@ -0,0 +1,474 @@
+/******************************************************************************
+ * 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.
+ *
+ * Tim Deegan and Andrew Warfield November 2004.
+ */
+
+#ifndef __XEN_PUBLIC_IO_RING_H__
+#define __XEN_PUBLIC_IO_RING_H__
+
+/*
+ * When #include'ing this header, you need to provide the following
+ * declaration upfront:
+ * - 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
+ * - memcpy
+ * - grant_ref_t
+ * These declarations are provided by string.h of the standard headers,
+ * and grant_table.h from the Xen public headers.
+ */
+
+typedef unsigned int RING_IDX;
+
+/* Round a 32-bit unsigned constant down to the nearest power of two. */
+#define __RD2(_x) (((_x) & 0x00000002) ? 0x2 : ((_x) & 0x1))
+#define __RD4(_x) (((_x) & 0x0000000c) ? __RD2((_x)>>2)<<2 : __RD2(_x))
+#define __RD8(_x) (((_x) & 0x000000f0) ? __RD4((_x)>>4)<<4 : __RD4(_x))
+#define __RD16(_x) (((_x) & 0x0000ff00) ? __RD8((_x)>>8)<<8 : __RD8(_x))
+#define __RD32(_x) (((_x) & 0xffff0000) ? __RD16((_x)>>16)<<16 : __RD16(_x))
+
+/*
+ * 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
+ * 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])))
+/*
+ * The same for passing in an actual pointer instead of a name tag.
+ */
+#define __RING_SIZE(_s, _sz) \
+ (__RD32(((_sz) - (long)(_s)->ring + (long)(_s)) / sizeof((_s)->ring[0])))
+
+/*
+ * 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.
+ *
+ * In a header where you want the ring datatype declared, you then do:
+ *
+ * DEFINE_RING_TYPES(mytag, request_t, response_t);
+ *
+ * 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.
+ *
+ * To initialize a ring in your code you need to know the location and size
+ * 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);
+ *
+ * Initializing the back follows similarly (note that only the front
+ * initializes the shared ring):
+ *
+ * mytag_back_ring_t back_ring;
+ * BACK_RING_INIT(&back_ring, (mytag_sring_t *)shared_page, PAGE_SIZE);
+ */
+
+#define DEFINE_RING_TYPES(__name, __req_t, __rsp_t) \
+ \
+/* Shared ring entry */ \
+union __name##_sring_entry { \
+ __req_t req; \
+ __rsp_t rsp; \
+}; \
+ \
+/* Shared ring page */ \
+struct __name##_sring { \
+ RING_IDX req_prod, req_event; \
+ RING_IDX rsp_prod, rsp_event; \
+ union { \
+ struct { \
+ uint8_t smartpoll_active; \
+ } netif; \
+ struct { \
+ uint8_t msg; \
+ } tapif_user; \
+ uint8_t pvt_pad[4]; \
+ } pvt; \
+ uint8_t __pad[44]; \
+ union __name##_sring_entry ring[1]; /* variable-length */ \
+}; \
+ \
+/* "Front" end's private variables */ \
+struct __name##_front_ring { \
+ RING_IDX req_prod_pvt; \
+ RING_IDX rsp_cons; \
+ unsigned int nr_ents; \
+ struct __name##_sring *sring; \
+}; \
+ \
+/* "Back" end's private variables */ \
+struct __name##_back_ring { \
+ RING_IDX rsp_prod_pvt; \
+ RING_IDX req_cons; \
+ unsigned int nr_ents; \
+ struct __name##_sring *sring; \
+}; \
+ \
+/* Syntactic sugar */ \
+typedef struct __name##_sring __name##_sring_t; \
+typedef struct __name##_front_ring __name##_front_ring_t; \
+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
+ * requests are pushed on to the ring and responses taken off it.
+ *
+ * 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
+ * requestor (front end) never has more than RING_SIZE()-1
+ * outstanding requests.
+ */
+
+/* Initialising empty rings */
+#define SHARED_RING_INIT(_s) do { \
+ (_s)->req_prod = (_s)->rsp_prod = 0; \
+ (_s)->req_event = (_s)->rsp_event = 1; \
+ (void)memset((_s)->pvt.pvt_pad, 0, sizeof((_s)->pvt.pvt_pad)); \
+ (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; \
+ (_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; \
+ (_r)->nr_ents = __RING_SIZE(_s, __size); \
+ (_r)->sring = (_s); \
+} while (0)
+
+/* How big is this ring? */
+#define RING_SIZE(_r) \
+ ((_r)->nr_ents)
+
+/* Number of free requests (for use on front side only). */
+#define RING_FREE_REQUESTS(_r) \
+ (RING_SIZE(_r) - ((_r)->req_prod_pvt - (_r)->rsp_cons))
+
+/* Test if there is an empty slot available on the front ring.
+ * (This is only meaningful from the front. )
+ */
+#define RING_FULL(_r) \
+ (RING_FREE_REQUESTS(_r) == 0)
+
+/* Test if there are outstanding messages to be processed on a ring. */
+#define RING_HAS_UNCONSUMED_RESPONSES(_r) \
+ ((_r)->sring->rsp_prod - (_r)->rsp_cons)
+
+#define RING_HAS_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); \
+ req < rsp ? req : rsp; \
+})
+
+/* Direct access to individual ring elements, by index. */
+#define RING_GET_REQUEST(_r, _idx) \
+ (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].req))
+
+/*
+ * Get a local copy of a request.
+ *
+ * Use this in preference to RING_GET_REQUEST() 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.
+ */
+#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); \
+} while (0)
+
+#define RING_GET_RESPONSE(_r, _idx) \
+ (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].rsp))
+
+/* Loop termination condition: Would the specified index overflow the ring? */
+#define RING_REQUEST_CONS_OVERFLOW(_r, _cons) \
+ (((_cons) - (_r)->rsp_prod_pvt) >= RING_SIZE(_r))
+
+/* Ill-behaved frontend determination: Can there be this many requests? */
+#define RING_REQUEST_PROD_OVERFLOW(_r, _prod) \
+ (((_prod) - (_r)->rsp_prod_pvt) > 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; \
+} while (0)
+
+#define RING_PUSH_RESPONSES(_r) do { \
+ xen_wmb(); /* front sees resps /before/ updated producer index */ \
+ (_r)->sring->rsp_prod = (_r)->rsp_prod_pvt; \
+} while (0)
+
+/*
+ * 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
+ * messages have been enqueued) then you will need to create a customised
+ * version of the FINAL_CHECK macro in your own code, which sets the event
+ * field appropriately.
+ */
+
+#define RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(_r, _notify) do { \
+ RING_IDX __old = (_r)->sring->req_prod; \
+ RING_IDX __new = (_r)->req_prod_pvt; \
+ xen_wmb(); /* back sees requests /before/ updated producer index */ \
+ (_r)->sring->req_prod = __new; \
+ xen_mb(); /* back sees new requests /before/ we check req_event */ \
+ (_notify) = ((RING_IDX)(__new - (_r)->sring->req_event) < \
+ (RING_IDX)(__new - __old)); \
+} while (0)
+
+#define RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(_r, _notify) do { \
+ RING_IDX __old = (_r)->sring->rsp_prod; \
+ RING_IDX __new = (_r)->rsp_prod_pvt; \
+ xen_wmb(); /* front sees resps /before/ updated producer index */ \
+ (_r)->sring->rsp_prod = __new; \
+ xen_mb(); /* front sees new resps /before/ we check rsp_event */ \
+ (_notify) = ((RING_IDX)(__new - (_r)->sring->rsp_event) < \
+ (RING_IDX)(__new - __old)); \
+} while (0)
+
+#define RING_FINAL_CHECK_FOR_REQUESTS(_r, _work_to_do) do { \
+ (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r); \
+ if (_work_to_do) break; \
+ (_r)->sring->req_event = (_r)->req_cons + 1; \
+ xen_mb(); \
+ (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r); \
+} while (0)
+
+#define RING_FINAL_CHECK_FOR_RESPONSES(_r, _work_to_do) do { \
+ (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \
+ if (_work_to_do) break; \
+ (_r)->sring->rsp_event = (_r)->rsp_cons + 1; \
+ xen_mb(); \
+ (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \
+} while (0)
+
+
+/*
+ * DEFINE_XEN_FLEX_RING_AND_INTF defines two monodirectional rings and
+ * functions to check if there is data on the ring, and to read and
+ * write to them.
+ *
+ * DEFINE_XEN_FLEX_RING is similar to DEFINE_XEN_FLEX_RING_AND_INTF, but
+ * does not define the indexes page. As different protocols can have
+ * extensions to the basic format, this macro allow them to define their
+ * own struct.
+ *
+ * XEN_FLEX_RING_SIZE
+ * Convenience macro to calculate the size of one of the two rings
+ * from the overall order.
+ *
+ * $NAME_mask
+ * Function to apply the size mask to an index, to reduce the index
+ * within the range [0-size].
+ *
+ * $NAME_read_packet
+ * Function to read data from the ring. The amount of data to read is
+ * specified by the "size" argument.
+ *
+ * $NAME_write_packet
+ * Function to write data to the ring. The amount of data to write is
+ * specified by the "size" argument.
+ *
+ * $NAME_get_ring_ptr
+ * Convenience function that returns a pointer to read/write to the
+ * ring at the right location.
+ *
+ * $NAME_data_intf
+ * Indexes page, shared between frontend and backend. It also
+ * contains the array of grant refs.
+ *
+ * $NAME_queued
+ * Function to calculate how many bytes are currently on the ring,
+ * ready to be read. It can also be used to calculate how much free
+ * space is currently on the ring (XEN_FLEX_RING_SIZE() -
+ * $NAME_queued()).
+ */
+
+#ifndef XEN_PAGE_SHIFT
+/* The PAGE_SIZE for ring protocols and hypercall interfaces is always
+ * 4K, regardless of the architecture, and page granularity chosen by
+ * operating systems.
+ */
+#define XEN_PAGE_SHIFT 12
+#endif
+#define XEN_FLEX_RING_SIZE(order) \
+ (1UL << ((order) + XEN_PAGE_SHIFT - 1))
+
+#define DEFINE_XEN_FLEX_RING(name) \
+static inline RING_IDX name##_mask(RING_IDX idx, RING_IDX ring_size) \
+{ \
+ return idx & (ring_size - 1); \
+} \
+ \
+static inline unsigned char *name##_get_ring_ptr(unsigned char *buf, \
+ RING_IDX idx, \
+ RING_IDX ring_size) \
+{ \
+ return buf + name##_mask(idx, ring_size); \
+} \
+ \
+static inline void name##_read_packet(void *opaque, \
+ const unsigned char *buf, \
+ size_t size, \
+ RING_IDX masked_prod, \
+ RING_IDX *masked_cons, \
+ RING_IDX ring_size) \
+{ \
+ if (*masked_cons < masked_prod || \
+ size <= ring_size - *masked_cons) { \
+ memcpy(opaque, buf + *masked_cons, size); \
+ } else { \
+ memcpy(opaque, buf + *masked_cons, ring_size - *masked_cons); \
+ memcpy((unsigned char *)opaque + ring_size - *masked_cons, buf, \
+ size - (ring_size - *masked_cons)); \
+ } \
+ *masked_cons = name##_mask(*masked_cons + size, ring_size); \
+} \
+ \
+static inline void name##_write_packet(unsigned char *buf, \
+ const void *opaque, \
+ size_t size, \
+ RING_IDX *masked_prod, \
+ RING_IDX masked_cons, \
+ RING_IDX ring_size) \
+{ \
+ if (*masked_prod < masked_cons || \
+ size <= ring_size - *masked_prod) { \
+ memcpy(buf + *masked_prod, opaque, size); \
+ } else { \
+ memcpy(buf + *masked_prod, opaque, ring_size - *masked_prod); \
+ memcpy(buf, (unsigned char *)opaque + (ring_size - *masked_prod), \
+ size - (ring_size - *masked_prod)); \
+ } \
+ *masked_prod = name##_mask(*masked_prod + size, ring_size); \
+} \
+ \
+static inline RING_IDX name##_queued(RING_IDX prod, \
+ RING_IDX cons, \
+ RING_IDX ring_size) \
+{ \
+ RING_IDX size; \
+ \
+ if (prod == cons) \
+ return 0; \
+ \
+ prod = name##_mask(prod, ring_size); \
+ cons = name##_mask(cons, ring_size); \
+ \
+ if (prod == cons) \
+ return ring_size; \
+ \
+ if (prod > cons) \
+ size = prod - cons; \
+ else \
+ size = ring_size - (cons - prod); \
+ return size; \
+} \
+ \
+struct name##_data { \
+ unsigned char *in; /* half of the allocation */ \
+ unsigned char *out; /* half of the allocation */ \
+}
+
+#define DEFINE_XEN_FLEX_RING_AND_INTF(name) \
+struct name##_data_intf { \
+ RING_IDX in_cons, in_prod; \
+ \
+ uint8_t pad1[56]; \
+ \
+ RING_IDX out_cons, out_prod; \
+ \
+ uint8_t pad2[56]; \
+ \
+ RING_IDX ring_order; \
+ grant_ref_t ref[]; \
+}; \
+DEFINE_XEN_FLEX_RING(name)
+
+#endif /* __XEN_PUBLIC_IO_RING_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/usbif.h b/include/hw/xen/interface/io/usbif.h
new file mode 100644
index 000000000..c6a58639d
--- /dev/null
+++ b/include/hw/xen/interface/io/usbif.h
@@ -0,0 +1,254 @@
+/*
+ * usbif.h
+ *
+ * USB I/O interface for Xen guest OSes.
+ *
+ * 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__
+#define __XEN_PUBLIC_IO_USBIF_H__
+
+#include "ring.h"
+#include "../grant_table.h"
+
+/*
+ * Feature and Parameter Negotiation
+ * =================================
+ * The two halves of a Xen pvUSB driver utilize nodes within the XenStore to
+ * communicate capabilities and to negotiate operating parameters. This
+ * section enumerates these nodes which reside in the respective front and
+ * backend portions of the XenStore, following the XenBus convention.
+ *
+ * Any specified default value is in effect if the corresponding XenBus node
+ * is not present in the XenStore.
+ *
+ * XenStore nodes in sections marked "PRIVATE" are solely for use by the
+ * driver side whose XenBus tree contains them.
+ *
+ *****************************************************************************
+ * Backend XenBus Nodes
+ *****************************************************************************
+ *
+ *------------------ Backend Device Identification (PRIVATE) ------------------
+ *
+ * num-ports
+ * Values: unsigned [1...31]
+ *
+ * Number of ports for this (virtual) USB host connector.
+ *
+ * usb-ver
+ * Values: unsigned [1...2]
+ *
+ * USB version of this host connector: 1 = USB 1.1, 2 = USB 2.0.
+ *
+ * port/[1...31]
+ * Values: string
+ *
+ * Physical USB device connected to the given port, e.g. "3-1.5".
+ *
+ *****************************************************************************
+ * Frontend XenBus Nodes
+ *****************************************************************************
+ *
+ *----------------------- Request Transport Parameters -----------------------
+ *
+ * event-channel
+ * Values: unsigned
+ *
+ * The identifier of the Xen event channel used to signal activity
+ * in the ring buffer.
+ *
+ * urb-ring-ref
+ * Values: unsigned
+ *
+ * The Xen grant reference granting permission for the backend to map
+ * the sole page in a single page sized ring buffer. This is the ring
+ * buffer for urb requests.
+ *
+ * conn-ring-ref
+ * Values: unsigned
+ *
+ * The Xen grant reference granting permission for the backend to map
+ * the sole page in a single page sized ring buffer. This is the ring
+ * buffer for connection/disconnection requests.
+ *
+ * protocol
+ * Values: string (XEN_IO_PROTO_ABI_*)
+ * Default Value: XEN_IO_PROTO_ABI_NATIVE
+ *
+ * The machine ABI rules governing the format of all ring request and
+ * response structures.
+ *
+ */
+
+enum usb_spec_version {
+ 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)
+ *
+ * - operation flag: bit 5
+ * (0 = submit urb,
+ * 1 = unlink urb)
+ *
+ * - direction: bit 7
+ * (0 = Host-to-Device [Out]
+ * 1 = Device-to-Host [In])
+ *
+ * - device address: bits 8-14
+ *
+ * - endpoint: bits 15-18
+ *
+ * - 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_MAX_SEGMENTS_PER_REQUEST (16)
+#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;
+};
+
+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];
+};
+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 */
+};
+typedef struct usbif_urb_response usbif_urb_response_t;
+
+DEFINE_RING_TYPES(usbif_urb, struct usbif_urb_request, struct usbif_urb_response);
+#define USB_URB_RING_SIZE __CONST_RING_SIZE(usbif_urb, USBIF_RING_SIZE)
+
+/*
+ * RING for notifying connect/disconnect events to frontend
+ */
+struct usbif_conn_request {
+ 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
+};
+typedef struct usbif_conn_response usbif_conn_response_t;
+
+DEFINE_RING_TYPES(usbif_conn, struct usbif_conn_request, struct usbif_conn_response);
+#define USB_CONN_RING_SIZE __CONST_RING_SIZE(usbif_conn, USBIF_RING_SIZE)
+
+#endif /* __XEN_PUBLIC_IO_USBIF_H__ */
diff --git a/include/hw/xen/interface/io/xenbus.h b/include/hw/xen/interface/io/xenbus.h
new file mode 100644
index 000000000..2fbf2a7fd
--- /dev/null
+++ b/include/hw/xen/interface/io/xenbus.h
@@ -0,0 +1,70 @@
+/*****************************************************************************
+ * 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.
+ */
+
+#ifndef _XEN_PUBLIC_IO_XENBUS_H
+#define _XEN_PUBLIC_IO_XENBUS_H
+
+/*
+ * The state of either end of the Xenbus, i.e. the current communication
+ * status of initialisation across the bus. States here imply nothing about
+ * the state of the connection between the driver and the kernel's device
+ * layers.
+ */
+enum xenbus_state {
+ XenbusStateUnknown = 0,
+
+ XenbusStateInitialising = 1,
+
+ /*
+ * InitWait: Finished early initialisation but waiting for information
+ * from the peer or hotplug scripts.
+ */
+ XenbusStateInitWait = 2,
+
+ /*
+ * Initialised: Waiting for a connection from the peer.
+ */
+ XenbusStateInitialised = 3,
+
+ XenbusStateConnected = 4,
+
+ /*
+ * Closing: The device is being closed due to an error or an unplug event.
+ */
+ XenbusStateClosing = 5,
+
+ XenbusStateClosed = 6,
+
+ /*
+ * Reconfiguring: The device is being reconfigured.
+ */
+ XenbusStateReconfiguring = 7,
+
+ XenbusStateReconfigured = 8
+};
+typedef enum xenbus_state XenbusState;
+
+#endif /* _XEN_PUBLIC_IO_XENBUS_H */
diff --git a/include/hw/xen/start_info.h b/include/hw/xen/start_info.h
new file mode 100644
index 000000000..6ed487779
--- /dev/null
+++ b/include/hw/xen/start_info.h
@@ -0,0 +1,146 @@
+/*
+ * 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) 2016, Citrix Systems, Inc.
+ */
+
+#ifndef XEN_PUBLIC_ARCH_X86_HVM_START_INFO_H
+#define XEN_PUBLIC_ARCH_X86_HVM_START_INFO_H
+
+/*
+ * Start of day structure passed to PVH guests and to HVM guests in %ebx.
+ *
+ * NOTE: nothing will be loaded at physical address 0, so a 0 value in any
+ * of the address fields should be treated as not present.
+ *
+ * 0 +----------------+
+ * | magic | Contains the magic value XEN_HVM_START_MAGIC_VALUE
+ * | | ("xEn3" with the 0x80 bit of the "E" set).
+ * 4 +----------------+
+ * | version | Version of this structure. Current version is 1. New
+ * | | versions are guaranteed to be backwards-compatible.
+ * 8 +----------------+
+ * | flags | SIF_xxx flags.
+ * 12 +----------------+
+ * | nr_modules | Number of modules passed to the kernel.
+ * 16 +----------------+
+ * | modlist_paddr | Physical address of an array of modules
+ * | | (layout of the structure below).
+ * 24 +----------------+
+ * | cmdline_paddr | Physical address of the command line,
+ * | | a zero-terminated ASCII string.
+ * 32 +----------------+
+ * | rsdp_paddr | Physical address of the RSDP ACPI data structure.
+ * 40 +----------------+
+ * | memmap_paddr | Physical address of the (optional) memory map. Only
+ * | | present in version 1 and newer of the structure.
+ * 48 +----------------+
+ * | memmap_entries | Number of entries in the memory map table. Only
+ * | | present in version 1 and newer of the structure.
+ * | | Zero if there is no memory map being provided.
+ * 52 +----------------+
+ * | reserved | Version 1 and newer only.
+ * 56 +----------------+
+ *
+ * The layout of each entry in the module structure is the following:
+ *
+ * 0 +----------------+
+ * | paddr | Physical address of the module.
+ * 8 +----------------+
+ * | size | Size of the module in bytes.
+ * 16 +----------------+
+ * | cmdline_paddr | Physical address of the command line,
+ * | | a zero-terminated ASCII string.
+ * 24 +----------------+
+ * | reserved |
+ * 32 +----------------+
+ *
+ * The layout of each entry in the memory map table is as follows:
+ *
+ * 0 +----------------+
+ * | addr | Base address
+ * 8 +----------------+
+ * | size | Size of mapping in bytes
+ * 16 +----------------+
+ * | type | Type of mapping as defined between the hypervisor
+ * | | and guest it's starting. E820_TYPE_xxx, for example.
+ * 20 +----------------|
+ * | reserved |
+ * 24 +----------------+
+ *
+ * The address and sizes are always a 64bit little endian unsigned integer.
+ *
+ * NB: Xen on x86 will always try to place all the data below the 4GiB
+ * boundary.
+ *
+ * Version numbers of the hvm_start_info structure have evolved like this:
+ *
+ * Version 0:
+ *
+ * Version 1: Added the memmap_paddr/memmap_entries fields (plus 4 bytes of
+ * padding) to the end of the hvm_start_info struct. These new
+ * fields can be used to pass a memory map to the guest. The
+ * memory map is optional and so guests that understand version 1
+ * of the structure must check that memmap_entries is non-zero
+ * before trying to read the memory map.
+ */
+#define XEN_HVM_START_MAGIC_VALUE 0x336ec578
+
+/*
+ * C representation of the x86/HVM start info layout.
+ *
+ * The canonical definition of this layout is above, this is just a way to
+ * represent the layout described there using C types.
+ */
+struct hvm_start_info {
+ uint32_t magic; /* Contains the magic value 0x336ec578 */
+ /* ("xEn3" with the 0x80 bit of the "E" set).*/
+ uint32_t version; /* Version of this structure. */
+ uint32_t flags; /* SIF_xxx flags. */
+ uint32_t nr_modules; /* Number of modules passed to the kernel. */
+ uint64_t modlist_paddr; /* Physical address of an array of */
+ /* hvm_modlist_entry. */
+ uint64_t cmdline_paddr; /* Physical address of the command line. */
+ uint64_t rsdp_paddr; /* Physical address of the RSDP ACPI data */
+ /* structure. */
+ uint64_t memmap_paddr; /* Physical address of an array of */
+ /* hvm_memmap_table_entry. Only present in */
+ /* version 1 and newer of the structure */
+ uint32_t memmap_entries; /* Number of entries in the memmap table. */
+ /* Only present in version 1 and newer of */
+ /* the structure. Value will be zero if */
+ /* there is no memory map being provided. */
+ uint32_t reserved;
+};
+
+struct hvm_modlist_entry {
+ uint64_t paddr; /* Physical address of the module. */
+ uint64_t size; /* Size of the module in bytes. */
+ uint64_t cmdline_paddr; /* Physical address of the command line. */
+ uint64_t reserved;
+};
+
+struct hvm_memmap_table_entry {
+ uint64_t addr; /* Base address of the memory region */
+ uint64_t size; /* Size of the memory region in bytes */
+ uint32_t type; /* Mapping type */
+ uint32_t reserved;
+};
+
+#endif /* XEN_PUBLIC_ARCH_X86_HVM_START_INFO_H */
diff --git a/include/hw/xen/xen-backend.h b/include/hw/xen/xen-backend.h
new file mode 100644
index 000000000..aac2fd454
--- /dev/null
+++ b/include/hw/xen/xen-backend.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2018 Citrix 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 HW_XEN_BACKEND_H
+#define HW_XEN_BACKEND_H
+
+#include "hw/xen/xen-bus.h"
+
+typedef struct XenBackendInstance XenBackendInstance;
+
+typedef void (*XenBackendDeviceCreate)(XenBackendInstance *backend,
+ QDict *opts, Error **errp);
+typedef void (*XenBackendDeviceDestroy)(XenBackendInstance *backend,
+ Error **errp);
+
+typedef struct XenBackendInfo {
+ const char *type;
+ XenBackendDeviceCreate create;
+ XenBackendDeviceDestroy destroy;
+} XenBackendInfo;
+
+XenBus *xen_backend_get_bus(XenBackendInstance *backend);
+const char *xen_backend_get_name(XenBackendInstance *backend);
+
+void xen_backend_set_device(XenBackendInstance *backend,
+ XenDevice *xendevice);
+XenDevice *xen_backend_get_device(XenBackendInstance *backend);
+
+void xen_backend_register(const XenBackendInfo *info);
+const char **xen_backend_get_types(unsigned int *nr);
+
+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);
+
+#endif /* HW_XEN_BACKEND_H */
diff --git a/include/hw/xen/xen-block.h b/include/hw/xen/xen-block.h
new file mode 100644
index 000000000..d692ea758
--- /dev/null
+++ b/include/hw/xen/xen-block.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2018 Citrix 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 HW_XEN_BLOCK_H
+#define HW_XEN_BLOCK_H
+
+#include "hw/xen/xen-bus.h"
+#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,
+ XEN_BLOCK_VDEV_TYPE_DP,
+ XEN_BLOCK_VDEV_TYPE_XVD,
+ XEN_BLOCK_VDEV_TYPE_HD,
+ XEN_BLOCK_VDEV_TYPE_SD,
+ XEN_BLOCK_VDEV_TYPE__MAX
+} XenBlockVdevType;
+
+typedef struct XenBlockVdev {
+ XenBlockVdevType type;
+ unsigned long disk;
+ unsigned long partition;
+ unsigned long number;
+} XenBlockVdev;
+
+
+typedef struct XenBlockProperties {
+ XenBlockVdev vdev;
+ BlockConf conf;
+ unsigned int max_ring_page_order;
+ IOThread *iothread;
+} XenBlockProperties;
+
+typedef struct XenBlockDrive {
+ char *id;
+ char *node_name;
+} XenBlockDrive;
+
+typedef struct XenBlockIOThread {
+ char *id;
+} XenBlockIOThread;
+
+struct XenBlockDevice {
+ XenDevice xendev;
+ XenBlockProperties props;
+ const char *device_type;
+ unsigned int info;
+ XenBlockDataPlane *dataplane;
+ XenBlockDrive *drive;
+ XenBlockIOThread *iothread;
+};
+typedef struct XenBlockDevice XenBlockDevice;
+
+typedef void (*XenBlockDeviceRealize)(XenBlockDevice *blockdev, Error **errp);
+typedef void (*XenBlockDeviceUnrealize)(XenBlockDevice *blockdev);
+
+struct XenBlockDeviceClass {
+ /*< private >*/
+ XenDeviceClass parent_class;
+ /*< public >*/
+ XenBlockDeviceRealize realize;
+ XenBlockDeviceUnrealize unrealize;
+};
+
+#define TYPE_XEN_BLOCK_DEVICE "xen-block"
+OBJECT_DECLARE_TYPE(XenBlockDevice, XenBlockDeviceClass, XEN_BLOCK_DEVICE)
+
+struct XenDiskDevice {
+ XenBlockDevice blockdev;
+};
+
+#define TYPE_XEN_DISK_DEVICE "xen-disk"
+OBJECT_DECLARE_SIMPLE_TYPE(XenDiskDevice, XEN_DISK_DEVICE)
+
+struct XenCDRomDevice {
+ XenBlockDevice blockdev;
+};
+
+#define TYPE_XEN_CDROM_DEVICE "xen-cdrom"
+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
new file mode 100644
index 000000000..4c0f74744
--- /dev/null
+++ b/include/hw/xen/xen-bus-helper.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018 Citrix 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 HW_XEN_BUS_HELPER_H
+#define HW_XEN_BUS_HELPER_H
+
+#include "hw/xen/xen_common.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,
+ 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,
+ 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,
+ const char *node, const char *key, Error **errp,
+ const char *fmt, ...)
+ GCC_FMT_ATTR(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,
+ 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 *node, const char *key, Error **errp,
+ const char *fmt, ...);
+
+/* 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);
+
+#endif /* HW_XEN_BUS_HELPER_H */
diff --git a/include/hw/xen/xen-bus.h b/include/hw/xen/xen-bus.h
new file mode 100644
index 000000000..6bdbf3ff8
--- /dev/null
+++ b/include/hw/xen/xen-bus.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2018 Citrix 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 HW_XEN_BUS_H
+#define HW_XEN_BUS_H
+
+#include "hw/xen/xen_common.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;
+
+struct XenDevice {
+ DeviceState qdev;
+ domid_t frontend_id;
+ char *name;
+ struct xs_handle *xsh;
+ XenWatchList *watch_list;
+ char *backend_path, *frontend_path;
+ enum xenbus_state backend_state, frontend_state;
+ Notifier exit;
+ XenWatch *backend_state_watch, *frontend_state_watch;
+ bool backend_online;
+ XenWatch *backend_online_watch;
+ xengnttab_handle *xgth;
+ bool feature_grant_copy;
+ bool inactive;
+ QLIST_HEAD(, XenEventChannel) event_channels;
+ QLIST_ENTRY(XenDevice) list;
+};
+typedef struct XenDevice XenDevice;
+
+typedef char *(*XenDeviceGetName)(XenDevice *xendev, Error **errp);
+typedef void (*XenDeviceRealize)(XenDevice *xendev, Error **errp);
+typedef void (*XenDeviceFrontendChanged)(XenDevice *xendev,
+ enum xenbus_state frontend_state,
+ Error **errp);
+typedef void (*XenDeviceUnrealize)(XenDevice *xendev);
+
+struct XenDeviceClass {
+ /*< private >*/
+ DeviceClass parent_class;
+ /*< public >*/
+ const char *backend;
+ const char *device;
+ XenDeviceGetName get_name;
+ XenDeviceRealize realize;
+ XenDeviceFrontendChanged frontend_changed;
+ XenDeviceUnrealize unrealize;
+};
+
+#define TYPE_XEN_DEVICE "xen-device"
+OBJECT_DECLARE_TYPE(XenDevice, XenDeviceClass, XEN_DEVICE)
+
+struct XenBus {
+ BusState qbus;
+ domid_t backend_id;
+ struct xs_handle *xsh;
+ XenWatchList *watch_list;
+ unsigned int backend_types;
+ XenWatch **backend_watch;
+ QLIST_HEAD(, XenDevice) inactive_devices;
+};
+
+struct XenBusClass {
+ /*< private >*/
+ BusClass parent_class;
+};
+
+#define TYPE_XEN_BUS "xen-bus"
+OBJECT_DECLARE_TYPE(XenBus, XenBusClass,
+ XEN_BUS)
+
+void xen_bus_init(void);
+
+void xen_device_backend_set_state(XenDevice *xendev,
+ enum xenbus_state state);
+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);
+void xen_device_frontend_printf(XenDevice *xendev, const char *key,
+ const char *fmt, ...)
+ GCC_FMT_ATTR(3, 4);
+
+int xen_device_frontend_scanf(XenDevice *xendev, const char *key,
+ const char *fmt, ...);
+
+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,
+ unsigned int nr_refs, Error **errp);
+
+typedef struct XenDeviceGrantCopySegment {
+ union {
+ void *virt;
+ struct {
+ uint32_t ref;
+ off_t offset;
+ } foreign;
+ } source, dest;
+ size_t len;
+} XenDeviceGrantCopySegment;
+
+void xen_device_copy_grant_refs(XenDevice *xendev, bool to_domain,
+ XenDeviceGrantCopySegment segs[],
+ unsigned int nr_segs, Error **errp);
+
+typedef bool (*XenEventHandler)(void *opaque);
+
+XenEventChannel *xen_device_bind_event_channel(XenDevice *xendev,
+ unsigned int port,
+ XenEventHandler handler,
+ void *opaque, Error **errp);
+void xen_device_set_event_channel_context(XenDevice *xendev,
+ XenEventChannel *channel,
+ AioContext *ctx,
+ Error **errp);
+void xen_device_notify_event_channel(XenDevice *xendev,
+ XenEventChannel *channel,
+ Error **errp);
+void xen_device_unbind_event_channel(XenDevice *xendev,
+ XenEventChannel *channel,
+ Error **errp);
+
+#endif /* HW_XEN_BUS_H */
diff --git a/include/hw/xen/xen-legacy-backend.h b/include/hw/xen/xen-legacy-backend.h
new file mode 100644
index 000000000..be281e1f3
--- /dev/null
+++ b/include/hw/xen/xen-legacy-backend.h
@@ -0,0 +1,105 @@
+#ifndef HW_XEN_LEGACY_BACKEND_H
+#define HW_XEN_LEGACY_BACKEND_H
+
+#include "hw/xen/xen_common.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"
+
+typedef struct XenLegacyDevice XenLegacyDevice;
+DECLARE_INSTANCE_CHECKER(XenLegacyDevice, XENBACKEND,
+ TYPE_XENBACKEND)
+
+/* variables */
+extern struct xs_handle *xenstore;
+extern const char *xen_protocol;
+extern DeviceState *xen_sysdev;
+extern BusState *xen_sysbus;
+
+int xenstore_mkdir(char *path, int p);
+int xenstore_write_be_str(struct XenLegacyDevice *xendev, const char *node,
+ const char *val);
+int xenstore_write_be_int(struct XenLegacyDevice *xendev, const char *node,
+ int ival);
+int xenstore_write_be_int64(struct XenLegacyDevice *xendev, const char *node,
+ int64_t ival);
+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);
+int xenstore_read_fe_uint64(struct XenLegacyDevice *xendev, const char *node,
+ uint64_t *uval);
+
+void xen_be_check_state(struct XenLegacyDevice *xendev);
+
+/* xen backend driver bits */
+int xen_be_init(void);
+void xen_be_register_common(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);
+void xen_be_set_max_grant_refs(struct XenLegacyDevice *xendev,
+ unsigned int nr_refs);
+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;
+
+int xen_be_copy_grant_refs(struct XenLegacyDevice *xendev,
+ bool to_domain, XenGrantCopySegment segs[],
+ unsigned int nr_segs);
+
+static inline void *xen_be_map_grant_ref(struct XenLegacyDevice *xendev,
+ uint32_t ref, int prot)
+{
+ return xen_be_map_grant_refs(xendev, &ref, 1, prot);
+}
+
+static inline void xen_be_unmap_grant_ref(struct XenLegacyDevice *xendev,
+ void *ptr)
+{
+ return xen_be_unmap_grant_refs(xendev, ptr, 1);
+}
+
+/* actual backend drivers */
+extern struct XenDevOps xen_console_ops; /* xen_console.c */
+extern struct XenDevOps xen_kbdmouse_ops; /* xen_framebuffer.c */
+extern struct XenDevOps xen_framebuffer_ops; /* xen_framebuffer.c */
+extern struct XenDevOps xen_blkdev_ops; /* xen_disk.c */
+#ifdef CONFIG_VIRTFS
+extern struct XenDevOps xen_9pfs_ops; /* xen-9p-backend.c */
+#endif
+extern struct XenDevOps xen_netdev_ops; /* xen_nic.c */
+#ifdef CONFIG_USB_LIBUSB
+extern struct XenDevOps xen_usb_ops; /* xen-usb.c */
+#endif
+
+/* 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);
+
+#endif /* HW_XEN_LEGACY_BACKEND_H */
diff --git a/include/hw/xen/xen-x86.h b/include/hw/xen/xen-x86.h
new file mode 100644
index 000000000..85e3db1b8
--- /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
new file mode 100644
index 000000000..0f9962b1c
--- /dev/null
+++ b/include/hw/xen/xen.h
@@ -0,0 +1,35 @@
+#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.
+ */
+
+#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
+};
+
+extern uint32_t xen_domid;
+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);
+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, Chardev *chr);
+
+void xen_register_framebuffer(struct MemoryRegion *mr);
+
+#endif /* QEMU_HW_XEN_H */
diff --git a/include/hw/xen/xen_common.h b/include/hw/xen/xen_common.h
new file mode 100644
index 000000000..a8118b41a
--- /dev/null
+++ b/include/hw/xen/xen_common.h
@@ -0,0 +1,696 @@
+#ifndef QEMU_HW_XEN_COMMON_H
+#define QEMU_HW_XEN_COMMON_H
+
+/*
+ * If we have new enough libxenctrl then we do not want/need these compat
+ * interfaces, despite what the user supplied cflags might say. They
+ * must be undefined before including xenctrl.h
+ */
+#undef XC_WANT_COMPAT_EVTCHN_API
+#undef XC_WANT_COMPAT_GNTTAB_API
+#undef XC_WANT_COMPAT_MAP_FOREIGN_API
+
+#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/xen/trace.h"
+
+extern xc_interface *xen_xc;
+
+/*
+ * We don't support Xen prior to 4.2.0.
+ */
+
+/* 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
+
+typedef xc_interface xendevicemodel_handle;
+
+#else /* CONFIG_XEN_CTRL_INTERFACE_VERSION >= 40900 */
+
+#undef XC_WANT_COMPAT_DEVICEMODEL_API
+#include <xendevicemodel.h>
+
+#endif
+
+#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 41100
+
+static inline int xendevicemodel_relocate_memory(
+ xendevicemodel_handle *dmod, domid_t domid, uint32_t size, uint64_t src_gfn,
+ uint64_t dst_gfn)
+{
+ uint32_t i;
+ int rc;
+
+ for (i = 0; i < size; i++) {
+ unsigned long idx = src_gfn + i;
+ xen_pfn_t gpfn = dst_gfn + i;
+
+ rc = xc_domain_add_to_physmap(xen_xc, domid, XENMAPSPACE_gmfn, idx,
+ gpfn);
+ if (rc) {
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+static inline int xendevicemodel_pin_memory_cacheattr(
+ xendevicemodel_handle *dmod, domid_t domid, uint64_t start, uint64_t end,
+ uint32_t type)
+{
+ return xc_domain_pin_memory_cacheattr(xen_xc, domid, start, end, type);
+}
+
+typedef void xenforeignmemory_resource_handle;
+
+#define XENMEM_resource_ioreq_server 0
+
+#define XENMEM_resource_ioreq_server_frame_bufioreq 0
+#define XENMEM_resource_ioreq_server_frame_ioreq(n) (1 + (n))
+
+static inline xenforeignmemory_resource_handle *xenforeignmemory_map_resource(
+ xenforeignmemory_handle *fmem, domid_t domid, unsigned int type,
+ unsigned int id, unsigned long frame, unsigned long nr_frames,
+ void **paddr, int prot, int flags)
+{
+ errno = EOPNOTSUPP;
+ 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
+
+#define XEN_COMPAT_PHYSMAP
+static inline void *xenforeignmemory_map2(xenforeignmemory_handle *h,
+ uint32_t dom, void *addr,
+ int prot, int flags, size_t pages,
+ const xen_pfn_t arr[/*pages*/],
+ int err[/*pages*/])
+{
+ assert(addr == NULL && flags == 0);
+ return xenforeignmemory_map(h, dom, prot, pages, arr, err);
+}
+
+static inline int xentoolcore_restrict_all(domid_t domid)
+{
+ errno = ENOTTY;
+ return -1;
+}
+
+static inline int xendevicemodel_shutdown(xendevicemodel_handle *dmod,
+ domid_t domid, unsigned int reason)
+{
+ errno = ENOTTY;
+ return -1;
+}
+
+#else /* CONFIG_XEN_CTRL_INTERFACE_VERSION >= 41000 */
+
+#include <xentoolcore.h>
+
+#endif
+
+#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 40900
+
+static inline xendevicemodel_handle *xendevicemodel_open(
+ struct xentoollog_logger *logger, unsigned int open_flags)
+{
+ 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)
+{
+ return xc_hvm_create_ioreq_server(dmod, domid, handle_bufioreq,
+ id);
+}
+
+static inline int xendevicemodel_get_ioreq_server_info(
+ xendevicemodel_handle *dmod, domid_t domid, ioservid_t id,
+ xen_pfn_t *ioreq_pfn, xen_pfn_t *bufioreq_pfn,
+ evtchn_port_t *bufioreq_port)
+{
+ return xc_hvm_get_ioreq_server_info(dmod, domid, id, ioreq_pfn,
+ bufioreq_pfn, bufioreq_port);
+}
+
+static inline int xendevicemodel_map_io_range_to_ioreq_server(
+ xendevicemodel_handle *dmod, domid_t domid, ioservid_t id, int is_mmio,
+ uint64_t start, uint64_t end)
+{
+ return xc_hvm_map_io_range_to_ioreq_server(dmod, domid, id, is_mmio,
+ start, end);
+}
+
+static inline int xendevicemodel_unmap_io_range_from_ioreq_server(
+ xendevicemodel_handle *dmod, domid_t domid, ioservid_t id, int is_mmio,
+ uint64_t start, uint64_t end)
+{
+ return xc_hvm_unmap_io_range_from_ioreq_server(dmod, domid, id, is_mmio,
+ start, end);
+}
+
+static inline int xendevicemodel_map_pcidev_to_ioreq_server(
+ xendevicemodel_handle *dmod, domid_t domid, ioservid_t id,
+ uint16_t segment, uint8_t bus, uint8_t device, uint8_t function)
+{
+ return xc_hvm_map_pcidev_to_ioreq_server(dmod, domid, id, segment,
+ bus, device, function);
+}
+
+static inline int xendevicemodel_unmap_pcidev_from_ioreq_server(
+ xendevicemodel_handle *dmod, domid_t domid, ioservid_t id,
+ uint16_t segment, uint8_t bus, uint8_t device, uint8_t function)
+{
+ return xc_hvm_unmap_pcidev_from_ioreq_server(dmod, domid, id, segment,
+ bus, device, function);
+}
+
+static inline int xendevicemodel_destroy_ioreq_server(
+ xendevicemodel_handle *dmod, domid_t domid, ioservid_t id)
+{
+ return xc_hvm_destroy_ioreq_server(dmod, domid, id);
+}
+
+static inline int xendevicemodel_set_ioreq_server_state(
+ xendevicemodel_handle *dmod, domid_t domid, ioservid_t id, int enabled)
+{
+ 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)
+{
+ return xc_hvm_set_pci_intx_level(dmod, domid, segment, bus, device,
+ intx, level);
+}
+
+static inline int xendevicemodel_set_isa_irq_level(
+ xendevicemodel_handle *dmod, domid_t domid, uint8_t irq,
+ unsigned int level)
+{
+ return xc_hvm_set_isa_irq_level(dmod, domid, irq, level);
+}
+
+static inline int xendevicemodel_set_pci_link_route(
+ xendevicemodel_handle *dmod, domid_t domid, uint8_t link, uint8_t irq)
+{
+ return xc_hvm_set_pci_link_route(dmod, domid, link, irq);
+}
+
+static inline int xendevicemodel_inject_msi(
+ xendevicemodel_handle *dmod, domid_t domid, uint64_t msi_addr,
+ uint32_t msi_data)
+{
+ return xc_hvm_inject_msi(dmod, domid, msi_addr, msi_data);
+}
+
+static inline int xendevicemodel_track_dirty_vram(
+ xendevicemodel_handle *dmod, domid_t domid, uint64_t first_pfn,
+ uint32_t nr, unsigned long *dirty_bitmap)
+{
+ return xc_hvm_track_dirty_vram(dmod, domid, first_pfn, nr,
+ dirty_bitmap);
+}
+
+static inline int xendevicemodel_modified_memory(
+ xendevicemodel_handle *dmod, domid_t domid, uint64_t first_pfn,
+ uint32_t nr)
+{
+ return xc_hvm_modified_memory(dmod, domid, first_pfn, nr);
+}
+
+static inline int xendevicemodel_set_mem_type(
+ xendevicemodel_handle *dmod, domid_t domid, hvmmem_type_t mem_type,
+ uint64_t first_pfn, uint32_t nr)
+{
+ return xc_hvm_set_mem_type(dmod, domid, mem_type, first_pfn, nr);
+}
+
+#endif
+
+extern xendevicemodel_handle *xen_dmod;
+
+static inline int xen_set_mem_type(domid_t domid, hvmmem_type_t type,
+ uint64_t first_pfn, uint32_t nr)
+{
+ return xendevicemodel_set_mem_type(xen_dmod, domid, type, first_pfn,
+ nr);
+}
+
+static inline int xen_set_pci_intx_level(domid_t domid, uint16_t segment,
+ uint8_t bus, uint8_t device,
+ uint8_t intx, unsigned int level)
+{
+ return xendevicemodel_set_pci_intx_level(xen_dmod, domid, segment, bus,
+ 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)
+{
+ return xendevicemodel_inject_msi(xen_dmod, domid, msi_addr, msi_data);
+}
+
+static inline int xen_set_isa_irq_level(domid_t domid, uint8_t irq,
+ unsigned int level)
+{
+ return xendevicemodel_set_isa_irq_level(xen_dmod, domid, irq, level);
+}
+
+static inline int xen_track_dirty_vram(domid_t domid, uint64_t first_pfn,
+ uint32_t nr, unsigned long *bitmap)
+{
+ return xendevicemodel_track_dirty_vram(xen_dmod, domid, first_pfn, nr,
+ bitmap);
+}
+
+static inline int xen_modified_memory(domid_t domid, uint64_t first_pfn,
+ uint32_t nr)
+{
+ return xendevicemodel_modified_memory(xen_dmod, domid, first_pfn, nr);
+}
+
+static inline int xen_restrict(domid_t domid)
+{
+ int rc;
+ rc = xentoolcore_restrict_all(domid);
+ trace_xen_domid_restrict(rc ? errno : 0);
+ return rc;
+}
+
+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);
+
+#ifdef HVM_PARAM_VMPORT_REGS_PFN
+static inline int xen_get_vmport_regs_pfn(xc_interface *xc, domid_t dom,
+ xen_pfn_t *vmport_regs_pfn)
+{
+ int rc;
+ uint64_t value;
+ rc = xc_hvm_param_get(xc, dom, HVM_PARAM_VMPORT_REGS_PFN, &value);
+ if (rc >= 0) {
+ *vmport_regs_pfn = (xen_pfn_t) value;
+ }
+ return rc;
+}
+#else
+static inline int xen_get_vmport_regs_pfn(xc_interface *xc, domid_t dom,
+ xen_pfn_t *vmport_regs_pfn)
+{
+ return -ENOSYS;
+}
+#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,
+ evtchn_port_t
+ *bufioreq_evtchn)
+{
+ unsigned long param;
+ int rc;
+
+ rc = xc_get_hvm_param(xen_xc, dom, HVM_PARAM_IOREQ_PFN, &param);
+ if (rc < 0) {
+ fprintf(stderr, "failed to get HVM_PARAM_IOREQ_PFN\n");
+ return -1;
+ }
+
+ *ioreq_pfn = param;
+
+ rc = xc_get_hvm_param(xen_xc, dom, HVM_PARAM_BUFIOREQ_PFN, &param);
+ if (rc < 0) {
+ fprintf(stderr, "failed to get HVM_PARAM_BUFIOREQ_PFN\n");
+ return -1;
+ }
+
+ *bufioreq_pfn = param;
+
+ rc = xc_get_hvm_param(xen_xc, dom, HVM_PARAM_BUFIOREQ_EVTCHN,
+ &param);
+ if (rc < 0) {
+ fprintf(stderr, "failed to get HVM_PARAM_BUFIOREQ_EVTCHN\n");
+ return -1;
+ }
+
+ *bufioreq_evtchn = param;
+
+ 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,
+ ioservid_t ioservid,
+ MemoryRegionSection *section)
+{
+ hwaddr start_addr = section->offset_within_address_space;
+ ram_addr_t size = int128_get64(section->size);
+ hwaddr end_addr = start_addr + size - 1;
+
+ if (use_default_ioreq_server) {
+ return;
+ }
+
+ trace_xen_map_mmio_range(ioservid, start_addr, end_addr);
+ xendevicemodel_map_io_range_to_ioreq_server(xen_dmod, dom, ioservid, 1,
+ start_addr, end_addr);
+}
+
+static inline void xen_unmap_memory_section(domid_t dom,
+ ioservid_t ioservid,
+ MemoryRegionSection *section)
+{
+ hwaddr start_addr = section->offset_within_address_space;
+ ram_addr_t size = int128_get64(section->size);
+ hwaddr end_addr = start_addr + size - 1;
+
+ if (use_default_ioreq_server) {
+ return;
+ }
+
+ trace_xen_unmap_mmio_range(ioservid, start_addr, end_addr);
+ xendevicemodel_unmap_io_range_from_ioreq_server(xen_dmod, dom, ioservid,
+ 1, start_addr, end_addr);
+}
+
+static inline void xen_map_io_section(domid_t dom,
+ ioservid_t ioservid,
+ MemoryRegionSection *section)
+{
+ hwaddr start_addr = section->offset_within_address_space;
+ ram_addr_t size = int128_get64(section->size);
+ hwaddr end_addr = start_addr + size - 1;
+
+ if (use_default_ioreq_server) {
+ return;
+ }
+
+ trace_xen_map_portio_range(ioservid, start_addr, end_addr);
+ xendevicemodel_map_io_range_to_ioreq_server(xen_dmod, dom, ioservid, 0,
+ start_addr, end_addr);
+}
+
+static inline void xen_unmap_io_section(domid_t dom,
+ ioservid_t ioservid,
+ MemoryRegionSection *section)
+{
+ hwaddr start_addr = section->offset_within_address_space;
+ ram_addr_t size = int128_get64(section->size);
+ hwaddr end_addr = start_addr + size - 1;
+
+ if (use_default_ioreq_server) {
+ return;
+ }
+
+ trace_xen_unmap_portio_range(ioservid, start_addr, end_addr);
+ xendevicemodel_unmap_io_range_from_ioreq_server(xen_dmod, dom, ioservid,
+ 0, start_addr, end_addr);
+}
+
+static inline void xen_map_pcidev(domid_t dom,
+ ioservid_t ioservid,
+ PCIDevice *pci_dev)
+{
+ if (use_default_ioreq_server) {
+ return;
+ }
+
+ trace_xen_map_pcidev(ioservid, pci_dev_bus_num(pci_dev),
+ PCI_SLOT(pci_dev->devfn), PCI_FUNC(pci_dev->devfn));
+ xendevicemodel_map_pcidev_to_ioreq_server(xen_dmod, dom, ioservid, 0,
+ pci_dev_bus_num(pci_dev),
+ PCI_SLOT(pci_dev->devfn),
+ PCI_FUNC(pci_dev->devfn));
+}
+
+static inline void xen_unmap_pcidev(domid_t dom,
+ ioservid_t ioservid,
+ PCIDevice *pci_dev)
+{
+ if (use_default_ioreq_server) {
+ return;
+ }
+
+ trace_xen_unmap_pcidev(ioservid, pci_dev_bus_num(pci_dev),
+ PCI_SLOT(pci_dev->devfn), PCI_FUNC(pci_dev->devfn));
+ xendevicemodel_unmap_pcidev_from_ioreq_server(xen_dmod, dom, ioservid, 0,
+ pci_dev_bus_num(pci_dev),
+ PCI_SLOT(pci_dev->devfn),
+ PCI_FUNC(pci_dev->devfn));
+}
+
+static inline void xen_create_ioreq_server(domid_t dom,
+ ioservid_t *ioservid)
+{
+ int rc = xendevicemodel_create_ioreq_server(xen_dmod, dom,
+ HVM_IOREQSRV_BUFIOREQ_ATOMIC,
+ ioservid);
+
+ if (rc == 0) {
+ trace_xen_ioreq_server_create(*ioservid);
+ return;
+ }
+
+ *ioservid = 0;
+ use_default_ioreq_server = true;
+ trace_xen_default_ioreq_server();
+}
+
+static inline void xen_destroy_ioreq_server(domid_t dom,
+ ioservid_t ioservid)
+{
+ if (use_default_ioreq_server) {
+ return;
+ }
+
+ trace_xen_ioreq_server_destroy(ioservid);
+ xendevicemodel_destroy_ioreq_server(xen_dmod, dom, 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)
+{
+ if (use_default_ioreq_server) {
+ return xen_get_default_ioreq_server_info(dom, ioreq_pfn,
+ bufioreq_pfn,
+ bufioreq_evtchn);
+ }
+
+ return xendevicemodel_get_ioreq_server_info(xen_dmod, dom, ioservid,
+ ioreq_pfn, bufioreq_pfn,
+ bufioreq_evtchn);
+}
+
+static inline int xen_set_ioreq_server_state(domid_t dom,
+ ioservid_t ioservid,
+ bool enable)
+{
+ if (use_default_ioreq_server) {
+ return 0;
+ }
+
+ trace_xen_ioreq_server_state(ioservid, enable);
+ return xendevicemodel_set_ioreq_server_state(xen_dmod, dom, ioservid,
+ enable);
+}
+
+#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;
+
+static inline int xengnttab_grant_copy(xengnttab_handle *xgt, uint32_t count,
+ xengnttab_grant_copy_segment_t *segs)
+{
+ return -ENOSYS;
+}
+#endif
+
+#endif /* QEMU_HW_XEN_COMMON_H */
diff --git a/include/hw/xen/xen_pvdev.h b/include/hw/xen/xen_pvdev.h
new file mode 100644
index 000000000..83e5174d9
--- /dev/null
+++ b/include/hw/xen/xen_pvdev.h
@@ -0,0 +1,81 @@
+#ifndef QEMU_HW_XEN_PVDEV_H
+#define QEMU_HW_XEN_PVDEV_H
+
+#include "hw/xen/xen_common.h"
+/* ------------------------------------------------------------- */
+
+#define XEN_BUFSIZE 1024
+
+struct XenLegacyDevice;
+
+/* driver uses grant tables -> open gntdev device (xendev->gnttabdev) */
+#define DEVOPS_FLAG_NEED_GNTDEV 1
+/* don't expect frontend doing correct state transitions (aka console quirk) */
+#define DEVOPS_FLAG_IGNORE_STATE 2
+
+struct XenDevOps {
+ size_t size;
+ uint32_t flags;
+ void (*alloc)(struct XenLegacyDevice *xendev);
+ int (*init)(struct XenLegacyDevice *xendev);
+ int (*initialise)(struct XenLegacyDevice *xendev);
+ void (*connected)(struct XenLegacyDevice *xendev);
+ void (*event)(struct XenLegacyDevice *xendev);
+ void (*disconnect)(struct XenLegacyDevice *xendev);
+ int (*free)(struct XenLegacyDevice *xendev);
+ void (*backend_changed)(struct XenLegacyDevice *xendev,
+ const char *node);
+ void (*frontend_changed)(struct XenLegacyDevice *xendev,
+ const char *node);
+ int (*backend_register)(void);
+};
+
+struct XenLegacyDevice {
+ DeviceState qdev;
+ const char *type;
+ int dom;
+ int dev;
+ char name[64];
+ int debug;
+
+ enum xenbus_state be_state;
+ enum xenbus_state fe_state;
+ int online;
+ char be[XEN_BUFSIZE];
+ char *fe;
+ char *protocol;
+ int remote_port;
+ int local_port;
+
+ xenevtchn_handle *evtchndev;
+ xengnttab_handle *gnttabdev;
+
+ struct XenDevOps *ops;
+ QTAILQ_ENTRY(XenLegacyDevice) next;
+};
+
+/* ------------------------------------------------------------- */
+
+/* xenstore helper functions */
+int xenstore_write_str(const char *base, const char *node, const char *val);
+int xenstore_write_int(const char *base, const char *node, int ival);
+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);
+
+void xen_pv_evtchn_event(void *opaque);
+void xen_pv_insert_xendev(struct XenLegacyDevice *xendev);
+void xen_pv_del_xendev(struct XenLegacyDevice *xendev);
+struct XenLegacyDevice *xen_pv_find_xendev(const char *type, int dom, int dev);
+
+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);
+
+#endif /* QEMU_HW_XEN_PVDEV_H */
diff --git a/include/hw/xtensa/mx_pic.h b/include/hw/xtensa/mx_pic.h
new file mode 100644
index 000000000..500424c8d
--- /dev/null
+++ b/include/hw/xtensa/mx_pic.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013 - 2019, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of the Open Source and Linux Lab nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 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 XTENSA_MX_PIC_H
+#define XTENSA_MX_PIC_H
+
+#include "exec/memory.h"
+
+struct XtensaMxPic;
+typedef struct XtensaMxPic XtensaMxPic;
+
+XtensaMxPic *xtensa_mx_pic_init(unsigned n_extint);
+void xtensa_mx_pic_reset(void *opaque);
+MemoryRegion *xtensa_mx_pic_register_cpu(XtensaMxPic *mx,
+ qemu_irq *irq,
+ qemu_irq runstall);
+qemu_irq *xtensa_mx_pic_get_extints(XtensaMxPic *mx);
+
+#endif
diff --git a/include/hw/xtensa/xtensa-isa.h b/include/hw/xtensa/xtensa-isa.h
new file mode 100644
index 000000000..a289531bd
--- /dev/null
+++ b/include/hw/xtensa/xtensa-isa.h
@@ -0,0 +1,836 @@
+/* Interface definition for configurable Xtensa ISA support.
+ *
+ * Copyright (c) 2001-2013 Tensilica 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 HW_XTENSA_XTENSA_ISA_H
+#define HW_XTENSA_XTENSA_ISA_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Version number: This is intended to help support code that works with
+ * versions of this library from multiple Xtensa releases.
+ */
+
+#define XTENSA_ISA_VERSION 7000
+
+/*
+ * This file defines the interface to the Xtensa ISA library. This
+ * library contains most of the ISA-specific information for a
+ * particular Xtensa processor. For example, the set of valid
+ * instructions, their opcode encodings and operand fields are all
+ * included here.
+ *
+ * This interface basically defines a number of abstract data types.
+ *
+ * . an instruction buffer - for holding the raw instruction bits
+ * . ISA info - information about the ISA as a whole
+ * . instruction formats - instruction size and slot structure
+ * . opcodes - information about individual instructions
+ * . operands - information about register and immediate instruction operands
+ * . stateOperands - information about processor state instruction operands
+ * . interfaceOperands - information about interface instruction operands
+ * . register files - register file information
+ * . processor states - internal processor state information
+ * . system registers - "special registers" and "user registers"
+ * . interfaces - TIE interfaces that are external to the processor
+ * . functional units - TIE shared functions
+ *
+ * The interface defines a set of functions to access each data type.
+ * With the exception of the instruction buffer, the internal
+ * representations of the data structures are hidden. All accesses must
+ * be made through the functions defined here.
+ */
+
+typedef struct xtensa_isa_opaque { int unused; } *xtensa_isa;
+
+
+/*
+ * Most of the Xtensa ISA entities (e.g., opcodes, regfiles, etc.) are
+ * represented here using sequential integers beginning with 0. The
+ * specific values are only fixed for a particular instantiation of an
+ * xtensa_isa structure, so these values should only be used
+ * internally.
+ */
+
+typedef int xtensa_opcode;
+typedef int xtensa_format;
+typedef int xtensa_regfile;
+typedef int xtensa_state;
+typedef int xtensa_sysreg;
+typedef int xtensa_interface;
+typedef int xtensa_funcUnit;
+
+
+/* Define a unique value for undefined items. */
+
+#define XTENSA_UNDEFINED -1
+
+
+/*
+ * Overview of using this interface to decode/encode instructions:
+ *
+ * Each Xtensa instruction is associated with a particular instruction
+ * format, where the format defines a fixed number of slots for
+ * operations. The formats for the core Xtensa ISA have only one slot,
+ * but FLIX instructions may have multiple slots. Within each slot,
+ * there is a single opcode and some number of associated operands.
+ *
+ * The encoding and decoding functions operate on instruction buffers,
+ * not on the raw bytes of the instructions. The same instruction
+ * buffer data structure is used for both entire instructions and
+ * individual slots in those instructions -- the contents of a slot need
+ * to be extracted from or inserted into the buffer for the instruction
+ * as a whole.
+ *
+ * Decoding an instruction involves first finding the format, which
+ * identifies the number of slots, and then decoding each slot
+ * separately. A slot is decoded by finding the opcode and then using
+ * the opcode to determine how many operands there are. For example:
+ *
+ * xtensa_insnbuf_from_chars
+ * xtensa_format_decode
+ * for each slot {
+ * xtensa_format_get_slot
+ * xtensa_opcode_decode
+ * for each operand {
+ * xtensa_operand_get_field
+ * xtensa_operand_decode
+ * }
+ * }
+ *
+ * Encoding an instruction is roughly the same procedure in reverse:
+ *
+ * xtensa_format_encode
+ * for each slot {
+ * xtensa_opcode_encode
+ * for each operand {
+ * xtensa_operand_encode
+ * xtensa_operand_set_field
+ * }
+ * xtensa_format_set_slot
+ * }
+ * xtensa_insnbuf_to_chars
+ */
+
+
+/* Error handling. */
+
+/*
+ * Error codes. The code for the most recent error condition can be
+ * retrieved with the "errno" function. For any result other than
+ * xtensa_isa_ok, an error message containing additional information
+ * about the problem can be retrieved using the "error_msg" function.
+ * The error messages are stored in an internal buffer, which should
+ * not be freed and may be overwritten by subsequent operations.
+ */
+
+typedef enum xtensa_isa_status_enum {
+ xtensa_isa_ok = 0,
+ xtensa_isa_bad_format,
+ xtensa_isa_bad_slot,
+ xtensa_isa_bad_opcode,
+ xtensa_isa_bad_operand,
+ xtensa_isa_bad_field,
+ xtensa_isa_bad_iclass,
+ xtensa_isa_bad_regfile,
+ xtensa_isa_bad_sysreg,
+ xtensa_isa_bad_state,
+ xtensa_isa_bad_interface,
+ xtensa_isa_bad_funcUnit,
+ xtensa_isa_wrong_slot,
+ xtensa_isa_no_field,
+ xtensa_isa_out_of_memory,
+ xtensa_isa_buffer_overflow,
+ xtensa_isa_internal_error,
+ xtensa_isa_bad_value
+} xtensa_isa_status;
+
+xtensa_isa_status xtensa_isa_errno(xtensa_isa isa);
+
+char *xtensa_isa_error_msg(xtensa_isa isa);
+
+
+
+/* Instruction buffers. */
+
+typedef uint32_t xtensa_insnbuf_word;
+typedef xtensa_insnbuf_word *xtensa_insnbuf;
+
+
+/* Get the size in "insnbuf_words" of the xtensa_insnbuf array. */
+
+int xtensa_insnbuf_size(xtensa_isa isa);
+
+
+/* Allocate an xtensa_insnbuf of the right size. */
+
+xtensa_insnbuf xtensa_insnbuf_alloc(xtensa_isa isa);
+
+
+/* Release an xtensa_insnbuf. */
+
+void xtensa_insnbuf_free(xtensa_isa isa, xtensa_insnbuf buf);
+
+
+/*
+ * Conversion between raw memory (char arrays) and our internal
+ * instruction representation. This is complicated by the Xtensa ISA's
+ * variable instruction lengths. When converting to chars, the buffer
+ * must contain a valid instruction so we know how many bytes to copy;
+ * thus, the "to_chars" function returns the number of bytes copied or
+ * XTENSA_UNDEFINED on error. The "from_chars" function first reads the
+ * minimal number of bytes required to decode the instruction length and
+ * then proceeds to copy the entire instruction into the buffer; if the
+ * memory does not contain a valid instruction, it copies the maximum
+ * number of bytes required for the longest Xtensa instruction. The
+ * "num_chars" argument may be used to limit the number of bytes that
+ * can be read or written. Otherwise, if "num_chars" is zero, the
+ * functions may read or write past the end of the code.
+ */
+
+int xtensa_insnbuf_to_chars(xtensa_isa isa, const xtensa_insnbuf insn,
+ unsigned char *cp, int num_chars);
+
+void xtensa_insnbuf_from_chars(xtensa_isa isa, xtensa_insnbuf insn,
+ const unsigned char *cp, int num_chars);
+
+
+
+/* ISA information. */
+
+/* Initialize the ISA information. */
+
+xtensa_isa xtensa_isa_init(void *xtensa_modules, xtensa_isa_status *errno_p,
+ char **error_msg_p);
+
+
+/* Deallocate an xtensa_isa structure. */
+
+void xtensa_isa_free(xtensa_isa isa);
+
+
+/* Get the maximum instruction size in bytes. */
+
+int xtensa_isa_maxlength(xtensa_isa isa);
+
+
+/*
+ * Decode the length in bytes of an instruction in raw memory (not an
+ * insnbuf). This function reads only the minimal number of bytes
+ * required to decode the instruction length. Returns
+ * XTENSA_UNDEFINED on error.
+ */
+
+int xtensa_isa_length_from_chars(xtensa_isa isa, const unsigned char *cp);
+
+
+/*
+ * Get the number of stages in the processor's pipeline. The pipeline
+ * stage values returned by other functions in this library will range
+ * from 0 to N-1, where N is the value returned by this function.
+ * Note that the stage numbers used here may not correspond to the
+ * actual processor hardware, e.g., the hardware may have additional
+ * stages before stage 0. Returns XTENSA_UNDEFINED on error.
+ */
+
+int xtensa_isa_num_pipe_stages(xtensa_isa isa);
+
+
+/* Get the number of various entities that are defined for this processor. */
+
+int xtensa_isa_num_formats(xtensa_isa isa);
+
+int xtensa_isa_num_opcodes(xtensa_isa isa);
+
+int xtensa_isa_num_regfiles(xtensa_isa isa);
+
+int xtensa_isa_num_states(xtensa_isa isa);
+
+int xtensa_isa_num_sysregs(xtensa_isa isa);
+
+int xtensa_isa_num_interfaces(xtensa_isa isa);
+
+int xtensa_isa_num_funcUnits(xtensa_isa isa);
+
+
+
+/* Instruction formats. */
+
+/* Get the name of a format. Returns null on error. */
+
+const char *xtensa_format_name(xtensa_isa isa, xtensa_format fmt);
+
+
+/*
+ * Given a format name, return the format number. Returns
+ * XTENSA_UNDEFINED if the name is not a valid format.
+ */
+
+xtensa_format xtensa_format_lookup(xtensa_isa isa, const char *fmtname);
+
+
+/*
+ * Decode the instruction format from a binary instruction buffer.
+ * Returns XTENSA_UNDEFINED if the format is not recognized.
+ */
+
+xtensa_format xtensa_format_decode(xtensa_isa isa, const xtensa_insnbuf insn);
+
+
+/*
+ * Set the instruction format field(s) in a binary instruction buffer.
+ * All the other fields are set to zero. Returns non-zero on error.
+ */
+
+int xtensa_format_encode(xtensa_isa isa, xtensa_format fmt,
+ xtensa_insnbuf insn);
+
+
+/*
+ * Find the length (in bytes) of an instruction. Returns
+ * XTENSA_UNDEFINED on error.
+ */
+
+int xtensa_format_length(xtensa_isa isa, xtensa_format fmt);
+
+
+/*
+ * Get the number of slots in an instruction. Returns XTENSA_UNDEFINED
+ * on error.
+ */
+
+int xtensa_format_num_slots(xtensa_isa isa, xtensa_format fmt);
+
+
+/*
+ * Get the opcode for a no-op in a particular slot.
+ * Returns XTENSA_UNDEFINED on error.
+ */
+
+xtensa_opcode xtensa_format_slot_nop_opcode(xtensa_isa isa, xtensa_format fmt,
+ int slot);
+
+
+/*
+ * Get the bits for a specified slot out of an insnbuf for the
+ * instruction as a whole and put them into an insnbuf for that one
+ * slot, and do the opposite to set a slot. Return non-zero on error.
+ */
+
+int xtensa_format_get_slot(xtensa_isa isa, xtensa_format fmt, int slot,
+ const xtensa_insnbuf insn, xtensa_insnbuf slotbuf);
+
+int xtensa_format_set_slot(xtensa_isa isa, xtensa_format fmt, int slot,
+ xtensa_insnbuf insn, const xtensa_insnbuf slotbuf);
+
+
+
+/* Opcode information. */
+
+/*
+ * Translate a mnemonic name to an opcode. Returns XTENSA_UNDEFINED if
+ * the name is not a valid opcode mnemonic.
+ */
+
+xtensa_opcode xtensa_opcode_lookup(xtensa_isa isa, const char *opname);
+
+
+/*
+ * Decode the opcode for one instruction slot from a binary instruction
+ * buffer. Returns the opcode or XTENSA_UNDEFINED if the opcode is
+ * illegal.
+ */
+
+xtensa_opcode xtensa_opcode_decode(xtensa_isa isa, xtensa_format fmt, int slot,
+ const xtensa_insnbuf slotbuf);
+
+
+/*
+ * Set the opcode field(s) for an instruction slot. All other fields
+ * in the slot are set to zero. Returns non-zero if the opcode cannot
+ * be encoded.
+ */
+
+int xtensa_opcode_encode(xtensa_isa isa, xtensa_format fmt, int slot,
+ xtensa_insnbuf slotbuf, xtensa_opcode opc);
+
+
+/* Get the mnemonic name for an opcode. Returns null on error. */
+
+const char *xtensa_opcode_name(xtensa_isa isa, xtensa_opcode opc);
+
+
+/* Check various properties of opcodes. These functions return 0 if
+ * the condition is false, 1 if the condition is true, and
+ * XTENSA_UNDEFINED on error. The instructions are classified as
+ * follows:
+ *
+ * branch: conditional branch; may fall through to next instruction (B*)
+ * jump: unconditional branch (J, JX, RET*, RF*)
+ * loop: zero-overhead loop (LOOP*)
+ * call: unconditional call; control returns to next instruction (CALL*)
+ *
+ * For the opcodes that affect control flow in some way, the branch
+ * target may be specified by an immediate operand or it may be an
+ * address stored in a register. You can distinguish these by
+ * checking if the instruction has a PC-relative immediate
+ * operand.
+ */
+
+int xtensa_opcode_is_branch(xtensa_isa isa, xtensa_opcode opc);
+
+int xtensa_opcode_is_jump(xtensa_isa isa, xtensa_opcode opc);
+
+int xtensa_opcode_is_loop(xtensa_isa isa, xtensa_opcode opc);
+
+int xtensa_opcode_is_call(xtensa_isa isa, xtensa_opcode opc);
+
+
+/*
+ * Find the number of ordinary operands, state operands, and interface
+ * operands for an instruction. These return XTENSA_UNDEFINED on
+ * error.
+ */
+
+int xtensa_opcode_num_operands(xtensa_isa isa, xtensa_opcode opc);
+
+int xtensa_opcode_num_stateOperands(xtensa_isa isa, xtensa_opcode opc);
+
+int xtensa_opcode_num_interfaceOperands(xtensa_isa isa, xtensa_opcode opc);
+
+
+/*
+ * Get functional unit usage requirements for an opcode. Each "use"
+ * is identified by a <functional unit, pipeline stage> pair. The
+ * "num_funcUnit_uses" function returns the number of these "uses" or
+ * XTENSA_UNDEFINED on error. The "funcUnit_use" function returns
+ * a pointer to a "use" pair or null on error.
+ */
+
+typedef struct xtensa_funcUnit_use_struct {
+ xtensa_funcUnit unit;
+ int stage;
+} xtensa_funcUnit_use;
+
+int xtensa_opcode_num_funcUnit_uses(xtensa_isa isa, xtensa_opcode opc);
+
+xtensa_funcUnit_use *xtensa_opcode_funcUnit_use(xtensa_isa isa,
+ xtensa_opcode opc, int u);
+
+
+
+/* Operand information. */
+
+/* Get the name of an operand. Returns null on error. */
+
+const char *xtensa_operand_name(xtensa_isa isa, xtensa_opcode opc, int opnd);
+
+
+/*
+ * Some operands are "invisible", i.e., not explicitly specified in
+ * assembly language. When assembling an instruction, you need not set
+ * the values of invisible operands, since they are either hardwired or
+ * derived from other field values. The values of invisible operands
+ * can be examined in the same way as other operands, but remember that
+ * an invisible operand may get its value from another visible one, so
+ * the entire instruction must be available before examining the
+ * invisible operand values. This function returns 1 if an operand is
+ * visible, 0 if it is invisible, or XTENSA_UNDEFINED on error. Note
+ * that whether an operand is visible is orthogonal to whether it is
+ * "implicit", i.e., whether it is encoded in a field in the
+ * instruction.
+ */
+
+int xtensa_operand_is_visible(xtensa_isa isa, xtensa_opcode opc, int opnd);
+
+
+/*
+ * Check if an operand is an input ('i'), output ('o'), or inout ('m')
+ * operand. Note: The output operand of a conditional assignment
+ * (e.g., movnez) appears here as an inout ('m') even if it is declared
+ * in the TIE code as an output ('o'); this allows the compiler to
+ * properly handle register allocation for conditional assignments.
+ * Returns 0 on error.
+ */
+
+char xtensa_operand_inout(xtensa_isa isa, xtensa_opcode opc, int opnd);
+
+
+/*
+ * Get and set the raw (encoded) value of the field for the specified
+ * operand. The "set" function does not check if the value fits in the
+ * field; that is done by the "encode" function below. Both of these
+ * functions return non-zero on error, e.g., if the field is not defined
+ * for the specified slot.
+ */
+
+int xtensa_operand_get_field(xtensa_isa isa, xtensa_opcode opc, int opnd,
+ xtensa_format fmt, int slot,
+ const xtensa_insnbuf slotbuf, uint32_t *valp);
+
+int xtensa_operand_set_field(xtensa_isa isa, xtensa_opcode opc, int opnd,
+ xtensa_format fmt, int slot,
+ xtensa_insnbuf slotbuf, uint32_t val);
+
+
+/*
+ * Encode and decode operands. The raw bits in the operand field may
+ * be encoded in a variety of different ways. These functions hide
+ * the details of that encoding. The result values are returned through
+ * the argument pointer. The return value is non-zero on error.
+ */
+
+int xtensa_operand_encode(xtensa_isa isa, xtensa_opcode opc, int opnd,
+ uint32_t *valp);
+
+int xtensa_operand_decode(xtensa_isa isa, xtensa_opcode opc, int opnd,
+ uint32_t *valp);
+
+
+/*
+ * An operand may be either a register operand or an immediate of some
+ * sort (e.g., PC-relative or not). The "is_register" function returns
+ * 0 if the operand is an immediate, 1 if it is a register, and
+ * XTENSA_UNDEFINED on error. The "regfile" function returns the
+ * regfile for a register operand, or XTENSA_UNDEFINED on error.
+ */
+
+int xtensa_operand_is_register(xtensa_isa isa, xtensa_opcode opc, int opnd);
+
+xtensa_regfile xtensa_operand_regfile(xtensa_isa isa, xtensa_opcode opc,
+ int opnd);
+
+
+/*
+ * Register operands may span multiple consecutive registers, e.g., a
+ * 64-bit data type may occupy two 32-bit registers. Only the first
+ * register is encoded in the operand field. This function specifies
+ * the number of consecutive registers occupied by this operand. For
+ * non-register operands, the return value is undefined. Returns
+ * XTENSA_UNDEFINED on error.
+ */
+
+int xtensa_operand_num_regs(xtensa_isa isa, xtensa_opcode opc, int opnd);
+
+
+/*
+ * Some register operands do not completely identify the register being
+ * accessed. For example, the operand value may be added to an internal
+ * state value. By definition, this implies that the corresponding
+ * regfile is not allocatable. Unknown registers should generally be
+ * treated with worst-case assumptions. The function returns 0 if the
+ * register value is unknown, 1 if known, and XTENSA_UNDEFINED on
+ * error.
+ */
+
+int xtensa_operand_is_known_reg(xtensa_isa isa, xtensa_opcode opc, int opnd);
+
+
+/*
+ * Check if an immediate operand is PC-relative. Returns 0 for register
+ * operands and non-PC-relative immediates, 1 for PC-relative
+ * immediates, and XTENSA_UNDEFINED on error.
+ */
+
+int xtensa_operand_is_PCrelative(xtensa_isa isa, xtensa_opcode opc, int opnd);
+
+
+/*
+ * For PC-relative offset operands, the interpretation of the offset may
+ * vary between opcodes, e.g., is it relative to the current PC or that
+ * of the next instruction? The following functions are defined to
+ * perform PC-relative relocations and to undo them (as in the
+ * disassembler). The "do_reloc" function takes the desired address
+ * value and the PC of the current instruction and sets the value to the
+ * corresponding PC-relative offset (which can then be encoded and
+ * stored into the operand field). The "undo_reloc" function takes the
+ * unencoded offset value and the current PC and sets the value to the
+ * appropriate address. The return values are non-zero on error. Note
+ * that these functions do not replace the encode/decode functions; the
+ * operands must be encoded/decoded separately and the encode functions
+ * are responsible for detecting invalid operand values.
+ */
+
+int xtensa_operand_do_reloc(xtensa_isa isa, xtensa_opcode opc, int opnd,
+ uint32_t *valp, uint32_t pc);
+
+int xtensa_operand_undo_reloc(xtensa_isa isa, xtensa_opcode opc, int opnd,
+ uint32_t *valp, uint32_t pc);
+
+
+
+/* State Operands. */
+
+/*
+ * Get the state accessed by a state operand. Returns XTENSA_UNDEFINED
+ * on error.
+ */
+
+xtensa_state xtensa_stateOperand_state(xtensa_isa isa, xtensa_opcode opc,
+ int stOp);
+
+
+/*
+ * Check if a state operand is an input ('i'), output ('o'), or inout
+ * ('m') operand. Returns 0 on error.
+ */
+
+char xtensa_stateOperand_inout(xtensa_isa isa, xtensa_opcode opc, int stOp);
+
+
+
+/* Interface Operands. */
+
+/*
+ * Get the external interface accessed by an interface operand.
+ * Returns XTENSA_UNDEFINED on error.
+ */
+
+xtensa_interface xtensa_interfaceOperand_interface(xtensa_isa isa,
+ xtensa_opcode opc,
+ int ifOp);
+
+
+
+/* Register Files. */
+
+/*
+ * Regfiles include both "real" regfiles and "views", where a view
+ * allows a group of adjacent registers in a real "parent" regfile to be
+ * viewed as a single register. A regfile view has all the same
+ * properties as its parent except for its (long) name, bit width, number
+ * of entries, and default ctype. You can use the parent function to
+ * distinguish these two classes.
+ */
+
+/*
+ * Look up a regfile by either its name or its abbreviated "short name".
+ * Returns XTENSA_UNDEFINED on error. The "lookup_shortname" function
+ * ignores "view" regfiles since they always have the same shortname as
+ * their parents.
+ */
+
+xtensa_regfile xtensa_regfile_lookup(xtensa_isa isa, const char *name);
+
+xtensa_regfile xtensa_regfile_lookup_shortname(xtensa_isa isa,
+ const char *shortname);
+
+
+/*
+ * Get the name or abbreviated "short name" of a regfile.
+ * Returns null on error.
+ */
+
+const char *xtensa_regfile_name(xtensa_isa isa, xtensa_regfile rf);
+
+const char *xtensa_regfile_shortname(xtensa_isa isa, xtensa_regfile rf);
+
+
+/*
+ * Get the parent regfile of a "view" regfile. If the regfile is not a
+ * view, the result is the same as the input parameter. Returns
+ * XTENSA_UNDEFINED on error.
+ */
+
+xtensa_regfile xtensa_regfile_view_parent(xtensa_isa isa, xtensa_regfile rf);
+
+
+/*
+ * Get the bit width of a regfile or regfile view.
+ * Returns XTENSA_UNDEFINED on error.
+ */
+
+int xtensa_regfile_num_bits(xtensa_isa isa, xtensa_regfile rf);
+
+
+/*
+ * Get the number of regfile entries. Returns XTENSA_UNDEFINED on
+ * error.
+ */
+
+int xtensa_regfile_num_entries(xtensa_isa isa, xtensa_regfile rf);
+
+
+
+/* Processor States. */
+
+/* Look up a state by name. Returns XTENSA_UNDEFINED on error. */
+
+xtensa_state xtensa_state_lookup(xtensa_isa isa, const char *name);
+
+
+/* Get the name for a processor state. Returns null on error. */
+
+const char *xtensa_state_name(xtensa_isa isa, xtensa_state st);
+
+
+/*
+ * Get the bit width for a processor state.
+ * Returns XTENSA_UNDEFINED on error.
+ */
+
+int xtensa_state_num_bits(xtensa_isa isa, xtensa_state st);
+
+
+/*
+ * Check if a state is exported from the processor core. Returns 0 if
+ * the condition is false, 1 if the condition is true, and
+ * XTENSA_UNDEFINED on error.
+ */
+
+int xtensa_state_is_exported(xtensa_isa isa, xtensa_state st);
+
+
+/*
+ * Check for a "shared_or" state. Returns 0 if the condition is false,
+ * 1 if the condition is true, and XTENSA_UNDEFINED on error.
+ */
+
+int xtensa_state_is_shared_or(xtensa_isa isa, xtensa_state st);
+
+
+
+/* Sysregs ("special registers" and "user registers"). */
+
+/*
+ * Look up a register by its number and whether it is a "user register"
+ * or a "special register". Returns XTENSA_UNDEFINED if the sysreg does
+ * not exist.
+ */
+
+xtensa_sysreg xtensa_sysreg_lookup(xtensa_isa isa, int num, int is_user);
+
+
+/*
+ * Check if there exists a sysreg with a given name.
+ * If not, this function returns XTENSA_UNDEFINED.
+ */
+
+xtensa_sysreg xtensa_sysreg_lookup_name(xtensa_isa isa, const char *name);
+
+
+/* Get the name of a sysreg. Returns null on error. */
+
+const char *xtensa_sysreg_name(xtensa_isa isa, xtensa_sysreg sysreg);
+
+
+/* Get the register number. Returns XTENSA_UNDEFINED on error. */
+
+int xtensa_sysreg_number(xtensa_isa isa, xtensa_sysreg sysreg);
+
+
+/*
+ * Check if a sysreg is a "special register" or a "user register".
+ * Returns 0 for special registers, 1 for user registers and
+ * XTENSA_UNDEFINED on error.
+ */
+
+int xtensa_sysreg_is_user(xtensa_isa isa, xtensa_sysreg sysreg);
+
+
+
+/* Interfaces. */
+
+/*
+ * Find an interface by name. The return value is XTENSA_UNDEFINED if
+ * the specified interface is not found.
+ */
+
+xtensa_interface xtensa_interface_lookup(xtensa_isa isa, const char *ifname);
+
+
+/* Get the name of an interface. Returns null on error. */
+
+const char *xtensa_interface_name(xtensa_isa isa, xtensa_interface intf);
+
+
+/*
+ * Get the bit width for an interface.
+ * Returns XTENSA_UNDEFINED on error.
+ */
+
+int xtensa_interface_num_bits(xtensa_isa isa, xtensa_interface intf);
+
+
+/*
+ * Check if an interface is an input ('i') or output ('o') with respect
+ * to the Xtensa processor core. Returns 0 on error.
+ */
+
+char xtensa_interface_inout(xtensa_isa isa, xtensa_interface intf);
+
+
+/*
+ * Check if accessing an interface has potential side effects.
+ * Currently "data" interfaces have side effects and "control"
+ * interfaces do not. Returns 1 if there are side effects, 0 if not,
+ * and XTENSA_UNDEFINED on error.
+ */
+
+int xtensa_interface_has_side_effect(xtensa_isa isa, xtensa_interface intf);
+
+
+/*
+ * Some interfaces may be related such that accessing one interface
+ * has side effects on a set of related interfaces. The interfaces
+ * are partitioned into equivalence classes of related interfaces, and
+ * each class is assigned a unique identifier number. This function
+ * returns the class identifier for an interface, or XTENSA_UNDEFINED
+ * on error. These identifiers can be compared to determine if two
+ * interfaces are related; the specific values of the identifiers have
+ * no particular meaning otherwise.
+ */
+
+int xtensa_interface_class_id(xtensa_isa isa, xtensa_interface intf);
+
+
+/* Functional Units. */
+
+/*
+ * Find a functional unit by name. The return value is XTENSA_UNDEFINED if
+ * the specified unit is not found.
+ */
+
+xtensa_funcUnit xtensa_funcUnit_lookup(xtensa_isa isa, const char *fname);
+
+
+/* Get the name of a functional unit. Returns null on error. */
+
+const char *xtensa_funcUnit_name(xtensa_isa isa, xtensa_funcUnit fun);
+
+
+/*
+ * Functional units may be replicated. See how many instances of a
+ * particular function unit exist. Returns XTENSA_UNDEFINED on error.
+ */
+
+int xtensa_funcUnit_num_copies(xtensa_isa isa, xtensa_funcUnit fun);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* HW_XTENSA_XTENSA_ISA_H */